aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbojie <bojie@dexon.org>2018-12-28 13:15:06 +0800
committerWei-Ning Huang <w@byzantine-lab.io>2019-06-12 17:27:20 +0800
commit3d46f69a10a60324ee6af0c96d064cc73ed5c37d (patch)
treeae9dd76f3f9a69c0acb18f6b0343601558d2e00f
parent2426b985ae9773afe12f5a9f982cf4f2629f81a3 (diff)
downloadgo-tangerine-3d46f69a10a60324ee6af0c96d064cc73ed5c37d.tar
go-tangerine-3d46f69a10a60324ee6af0c96d064cc73ed5c37d.tar.gz
go-tangerine-3d46f69a10a60324ee6af0c96d064cc73ed5c37d.tar.bz2
go-tangerine-3d46f69a10a60324ee6af0c96d064cc73ed5c37d.tar.lz
go-tangerine-3d46f69a10a60324ee6af0c96d064cc73ed5c37d.tar.xz
go-tangerine-3d46f69a10a60324ee6af0c96d064cc73ed5c37d.tar.zst
go-tangerine-3d46f69a10a60324ee6af0c96d064cc73ed5c37d.zip
app: use gcp storage instead of azure for builds (#81)
* vendor: add dependencies for using GCP storage * app: use gcp storage instead of azure for builds
-rw-r--r--.ci/DEXON-7548b3622930.json.encbin0 -> 2320 bytes
-rw-r--r--.travis.yml340
-rwxr-xr-xbuild/bls-arm64.sh43
-rw-r--r--build/ci.go154
-rw-r--r--build/deb/dexon-swarm/deb.changelog (renamed from build/deb/ethereum-swarm/deb.changelog)0
-rw-r--r--build/deb/dexon-swarm/deb.control (renamed from build/deb/ethereum-swarm/deb.control)0
-rw-r--r--build/deb/dexon-swarm/deb.copyright (renamed from build/deb/ethereum-swarm/deb.copyright)0
-rw-r--r--build/deb/dexon-swarm/deb.docs (renamed from build/deb/ethereum-swarm/deb.docs)0
-rw-r--r--build/deb/dexon-swarm/deb.install (renamed from build/deb/ethereum-swarm/deb.install)0
-rw-r--r--build/deb/dexon-swarm/deb.rules (renamed from build/deb/ethereum-swarm/deb.rules)0
-rw-r--r--build/deb/dexon/deb.changelog (renamed from build/deb/ethereum/deb.changelog)0
-rw-r--r--build/deb/dexon/deb.control (renamed from build/deb/ethereum/deb.control)0
-rw-r--r--build/deb/dexon/deb.copyright (renamed from build/deb/ethereum/deb.copyright)0
-rw-r--r--build/deb/dexon/deb.docs (renamed from build/deb/ethereum/deb.docs)0
-rw-r--r--build/deb/dexon/deb.install (renamed from build/deb/ethereum/deb.install)0
-rw-r--r--build/deb/dexon/deb.rules (renamed from build/deb/ethereum/deb.rules)0
-rw-r--r--build/utils.go39
-rw-r--r--internal/build/gcp.go82
-rw-r--r--vendor/cloud.google.com/go/LICENSE202
-rw-r--r--vendor/cloud.google.com/go/compute/metadata/metadata.go513
-rw-r--r--vendor/cloud.google.com/go/iam/iam.go292
-rw-r--r--vendor/cloud.google.com/go/internal/annotate.go54
-rw-r--r--vendor/cloud.google.com/go/internal/optional/optional.go108
-rw-r--r--vendor/cloud.google.com/go/internal/retry.go54
-rw-r--r--vendor/cloud.google.com/go/internal/trace/trace.go84
-rwxr-xr-xvendor/cloud.google.com/go/internal/version/update_version.sh6
-rw-r--r--vendor/cloud.google.com/go/internal/version/version.go71
-rw-r--r--vendor/cloud.google.com/go/storage/acl.go335
-rw-r--r--vendor/cloud.google.com/go/storage/bucket.go1129
-rw-r--r--vendor/cloud.google.com/go/storage/copy.go228
-rw-r--r--vendor/cloud.google.com/go/storage/doc.go176
-rw-r--r--vendor/cloud.google.com/go/storage/go110.go32
-rw-r--r--vendor/cloud.google.com/go/storage/iam.go130
-rw-r--r--vendor/cloud.google.com/go/storage/invoke.go37
-rw-r--r--vendor/cloud.google.com/go/storage/not_go110.go42
-rw-r--r--vendor/cloud.google.com/go/storage/notifications.go188
-rw-r--r--vendor/cloud.google.com/go/storage/reader.go385
-rw-r--r--vendor/cloud.google.com/go/storage/storage.go1123
-rw-r--r--vendor/cloud.google.com/go/storage/storage.replay53540
-rw-r--r--vendor/cloud.google.com/go/storage/writer.go261
-rw-r--r--vendor/github.com/golang/protobuf/LICENSE3
-rw-r--r--vendor/github.com/golang/protobuf/proto/Makefile43
-rw-r--r--vendor/github.com/golang/protobuf/proto/clone.go46
-rw-r--r--vendor/github.com/golang/protobuf/proto/decode.go669
-rw-r--r--vendor/github.com/golang/protobuf/proto/deprecated.go63
-rw-r--r--vendor/github.com/golang/protobuf/proto/discard.go350
-rw-r--r--vendor/github.com/golang/protobuf/proto/encode.go1209
-rw-r--r--vendor/github.com/golang/protobuf/proto/equal.go33
-rw-r--r--vendor/github.com/golang/protobuf/proto/extensions.go282
-rw-r--r--vendor/github.com/golang/protobuf/proto/lib.go166
-rw-r--r--vendor/github.com/golang/protobuf/proto/message_set.go138
-rw-r--r--vendor/github.com/golang/protobuf/proto/pointer_reflect.go598
-rw-r--r--vendor/github.com/golang/protobuf/proto/pointer_unsafe.go377
-rw-r--r--vendor/github.com/golang/protobuf/proto/properties.go471
-rw-r--r--vendor/github.com/golang/protobuf/proto/table_marshal.go2776
-rw-r--r--vendor/github.com/golang/protobuf/proto/table_merge.go654
-rw-r--r--vendor/github.com/golang/protobuf/proto/table_unmarshal.go2053
-rw-r--r--vendor/github.com/golang/protobuf/proto/text.go65
-rw-r--r--vendor/github.com/golang/protobuf/proto/text_parser.go83
-rw-r--r--vendor/github.com/golang/protobuf/ptypes/any.go139
-rw-r--r--vendor/github.com/golang/protobuf/ptypes/any/any.pb.go200
-rw-r--r--vendor/github.com/golang/protobuf/ptypes/any/any.proto154
-rw-r--r--vendor/github.com/golang/protobuf/ptypes/doc.go35
-rw-r--r--vendor/github.com/golang/protobuf/ptypes/duration.go102
-rw-r--r--vendor/github.com/golang/protobuf/ptypes/duration/duration.pb.go161
-rw-r--r--vendor/github.com/golang/protobuf/ptypes/duration/duration.proto117
-rw-r--r--vendor/github.com/golang/protobuf/ptypes/timestamp.go134
-rw-r--r--vendor/github.com/golang/protobuf/ptypes/timestamp/timestamp.pb.go179
-rw-r--r--vendor/github.com/golang/protobuf/ptypes/timestamp/timestamp.proto135
-rw-r--r--vendor/github.com/googleapis/gax-go/CODE_OF_CONDUCT.md43
-rw-r--r--vendor/github.com/googleapis/gax-go/CONTRIBUTING.md27
-rw-r--r--vendor/github.com/googleapis/gax-go/LICENSE27
-rw-r--r--vendor/github.com/googleapis/gax-go/README.md27
-rw-r--r--vendor/github.com/googleapis/gax-go/call_option.go71
-rw-r--r--vendor/github.com/googleapis/gax-go/gax.go39
-rw-r--r--vendor/github.com/googleapis/gax-go/go.mod6
-rw-r--r--vendor/github.com/googleapis/gax-go/go.sum28
-rw-r--r--vendor/github.com/googleapis/gax-go/header.go40
-rw-r--r--vendor/github.com/googleapis/gax-go/invoke.go52
-rw-r--r--vendor/github.com/googleapis/gax-go/v2/call_option.go161
-rw-r--r--vendor/github.com/googleapis/gax-go/v2/gax.go39
-rw-r--r--vendor/github.com/googleapis/gax-go/v2/go.mod3
-rw-r--r--vendor/github.com/googleapis/gax-go/v2/go.sum26
-rw-r--r--vendor/github.com/googleapis/gax-go/v2/header.go53
-rw-r--r--vendor/github.com/googleapis/gax-go/v2/invoke.go89
-rw-r--r--vendor/github.com/influxdata/influxdb/LICENSE_OF_DEPENDENCIES.md45
-rw-r--r--vendor/github.com/influxdata/influxdb/client/influxdb.go2
-rw-r--r--vendor/github.com/mattn/go-colorable/colorable_appengine.go29
-rw-r--r--vendor/go.opencensus.io/AUTHORS1
-rw-r--r--vendor/go.opencensus.io/CONTRIBUTING.md56
-rw-r--r--vendor/go.opencensus.io/Gopkg.lock231
-rw-r--r--vendor/go.opencensus.io/Gopkg.toml36
-rw-r--r--vendor/go.opencensus.io/LICENSE202
-rw-r--r--vendor/go.opencensus.io/README.md263
-rw-r--r--vendor/go.opencensus.io/appveyor.yml24
-rw-r--r--vendor/go.opencensus.io/exemplar/exemplar.go78
-rw-r--r--vendor/go.opencensus.io/go.mod25
-rw-r--r--vendor/go.opencensus.io/go.sum48
-rw-r--r--vendor/go.opencensus.io/internal/internal.go37
-rw-r--r--vendor/go.opencensus.io/internal/sanitize.go50
-rw-r--r--vendor/go.opencensus.io/internal/tagencoding/tagencoding.go72
-rw-r--r--vendor/go.opencensus.io/internal/traceinternals.go52
-rw-r--r--vendor/go.opencensus.io/opencensus.go21
-rw-r--r--vendor/go.opencensus.io/plugin/ochttp/client.go117
-rw-r--r--vendor/go.opencensus.io/plugin/ochttp/client_stats.go135
-rw-r--r--vendor/go.opencensus.io/plugin/ochttp/doc.go19
-rw-r--r--vendor/go.opencensus.io/plugin/ochttp/propagation/b3/b3.go123
-rw-r--r--vendor/go.opencensus.io/plugin/ochttp/route.go51
-rw-r--r--vendor/go.opencensus.io/plugin/ochttp/server.go440
-rw-r--r--vendor/go.opencensus.io/plugin/ochttp/span_annotating_client_trace.go169
-rw-r--r--vendor/go.opencensus.io/plugin/ochttp/stats.go265
-rw-r--r--vendor/go.opencensus.io/plugin/ochttp/trace.go228
-rw-r--r--vendor/go.opencensus.io/stats/doc.go69
-rw-r--r--vendor/go.opencensus.io/stats/internal/record.go25
-rw-r--r--vendor/go.opencensus.io/stats/internal/validation.go28
-rw-r--r--vendor/go.opencensus.io/stats/measure.go109
-rw-r--r--vendor/go.opencensus.io/stats/measure_float64.go55
-rw-r--r--vendor/go.opencensus.io/stats/measure_int64.go55
-rw-r--r--vendor/go.opencensus.io/stats/record.go69
-rw-r--r--vendor/go.opencensus.io/stats/units.go25
-rw-r--r--vendor/go.opencensus.io/stats/view/aggregation.go120
-rw-r--r--vendor/go.opencensus.io/stats/view/aggregation_data.go235
-rw-r--r--vendor/go.opencensus.io/stats/view/collector.go87
-rw-r--r--vendor/go.opencensus.io/stats/view/doc.go47
-rw-r--r--vendor/go.opencensus.io/stats/view/export.go58
-rw-r--r--vendor/go.opencensus.io/stats/view/view.go185
-rw-r--r--vendor/go.opencensus.io/stats/view/worker.go229
-rw-r--r--vendor/go.opencensus.io/stats/view/worker_commands.go183
-rw-r--r--vendor/go.opencensus.io/tag/context.go67
-rw-r--r--vendor/go.opencensus.io/tag/doc.go26
-rw-r--r--vendor/go.opencensus.io/tag/key.go35
-rw-r--r--vendor/go.opencensus.io/tag/map.go197
-rw-r--r--vendor/go.opencensus.io/tag/map_codec.go234
-rw-r--r--vendor/go.opencensus.io/tag/profile_19.go31
-rw-r--r--vendor/go.opencensus.io/tag/profile_not19.go23
-rw-r--r--vendor/go.opencensus.io/tag/validate.go56
-rw-r--r--vendor/go.opencensus.io/trace/basetypes.go119
-rw-r--r--vendor/go.opencensus.io/trace/config.go86
-rw-r--r--vendor/go.opencensus.io/trace/doc.go53
-rw-r--r--vendor/go.opencensus.io/trace/evictedqueue.go38
-rw-r--r--vendor/go.opencensus.io/trace/exemplar.go43
-rw-r--r--vendor/go.opencensus.io/trace/export.go97
-rw-r--r--vendor/go.opencensus.io/trace/internal/internal.go21
-rw-r--r--vendor/go.opencensus.io/trace/lrumap.go37
-rw-r--r--vendor/go.opencensus.io/trace/propagation/propagation.go108
-rw-r--r--vendor/go.opencensus.io/trace/sampling.go75
-rw-r--r--vendor/go.opencensus.io/trace/spanbucket.go130
-rw-r--r--vendor/go.opencensus.io/trace/spanstore.go306
-rw-r--r--vendor/go.opencensus.io/trace/status_codes.go37
-rw-r--r--vendor/go.opencensus.io/trace/trace.go598
-rw-r--r--vendor/go.opencensus.io/trace/trace_go11.go32
-rw-r--r--vendor/go.opencensus.io/trace/trace_nongo11.go25
-rw-r--r--vendor/go.opencensus.io/trace/tracestate/tracestate.go147
-rw-r--r--vendor/golang.org/x/net/context/ctxhttp/ctxhttp.go74
-rw-r--r--vendor/golang.org/x/net/context/ctxhttp/ctxhttp_pre17.go147
-rw-r--r--vendor/golang.org/x/net/http/httpguts/guts.go50
-rw-r--r--vendor/golang.org/x/net/http/httpguts/httplex.go346
-rw-r--r--vendor/golang.org/x/net/http2/Dockerfile51
-rw-r--r--vendor/golang.org/x/net/http2/Makefile3
-rw-r--r--vendor/golang.org/x/net/http2/README20
-rw-r--r--vendor/golang.org/x/net/http2/ciphers.go641
-rw-r--r--vendor/golang.org/x/net/http2/client_conn_pool.go282
-rw-r--r--vendor/golang.org/x/net/http2/databuffer.go146
-rw-r--r--vendor/golang.org/x/net/http2/errors.go133
-rw-r--r--vendor/golang.org/x/net/http2/flow.go50
-rw-r--r--vendor/golang.org/x/net/http2/frame.go1614
-rw-r--r--vendor/golang.org/x/net/http2/go111.go29
-rw-r--r--vendor/golang.org/x/net/http2/gotrack.go170
-rw-r--r--vendor/golang.org/x/net/http2/headermap.go88
-rw-r--r--vendor/golang.org/x/net/http2/hpack/encode.go240
-rw-r--r--vendor/golang.org/x/net/http2/hpack/hpack.go496
-rw-r--r--vendor/golang.org/x/net/http2/hpack/huffman.go222
-rw-r--r--vendor/golang.org/x/net/http2/hpack/tables.go479
-rw-r--r--vendor/golang.org/x/net/http2/http2.go384
-rw-r--r--vendor/golang.org/x/net/http2/not_go111.go20
-rw-r--r--vendor/golang.org/x/net/http2/pipe.go163
-rw-r--r--vendor/golang.org/x/net/http2/server.go2895
-rw-r--r--vendor/golang.org/x/net/http2/transport.go2603
-rw-r--r--vendor/golang.org/x/net/http2/write.go365
-rw-r--r--vendor/golang.org/x/net/http2/writesched.go242
-rw-r--r--vendor/golang.org/x/net/http2/writesched_priority.go452
-rw-r--r--vendor/golang.org/x/net/http2/writesched_random.go72
-rw-r--r--vendor/golang.org/x/net/internal/timeseries/timeseries.go525
-rw-r--r--vendor/golang.org/x/net/trace/events.go532
-rw-r--r--vendor/golang.org/x/net/trace/histogram.go365
-rw-r--r--vendor/golang.org/x/net/trace/trace.go1082
-rw-r--r--vendor/golang.org/x/net/trace/trace_go16.go21
-rw-r--r--vendor/golang.org/x/net/trace/trace_go17.go21
-rw-r--r--vendor/golang.org/x/oauth2/AUTHORS3
-rw-r--r--vendor/golang.org/x/oauth2/CONTRIBUTING.md26
-rw-r--r--vendor/golang.org/x/oauth2/CONTRIBUTORS3
-rw-r--r--vendor/golang.org/x/oauth2/LICENSE27
-rw-r--r--vendor/golang.org/x/oauth2/README.md86
-rw-r--r--vendor/golang.org/x/oauth2/google/appengine.go38
-rw-r--r--vendor/golang.org/x/oauth2/google/appengine_gen1.go77
-rw-r--r--vendor/golang.org/x/oauth2/google/appengine_gen2_flex.go27
-rw-r--r--vendor/golang.org/x/oauth2/google/default.go155
-rw-r--r--vendor/golang.org/x/oauth2/google/doc.go40
-rw-r--r--vendor/golang.org/x/oauth2/google/google.go192
-rw-r--r--vendor/golang.org/x/oauth2/google/jwt.go74
-rw-r--r--vendor/golang.org/x/oauth2/google/sdk.go201
-rw-r--r--vendor/golang.org/x/oauth2/internal/client_appengine.go13
-rw-r--r--vendor/golang.org/x/oauth2/internal/doc.go6
-rw-r--r--vendor/golang.org/x/oauth2/internal/oauth2.go37
-rw-r--r--vendor/golang.org/x/oauth2/internal/token.go277
-rw-r--r--vendor/golang.org/x/oauth2/internal/transport.go33
-rw-r--r--vendor/golang.org/x/oauth2/jws/jws.go182
-rw-r--r--vendor/golang.org/x/oauth2/jwt/jwt.go162
-rw-r--r--vendor/golang.org/x/oauth2/oauth2.go360
-rw-r--r--vendor/golang.org/x/oauth2/token.go175
-rw-r--r--vendor/golang.org/x/oauth2/transport.go144
-rwxr-xr-xvendor/golang.org/x/sys/unix/mksyscall_aix_ppc.pl384
-rwxr-xr-xvendor/golang.org/x/sys/unix/mksyscall_aix_ppc64.pl579
-rwxr-xr-xvendor/golang.org/x/sys/unix/mksyscall_solaris.pl294
-rwxr-xr-xvendor/golang.org/x/sys/unix/mksysnum_freebsd.pl50
-rw-r--r--vendor/google.golang.org/api/LICENSE27
-rw-r--r--vendor/google.golang.org/api/gensupport/backoff.go51
-rw-r--r--vendor/google.golang.org/api/gensupport/buffer.go79
-rw-r--r--vendor/google.golang.org/api/gensupport/doc.go10
-rw-r--r--vendor/google.golang.org/api/gensupport/header.go22
-rw-r--r--vendor/google.golang.org/api/gensupport/json.go211
-rw-r--r--vendor/google.golang.org/api/gensupport/jsonfloat.go57
-rw-r--r--vendor/google.golang.org/api/gensupport/media.go342
-rw-r--r--vendor/google.golang.org/api/gensupport/params.go51
-rw-r--r--vendor/google.golang.org/api/gensupport/resumable.go216
-rw-r--r--vendor/google.golang.org/api/gensupport/retry.go84
-rw-r--r--vendor/google.golang.org/api/gensupport/send.go87
-rw-r--r--vendor/google.golang.org/api/googleapi/googleapi.go429
-rw-r--r--vendor/google.golang.org/api/googleapi/internal/uritemplates/LICENSE18
-rw-r--r--vendor/google.golang.org/api/googleapi/internal/uritemplates/uritemplates.go248
-rw-r--r--vendor/google.golang.org/api/googleapi/internal/uritemplates/utils.go17
-rw-r--r--vendor/google.golang.org/api/googleapi/transport/apikey.go38
-rw-r--r--vendor/google.golang.org/api/googleapi/types.go202
-rw-r--r--vendor/google.golang.org/api/internal/creds.go45
-rw-r--r--vendor/google.golang.org/api/internal/pool.go61
-rw-r--r--vendor/google.golang.org/api/internal/service-account.json12
-rw-r--r--vendor/google.golang.org/api/internal/settings.go81
-rw-r--r--vendor/google.golang.org/api/iterator/iterator.go231
-rw-r--r--vendor/google.golang.org/api/option/credentials_go19.go33
-rw-r--r--vendor/google.golang.org/api/option/credentials_notgo19.go32
-rw-r--r--vendor/google.golang.org/api/option/option.go191
-rw-r--r--vendor/google.golang.org/api/storage/v1/storage-api.json3818
-rw-r--r--vendor/google.golang.org/api/storage/v1/storage-gen.go11472
-rw-r--r--vendor/google.golang.org/api/transport/http/dial.go147
-rw-r--r--vendor/google.golang.org/api/transport/http/dial_appengine.go30
-rw-r--r--vendor/google.golang.org/api/transport/http/internal/propagation/http.go96
-rw-r--r--vendor/google.golang.org/appengine/CONTRIBUTING.md90
-rw-r--r--vendor/google.golang.org/appengine/LICENSE202
-rw-r--r--vendor/google.golang.org/appengine/README.md73
-rw-r--r--vendor/google.golang.org/appengine/appengine.go137
-rw-r--r--vendor/google.golang.org/appengine/appengine_vm.go20
-rw-r--r--vendor/google.golang.org/appengine/errors.go46
-rw-r--r--vendor/google.golang.org/appengine/go.mod7
-rw-r--r--vendor/google.golang.org/appengine/go.sum6
-rw-r--r--vendor/google.golang.org/appengine/identity.go142
-rw-r--r--vendor/google.golang.org/appengine/internal/api.go671
-rw-r--r--vendor/google.golang.org/appengine/internal/api_classic.go169
-rw-r--r--vendor/google.golang.org/appengine/internal/api_common.go123
-rw-r--r--vendor/google.golang.org/appengine/internal/app_id.go28
-rw-r--r--vendor/google.golang.org/appengine/internal/app_identity/app_identity_service.pb.go611
-rw-r--r--vendor/google.golang.org/appengine/internal/app_identity/app_identity_service.proto64
-rw-r--r--vendor/google.golang.org/appengine/internal/identity.go55
-rw-r--r--vendor/google.golang.org/appengine/internal/identity_classic.go61
-rw-r--r--vendor/google.golang.org/appengine/internal/identity_flex.go11
-rw-r--r--vendor/google.golang.org/appengine/internal/identity_vm.go134
-rw-r--r--vendor/google.golang.org/appengine/internal/internal.go110
-rw-r--r--vendor/google.golang.org/appengine/internal/main.go15
-rw-r--r--vendor/google.golang.org/appengine/internal/main_vm.go48
-rw-r--r--vendor/google.golang.org/appengine/internal/metadata.go60
-rw-r--r--vendor/google.golang.org/appengine/internal/modules/modules_service.pb.go786
-rw-r--r--vendor/google.golang.org/appengine/internal/modules/modules_service.proto80
-rw-r--r--vendor/google.golang.org/appengine/internal/net.go56
-rwxr-xr-xvendor/google.golang.org/appengine/internal/regen.sh40
-rw-r--r--vendor/google.golang.org/appengine/internal/remote_api/remote_api.pb.go361
-rw-r--r--vendor/google.golang.org/appengine/internal/remote_api/remote_api.proto44
-rw-r--r--vendor/google.golang.org/appengine/internal/transaction.go115
-rw-r--r--vendor/google.golang.org/appengine/namespace.go25
-rw-r--r--vendor/google.golang.org/appengine/timeout.go20
-rwxr-xr-xvendor/google.golang.org/appengine/travis_install.sh18
-rwxr-xr-xvendor/google.golang.org/appengine/travis_test.sh12
-rw-r--r--vendor/google.golang.org/appengine/urlfetch/urlfetch.go210
-rw-r--r--vendor/google.golang.org/genproto/LICENSE202
-rw-r--r--vendor/google.golang.org/genproto/googleapis/api/annotations/annotations.pb.go54
-rw-r--r--vendor/google.golang.org/genproto/googleapis/api/annotations/http.pb.go688
-rw-r--r--vendor/google.golang.org/genproto/googleapis/iam/v1/iam_policy.pb.go412
-rw-r--r--vendor/google.golang.org/genproto/googleapis/iam/v1/policy.pb.go366
-rw-r--r--vendor/google.golang.org/genproto/googleapis/rpc/code/code.pb.go246
-rw-r--r--vendor/google.golang.org/genproto/googleapis/rpc/status/status.pb.go156
-rw-r--r--vendor/google.golang.org/grpc/AUTHORS1
-rw-r--r--vendor/google.golang.org/grpc/CONTRIBUTING.md36
-rw-r--r--vendor/google.golang.org/grpc/LICENSE202
-rw-r--r--vendor/google.golang.org/grpc/Makefile60
-rw-r--r--vendor/google.golang.org/grpc/README.md67
-rw-r--r--vendor/google.golang.org/grpc/backoff.go38
-rw-r--r--vendor/google.golang.org/grpc/balancer.go391
-rw-r--r--vendor/google.golang.org/grpc/balancer/balancer.go290
-rw-r--r--vendor/google.golang.org/grpc/balancer/base/balancer.go212
-rw-r--r--vendor/google.golang.org/grpc/balancer/base/base.go64
-rw-r--r--vendor/google.golang.org/grpc/balancer/roundrobin/roundrobin.go79
-rw-r--r--vendor/google.golang.org/grpc/balancer_conn_wrappers.go306
-rw-r--r--vendor/google.golang.org/grpc/balancer_v1_wrapper.go328
-rw-r--r--vendor/google.golang.org/grpc/binarylog/grpc_binarylog_v1/binarylog.pb.go900
-rw-r--r--vendor/google.golang.org/grpc/call.go74
-rw-r--r--vendor/google.golang.org/grpc/clientconn.go1508
-rw-r--r--vendor/google.golang.org/grpc/codec.go50
-rwxr-xr-xvendor/google.golang.org/grpc/codegen.sh17
-rw-r--r--vendor/google.golang.org/grpc/codes/code_string.go62
-rw-r--r--vendor/google.golang.org/grpc/codes/codes.go197
-rw-r--r--vendor/google.golang.org/grpc/connectivity/connectivity.go73
-rw-r--r--vendor/google.golang.org/grpc/credentials/credentials.go328
-rw-r--r--vendor/google.golang.org/grpc/credentials/internal/syscallconn.go61
-rw-r--r--vendor/google.golang.org/grpc/credentials/internal/syscallconn_appengine.go30
-rw-r--r--vendor/google.golang.org/grpc/dialoptions.go480
-rw-r--r--vendor/google.golang.org/grpc/doc.go24
-rw-r--r--vendor/google.golang.org/grpc/encoding/encoding.go118
-rw-r--r--vendor/google.golang.org/grpc/encoding/proto/proto.go110
-rw-r--r--vendor/google.golang.org/grpc/go.mod20
-rw-r--r--vendor/google.golang.org/grpc/go.sum32
-rw-r--r--vendor/google.golang.org/grpc/grpclog/grpclog.go126
-rw-r--r--vendor/google.golang.org/grpc/grpclog/logger.go85
-rw-r--r--vendor/google.golang.org/grpc/grpclog/loggerv2.go195
-rwxr-xr-xvendor/google.golang.org/grpc/install_gae.sh6
-rw-r--r--vendor/google.golang.org/grpc/interceptor.go77
-rw-r--r--vendor/google.golang.org/grpc/internal/backoff/backoff.go78
-rw-r--r--vendor/google.golang.org/grpc/internal/binarylog/binarylog.go167
-rw-r--r--vendor/google.golang.org/grpc/internal/binarylog/binarylog_testutil.go42
-rw-r--r--vendor/google.golang.org/grpc/internal/binarylog/env_config.go210
-rw-r--r--vendor/google.golang.org/grpc/internal/binarylog/method_logger.go426
-rwxr-xr-xvendor/google.golang.org/grpc/internal/binarylog/regenerate.sh33
-rw-r--r--vendor/google.golang.org/grpc/internal/binarylog/sink.go162
-rw-r--r--vendor/google.golang.org/grpc/internal/binarylog/util.go41
-rw-r--r--vendor/google.golang.org/grpc/internal/channelz/funcs.go668
-rw-r--r--vendor/google.golang.org/grpc/internal/channelz/types.go702
-rw-r--r--vendor/google.golang.org/grpc/internal/channelz/types_linux.go53
-rw-r--r--vendor/google.golang.org/grpc/internal/channelz/types_nonlinux.go44
-rw-r--r--vendor/google.golang.org/grpc/internal/channelz/util_linux.go39
-rw-r--r--vendor/google.golang.org/grpc/internal/channelz/util_nonlinux.go26
-rw-r--r--vendor/google.golang.org/grpc/internal/envconfig/envconfig.go69
-rw-r--r--vendor/google.golang.org/grpc/internal/grpcrand/grpcrand.go56
-rw-r--r--vendor/google.golang.org/grpc/internal/grpcsync/event.go61
-rw-r--r--vendor/google.golang.org/grpc/internal/internal.go43
-rw-r--r--vendor/google.golang.org/grpc/internal/syscall/syscall_linux.go114
-rw-r--r--vendor/google.golang.org/grpc/internal/syscall/syscall_nonlinux.go63
-rw-r--r--vendor/google.golang.org/grpc/internal/transport/bdp_estimator.go141
-rw-r--r--vendor/google.golang.org/grpc/internal/transport/controlbuf.go852
-rw-r--r--vendor/google.golang.org/grpc/internal/transport/defaults.go49
-rw-r--r--vendor/google.golang.org/grpc/internal/transport/flowcontrol.go218
-rw-r--r--vendor/google.golang.org/grpc/internal/transport/handler_server.go449
-rw-r--r--vendor/google.golang.org/grpc/internal/transport/http2_client.go1377
-rw-r--r--vendor/google.golang.org/grpc/internal/transport/http2_server.go1180
-rw-r--r--vendor/google.golang.org/grpc/internal/transport/http_util.go623
-rw-r--r--vendor/google.golang.org/grpc/internal/transport/log.go44
-rw-r--r--vendor/google.golang.org/grpc/internal/transport/transport.go736
-rw-r--r--vendor/google.golang.org/grpc/keepalive/keepalive.go83
-rw-r--r--vendor/google.golang.org/grpc/metadata/metadata.go209
-rw-r--r--vendor/google.golang.org/grpc/naming/dns_resolver.go293
-rw-r--r--vendor/google.golang.org/grpc/naming/naming.go69
-rw-r--r--vendor/google.golang.org/grpc/peer/peer.go51
-rw-r--r--vendor/google.golang.org/grpc/picker_wrapper.go180
-rw-r--r--vendor/google.golang.org/grpc/pickfirst.go110
-rw-r--r--vendor/google.golang.org/grpc/proxy.go152
-rw-r--r--vendor/google.golang.org/grpc/resolver/dns/dns_resolver.go436
-rw-r--r--vendor/google.golang.org/grpc/resolver/passthrough/passthrough.go57
-rw-r--r--vendor/google.golang.org/grpc/resolver/resolver.go158
-rw-r--r--vendor/google.golang.org/grpc/resolver_conn_wrapper.go155
-rw-r--r--vendor/google.golang.org/grpc/rpc_util.go815
-rw-r--r--vendor/google.golang.org/grpc/server.go1486
-rw-r--r--vendor/google.golang.org/grpc/service_config.go372
-rw-r--r--vendor/google.golang.org/grpc/stats/handlers.go63
-rw-r--r--vendor/google.golang.org/grpc/stats/stats.go295
-rw-r--r--vendor/google.golang.org/grpc/status/status.go210
-rw-r--r--vendor/google.golang.org/grpc/stream.go1489
-rw-r--r--vendor/google.golang.org/grpc/tap/tap.go51
-rw-r--r--vendor/google.golang.org/grpc/trace.go113
-rw-r--r--vendor/google.golang.org/grpc/version.go22
-rwxr-xr-xvendor/google.golang.org/grpc/vet.sh136
-rw-r--r--vendor/vendor.json561
377 files changed, 142209 insertions, 3483 deletions
diff --git a/.ci/DEXON-7548b3622930.json.enc b/.ci/DEXON-7548b3622930.json.enc
new file mode 100644
index 000000000..62a94fbe0
--- /dev/null
+++ b/.ci/DEXON-7548b3622930.json.enc
Binary files differ
diff --git a/.travis.yml b/.travis.yml
index d5a420445..8cd468e4e 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -8,12 +8,12 @@ matrix:
sudo: required
go: 1.10.x
script:
- - sudo modprobe fuse
- - sudo chmod 666 /dev/fuse
- - sudo chown root:$USER /etc/fuse.conf
- - make libbls
- - go run build/ci.go install
- - travis_retry go run build/ci.go test -coverage $TEST_PACKAGES
+ - sudo modprobe fuse
+ - sudo chmod 666 /dev/fuse
+ - sudo chown root:$USER /etc/fuse.conf
+ - make libbls
+ - go run build/ci.go install
+ - travis_retry go run build/ci.go test -coverage $TEST_PACKAGES
# These are the latest Go versions.
- os: linux
@@ -56,164 +56,170 @@ matrix:
- go run build/ci.go lint
# This builder does the Ubuntu PPA upload
- # - if: type = push
- # os: linux
- # dist: trusty
- # go: 1.11.x
- # env:
- # - ubuntu-ppa
- # git:
- # submodules: false # avoid cloning ethereum/tests
- # addons:
- # apt:
- # packages:
- # - devscripts
- # - debhelper
- # - dput
- # - fakeroot
- # - python-bzrlib
- # - python-paramiko
- # script:
- # - echo '|1|7SiYPr9xl3uctzovOTj4gMwAC1M=|t6ReES75Bo/PxlOPJ6/GsGbTrM0= ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA0aKz5UTUndYgIGG7dQBV+HaeuEZJ2xPHo2DS2iSKvUL4xNMSAY4UguNW+pX56nAQmZKIZZ8MaEvSj6zMEDiq6HFfn5JcTlM80UwlnyKe8B8p7Nk06PPQLrnmQt5fh0HmEcZx+JU9TZsfCHPnX7MNz4ELfZE6cFsclClrKim3BHUIGq//t93DllB+h4O9LHjEUsQ1Sr63irDLSutkLJD6RXchjROXkNirlcNVHH/jwLWR5RcYilNX7S5bIkK8NlWPjsn/8Ua5O7I9/YoE97PpO6i73DTGLh5H9JN/SITwCKBkgSDWUt61uPK3Y11Gty7o2lWsBjhBUm2Y38CBsoGmBw==' >> ~/.ssh/known_hosts
- # - go run build/ci.go debsrc -upload ethereum/ethereum -sftp-user geth-ci -signer "Go Ethereum Linux Builder <geth-ci@ethereum.org>"
-
- # # This builder does the Linux Azure uploads
- # - if: type = push
- # os: linux
- # dist: trusty
- # sudo: required
- # go: 1.11.x
- # env:
- # - azure-linux
- # git:
- # submodules: false # avoid cloning ethereum/tests
- # addons:
- # apt:
- # packages:
- # - gcc-multilib
- # script:
- # # Build for the primary platforms that Trusty can manage
- # - go run build/ci.go install
- # - go run build/ci.go archive -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds
- # - go run build/ci.go install -arch 386
- # - go run build/ci.go archive -arch 386 -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds
-
- # # Switch over GCC to cross compilation (breaks 386, hence why do it here only)
- # - sudo -E apt-get -yq --no-install-suggests --no-install-recommends --force-yes install gcc-arm-linux-gnueabi libc6-dev-armel-cross gcc-arm-linux-gnueabihf libc6-dev-armhf-cross gcc-aarch64-linux-gnu libc6-dev-arm64-cross
- # - sudo ln -s /usr/include/asm-generic /usr/include/asm
-
- # - GOARM=5 go run build/ci.go install -arch arm -cc arm-linux-gnueabi-gcc
- # - GOARM=5 go run build/ci.go archive -arch arm -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds
- # - GOARM=6 go run build/ci.go install -arch arm -cc arm-linux-gnueabi-gcc
- # - GOARM=6 go run build/ci.go archive -arch arm -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds
- # - GOARM=7 go run build/ci.go install -arch arm -cc arm-linux-gnueabihf-gcc
- # - GOARM=7 go run build/ci.go archive -arch arm -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds
- # - go run build/ci.go install -arch arm64 -cc aarch64-linux-gnu-gcc
- # - go run build/ci.go archive -arch arm64 -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds
-
- # # This builder does the Linux Azure MIPS xgo uploads
- # - if: type = push
- # os: linux
- # dist: trusty
- # services:
- # - docker
- # go: 1.11.x
- # env:
- # - azure-linux-mips
- # git:
- # submodules: false # avoid cloning ethereum/tests
- # script:
- # - go run build/ci.go xgo --alltools -- --targets=linux/mips --ldflags '-extldflags "-static"' -v
- # - for bin in build/bin/*-linux-mips; do mv -f "${bin}" "${bin/-linux-mips/}"; done
- # - go run build/ci.go archive -arch mips -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds
-
- # - go run build/ci.go xgo --alltools -- --targets=linux/mipsle --ldflags '-extldflags "-static"' -v
- # - for bin in build/bin/*-linux-mipsle; do mv -f "${bin}" "${bin/-linux-mipsle/}"; done
- # - go run build/ci.go archive -arch mipsle -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds
-
- # - go run build/ci.go xgo --alltools -- --targets=linux/mips64 --ldflags '-extldflags "-static"' -v
- # - for bin in build/bin/*-linux-mips64; do mv -f "${bin}" "${bin/-linux-mips64/}"; done
- # - go run build/ci.go archive -arch mips64 -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds
-
- # - go run build/ci.go xgo --alltools -- --targets=linux/mips64le --ldflags '-extldflags "-static"' -v
- # - for bin in build/bin/*-linux-mips64le; do mv -f "${bin}" "${bin/-linux-mips64le/}"; done
- # - go run build/ci.go archive -arch mips64le -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds
-
- # # This builder does the Android Maven and Azure uploads
- # - if: type = push
- # os: linux
- # dist: trusty
- # addons:
- # apt:
- # packages:
- # - oracle-java8-installer
- # - oracle-java8-set-default
- # language: android
- # android:
- # components:
- # - platform-tools
- # - tools
- # - android-15
- # - android-19
- # - android-24
- # env:
- # - azure-android
- # - maven-android
- # git:
- # submodules: false # avoid cloning ethereum/tests
- # before_install:
- # - curl https://storage.googleapis.com/golang/go1.11.5.linux-amd64.tar.gz | tar -xz
- # - export PATH=`pwd`/go/bin:$PATH
- # - export GOROOT=`pwd`/go
- # - export GOPATH=$HOME/go
- # script:
- # # Build the Android archive and upload it to Maven Central and Azure
- # - curl https://dl.google.com/android/repository/android-ndk-r17b-linux-x86_64.zip -o android-ndk-r17b.zip
- # - unzip -q android-ndk-r17b.zip && rm android-ndk-r17b.zip
- # - mv android-ndk-r17b $HOME
- # - export ANDROID_NDK=$HOME/android-ndk-r17b
-
- # - mkdir -p $GOPATH/src/github.com/ethereum
- # - ln -s `pwd` $GOPATH/src/github.com/ethereum
- # - go run build/ci.go aar -signer ANDROID_SIGNING_KEY -deploy https://oss.sonatype.org -upload gethstore/builds
-
- # # This builder does the OSX Azure, iOS CocoaPods and iOS Azure uploads
- # - if: type = push
- # os: osx
- # go: 1.11.x
- # env:
- # - azure-osx
- # - azure-ios
- # - cocoapods-ios
- # git:
- # submodules: false # avoid cloning ethereum/tests
- # script:
- # - go run build/ci.go install
- # - go run build/ci.go archive -type tar -signer OSX_SIGNING_KEY -upload gethstore/builds
-
- # # Build the iOS framework and upload it to CocoaPods and Azure
- # - gem uninstall cocoapods -a -x
- # - gem install cocoapods
-
- # - mv ~/.cocoapods/repos/master ~/.cocoapods/repos/master.bak
- # - sed -i '.bak' 's/repo.join/!repo.join/g' $(dirname `gem which cocoapods`)/cocoapods/sources_manager.rb
- # - if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then git clone --depth=1 https://github.com/CocoaPods/Specs.git ~/.cocoapods/repos/master && pod setup --verbose; fi
-
- # - xctool -version
- # - xcrun simctl list
-
- # # Workaround for https://github.com/golang/go/issues/23749
- # - export CGO_CFLAGS_ALLOW='-fmodules|-fblocks|-fobjc-arc'
- # - go run build/ci.go xcode -signer IOS_SIGNING_KEY -deploy trunk -upload gethstore/builds
-
- # # This builder does the Azure archive purges to avoid accumulating junk
- # - if: type = cron
- # os: linux
- # dist: trusty
- # go: 1.11.x
- # env:
- # - azure-purge
- # git:
- # submodules: false # avoid cloning ethereum/tests
- # script:
- # - go run build/ci.go purge -store gethstore/builds -days 14
+ #- if: type = push
+ # os: linux
+ # dist: trusty
+ # go: 1.11.x
+ # env:
+ # - ubuntu-ppa
+ # git:
+ # submodules: false # avoid cloning ethereum/tests
+ # addons:
+ # apt:
+ # packages:
+ # - devscripts
+ # - debhelper
+ # - dput
+ # - fakeroot
+ # script:
+ # - go run build/ci.go debsrc -signer "Go Ethereum Linux Builder <geth-ci@ethereum.org>" -upload ppa:ethereum/ethereum
+
+ # This builder does the Linux GCP uploads
+ - if: type = push
+ os: linux
+ dist: trusty
+ sudo: required
+ go: 1.11.x
+ env:
+ - gcp-linux
+ git:
+ submodules: false
+ addons:
+ apt:
+ packages:
+ - gcc-multilib
+ script:
+ - make libbls
+ - go run build/ci.go install
+ - go run build/ci.go archive -type tar -signer LINUX_SIGNING_KEY -upload dexon-builds
+ - ./build/bls-arm64.sh
+ - go run build/ci.go install -arch arm64 -cc aarch64-linux-gnu-gcc
+ - go run build/ci.go archive -arch arm64 -type tar -signer LINUX_SIGNING_KEY -upload
+ dexon-builds
+ # BLS lib does not support 32-bit platform
+ # - go run build/ci.go install -arch 386
+ # - go run build/ci.go archive -arch 386 -type tar -signer LINUX_SIGNING_KEY -upload
+ # dexon-builds
+ # - sudo -E apt-get -yq --no-install-suggests --no-install-recommends --force-yes
+ # install gcc-arm-linux-gnueabi libc6-dev-armel-cross gcc-arm-linux-gnueabihf
+ # libc6-dev-armhf-cross gcc-aarch64-linux-gnu libc6-dev-arm64-cross
+ # - sudo ln -s /usr/include/asm-generic /usr/include/asm
+ # - GOARM=5 go run build/ci.go install -arch arm -cc arm-linux-gnueabi-gcc
+ # - GOARM=5 go run build/ci.go archive -arch arm -type tar -signer LINUX_SIGNING_KEY
+ # -upload dexon-builds
+ # - GOARM=6 go run build/ci.go install -arch arm -cc arm-linux-gnueabi-gcc
+ # - GOARM=6 go run build/ci.go archive -arch arm -type tar -signer LINUX_SIGNING_KEY
+ # -upload dexon-builds
+ # - GOARM=7 go run build/ci.go install -arch arm -cc arm-linux-gnueabihf-gcc
+ # - GOARM=7 go run build/ci.go archive -arch arm -type tar -signer LINUX_SIGNING_KEY
+ # -upload dexon-builds
+ #- if: type = push
+ # os: linux
+ # dist: trusty
+ # services:
+ # - docker
+ # go: 1.11.x
+ # env:
+ # - gcp-linux-mips
+ # git:
+ # submodules: false
+ # script:
+ # - make libbls
+ # - go run build/ci.go xgo --alltools -- --targets=linux/mips --ldflags '-extldflags
+ # "-static"' -v
+ # - for bin in build/bin/*-linux-mips; do mv -f "${bin}" "${bin/-linux-mips/}";
+ # done
+ # - go run build/ci.go archive -arch mips -type tar -signer LINUX_SIGNING_KEY -upload
+ # dexon-builds
+ # - go run build/ci.go xgo --alltools -- --targets=linux/mipsle --ldflags '-extldflags
+ # "-static"' -v
+ # - for bin in build/bin/*-linux-mipsle; do mv -f "${bin}" "${bin/-linux-mipsle/}";
+ # done
+ # - go run build/ci.go archive -arch mipsle -type tar -signer LINUX_SIGNING_KEY
+ # -upload dexon-builds
+ # - go run build/ci.go xgo --alltools -- --targets=linux/mips64 --ldflags '-extldflags
+ # "-static"' -v
+ # - for bin in build/bin/*-linux-mips64; do mv -f "${bin}" "${bin/-linux-mips64/}";
+ # done
+ # - go run build/ci.go archive -arch mips64 -type tar -signer LINUX_SIGNING_KEY
+ # -upload dexon-builds
+ # - go run build/ci.go xgo --alltools -- --targets=linux/mips64le --ldflags '-extldflags
+ # "-static"' -v
+ # - for bin in build/bin/*-linux-mips64le; do mv -f "${bin}" "${bin/-linux-mips64le/}";
+ # done
+ # - go run build/ci.go archive -arch mips64le -type tar -signer LINUX_SIGNING_KEY
+ # -upload dexon-builds
+ #- if: type = push
+ # os: linux
+ # dist: trusty
+ # addons:
+ # apt:
+ # packages:
+ # - oracle-java8-installer
+ # - oracle-java8-set-default
+ # language: android
+ # android:
+ # components:
+ # - platform-tools
+ # - tools
+ # - android-15
+ # - android-19
+ # - android-24
+ # env:
+ # - gcp-android
+ # - maven-android
+ # git:
+ # submodules: false
+ # before_install:
+ # - curl https://storage.googleapis.com/golang/go1.11.1.linux-amd64.tar.gz | tar
+ # -xz
+ # - export PATH=`pwd`/go/bin:$PATH
+ # - export GOROOT=`pwd`/go
+ # - export GOPATH=$HOME/go
+ # script:
+ # - make libbls
+ # - curl https://dl.google.com/android/repository/android-ndk-r17b-linux-x86_64.zip
+ # -o android-ndk-r17b.zip
+ # - unzip -q android-ndk-r17b.zip && rm android-ndk-r17b.zip
+ # - mv android-ndk-r17b $HOME
+ # - export ANDROID_NDK=$HOME/android-ndk-r17b
+ # - mkdir -p $GOPATH/src/github.com/dexon-foundation/dexon
+ # - ln -s `pwd` $GOPATH/src/github.com/dexon-foundation/dexon
+ # - go run build/ci.go aar -signer ANDROID_SIGNING_KEY -deploy https://oss.sonatype.org
+ # -upload dexon-builds
+ - if: type = push
+ os: osx
+ go: 1.11.x
+ env:
+ - gcp-osx
+ - gcp-ios
+ - cocoapods-ios
+ git:
+ submodules: false
+ script:
+ - make libbls
+ - go run build/ci.go install
+ - go run build/ci.go archive -type tar -signer OSX_SIGNING_KEY -upload dexon-builds
+ # - gem uninstall cocoapods -a -x
+ # - gem install cocoapods
+ # - mv ~/.cocoapods/repos/master ~/.cocoapods/repos/master.bak
+ # - sed -i '.bak' 's/repo.join/!repo.join/g' $(dirname `gem which cocoapods`)/cocoapods/sources_manager.rb
+ # - if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then git clone --depth=1 https://github.com/CocoaPods/Specs.git
+ # ~/.cocoapods/repos/master && pod setup --verbose; fi
+ # - xctool -version
+ # - xcrun simctl list
+ # - export CGO_CFLAGS_ALLOW='-fmodules|-fblocks|-fobjc-arc'
+ # - go run build/ci.go xcode -signer IOS_SIGNING_KEY -deploy trunk -upload dexon-builds
+ - if: type = cron
+ os: linux
+ dist: trusty
+ go: 1.11.x
+ env:
+ - gcp-purge
+ git:
+ submodules: false
+ script:
+ - go run build/ci.go purge -store dexon-builds -days 14
+before_install:
+ - openssl aes-256-cbc -K $encrypted_556a2b2ff7f6_key -iv $encrypted_556a2b2ff7f6_iv
+ -in .ci/DEXON-7548b3622930.json.enc -out ./COBINHOOD-7548b3622930.json -d
diff --git a/build/bls-arm64.sh b/build/bls-arm64.sh
new file mode 100755
index 000000000..e2046dee0
--- /dev/null
+++ b/build/bls-arm64.sh
@@ -0,0 +1,43 @@
+#!/bin/bash -f
+
+cd vendor/github.com/dexon-foundation/
+
+sudo apt-get update
+
+sudo apt-get -yq --no-install-suggests --no-install-recommends --allow-downgrades --allow-remove-essential --allow-change-held-packages install gcc-aarch64-linux-gnu libc6-dev-arm64-cross g++-aarch64-linux-gnu
+
+rm -rf dep
+mkdir dep; cd dep
+
+echo 'travis_fold:start:aarch64-libgmp'
+echo 'Cross compiling libgmp for aarch64'
+mkdir libgmp; cd libgmp
+wget https://gmplib.org/download/gmp/gmp-6.1.2.tar.bz2
+tar -xjf gmp-6.1.2.tar.bz2
+cd gmp-6.1.2
+./configure --host=aarch64-linux-gnu --prefix=/usr/aarch64-linux-gnu --enable-cxx
+sudo make -j8
+sudo make install
+cd ../..
+echo 'travis_fold:end:aarch64-libgmp'
+
+echo 'travis_fold:start:aarch64-openssl'
+echo 'Cross compiling OpenSSL for aarch64'
+mkdir openssl; cd openssl
+wget https://www.openssl.org/source/openssl-1.1.1a.tar.gz
+tar -xzf openssl-1.1.1a.tar.gz
+cd openssl-1.1.1a
+./Configure linux-aarch64 --prefix=/usr/aarch64-linux-gnu
+sudo make CC=aarch64-linux-gnu-gcc -j8
+sudo make install
+cd ../..
+echo 'travis_fold:end:aarch64-openssl'
+
+cd ../
+
+echo 'travis_fold:start:aarch64-bls'
+echo 'Cross compiling bls for aarch64'
+cd bls
+make -C ../mcl clean
+GMP_PREFIX=/usr/aarch64-linux-gnu/lib OPENSSL_PREFIX=/usr/aarch64-linux-gnu/lib ARCH=aarch64 CXX=aarch64-linux-gnu-g++ make clean all
+echo 'travis_fold:end:aarch64-bls'
diff --git a/build/ci.go b/build/ci.go
index c29992f50..f49071295 100644
--- a/build/ci.go
+++ b/build/ci.go
@@ -1,18 +1,18 @@
-// Copyright 2016 The go-ethereum Authors
-// This file is part of the go-ethereum library.
+// Copyright 2016 The go-dexon Authors
+// This file is part of the go-dexon library.
//
-// The go-ethereum library is free software: you can redistribute it and/or modify
+// The go-dexon library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
-// The go-ethereum library is distributed in the hope that it will be useful,
+// The go-dexon library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
-// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
+// along with the go-dexon library. If not, see <http://www.gnu.org/licenses/>.
// +build none
@@ -64,19 +64,19 @@ import (
)
var (
- // Files that end up in the geth*.zip archive.
- gethArchiveFiles = []string{
+ // Files that end up in the gdex*.zip archive.
+ gdexArchiveFiles = []string{
"COPYING",
- executablePath("geth"),
+ executablePath("gdex"),
}
- // Files that end up in the geth-alltools*.zip archive.
+ // Files that end up in the gdex-alltools*.zip archive.
allToolsArchiveFiles = []string{
"COPYING",
executablePath("abigen"),
executablePath("bootnode"),
executablePath("evm"),
- executablePath("geth"),
+ executablePath("gdex"),
executablePath("puppeth"),
executablePath("rlpdump"),
executablePath("wnode"),
@@ -92,23 +92,23 @@ var (
debExecutables = []debExecutable{
{
BinaryName: "abigen",
- Description: "Source code generator to convert Ethereum contract definitions into easy to use, compile-time type-safe Go packages.",
+ Description: "Source code generator to convert Dexon contract definitions into easy to use, compile-time type-safe Go packages.",
},
{
BinaryName: "bootnode",
- Description: "Ethereum bootnode.",
+ Description: "Dexon bootnode.",
},
{
BinaryName: "evm",
- Description: "Developer utility version of the EVM (Ethereum Virtual Machine) that is capable of running bytecode snippets within a configurable environment and execution mode.",
+ Description: "Developer utility version of the EVM (Dexon Virtual Machine) that is capable of running bytecode snippets within a configurable environment and execution mode.",
},
{
- BinaryName: "geth",
- Description: "Ethereum CLI client.",
+ BinaryName: "gdex",
+ Description: "Dexon CLI client.",
},
{
BinaryName: "puppeth",
- Description: "Ethereum private network manager.",
+ Description: "Dexon private network manager.",
},
{
BinaryName: "rlpdump",
@@ -116,7 +116,7 @@ var (
},
{
BinaryName: "wnode",
- Description: "Ethereum Whisper diagnostic tool",
+ Description: "Dexon Whisper diagnostic tool",
},
}
@@ -124,19 +124,19 @@ var (
debSwarmExecutables = []debExecutable{
{
BinaryName: "swarm",
- PackageName: "ethereum-swarm",
- Description: "Ethereum Swarm daemon and tools",
+ PackageName: "dexon-swarm",
+ Description: "Dexon Swarm daemon and tools",
},
}
- debEthereum = debPackage{
- Name: "ethereum",
+ debDexon = debPackage{
+ Name: "dexon",
Version: params.Version,
Executables: debExecutables,
}
debSwarm = debPackage{
- Name: "ethereum-swarm",
+ Name: "dexon-swarm",
Version: sv.Version,
Executables: debSwarmExecutables,
}
@@ -144,7 +144,7 @@ var (
// Debian meta packages to build and push to Ubuntu PPA
debPackages = []debPackage{
debSwarm,
- debEthereum,
+ debDexon,
}
// Packages to be cross-compiled by the xgo command
@@ -222,7 +222,7 @@ func doInstall(cmdline []string) {
if minor < 9 {
log.Println("You have Go version", runtime.Version())
- log.Println("go-ethereum requires at least Go version 1.9 and cannot")
+ log.Println("go-dexon requires at least Go version 1.9 and cannot")
log.Println("be compiled with an earlier version. Please upgrade your Go installation.")
os.Exit(1)
}
@@ -384,7 +384,7 @@ func doArchive(cmdline []string) {
arch = flag.String("arch", runtime.GOARCH, "Architecture cross packaging")
atype = flag.String("type", "zip", "Type of archive to write (zip|tar)")
signer = flag.String("signer", "", `Environment variable holding the signing key (e.g. LINUX_SIGNING_KEY)`)
- upload = flag.String("upload", "", `Destination to upload the archives (usually "gethstore/builds")`)
+ upload = flag.String("upload", "", `Destination to upload the archives (usually "dexon-builds")`)
ext string
)
flag.CommandLine.Parse(cmdline)
@@ -400,15 +400,15 @@ func doArchive(cmdline []string) {
var (
env = build.Env()
- basegeth = archiveBasename(*arch, params.ArchiveVersion(env.Commit))
- geth = "geth-" + basegeth + ext
- alltools = "geth-alltools-" + basegeth + ext
+ basegdex = archiveBasename(*arch, params.ArchiveVersion(env.Commit))
+ gdex = "gdex-" + basegdex + ext
+ alltools = "gdex-alltools-" + basegdex + ext
baseswarm = archiveBasename(*arch, sv.ArchiveVersion(env.Commit))
swarm = "swarm-" + baseswarm + ext
)
maybeSkipArchive(env)
- if err := build.WriteArchive(geth, gethArchiveFiles); err != nil {
+ if err := build.WriteArchive(gdex, gdexArchiveFiles); err != nil {
log.Fatal(err)
}
if err := build.WriteArchive(alltools, allToolsArchiveFiles); err != nil {
@@ -417,7 +417,7 @@ func doArchive(cmdline []string) {
if err := build.WriteArchive(swarm, swarmArchiveFiles); err != nil {
log.Fatal(err)
}
- for _, archive := range []string{geth, alltools, swarm} {
+ for _, archive := range []string{gdex, alltools, swarm} {
if err := archiveUpload(archive, *upload, *signer); err != nil {
log.Fatal(err)
}
@@ -448,16 +448,14 @@ func archiveUpload(archive string, blobstore string, signer string) error {
}
// If uploading to Azure was requested, push the archive possibly with its signature
if blobstore != "" {
- auth := build.AzureBlobstoreConfig{
- Account: strings.Split(blobstore, "/")[0],
- Token: os.Getenv("AZURE_BLOBSTORE_TOKEN"),
- Container: strings.SplitN(blobstore, "/", 2)[1],
+ auth := build.GCPOption{
+ CredentialPath: os.Getenv("GCP_CREDENTIAL_PATH"),
}
- if err := build.AzureBlobstoreUpload(archive, filepath.Base(archive), auth); err != nil {
+ if err := build.GCPFileUpload(archive, blobstore, filepath.Base(archive), auth); err != nil {
return err
}
if signer != "" {
- if err := build.AzureBlobstoreUpload(archive+".asc", filepath.Base(archive+".asc"), auth); err != nil {
+ if err := build.GCPFileUpload(archive+".asc", blobstore, filepath.Base(archive+".asc"), auth); err != nil {
return err
}
}
@@ -475,7 +473,7 @@ func maybeSkipArchive(env build.Environment) {
log.Printf("skipping because this is a cron job")
os.Exit(0)
}
- if env.Branch != "master" && !strings.HasPrefix(env.Tag, "v1.") {
+ if env.Branch != "dev" && !strings.HasPrefix(env.Tag, "v1.") {
log.Printf("skipping because branch %q, tag %q is not on the whitelist", env.Branch, env.Tag)
os.Exit(0)
}
@@ -485,7 +483,7 @@ func maybeSkipArchive(env build.Environment) {
func doDebianSource(cmdline []string) {
var (
signer = flag.String("signer", "", `Signing key name, also used as package author`)
- upload = flag.String("upload", "", `Where to upload the source package (usually "ethereum/ethereum")`)
+ upload = flag.String("upload", "", `Where to upload the source package (usually "ppa:dexon/dexon")`)
sshUser = flag.String("sftp-user", "", `Username for SFTP upload (usually "geth-ci")`)
workdir = flag.String("workdir", "", `Output directory for packages (uses temp dir if unset)`)
now = time.Now()
@@ -564,7 +562,7 @@ func makeWorkdir(wdflag string) string {
if wdflag != "" {
err = os.MkdirAll(wdflag, 0744)
} else {
- wdflag, err = ioutil.TempDir("", "geth-build-")
+ wdflag, err = ioutil.TempDir("", "gdex-build-")
}
if err != nil {
log.Fatal(err)
@@ -580,7 +578,7 @@ func isUnstableBuild(env build.Environment) bool {
}
type debPackage struct {
- Name string // the name of the Debian package to produce, e.g. "ethereum", or "ethereum-swarm"
+ Name string // the name of the Debian package to produce, e.g. "dexon", or "dexon-swarm"
Version string // the clean version of the debPackage, e.g. 1.8.12 or 0.3.0, without any metadata
Executables []debExecutable // executables to be included in the package
}
@@ -590,7 +588,7 @@ type debMetadata struct {
PackageName string
- // go-ethereum version being built. Note that this
+ // go-dexon version being built. Note that this
// is not the debian package version. The package version
// is constructed by VersionString.
Version string
@@ -618,7 +616,7 @@ func (d debExecutable) Package() string {
func newDebMetadata(distro, author string, env build.Environment, t time.Time, name string, version string, exes []debExecutable) debMetadata {
if author == "" {
// No signing key, use default author.
- author = "Ethereum Builds <fjl@ethereum.org>"
+ author = "Dexon Builds <fjl@dexon.org>"
}
return debMetadata{
PackageName: name,
@@ -681,7 +679,7 @@ func (meta debMetadata) ExeConflicts(exe debExecutable) string {
// be preferred and the conflicting files should be handled via
// alternates. We might do this eventually but using a conflict is
// easier now.
- return "ethereum, " + exe.Package()
+ return "dexon, " + exe.Package()
}
return ""
}
@@ -720,7 +718,7 @@ func doWindowsInstaller(cmdline []string) {
var (
arch = flag.String("arch", runtime.GOARCH, "Architecture for cross build packaging")
signer = flag.String("signer", "", `Environment variable holding the signing key (e.g. WINDOWS_SIGNING_KEY)`)
- upload = flag.String("upload", "", `Destination to upload the archives (usually "gethstore/builds")`)
+ upload = flag.String("upload", "", `Destination to upload the archives (usually "dexon.build")`)
workdir = flag.String("workdir", "", `Output directory for packages (uses temp dir if unset)`)
)
flag.CommandLine.Parse(cmdline)
@@ -732,28 +730,28 @@ func doWindowsInstaller(cmdline []string) {
var (
devTools []string
allTools []string
- gethTool string
+ gdexTool string
)
for _, file := range allToolsArchiveFiles {
if file == "COPYING" { // license, copied later
continue
}
allTools = append(allTools, filepath.Base(file))
- if filepath.Base(file) == "geth.exe" {
- gethTool = file
+ if filepath.Base(file) == "gdex.exe" {
+ gdexTool = file
} else {
devTools = append(devTools, file)
}
}
// Render NSIS scripts: Installer NSIS contains two installer sections,
- // first section contains the geth binary, second section holds the dev tools.
+ // first section contains the gdex binary, second section holds the dev tools.
templateData := map[string]interface{}{
"License": "COPYING",
- "Geth": gethTool,
+ "Gdex": gdexTool,
"DevTools": devTools,
}
- build.Render("build/nsis.geth.nsi", filepath.Join(*workdir, "geth.nsi"), 0644, nil)
+ build.Render("build/nsis.gdex.nsi", filepath.Join(*workdir, "gdex.nsi"), 0644, nil)
build.Render("build/nsis.install.nsh", filepath.Join(*workdir, "install.nsh"), 0644, templateData)
build.Render("build/nsis.uninstall.nsh", filepath.Join(*workdir, "uninstall.nsh"), 0644, allTools)
build.Render("build/nsis.pathupdate.nsh", filepath.Join(*workdir, "PathUpdate.nsh"), 0644, nil)
@@ -768,14 +766,14 @@ func doWindowsInstaller(cmdline []string) {
if env.Commit != "" {
version[2] += "-" + env.Commit[:8]
}
- installer, _ := filepath.Abs("geth-" + archiveBasename(*arch, params.ArchiveVersion(env.Commit)) + ".exe")
+ installer, _ := filepath.Abs("gdex-" + archiveBasename(*arch, params.ArchiveVersion(env.Commit)) + ".exe")
build.MustRunCommand("makensis.exe",
"/DOUTPUTFILE="+installer,
"/DMAJORVERSION="+version[0],
"/DMINORVERSION="+version[1],
"/DBUILDVERSION="+version[2],
"/DARCH="+*arch,
- filepath.Join(*workdir, "geth.nsi"),
+ filepath.Join(*workdir, "gdex.nsi"),
)
// Sign and publish installer.
@@ -791,7 +789,7 @@ func doAndroidArchive(cmdline []string) {
local = flag.Bool("local", false, `Flag whether we're only doing a local build (skip Maven artifacts)`)
signer = flag.String("signer", "", `Environment variable holding the signing key (e.g. ANDROID_SIGNING_KEY)`)
deploy = flag.String("deploy", "", `Destination to deploy the archive (usually "https://oss.sonatype.org")`)
- upload = flag.String("upload", "", `Destination to upload the archive (usually "gethstore/builds")`)
+ upload = flag.String("upload", "", `Destination to upload the archive (usually "dexon-builds")`)
)
flag.CommandLine.Parse(cmdline)
env := build.Env()
@@ -806,11 +804,11 @@ func doAndroidArchive(cmdline []string) {
// Build the Android archive and Maven resources
build.MustRun(goTool("get", "golang.org/x/mobile/cmd/gomobile", "golang.org/x/mobile/cmd/gobind"))
build.MustRun(gomobileTool("init", "--ndk", os.Getenv("ANDROID_NDK")))
- build.MustRun(gomobileTool("bind", "-ldflags", "-s -w", "--target", "android", "--javapkg", "org.ethereum", "-v", "github.com/dexon-foundation/dexon/mobile"))
+ build.MustRun(gomobileTool("bind", "-ldflags", "-s -w", "--target", "android", "--javapkg", "org.dexon", "-v", "github.com/dexon-foundation/dexon/mobile"))
if *local {
// If we're building locally, copy bundle to build dir and skip Maven
- os.Rename("geth.aar", filepath.Join(GOBIN, "geth.aar"))
+ os.Rename("gdex.aar", filepath.Join(GOBIN, "gdex.aar"))
return
}
meta := newMavenMetadata(env)
@@ -820,8 +818,8 @@ func doAndroidArchive(cmdline []string) {
maybeSkipArchive(env)
// Sign and upload the archive to Azure
- archive := "geth-" + archiveBasename("android", params.ArchiveVersion(env.Commit)) + ".aar"
- os.Rename("geth.aar", archive)
+ archive := "gdex-" + archiveBasename("android", params.ArchiveVersion(env.Commit)) + ".aar"
+ os.Rename("gdex.aar", archive)
if err := archiveUpload(archive, *upload, *signer); err != nil {
log.Fatal(err)
@@ -906,7 +904,7 @@ func newMavenMetadata(env build.Environment) mavenMetadata {
}
return mavenMetadata{
Version: version,
- Package: "geth-" + version,
+ Package: "gdex-" + version,
Develop: isUnstableBuild(env),
Contributors: contribs,
}
@@ -919,7 +917,7 @@ func doXCodeFramework(cmdline []string) {
local = flag.Bool("local", false, `Flag whether we're only doing a local build (skip Maven artifacts)`)
signer = flag.String("signer", "", `Environment variable holding the signing key (e.g. IOS_SIGNING_KEY)`)
deploy = flag.String("deploy", "", `Destination to deploy the archive (usually "trunk")`)
- upload = flag.String("upload", "", `Destination to upload the archives (usually "gethstore/builds")`)
+ upload = flag.String("upload", "", `Destination to upload the archives (usually "dexon-builds")`)
)
flag.CommandLine.Parse(cmdline)
env := build.Env()
@@ -935,7 +933,7 @@ func doXCodeFramework(cmdline []string) {
build.MustRun(bind)
return
}
- archive := "geth-" + archiveBasename("ios", params.ArchiveVersion(env.Commit))
+ archive := "gdex-" + archiveBasename("ios", params.ArchiveVersion(env.Commit))
if err := os.Mkdir(archive, os.ModePerm); err != nil {
log.Fatal(err)
}
@@ -953,8 +951,8 @@ func doXCodeFramework(cmdline []string) {
// Prepare and upload a PodSpec to CocoaPods
if *deploy != "" {
meta := newPodMetadata(env, archive)
- build.Render("build/pod.podspec", "Geth.podspec", 0755, meta)
- build.MustRunCommand("pod", *deploy, "push", "Geth.podspec", "--allow-warnings", "--verbose")
+ build.Render("build/pod.podspec", "Gdex.podspec", 0755, meta)
+ build.MustRunCommand("pod", *deploy, "push", "Gdex.podspec", "--allow-warnings", "--verbose")
}
}
@@ -1059,7 +1057,7 @@ func xgoTool(args []string) *exec.Cmd {
func doPurge(cmdline []string) {
var (
- store = flag.String("store", "", `Destination from where to purge archives (usually "gethstore/builds")`)
+ store = flag.String("store", "", `Destination from where to purge archives (usually "dexon-builds")`)
limit = flag.Int("days", 30, `Age threshold above which to delete unstable archives`)
)
flag.CommandLine.Parse(cmdline)
@@ -1069,38 +1067,36 @@ func doPurge(cmdline []string) {
os.Exit(0)
}
// Create the azure authentication and list the current archives
- auth := build.AzureBlobstoreConfig{
- Account: strings.Split(*store, "/")[0],
- Token: os.Getenv("AZURE_BLOBSTORE_TOKEN"),
- Container: strings.SplitN(*store, "/", 2)[1],
+ auth := build.GCPOption{
+ CredentialPath: os.Getenv("GCP_CREDENTIAL_PATH"),
}
- blobs, err := build.AzureBlobstoreList(auth)
+ objects, err := build.GCPFileList(*store, auth)
if err != nil {
log.Fatal(err)
}
// Iterate over the blobs, collect and sort all unstable builds
- for i := 0; i < len(blobs); i++ {
- if !strings.Contains(blobs[i].Name, "unstable") {
- blobs = append(blobs[:i], blobs[i+1:]...)
+ for i := 0; i < len(objects); i++ {
+ if !strings.Contains(objects[i].Name, "unstable") {
+ objects = append(objects[:i], objects[i+1:]...)
i--
}
}
- for i := 0; i < len(blobs); i++ {
- for j := i + 1; j < len(blobs); j++ {
- if blobs[i].Properties.LastModified.After(blobs[j].Properties.LastModified) {
- blobs[i], blobs[j] = blobs[j], blobs[i]
+ for i := 0; i < len(objects); i++ {
+ for j := i + 1; j < len(objects); j++ {
+ if objects[i].Updated.After(objects[j].Updated) {
+ objects[i], objects[j] = objects[j], objects[i]
}
}
}
// Filter out all archives more recent that the given threshold
- for i, blob := range blobs {
- if time.Since(blob.Properties.LastModified) < time.Duration(*limit)*24*time.Hour {
- blobs = blobs[:i]
+ for i, blob := range objects {
+ if time.Since(blob.Updated) < time.Duration(*limit)*24*time.Hour {
+ objects = objects[:i]
break
}
}
// Delete all marked as such and return
- if err := build.AzureBlobstoreDelete(auth, blobs); err != nil {
+ if err := build.GCPFileDelete(*store, objects, auth); err != nil {
log.Fatal(err)
}
}
diff --git a/build/deb/ethereum-swarm/deb.changelog b/build/deb/dexon-swarm/deb.changelog
index 83f804a83..83f804a83 100644
--- a/build/deb/ethereum-swarm/deb.changelog
+++ b/build/deb/dexon-swarm/deb.changelog
diff --git a/build/deb/ethereum-swarm/deb.control b/build/deb/dexon-swarm/deb.control
index b787fe391..b787fe391 100644
--- a/build/deb/ethereum-swarm/deb.control
+++ b/build/deb/dexon-swarm/deb.control
diff --git a/build/deb/ethereum-swarm/deb.copyright b/build/deb/dexon-swarm/deb.copyright
index fe6e36ad9..fe6e36ad9 100644
--- a/build/deb/ethereum-swarm/deb.copyright
+++ b/build/deb/dexon-swarm/deb.copyright
diff --git a/build/deb/ethereum-swarm/deb.docs b/build/deb/dexon-swarm/deb.docs
index 62deb0497..62deb0497 100644
--- a/build/deb/ethereum-swarm/deb.docs
+++ b/build/deb/dexon-swarm/deb.docs
diff --git a/build/deb/ethereum-swarm/deb.install b/build/deb/dexon-swarm/deb.install
index e7666ce5f..e7666ce5f 100644
--- a/build/deb/ethereum-swarm/deb.install
+++ b/build/deb/dexon-swarm/deb.install
diff --git a/build/deb/ethereum-swarm/deb.rules b/build/deb/dexon-swarm/deb.rules
index 7f286569e..7f286569e 100644
--- a/build/deb/ethereum-swarm/deb.rules
+++ b/build/deb/dexon-swarm/deb.rules
diff --git a/build/deb/ethereum/deb.changelog b/build/deb/dexon/deb.changelog
index 83f804a83..83f804a83 100644
--- a/build/deb/ethereum/deb.changelog
+++ b/build/deb/dexon/deb.changelog
diff --git a/build/deb/ethereum/deb.control b/build/deb/dexon/deb.control
index 6d9c51346..6d9c51346 100644
--- a/build/deb/ethereum/deb.control
+++ b/build/deb/dexon/deb.control
diff --git a/build/deb/ethereum/deb.copyright b/build/deb/dexon/deb.copyright
index fe6e36ad9..fe6e36ad9 100644
--- a/build/deb/ethereum/deb.copyright
+++ b/build/deb/dexon/deb.copyright
diff --git a/build/deb/ethereum/deb.docs b/build/deb/dexon/deb.docs
index 62deb0497..62deb0497 100644
--- a/build/deb/ethereum/deb.docs
+++ b/build/deb/dexon/deb.docs
diff --git a/build/deb/ethereum/deb.install b/build/deb/dexon/deb.install
index e7666ce5f..e7666ce5f 100644
--- a/build/deb/ethereum/deb.install
+++ b/build/deb/dexon/deb.install
diff --git a/build/deb/ethereum/deb.rules b/build/deb/dexon/deb.rules
index 7f286569e..7f286569e 100644
--- a/build/deb/ethereum/deb.rules
+++ b/build/deb/dexon/deb.rules
diff --git a/build/utils.go b/build/utils.go
new file mode 100644
index 000000000..df869efd0
--- /dev/null
+++ b/build/utils.go
@@ -0,0 +1,39 @@
+// +build none
+
+package build
+
+import (
+ "bytes"
+ "encoding/base64"
+
+ "golang.org/x/crypto/openpgp"
+ "golang.org/x/crypto/openpgp/armor"
+)
+
+// GenerateEncodedPGPKeyPair generate base64 encoded PGP key pair
+func GenerateEncodedPGPKeyPair(name, comment, email string) (string, error) {
+ var e *openpgp.Entity
+ e, err := openpgp.NewEntity(name, comment, email, nil)
+ if err != nil {
+ return "", err
+ }
+
+ keyBuffer := bytes.Buffer{}
+ w, err := armor.Encode(&keyBuffer, openpgp.PrivateKeyType, nil)
+ if err != nil {
+ return "", err
+ }
+
+ err = e.SerializePrivate(w, nil)
+ if err != nil {
+ return "", err
+ }
+ w.Close()
+
+ base64Buffer := bytes.Buffer{}
+ en := base64.NewEncoder(base64.StdEncoding, &base64Buffer)
+ en.Write(keyBuffer.Bytes())
+ en.Close()
+
+ return base64Buffer.String(), nil
+}
diff --git a/internal/build/gcp.go b/internal/build/gcp.go
new file mode 100644
index 000000000..3c312a341
--- /dev/null
+++ b/internal/build/gcp.go
@@ -0,0 +1,82 @@
+package build
+
+import (
+ "io"
+ "os"
+
+ "cloud.google.com/go/storage"
+ "golang.org/x/net/context"
+ "google.golang.org/api/iterator"
+ "google.golang.org/api/option"
+)
+
+type GCPOption struct {
+ CredentialPath string
+}
+
+// GCPFileUpload upload file to GCP storage
+func GCPFileUpload(path, bucket, name string, opt GCPOption) error {
+ ctx := context.Background()
+ client, err := storage.NewClient(ctx, option.WithCredentialsFile(opt.CredentialPath))
+ if err != nil {
+ return err
+ }
+
+ wc := client.Bucket(bucket).Object(name).NewWriter(ctx)
+
+ in, err := os.Open(path)
+ if err != nil {
+ return err
+ }
+ defer in.Close()
+
+ if _, err = io.Copy(wc, in); err != nil {
+ return err
+ }
+ if err := wc.Close(); err != nil {
+ return err
+ }
+
+ return nil
+}
+
+// GCPFileList list files from GCP storage
+func GCPFileList(bucket string, opt GCPOption) ([]*storage.ObjectAttrs, error) {
+ ctx := context.Background()
+ client, err := storage.NewClient(ctx, option.WithCredentialsFile(opt.CredentialPath))
+ if err != nil {
+ return nil, err
+ }
+
+ var list []*storage.ObjectAttrs
+ it := client.Bucket(bucket).Objects(ctx, nil)
+ for {
+ attrs, err := it.Next()
+ if err == iterator.Done {
+ break
+ }
+ if err != nil {
+ return nil, err
+ }
+ list = append(list, attrs)
+ }
+
+ return list, nil
+}
+
+// GCPFileDelete delete files from GCP storage
+func GCPFileDelete(bucket string, objects []*storage.ObjectAttrs, opt GCPOption) error {
+ ctx := context.Background()
+ client, err := storage.NewClient(ctx, option.WithCredentialsFile(opt.CredentialPath))
+ if err != nil {
+ return err
+ }
+
+ for _, obj := range objects {
+ if err := client.Bucket(bucket).Object(obj.Name).Delete(ctx); err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
diff --git a/vendor/cloud.google.com/go/LICENSE b/vendor/cloud.google.com/go/LICENSE
new file mode 100644
index 000000000..d64569567
--- /dev/null
+++ b/vendor/cloud.google.com/go/LICENSE
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/vendor/cloud.google.com/go/compute/metadata/metadata.go b/vendor/cloud.google.com/go/compute/metadata/metadata.go
new file mode 100644
index 000000000..8a2f6c046
--- /dev/null
+++ b/vendor/cloud.google.com/go/compute/metadata/metadata.go
@@ -0,0 +1,513 @@
+// Copyright 2014 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package metadata provides access to Google Compute Engine (GCE)
+// metadata and API service accounts.
+//
+// This package is a wrapper around the GCE metadata service,
+// as documented at https://developers.google.com/compute/docs/metadata.
+package metadata // import "cloud.google.com/go/compute/metadata"
+
+import (
+ "context"
+ "encoding/json"
+ "fmt"
+ "io/ioutil"
+ "net"
+ "net/http"
+ "net/url"
+ "os"
+ "runtime"
+ "strings"
+ "sync"
+ "time"
+)
+
+const (
+ // metadataIP is the documented metadata server IP address.
+ metadataIP = "169.254.169.254"
+
+ // metadataHostEnv is the environment variable specifying the
+ // GCE metadata hostname. If empty, the default value of
+ // metadataIP ("169.254.169.254") is used instead.
+ // This is variable name is not defined by any spec, as far as
+ // I know; it was made up for the Go package.
+ metadataHostEnv = "GCE_METADATA_HOST"
+
+ userAgent = "gcloud-golang/0.1"
+)
+
+type cachedValue struct {
+ k string
+ trim bool
+ mu sync.Mutex
+ v string
+}
+
+var (
+ projID = &cachedValue{k: "project/project-id", trim: true}
+ projNum = &cachedValue{k: "project/numeric-project-id", trim: true}
+ instID = &cachedValue{k: "instance/id", trim: true}
+)
+
+var (
+ defaultClient = &Client{hc: &http.Client{
+ Transport: &http.Transport{
+ Dial: (&net.Dialer{
+ Timeout: 2 * time.Second,
+ KeepAlive: 30 * time.Second,
+ }).Dial,
+ ResponseHeaderTimeout: 2 * time.Second,
+ },
+ }}
+ subscribeClient = &Client{hc: &http.Client{
+ Transport: &http.Transport{
+ Dial: (&net.Dialer{
+ Timeout: 2 * time.Second,
+ KeepAlive: 30 * time.Second,
+ }).Dial,
+ },
+ }}
+)
+
+// NotDefinedError is returned when requested metadata is not defined.
+//
+// The underlying string is the suffix after "/computeMetadata/v1/".
+//
+// This error is not returned if the value is defined to be the empty
+// string.
+type NotDefinedError string
+
+func (suffix NotDefinedError) Error() string {
+ return fmt.Sprintf("metadata: GCE metadata %q not defined", string(suffix))
+}
+
+func (c *cachedValue) get(cl *Client) (v string, err error) {
+ defer c.mu.Unlock()
+ c.mu.Lock()
+ if c.v != "" {
+ return c.v, nil
+ }
+ if c.trim {
+ v, err = cl.getTrimmed(c.k)
+ } else {
+ v, err = cl.Get(c.k)
+ }
+ if err == nil {
+ c.v = v
+ }
+ return
+}
+
+var (
+ onGCEOnce sync.Once
+ onGCE bool
+)
+
+// OnGCE reports whether this process is running on Google Compute Engine.
+func OnGCE() bool {
+ onGCEOnce.Do(initOnGCE)
+ return onGCE
+}
+
+func initOnGCE() {
+ onGCE = testOnGCE()
+}
+
+func testOnGCE() bool {
+ // The user explicitly said they're on GCE, so trust them.
+ if os.Getenv(metadataHostEnv) != "" {
+ return true
+ }
+
+ ctx, cancel := context.WithCancel(context.Background())
+ defer cancel()
+
+ resc := make(chan bool, 2)
+
+ // Try two strategies in parallel.
+ // See https://github.com/GoogleCloudPlatform/google-cloud-go/issues/194
+ go func() {
+ req, _ := http.NewRequest("GET", "http://"+metadataIP, nil)
+ req.Header.Set("User-Agent", userAgent)
+ res, err := defaultClient.hc.Do(req.WithContext(ctx))
+ if err != nil {
+ resc <- false
+ return
+ }
+ defer res.Body.Close()
+ resc <- res.Header.Get("Metadata-Flavor") == "Google"
+ }()
+
+ go func() {
+ addrs, err := net.LookupHost("metadata.google.internal")
+ if err != nil || len(addrs) == 0 {
+ resc <- false
+ return
+ }
+ resc <- strsContains(addrs, metadataIP)
+ }()
+
+ tryHarder := systemInfoSuggestsGCE()
+ if tryHarder {
+ res := <-resc
+ if res {
+ // The first strategy succeeded, so let's use it.
+ return true
+ }
+ // Wait for either the DNS or metadata server probe to
+ // contradict the other one and say we are running on
+ // GCE. Give it a lot of time to do so, since the system
+ // info already suggests we're running on a GCE BIOS.
+ timer := time.NewTimer(5 * time.Second)
+ defer timer.Stop()
+ select {
+ case res = <-resc:
+ return res
+ case <-timer.C:
+ // Too slow. Who knows what this system is.
+ return false
+ }
+ }
+
+ // There's no hint from the system info that we're running on
+ // GCE, so use the first probe's result as truth, whether it's
+ // true or false. The goal here is to optimize for speed for
+ // users who are NOT running on GCE. We can't assume that
+ // either a DNS lookup or an HTTP request to a blackholed IP
+ // address is fast. Worst case this should return when the
+ // metaClient's Transport.ResponseHeaderTimeout or
+ // Transport.Dial.Timeout fires (in two seconds).
+ return <-resc
+}
+
+// systemInfoSuggestsGCE reports whether the local system (without
+// doing network requests) suggests that we're running on GCE. If this
+// returns true, testOnGCE tries a bit harder to reach its metadata
+// server.
+func systemInfoSuggestsGCE() bool {
+ if runtime.GOOS != "linux" {
+ // We don't have any non-Linux clues available, at least yet.
+ return false
+ }
+ slurp, _ := ioutil.ReadFile("/sys/class/dmi/id/product_name")
+ name := strings.TrimSpace(string(slurp))
+ return name == "Google" || name == "Google Compute Engine"
+}
+
+// Subscribe calls Client.Subscribe on a client designed for subscribing (one with no
+// ResponseHeaderTimeout).
+func Subscribe(suffix string, fn func(v string, ok bool) error) error {
+ return subscribeClient.Subscribe(suffix, fn)
+}
+
+// Get calls Client.Get on the default client.
+func Get(suffix string) (string, error) { return defaultClient.Get(suffix) }
+
+// ProjectID returns the current instance's project ID string.
+func ProjectID() (string, error) { return defaultClient.ProjectID() }
+
+// NumericProjectID returns the current instance's numeric project ID.
+func NumericProjectID() (string, error) { return defaultClient.NumericProjectID() }
+
+// InternalIP returns the instance's primary internal IP address.
+func InternalIP() (string, error) { return defaultClient.InternalIP() }
+
+// ExternalIP returns the instance's primary external (public) IP address.
+func ExternalIP() (string, error) { return defaultClient.ExternalIP() }
+
+// Hostname returns the instance's hostname. This will be of the form
+// "<instanceID>.c.<projID>.internal".
+func Hostname() (string, error) { return defaultClient.Hostname() }
+
+// InstanceTags returns the list of user-defined instance tags,
+// assigned when initially creating a GCE instance.
+func InstanceTags() ([]string, error) { return defaultClient.InstanceTags() }
+
+// InstanceID returns the current VM's numeric instance ID.
+func InstanceID() (string, error) { return defaultClient.InstanceID() }
+
+// InstanceName returns the current VM's instance ID string.
+func InstanceName() (string, error) { return defaultClient.InstanceName() }
+
+// Zone returns the current VM's zone, such as "us-central1-b".
+func Zone() (string, error) { return defaultClient.Zone() }
+
+// InstanceAttributes calls Client.InstanceAttributes on the default client.
+func InstanceAttributes() ([]string, error) { return defaultClient.InstanceAttributes() }
+
+// ProjectAttributes calls Client.ProjectAttributes on the default client.
+func ProjectAttributes() ([]string, error) { return defaultClient.ProjectAttributes() }
+
+// InstanceAttributeValue calls Client.InstanceAttributeValue on the default client.
+func InstanceAttributeValue(attr string) (string, error) {
+ return defaultClient.InstanceAttributeValue(attr)
+}
+
+// ProjectAttributeValue calls Client.ProjectAttributeValue on the default client.
+func ProjectAttributeValue(attr string) (string, error) {
+ return defaultClient.ProjectAttributeValue(attr)
+}
+
+// Scopes calls Client.Scopes on the default client.
+func Scopes(serviceAccount string) ([]string, error) { return defaultClient.Scopes(serviceAccount) }
+
+func strsContains(ss []string, s string) bool {
+ for _, v := range ss {
+ if v == s {
+ return true
+ }
+ }
+ return false
+}
+
+// A Client provides metadata.
+type Client struct {
+ hc *http.Client
+}
+
+// NewClient returns a Client that can be used to fetch metadata. All HTTP requests
+// will use the given http.Client instead of the default client.
+func NewClient(c *http.Client) *Client {
+ return &Client{hc: c}
+}
+
+// getETag returns a value from the metadata service as well as the associated ETag.
+// This func is otherwise equivalent to Get.
+func (c *Client) getETag(suffix string) (value, etag string, err error) {
+ // Using a fixed IP makes it very difficult to spoof the metadata service in
+ // a container, which is an important use-case for local testing of cloud
+ // deployments. To enable spoofing of the metadata service, the environment
+ // variable GCE_METADATA_HOST is first inspected to decide where metadata
+ // requests shall go.
+ host := os.Getenv(metadataHostEnv)
+ if host == "" {
+ // Using 169.254.169.254 instead of "metadata" here because Go
+ // binaries built with the "netgo" tag and without cgo won't
+ // know the search suffix for "metadata" is
+ // ".google.internal", and this IP address is documented as
+ // being stable anyway.
+ host = metadataIP
+ }
+ u := "http://" + host + "/computeMetadata/v1/" + suffix
+ req, _ := http.NewRequest("GET", u, nil)
+ req.Header.Set("Metadata-Flavor", "Google")
+ req.Header.Set("User-Agent", userAgent)
+ res, err := c.hc.Do(req)
+ if err != nil {
+ return "", "", err
+ }
+ defer res.Body.Close()
+ if res.StatusCode == http.StatusNotFound {
+ return "", "", NotDefinedError(suffix)
+ }
+ all, err := ioutil.ReadAll(res.Body)
+ if err != nil {
+ return "", "", err
+ }
+ if res.StatusCode != 200 {
+ return "", "", &Error{Code: res.StatusCode, Message: string(all)}
+ }
+ return string(all), res.Header.Get("Etag"), nil
+}
+
+// Get returns a value from the metadata service.
+// The suffix is appended to "http://${GCE_METADATA_HOST}/computeMetadata/v1/".
+//
+// If the GCE_METADATA_HOST environment variable is not defined, a default of
+// 169.254.169.254 will be used instead.
+//
+// If the requested metadata is not defined, the returned error will
+// be of type NotDefinedError.
+func (c *Client) Get(suffix string) (string, error) {
+ val, _, err := c.getETag(suffix)
+ return val, err
+}
+
+func (c *Client) getTrimmed(suffix string) (s string, err error) {
+ s, err = c.Get(suffix)
+ s = strings.TrimSpace(s)
+ return
+}
+
+func (c *Client) lines(suffix string) ([]string, error) {
+ j, err := c.Get(suffix)
+ if err != nil {
+ return nil, err
+ }
+ s := strings.Split(strings.TrimSpace(j), "\n")
+ for i := range s {
+ s[i] = strings.TrimSpace(s[i])
+ }
+ return s, nil
+}
+
+// ProjectID returns the current instance's project ID string.
+func (c *Client) ProjectID() (string, error) { return projID.get(c) }
+
+// NumericProjectID returns the current instance's numeric project ID.
+func (c *Client) NumericProjectID() (string, error) { return projNum.get(c) }
+
+// InstanceID returns the current VM's numeric instance ID.
+func (c *Client) InstanceID() (string, error) { return instID.get(c) }
+
+// InternalIP returns the instance's primary internal IP address.
+func (c *Client) InternalIP() (string, error) {
+ return c.getTrimmed("instance/network-interfaces/0/ip")
+}
+
+// ExternalIP returns the instance's primary external (public) IP address.
+func (c *Client) ExternalIP() (string, error) {
+ return c.getTrimmed("instance/network-interfaces/0/access-configs/0/external-ip")
+}
+
+// Hostname returns the instance's hostname. This will be of the form
+// "<instanceID>.c.<projID>.internal".
+func (c *Client) Hostname() (string, error) {
+ return c.getTrimmed("instance/hostname")
+}
+
+// InstanceTags returns the list of user-defined instance tags,
+// assigned when initially creating a GCE instance.
+func (c *Client) InstanceTags() ([]string, error) {
+ var s []string
+ j, err := c.Get("instance/tags")
+ if err != nil {
+ return nil, err
+ }
+ if err := json.NewDecoder(strings.NewReader(j)).Decode(&s); err != nil {
+ return nil, err
+ }
+ return s, nil
+}
+
+// InstanceName returns the current VM's instance ID string.
+func (c *Client) InstanceName() (string, error) {
+ host, err := c.Hostname()
+ if err != nil {
+ return "", err
+ }
+ return strings.Split(host, ".")[0], nil
+}
+
+// Zone returns the current VM's zone, such as "us-central1-b".
+func (c *Client) Zone() (string, error) {
+ zone, err := c.getTrimmed("instance/zone")
+ // zone is of the form "projects/<projNum>/zones/<zoneName>".
+ if err != nil {
+ return "", err
+ }
+ return zone[strings.LastIndex(zone, "/")+1:], nil
+}
+
+// InstanceAttributes returns the list of user-defined attributes,
+// assigned when initially creating a GCE VM instance. The value of an
+// attribute can be obtained with InstanceAttributeValue.
+func (c *Client) InstanceAttributes() ([]string, error) { return c.lines("instance/attributes/") }
+
+// ProjectAttributes returns the list of user-defined attributes
+// applying to the project as a whole, not just this VM. The value of
+// an attribute can be obtained with ProjectAttributeValue.
+func (c *Client) ProjectAttributes() ([]string, error) { return c.lines("project/attributes/") }
+
+// InstanceAttributeValue returns the value of the provided VM
+// instance attribute.
+//
+// If the requested attribute is not defined, the returned error will
+// be of type NotDefinedError.
+//
+// InstanceAttributeValue may return ("", nil) if the attribute was
+// defined to be the empty string.
+func (c *Client) InstanceAttributeValue(attr string) (string, error) {
+ return c.Get("instance/attributes/" + attr)
+}
+
+// ProjectAttributeValue returns the value of the provided
+// project attribute.
+//
+// If the requested attribute is not defined, the returned error will
+// be of type NotDefinedError.
+//
+// ProjectAttributeValue may return ("", nil) if the attribute was
+// defined to be the empty string.
+func (c *Client) ProjectAttributeValue(attr string) (string, error) {
+ return c.Get("project/attributes/" + attr)
+}
+
+// Scopes returns the service account scopes for the given account.
+// The account may be empty or the string "default" to use the instance's
+// main account.
+func (c *Client) Scopes(serviceAccount string) ([]string, error) {
+ if serviceAccount == "" {
+ serviceAccount = "default"
+ }
+ return c.lines("instance/service-accounts/" + serviceAccount + "/scopes")
+}
+
+// Subscribe subscribes to a value from the metadata service.
+// The suffix is appended to "http://${GCE_METADATA_HOST}/computeMetadata/v1/".
+// The suffix may contain query parameters.
+//
+// Subscribe calls fn with the latest metadata value indicated by the provided
+// suffix. If the metadata value is deleted, fn is called with the empty string
+// and ok false. Subscribe blocks until fn returns a non-nil error or the value
+// is deleted. Subscribe returns the error value returned from the last call to
+// fn, which may be nil when ok == false.
+func (c *Client) Subscribe(suffix string, fn func(v string, ok bool) error) error {
+ const failedSubscribeSleep = time.Second * 5
+
+ // First check to see if the metadata value exists at all.
+ val, lastETag, err := c.getETag(suffix)
+ if err != nil {
+ return err
+ }
+
+ if err := fn(val, true); err != nil {
+ return err
+ }
+
+ ok := true
+ if strings.ContainsRune(suffix, '?') {
+ suffix += "&wait_for_change=true&last_etag="
+ } else {
+ suffix += "?wait_for_change=true&last_etag="
+ }
+ for {
+ val, etag, err := c.getETag(suffix + url.QueryEscape(lastETag))
+ if err != nil {
+ if _, deleted := err.(NotDefinedError); !deleted {
+ time.Sleep(failedSubscribeSleep)
+ continue // Retry on other errors.
+ }
+ ok = false
+ }
+ lastETag = etag
+
+ if err := fn(val, ok); err != nil || !ok {
+ return err
+ }
+ }
+}
+
+// Error contains an error response from the server.
+type Error struct {
+ // Code is the HTTP response status code.
+ Code int
+ // Message is the server response message.
+ Message string
+}
+
+func (e *Error) Error() string {
+ return fmt.Sprintf("compute: Received %d `%s`", e.Code, e.Message)
+}
diff --git a/vendor/cloud.google.com/go/iam/iam.go b/vendor/cloud.google.com/go/iam/iam.go
new file mode 100644
index 000000000..76df63561
--- /dev/null
+++ b/vendor/cloud.google.com/go/iam/iam.go
@@ -0,0 +1,292 @@
+// Copyright 2016 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package iam supports the resource-specific operations of Google Cloud
+// IAM (Identity and Access Management) for the Google Cloud Libraries.
+// See https://cloud.google.com/iam for more about IAM.
+//
+// Users of the Google Cloud Libraries will typically not use this package
+// directly. Instead they will begin with some resource that supports IAM, like
+// a pubsub topic, and call its IAM method to get a Handle for that resource.
+package iam
+
+import (
+ "context"
+ "time"
+
+ gax "github.com/googleapis/gax-go"
+ pb "google.golang.org/genproto/googleapis/iam/v1"
+ "google.golang.org/grpc"
+ "google.golang.org/grpc/codes"
+)
+
+// client abstracts the IAMPolicy API to allow multiple implementations.
+type client interface {
+ Get(ctx context.Context, resource string) (*pb.Policy, error)
+ Set(ctx context.Context, resource string, p *pb.Policy) error
+ Test(ctx context.Context, resource string, perms []string) ([]string, error)
+}
+
+// grpcClient implements client for the standard gRPC-based IAMPolicy service.
+type grpcClient struct {
+ c pb.IAMPolicyClient
+}
+
+var withRetry = gax.WithRetry(func() gax.Retryer {
+ return gax.OnCodes([]codes.Code{
+ codes.DeadlineExceeded,
+ codes.Unavailable,
+ }, gax.Backoff{
+ Initial: 100 * time.Millisecond,
+ Max: 60 * time.Second,
+ Multiplier: 1.3,
+ })
+})
+
+func (g *grpcClient) Get(ctx context.Context, resource string) (*pb.Policy, error) {
+ var proto *pb.Policy
+ err := gax.Invoke(ctx, func(ctx context.Context, _ gax.CallSettings) error {
+ var err error
+ proto, err = g.c.GetIamPolicy(ctx, &pb.GetIamPolicyRequest{Resource: resource})
+ return err
+ }, withRetry)
+ if err != nil {
+ return nil, err
+ }
+ return proto, nil
+}
+
+func (g *grpcClient) Set(ctx context.Context, resource string, p *pb.Policy) error {
+ return gax.Invoke(ctx, func(ctx context.Context, _ gax.CallSettings) error {
+ _, err := g.c.SetIamPolicy(ctx, &pb.SetIamPolicyRequest{
+ Resource: resource,
+ Policy: p,
+ })
+ return err
+ }, withRetry)
+}
+
+func (g *grpcClient) Test(ctx context.Context, resource string, perms []string) ([]string, error) {
+ var res *pb.TestIamPermissionsResponse
+ err := gax.Invoke(ctx, func(ctx context.Context, _ gax.CallSettings) error {
+ var err error
+ res, err = g.c.TestIamPermissions(ctx, &pb.TestIamPermissionsRequest{
+ Resource: resource,
+ Permissions: perms,
+ })
+ return err
+ }, withRetry)
+ if err != nil {
+ return nil, err
+ }
+ return res.Permissions, nil
+}
+
+// A Handle provides IAM operations for a resource.
+type Handle struct {
+ c client
+ resource string
+}
+
+// InternalNewHandle is for use by the Google Cloud Libraries only.
+//
+// InternalNewHandle returns a Handle for resource.
+// The conn parameter refers to a server that must support the IAMPolicy service.
+func InternalNewHandle(conn *grpc.ClientConn, resource string) *Handle {
+ return InternalNewHandleGRPCClient(pb.NewIAMPolicyClient(conn), resource)
+}
+
+// InternalNewHandleGRPCClient is for use by the Google Cloud Libraries only.
+//
+// InternalNewHandleClient returns a Handle for resource using the given
+// grpc service that implements IAM as a mixin
+func InternalNewHandleGRPCClient(c pb.IAMPolicyClient, resource string) *Handle {
+ return InternalNewHandleClient(&grpcClient{c: c}, resource)
+}
+
+// InternalNewHandleClient is for use by the Google Cloud Libraries only.
+//
+// InternalNewHandleClient returns a Handle for resource using the given
+// client implementation.
+func InternalNewHandleClient(c client, resource string) *Handle {
+ return &Handle{
+ c: c,
+ resource: resource,
+ }
+}
+
+// Policy retrieves the IAM policy for the resource.
+func (h *Handle) Policy(ctx context.Context) (*Policy, error) {
+ proto, err := h.c.Get(ctx, h.resource)
+ if err != nil {
+ return nil, err
+ }
+ return &Policy{InternalProto: proto}, nil
+}
+
+// SetPolicy replaces the resource's current policy with the supplied Policy.
+//
+// If policy was created from a prior call to Get, then the modification will
+// only succeed if the policy has not changed since the Get.
+func (h *Handle) SetPolicy(ctx context.Context, policy *Policy) error {
+ return h.c.Set(ctx, h.resource, policy.InternalProto)
+}
+
+// TestPermissions returns the subset of permissions that the caller has on the resource.
+func (h *Handle) TestPermissions(ctx context.Context, permissions []string) ([]string, error) {
+ return h.c.Test(ctx, h.resource, permissions)
+}
+
+// A RoleName is a name representing a collection of permissions.
+type RoleName string
+
+// Common role names.
+const (
+ Owner RoleName = "roles/owner"
+ Editor RoleName = "roles/editor"
+ Viewer RoleName = "roles/viewer"
+)
+
+const (
+ // AllUsers is a special member that denotes all users, even unauthenticated ones.
+ AllUsers = "allUsers"
+
+ // AllAuthenticatedUsers is a special member that denotes all authenticated users.
+ AllAuthenticatedUsers = "allAuthenticatedUsers"
+)
+
+// A Policy is a list of Bindings representing roles
+// granted to members.
+//
+// The zero Policy is a valid policy with no bindings.
+type Policy struct {
+ // TODO(jba): when type aliases are available, put Policy into an internal package
+ // and provide an exported alias here.
+
+ // This field is exported for use by the Google Cloud Libraries only.
+ // It may become unexported in a future release.
+ InternalProto *pb.Policy
+}
+
+// Members returns the list of members with the supplied role.
+// The return value should not be modified. Use Add and Remove
+// to modify the members of a role.
+func (p *Policy) Members(r RoleName) []string {
+ b := p.binding(r)
+ if b == nil {
+ return nil
+ }
+ return b.Members
+}
+
+// HasRole reports whether member has role r.
+func (p *Policy) HasRole(member string, r RoleName) bool {
+ return memberIndex(member, p.binding(r)) >= 0
+}
+
+// Add adds member member to role r if it is not already present.
+// A new binding is created if there is no binding for the role.
+func (p *Policy) Add(member string, r RoleName) {
+ b := p.binding(r)
+ if b == nil {
+ if p.InternalProto == nil {
+ p.InternalProto = &pb.Policy{}
+ }
+ p.InternalProto.Bindings = append(p.InternalProto.Bindings, &pb.Binding{
+ Role: string(r),
+ Members: []string{member},
+ })
+ return
+ }
+ if memberIndex(member, b) < 0 {
+ b.Members = append(b.Members, member)
+ return
+ }
+}
+
+// Remove removes member from role r if it is present.
+func (p *Policy) Remove(member string, r RoleName) {
+ bi := p.bindingIndex(r)
+ if bi < 0 {
+ return
+ }
+ bindings := p.InternalProto.Bindings
+ b := bindings[bi]
+ mi := memberIndex(member, b)
+ if mi < 0 {
+ return
+ }
+ // Order doesn't matter for bindings or members, so to remove, move the last item
+ // into the removed spot and shrink the slice.
+ if len(b.Members) == 1 {
+ // Remove binding.
+ last := len(bindings) - 1
+ bindings[bi] = bindings[last]
+ bindings[last] = nil
+ p.InternalProto.Bindings = bindings[:last]
+ return
+ }
+ // Remove member.
+ // TODO(jba): worry about multiple copies of m?
+ last := len(b.Members) - 1
+ b.Members[mi] = b.Members[last]
+ b.Members[last] = ""
+ b.Members = b.Members[:last]
+}
+
+// Roles returns the names of all the roles that appear in the Policy.
+func (p *Policy) Roles() []RoleName {
+ if p.InternalProto == nil {
+ return nil
+ }
+ var rns []RoleName
+ for _, b := range p.InternalProto.Bindings {
+ rns = append(rns, RoleName(b.Role))
+ }
+ return rns
+}
+
+// binding returns the Binding for the suppied role, or nil if there isn't one.
+func (p *Policy) binding(r RoleName) *pb.Binding {
+ i := p.bindingIndex(r)
+ if i < 0 {
+ return nil
+ }
+ return p.InternalProto.Bindings[i]
+}
+
+func (p *Policy) bindingIndex(r RoleName) int {
+ if p.InternalProto == nil {
+ return -1
+ }
+ for i, b := range p.InternalProto.Bindings {
+ if b.Role == string(r) {
+ return i
+ }
+ }
+ return -1
+}
+
+// memberIndex returns the index of m in b's Members, or -1 if not found.
+func memberIndex(m string, b *pb.Binding) int {
+ if b == nil {
+ return -1
+ }
+ for i, mm := range b.Members {
+ if mm == m {
+ return i
+ }
+ }
+ return -1
+}
diff --git a/vendor/cloud.google.com/go/internal/annotate.go b/vendor/cloud.google.com/go/internal/annotate.go
new file mode 100644
index 000000000..6435695ba
--- /dev/null
+++ b/vendor/cloud.google.com/go/internal/annotate.go
@@ -0,0 +1,54 @@
+// Copyright 2017 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package internal
+
+import (
+ "fmt"
+
+ "google.golang.org/api/googleapi"
+ "google.golang.org/grpc/status"
+)
+
+// Annotate prepends msg to the error message in err, attempting
+// to preserve other information in err, like an error code.
+//
+// Annotate panics if err is nil.
+//
+// Annotate knows about these error types:
+// - "google.golang.org/grpc/status".Status
+// - "google.golang.org/api/googleapi".Error
+// If the error is not one of these types, Annotate behaves
+// like
+// fmt.Errorf("%s: %v", msg, err)
+func Annotate(err error, msg string) error {
+ if err == nil {
+ panic("Annotate called with nil")
+ }
+ if s, ok := status.FromError(err); ok {
+ p := s.Proto()
+ p.Message = msg + ": " + p.Message
+ return status.ErrorProto(p)
+ }
+ if g, ok := err.(*googleapi.Error); ok {
+ g.Message = msg + ": " + g.Message
+ return g
+ }
+ return fmt.Errorf("%s: %v", msg, err)
+}
+
+// Annotatef uses format and args to format a string, then calls Annotate.
+func Annotatef(err error, format string, args ...interface{}) error {
+ return Annotate(err, fmt.Sprintf(format, args...))
+}
diff --git a/vendor/cloud.google.com/go/internal/optional/optional.go b/vendor/cloud.google.com/go/internal/optional/optional.go
new file mode 100644
index 000000000..72780f764
--- /dev/null
+++ b/vendor/cloud.google.com/go/internal/optional/optional.go
@@ -0,0 +1,108 @@
+// Copyright 2016 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package optional provides versions of primitive types that can
+// be nil. These are useful in methods that update some of an API object's
+// fields.
+package optional
+
+import (
+ "fmt"
+ "strings"
+ "time"
+)
+
+type (
+ // Bool is either a bool or nil.
+ Bool interface{}
+
+ // String is either a string or nil.
+ String interface{}
+
+ // Int is either an int or nil.
+ Int interface{}
+
+ // Uint is either a uint or nil.
+ Uint interface{}
+
+ // Float64 is either a float64 or nil.
+ Float64 interface{}
+
+ // Duration is either a time.Duration or nil.
+ Duration interface{}
+)
+
+// ToBool returns its argument as a bool.
+// It panics if its argument is nil or not a bool.
+func ToBool(v Bool) bool {
+ x, ok := v.(bool)
+ if !ok {
+ doPanic("Bool", v)
+ }
+ return x
+}
+
+// ToString returns its argument as a string.
+// It panics if its argument is nil or not a string.
+func ToString(v String) string {
+ x, ok := v.(string)
+ if !ok {
+ doPanic("String", v)
+ }
+ return x
+}
+
+// ToInt returns its argument as an int.
+// It panics if its argument is nil or not an int.
+func ToInt(v Int) int {
+ x, ok := v.(int)
+ if !ok {
+ doPanic("Int", v)
+ }
+ return x
+}
+
+// ToUint returns its argument as a uint.
+// It panics if its argument is nil or not a uint.
+func ToUint(v Uint) uint {
+ x, ok := v.(uint)
+ if !ok {
+ doPanic("Uint", v)
+ }
+ return x
+}
+
+// ToFloat64 returns its argument as a float64.
+// It panics if its argument is nil or not a float64.
+func ToFloat64(v Float64) float64 {
+ x, ok := v.(float64)
+ if !ok {
+ doPanic("Float64", v)
+ }
+ return x
+}
+
+// ToDuration returns its argument as a time.Duration.
+// It panics if its argument is nil or not a time.Duration.
+func ToDuration(v Duration) time.Duration {
+ x, ok := v.(time.Duration)
+ if !ok {
+ doPanic("Duration", v)
+ }
+ return x
+}
+
+func doPanic(capType string, v interface{}) {
+ panic(fmt.Sprintf("optional.%s value should be %s, got %T", capType, strings.ToLower(capType), v))
+}
diff --git a/vendor/cloud.google.com/go/internal/retry.go b/vendor/cloud.google.com/go/internal/retry.go
new file mode 100644
index 000000000..99093cc46
--- /dev/null
+++ b/vendor/cloud.google.com/go/internal/retry.go
@@ -0,0 +1,54 @@
+// Copyright 2016 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package internal
+
+import (
+ "context"
+ "time"
+
+ gax "github.com/googleapis/gax-go"
+)
+
+// Retry calls the supplied function f repeatedly according to the provided
+// backoff parameters. It returns when one of the following occurs:
+// When f's first return value is true, Retry immediately returns with f's second
+// return value.
+// When the provided context is done, Retry returns with an error that
+// includes both ctx.Error() and the last error returned by f.
+func Retry(ctx context.Context, bo gax.Backoff, f func() (stop bool, err error)) error {
+ return retry(ctx, bo, f, gax.Sleep)
+}
+
+func retry(ctx context.Context, bo gax.Backoff, f func() (stop bool, err error),
+ sleep func(context.Context, time.Duration) error) error {
+ var lastErr error
+ for {
+ stop, err := f()
+ if stop {
+ return err
+ }
+ // Remember the last "real" error from f.
+ if err != nil && err != context.Canceled && err != context.DeadlineExceeded {
+ lastErr = err
+ }
+ p := bo.Pause()
+ if cerr := sleep(ctx, p); cerr != nil {
+ if lastErr != nil {
+ return Annotatef(lastErr, "retry failed with %v; last error", cerr)
+ }
+ return cerr
+ }
+ }
+}
diff --git a/vendor/cloud.google.com/go/internal/trace/trace.go b/vendor/cloud.google.com/go/internal/trace/trace.go
new file mode 100644
index 000000000..95c7821c2
--- /dev/null
+++ b/vendor/cloud.google.com/go/internal/trace/trace.go
@@ -0,0 +1,84 @@
+// Copyright 2018 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package trace
+
+import (
+ "context"
+
+ "go.opencensus.io/trace"
+ "google.golang.org/api/googleapi"
+ "google.golang.org/genproto/googleapis/rpc/code"
+ "google.golang.org/grpc/status"
+)
+
+// StartSpan adds a span to the trace with the given name.
+func StartSpan(ctx context.Context, name string) context.Context {
+ ctx, _ = trace.StartSpan(ctx, name)
+ return ctx
+}
+
+// EndSpan ends a span with the given error.
+func EndSpan(ctx context.Context, err error) {
+ span := trace.FromContext(ctx)
+ if err != nil {
+ span.SetStatus(toStatus(err))
+ }
+ span.End()
+}
+
+// ToStatus interrogates an error and converts it to an appropriate
+// OpenCensus status.
+func toStatus(err error) trace.Status {
+ if err2, ok := err.(*googleapi.Error); ok {
+ return trace.Status{Code: httpStatusCodeToOCCode(err2.Code), Message: err2.Message}
+ } else if s, ok := status.FromError(err); ok {
+ return trace.Status{Code: int32(s.Code()), Message: s.Message()}
+ } else {
+ return trace.Status{Code: int32(code.Code_UNKNOWN), Message: err.Error()}
+ }
+}
+
+// TODO (deklerk): switch to using OpenCensus function when it becomes available.
+// Reference: https://github.com/googleapis/googleapis/blob/26b634d2724ac5dd30ae0b0cbfb01f07f2e4050e/google/rpc/code.proto
+func httpStatusCodeToOCCode(httpStatusCode int) int32 {
+ switch httpStatusCode {
+ case 200:
+ return int32(code.Code_OK)
+ case 499:
+ return int32(code.Code_CANCELLED)
+ case 500:
+ return int32(code.Code_UNKNOWN) // Could also be Code_INTERNAL, Code_DATA_LOSS
+ case 400:
+ return int32(code.Code_INVALID_ARGUMENT) // Could also be Code_OUT_OF_RANGE
+ case 504:
+ return int32(code.Code_DEADLINE_EXCEEDED)
+ case 404:
+ return int32(code.Code_NOT_FOUND)
+ case 409:
+ return int32(code.Code_ALREADY_EXISTS) // Could also be Code_ABORTED
+ case 403:
+ return int32(code.Code_PERMISSION_DENIED)
+ case 401:
+ return int32(code.Code_UNAUTHENTICATED)
+ case 429:
+ return int32(code.Code_RESOURCE_EXHAUSTED)
+ case 501:
+ return int32(code.Code_UNIMPLEMENTED)
+ case 503:
+ return int32(code.Code_UNAVAILABLE)
+ default:
+ return int32(code.Code_UNKNOWN)
+ }
+}
diff --git a/vendor/cloud.google.com/go/internal/version/update_version.sh b/vendor/cloud.google.com/go/internal/version/update_version.sh
new file mode 100755
index 000000000..fecf1f03f
--- /dev/null
+++ b/vendor/cloud.google.com/go/internal/version/update_version.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+
+today=$(date +%Y%m%d)
+
+sed -i -r -e 's/const Repo = "([0-9]{8})"/const Repo = "'$today'"/' $GOFILE
+
diff --git a/vendor/cloud.google.com/go/internal/version/version.go b/vendor/cloud.google.com/go/internal/version/version.go
new file mode 100644
index 000000000..220f02c1e
--- /dev/null
+++ b/vendor/cloud.google.com/go/internal/version/version.go
@@ -0,0 +1,71 @@
+// Copyright 2016 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//go:generate ./update_version.sh
+
+// Package version contains version information for Google Cloud Client
+// Libraries for Go, as reported in request headers.
+package version
+
+import (
+ "runtime"
+ "strings"
+ "unicode"
+)
+
+// Repo is the current version of the client libraries in this
+// repo. It should be a date in YYYYMMDD format.
+const Repo = "20180226"
+
+// Go returns the Go runtime version. The returned string
+// has no whitespace.
+func Go() string {
+ return goVersion
+}
+
+var goVersion = goVer(runtime.Version())
+
+const develPrefix = "devel +"
+
+func goVer(s string) string {
+ if strings.HasPrefix(s, develPrefix) {
+ s = s[len(develPrefix):]
+ if p := strings.IndexFunc(s, unicode.IsSpace); p >= 0 {
+ s = s[:p]
+ }
+ return s
+ }
+
+ if strings.HasPrefix(s, "go1") {
+ s = s[2:]
+ var prerelease string
+ if p := strings.IndexFunc(s, notSemverRune); p >= 0 {
+ s, prerelease = s[:p], s[p:]
+ }
+ if strings.HasSuffix(s, ".") {
+ s += "0"
+ } else if strings.Count(s, ".") < 2 {
+ s += ".0"
+ }
+ if prerelease != "" {
+ s += "-" + prerelease
+ }
+ return s
+ }
+ return ""
+}
+
+func notSemverRune(r rune) bool {
+ return strings.IndexRune("0123456789.", r) < 0
+}
diff --git a/vendor/cloud.google.com/go/storage/acl.go b/vendor/cloud.google.com/go/storage/acl.go
new file mode 100644
index 000000000..7855d110a
--- /dev/null
+++ b/vendor/cloud.google.com/go/storage/acl.go
@@ -0,0 +1,335 @@
+// Copyright 2014 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package storage
+
+import (
+ "context"
+ "net/http"
+ "reflect"
+
+ "cloud.google.com/go/internal/trace"
+ "google.golang.org/api/googleapi"
+ raw "google.golang.org/api/storage/v1"
+)
+
+// ACLRole is the level of access to grant.
+type ACLRole string
+
+const (
+ RoleOwner ACLRole = "OWNER"
+ RoleReader ACLRole = "READER"
+ RoleWriter ACLRole = "WRITER"
+)
+
+// ACLEntity refers to a user or group.
+// They are sometimes referred to as grantees.
+//
+// It could be in the form of:
+// "user-<userId>", "user-<email>", "group-<groupId>", "group-<email>",
+// "domain-<domain>" and "project-team-<projectId>".
+//
+// Or one of the predefined constants: AllUsers, AllAuthenticatedUsers.
+type ACLEntity string
+
+const (
+ AllUsers ACLEntity = "allUsers"
+ AllAuthenticatedUsers ACLEntity = "allAuthenticatedUsers"
+)
+
+// ACLRule represents a grant for a role to an entity (user, group or team) for a
+// Google Cloud Storage object or bucket.
+type ACLRule struct {
+ Entity ACLEntity
+ EntityID string
+ Role ACLRole
+ Domain string
+ Email string
+ ProjectTeam *ProjectTeam
+}
+
+// ProjectTeam is the project team associated with the entity, if any.
+type ProjectTeam struct {
+ ProjectNumber string
+ Team string
+}
+
+// ACLHandle provides operations on an access control list for a Google Cloud Storage bucket or object.
+type ACLHandle struct {
+ c *Client
+ bucket string
+ object string
+ isDefault bool
+ userProject string // for requester-pays buckets
+}
+
+// Delete permanently deletes the ACL entry for the given entity.
+func (a *ACLHandle) Delete(ctx context.Context, entity ACLEntity) (err error) {
+ ctx = trace.StartSpan(ctx, "cloud.google.com/go/storage.ACL.Delete")
+ defer func() { trace.EndSpan(ctx, err) }()
+
+ if a.object != "" {
+ return a.objectDelete(ctx, entity)
+ }
+ if a.isDefault {
+ return a.bucketDefaultDelete(ctx, entity)
+ }
+ return a.bucketDelete(ctx, entity)
+}
+
+// Set sets the role for the given entity.
+func (a *ACLHandle) Set(ctx context.Context, entity ACLEntity, role ACLRole) (err error) {
+ ctx = trace.StartSpan(ctx, "cloud.google.com/go/storage.ACL.Set")
+ defer func() { trace.EndSpan(ctx, err) }()
+
+ if a.object != "" {
+ return a.objectSet(ctx, entity, role, false)
+ }
+ if a.isDefault {
+ return a.objectSet(ctx, entity, role, true)
+ }
+ return a.bucketSet(ctx, entity, role)
+}
+
+// List retrieves ACL entries.
+func (a *ACLHandle) List(ctx context.Context) (rules []ACLRule, err error) {
+ ctx = trace.StartSpan(ctx, "cloud.google.com/go/storage.ACL.List")
+ defer func() { trace.EndSpan(ctx, err) }()
+
+ if a.object != "" {
+ return a.objectList(ctx)
+ }
+ if a.isDefault {
+ return a.bucketDefaultList(ctx)
+ }
+ return a.bucketList(ctx)
+}
+
+func (a *ACLHandle) bucketDefaultList(ctx context.Context) ([]ACLRule, error) {
+ var acls *raw.ObjectAccessControls
+ var err error
+ err = runWithRetry(ctx, func() error {
+ req := a.c.raw.DefaultObjectAccessControls.List(a.bucket)
+ a.configureCall(ctx, req)
+ acls, err = req.Do()
+ return err
+ })
+ if err != nil {
+ return nil, err
+ }
+ return toObjectACLRules(acls.Items), nil
+}
+
+func (a *ACLHandle) bucketDefaultDelete(ctx context.Context, entity ACLEntity) error {
+ return runWithRetry(ctx, func() error {
+ req := a.c.raw.DefaultObjectAccessControls.Delete(a.bucket, string(entity))
+ a.configureCall(ctx, req)
+ return req.Do()
+ })
+}
+
+func (a *ACLHandle) bucketList(ctx context.Context) ([]ACLRule, error) {
+ var acls *raw.BucketAccessControls
+ var err error
+ err = runWithRetry(ctx, func() error {
+ req := a.c.raw.BucketAccessControls.List(a.bucket)
+ a.configureCall(ctx, req)
+ acls, err = req.Do()
+ return err
+ })
+ if err != nil {
+ return nil, err
+ }
+ return toBucketACLRules(acls.Items), nil
+}
+
+func (a *ACLHandle) bucketSet(ctx context.Context, entity ACLEntity, role ACLRole) error {
+ acl := &raw.BucketAccessControl{
+ Bucket: a.bucket,
+ Entity: string(entity),
+ Role: string(role),
+ }
+ err := runWithRetry(ctx, func() error {
+ req := a.c.raw.BucketAccessControls.Update(a.bucket, string(entity), acl)
+ a.configureCall(ctx, req)
+ _, err := req.Do()
+ return err
+ })
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
+func (a *ACLHandle) bucketDelete(ctx context.Context, entity ACLEntity) error {
+ return runWithRetry(ctx, func() error {
+ req := a.c.raw.BucketAccessControls.Delete(a.bucket, string(entity))
+ a.configureCall(ctx, req)
+ return req.Do()
+ })
+}
+
+func (a *ACLHandle) objectList(ctx context.Context) ([]ACLRule, error) {
+ var acls *raw.ObjectAccessControls
+ var err error
+ err = runWithRetry(ctx, func() error {
+ req := a.c.raw.ObjectAccessControls.List(a.bucket, a.object)
+ a.configureCall(ctx, req)
+ acls, err = req.Do()
+ return err
+ })
+ if err != nil {
+ return nil, err
+ }
+ return toObjectACLRules(acls.Items), nil
+}
+
+func (a *ACLHandle) objectSet(ctx context.Context, entity ACLEntity, role ACLRole, isBucketDefault bool) error {
+ type setRequest interface {
+ Do(opts ...googleapi.CallOption) (*raw.ObjectAccessControl, error)
+ Header() http.Header
+ }
+
+ acl := &raw.ObjectAccessControl{
+ Bucket: a.bucket,
+ Entity: string(entity),
+ Role: string(role),
+ }
+ var req setRequest
+ if isBucketDefault {
+ req = a.c.raw.DefaultObjectAccessControls.Update(a.bucket, string(entity), acl)
+ } else {
+ req = a.c.raw.ObjectAccessControls.Update(a.bucket, a.object, string(entity), acl)
+ }
+ a.configureCall(ctx, req)
+ return runWithRetry(ctx, func() error {
+ _, err := req.Do()
+ return err
+ })
+}
+
+func (a *ACLHandle) objectDelete(ctx context.Context, entity ACLEntity) error {
+ return runWithRetry(ctx, func() error {
+ req := a.c.raw.ObjectAccessControls.Delete(a.bucket, a.object, string(entity))
+ a.configureCall(ctx, req)
+ return req.Do()
+ })
+}
+
+func (a *ACLHandle) configureCall(ctx context.Context, call interface{ Header() http.Header }) {
+ vc := reflect.ValueOf(call)
+ vc.MethodByName("Context").Call([]reflect.Value{reflect.ValueOf(ctx)})
+ if a.userProject != "" {
+ vc.MethodByName("UserProject").Call([]reflect.Value{reflect.ValueOf(a.userProject)})
+ }
+ setClientHeader(call.Header())
+}
+
+func toObjectACLRules(items []*raw.ObjectAccessControl) []ACLRule {
+ var rs []ACLRule
+ for _, item := range items {
+ rs = append(rs, toObjectACLRule(item))
+ }
+ return rs
+}
+
+func toBucketACLRules(items []*raw.BucketAccessControl) []ACLRule {
+ var rs []ACLRule
+ for _, item := range items {
+ rs = append(rs, toBucketACLRule(item))
+ }
+ return rs
+}
+
+func toObjectACLRule(a *raw.ObjectAccessControl) ACLRule {
+ return ACLRule{
+ Entity: ACLEntity(a.Entity),
+ EntityID: a.EntityId,
+ Role: ACLRole(a.Role),
+ Domain: a.Domain,
+ Email: a.Email,
+ ProjectTeam: toObjectProjectTeam(a.ProjectTeam),
+ }
+}
+
+func toBucketACLRule(a *raw.BucketAccessControl) ACLRule {
+ return ACLRule{
+ Entity: ACLEntity(a.Entity),
+ EntityID: a.EntityId,
+ Role: ACLRole(a.Role),
+ Domain: a.Domain,
+ Email: a.Email,
+ ProjectTeam: toBucketProjectTeam(a.ProjectTeam),
+ }
+}
+
+func toRawObjectACL(rules []ACLRule) []*raw.ObjectAccessControl {
+ if len(rules) == 0 {
+ return nil
+ }
+ r := make([]*raw.ObjectAccessControl, 0, len(rules))
+ for _, rule := range rules {
+ r = append(r, rule.toRawObjectAccessControl("")) // bucket name unnecessary
+ }
+ return r
+}
+
+func toRawBucketACL(rules []ACLRule) []*raw.BucketAccessControl {
+ if len(rules) == 0 {
+ return nil
+ }
+ r := make([]*raw.BucketAccessControl, 0, len(rules))
+ for _, rule := range rules {
+ r = append(r, rule.toRawBucketAccessControl("")) // bucket name unnecessary
+ }
+ return r
+}
+
+func (r ACLRule) toRawBucketAccessControl(bucket string) *raw.BucketAccessControl {
+ return &raw.BucketAccessControl{
+ Bucket: bucket,
+ Entity: string(r.Entity),
+ Role: string(r.Role),
+ // The other fields are not settable.
+ }
+}
+
+func (r ACLRule) toRawObjectAccessControl(bucket string) *raw.ObjectAccessControl {
+ return &raw.ObjectAccessControl{
+ Bucket: bucket,
+ Entity: string(r.Entity),
+ Role: string(r.Role),
+ // The other fields are not settable.
+ }
+}
+
+func toBucketProjectTeam(p *raw.BucketAccessControlProjectTeam) *ProjectTeam {
+ if p == nil {
+ return nil
+ }
+ return &ProjectTeam{
+ ProjectNumber: p.ProjectNumber,
+ Team: p.Team,
+ }
+}
+
+func toObjectProjectTeam(p *raw.ObjectAccessControlProjectTeam) *ProjectTeam {
+ if p == nil {
+ return nil
+ }
+ return &ProjectTeam{
+ ProjectNumber: p.ProjectNumber,
+ Team: p.Team,
+ }
+}
diff --git a/vendor/cloud.google.com/go/storage/bucket.go b/vendor/cloud.google.com/go/storage/bucket.go
new file mode 100644
index 000000000..3b0018aff
--- /dev/null
+++ b/vendor/cloud.google.com/go/storage/bucket.go
@@ -0,0 +1,1129 @@
+// Copyright 2014 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package storage
+
+import (
+ "context"
+ "fmt"
+ "net/http"
+ "reflect"
+ "time"
+
+ "cloud.google.com/go/internal/optional"
+ "cloud.google.com/go/internal/trace"
+ "google.golang.org/api/googleapi"
+ "google.golang.org/api/iterator"
+ raw "google.golang.org/api/storage/v1"
+)
+
+// BucketHandle provides operations on a Google Cloud Storage bucket.
+// Use Client.Bucket to get a handle.
+type BucketHandle struct {
+ c *Client
+ name string
+ acl ACLHandle
+ defaultObjectACL ACLHandle
+ conds *BucketConditions
+ userProject string // project for Requester Pays buckets
+}
+
+// Bucket returns a BucketHandle, which provides operations on the named bucket.
+// This call does not perform any network operations.
+//
+// The supplied name must contain only lowercase letters, numbers, dashes,
+// underscores, and dots. The full specification for valid bucket names can be
+// found at:
+// https://cloud.google.com/storage/docs/bucket-naming
+func (c *Client) Bucket(name string) *BucketHandle {
+ return &BucketHandle{
+ c: c,
+ name: name,
+ acl: ACLHandle{
+ c: c,
+ bucket: name,
+ },
+ defaultObjectACL: ACLHandle{
+ c: c,
+ bucket: name,
+ isDefault: true,
+ },
+ }
+}
+
+// Create creates the Bucket in the project.
+// If attrs is nil the API defaults will be used.
+func (b *BucketHandle) Create(ctx context.Context, projectID string, attrs *BucketAttrs) (err error) {
+ ctx = trace.StartSpan(ctx, "cloud.google.com/go/storage.Bucket.Create")
+ defer func() { trace.EndSpan(ctx, err) }()
+
+ var bkt *raw.Bucket
+ if attrs != nil {
+ bkt = attrs.toRawBucket()
+ } else {
+ bkt = &raw.Bucket{}
+ }
+ bkt.Name = b.name
+ // If there is lifecycle information but no location, explicitly set
+ // the location. This is a GCS quirk/bug.
+ if bkt.Location == "" && bkt.Lifecycle != nil {
+ bkt.Location = "US"
+ }
+ req := b.c.raw.Buckets.Insert(projectID, bkt)
+ setClientHeader(req.Header())
+ if attrs != nil && attrs.PredefinedACL != "" {
+ req.PredefinedAcl(attrs.PredefinedACL)
+ }
+ if attrs != nil && attrs.PredefinedDefaultObjectACL != "" {
+ req.PredefinedDefaultObjectAcl(attrs.PredefinedDefaultObjectACL)
+ }
+ return runWithRetry(ctx, func() error { _, err := req.Context(ctx).Do(); return err })
+}
+
+// Delete deletes the Bucket.
+func (b *BucketHandle) Delete(ctx context.Context) (err error) {
+ ctx = trace.StartSpan(ctx, "cloud.google.com/go/storage.Bucket.Delete")
+ defer func() { trace.EndSpan(ctx, err) }()
+
+ req, err := b.newDeleteCall()
+ if err != nil {
+ return err
+ }
+ return runWithRetry(ctx, func() error { return req.Context(ctx).Do() })
+}
+
+func (b *BucketHandle) newDeleteCall() (*raw.BucketsDeleteCall, error) {
+ req := b.c.raw.Buckets.Delete(b.name)
+ setClientHeader(req.Header())
+ if err := applyBucketConds("BucketHandle.Delete", b.conds, req); err != nil {
+ return nil, err
+ }
+ if b.userProject != "" {
+ req.UserProject(b.userProject)
+ }
+ return req, nil
+}
+
+// ACL returns an ACLHandle, which provides access to the bucket's access control list.
+// This controls who can list, create or overwrite the objects in a bucket.
+// This call does not perform any network operations.
+func (b *BucketHandle) ACL() *ACLHandle {
+ return &b.acl
+}
+
+// DefaultObjectACL returns an ACLHandle, which provides access to the bucket's default object ACLs.
+// These ACLs are applied to newly created objects in this bucket that do not have a defined ACL.
+// This call does not perform any network operations.
+func (b *BucketHandle) DefaultObjectACL() *ACLHandle {
+ return &b.defaultObjectACL
+}
+
+// Object returns an ObjectHandle, which provides operations on the named object.
+// This call does not perform any network operations.
+//
+// name must consist entirely of valid UTF-8-encoded runes. The full specification
+// for valid object names can be found at:
+// https://cloud.google.com/storage/docs/bucket-naming
+func (b *BucketHandle) Object(name string) *ObjectHandle {
+ return &ObjectHandle{
+ c: b.c,
+ bucket: b.name,
+ object: name,
+ acl: ACLHandle{
+ c: b.c,
+ bucket: b.name,
+ object: name,
+ userProject: b.userProject,
+ },
+ gen: -1,
+ userProject: b.userProject,
+ }
+}
+
+// Attrs returns the metadata for the bucket.
+func (b *BucketHandle) Attrs(ctx context.Context) (attrs *BucketAttrs, err error) {
+ ctx = trace.StartSpan(ctx, "cloud.google.com/go/storage.Bucket.Attrs")
+ defer func() { trace.EndSpan(ctx, err) }()
+
+ req, err := b.newGetCall()
+ if err != nil {
+ return nil, err
+ }
+ var resp *raw.Bucket
+ err = runWithRetry(ctx, func() error {
+ resp, err = req.Context(ctx).Do()
+ return err
+ })
+ if e, ok := err.(*googleapi.Error); ok && e.Code == http.StatusNotFound {
+ return nil, ErrBucketNotExist
+ }
+ if err != nil {
+ return nil, err
+ }
+ return newBucket(resp)
+}
+
+func (b *BucketHandle) newGetCall() (*raw.BucketsGetCall, error) {
+ req := b.c.raw.Buckets.Get(b.name).Projection("full")
+ setClientHeader(req.Header())
+ if err := applyBucketConds("BucketHandle.Attrs", b.conds, req); err != nil {
+ return nil, err
+ }
+ if b.userProject != "" {
+ req.UserProject(b.userProject)
+ }
+ return req, nil
+}
+
+// Update updates a bucket's attributes.
+func (b *BucketHandle) Update(ctx context.Context, uattrs BucketAttrsToUpdate) (attrs *BucketAttrs, err error) {
+ ctx = trace.StartSpan(ctx, "cloud.google.com/go/storage.Bucket.Create")
+ defer func() { trace.EndSpan(ctx, err) }()
+
+ req, err := b.newPatchCall(&uattrs)
+ if err != nil {
+ return nil, err
+ }
+ if uattrs.PredefinedACL != "" {
+ req.PredefinedAcl(uattrs.PredefinedACL)
+ }
+ if uattrs.PredefinedDefaultObjectACL != "" {
+ req.PredefinedDefaultObjectAcl(uattrs.PredefinedDefaultObjectACL)
+ }
+ // TODO(jba): retry iff metagen is set?
+ rb, err := req.Context(ctx).Do()
+ if err != nil {
+ return nil, err
+ }
+ return newBucket(rb)
+}
+
+func (b *BucketHandle) newPatchCall(uattrs *BucketAttrsToUpdate) (*raw.BucketsPatchCall, error) {
+ rb := uattrs.toRawBucket()
+ req := b.c.raw.Buckets.Patch(b.name, rb).Projection("full")
+ setClientHeader(req.Header())
+ if err := applyBucketConds("BucketHandle.Update", b.conds, req); err != nil {
+ return nil, err
+ }
+ if b.userProject != "" {
+ req.UserProject(b.userProject)
+ }
+ return req, nil
+}
+
+// BucketAttrs represents the metadata for a Google Cloud Storage bucket.
+// Read-only fields are ignored by BucketHandle.Create.
+type BucketAttrs struct {
+ // Name is the name of the bucket.
+ // This field is read-only.
+ Name string
+
+ // ACL is the list of access control rules on the bucket.
+ ACL []ACLRule
+
+ // DefaultObjectACL is the list of access controls to
+ // apply to new objects when no object ACL is provided.
+ DefaultObjectACL []ACLRule
+
+ // DefaultEventBasedHold is the default value for event-based hold on
+ // newly created objects in this bucket. It defaults to false.
+ DefaultEventBasedHold bool
+
+ // If not empty, applies a predefined set of access controls. It should be set
+ // only when creating a bucket.
+ // It is always empty for BucketAttrs returned from the service.
+ // See https://cloud.google.com/storage/docs/json_api/v1/buckets/insert
+ // for valid values.
+ PredefinedACL string
+
+ // If not empty, applies a predefined set of default object access controls.
+ // It should be set only when creating a bucket.
+ // It is always empty for BucketAttrs returned from the service.
+ // See https://cloud.google.com/storage/docs/json_api/v1/buckets/insert
+ // for valid values.
+ PredefinedDefaultObjectACL string
+
+ // Location is the location of the bucket. It defaults to "US".
+ Location string
+
+ // MetaGeneration is the metadata generation of the bucket.
+ // This field is read-only.
+ MetaGeneration int64
+
+ // StorageClass is the default storage class of the bucket. This defines
+ // how objects in the bucket are stored and determines the SLA
+ // and the cost of storage. Typical values are "MULTI_REGIONAL",
+ // "REGIONAL", "NEARLINE", "COLDLINE", "STANDARD" and
+ // "DURABLE_REDUCED_AVAILABILITY". Defaults to "STANDARD", which
+ // is equivalent to "MULTI_REGIONAL" or "REGIONAL" depending on
+ // the bucket's location settings.
+ StorageClass string
+
+ // Created is the creation time of the bucket.
+ // This field is read-only.
+ Created time.Time
+
+ // VersioningEnabled reports whether this bucket has versioning enabled.
+ VersioningEnabled bool
+
+ // Labels are the bucket's labels.
+ Labels map[string]string
+
+ // RequesterPays reports whether the bucket is a Requester Pays bucket.
+ // Clients performing operations on Requester Pays buckets must provide
+ // a user project (see BucketHandle.UserProject), which will be billed
+ // for the operations.
+ RequesterPays bool
+
+ // Lifecycle is the lifecycle configuration for objects in the bucket.
+ Lifecycle Lifecycle
+
+ // Retention policy enforces a minimum retention time for all objects
+ // contained in the bucket. A RetentionPolicy of nil implies the bucket
+ // has no minimum data retention.
+ //
+ // This feature is in private alpha release. It is not currently available to
+ // most customers. It might be changed in backwards-incompatible ways and is not
+ // subject to any SLA or deprecation policy.
+ RetentionPolicy *RetentionPolicy
+
+ // The bucket's Cross-Origin Resource Sharing (CORS) configuration.
+ CORS []CORS
+
+ // The encryption configuration used by default for newly inserted objects.
+ Encryption *BucketEncryption
+
+ // The logging configuration.
+ Logging *BucketLogging
+
+ // The website configuration.
+ Website *BucketWebsite
+}
+
+// Lifecycle is the lifecycle configuration for objects in the bucket.
+type Lifecycle struct {
+ Rules []LifecycleRule
+}
+
+// RetentionPolicy enforces a minimum retention time for all objects
+// contained in the bucket.
+//
+// Any attempt to overwrite or delete objects younger than the retention
+// period will result in an error. An unlocked retention policy can be
+// modified or removed from the bucket via the Update method. A
+// locked retention policy cannot be removed or shortened in duration
+// for the lifetime of the bucket.
+//
+// This feature is in private alpha release. It is not currently available to
+// most customers. It might be changed in backwards-incompatible ways and is not
+// subject to any SLA or deprecation policy.
+type RetentionPolicy struct {
+ // RetentionPeriod specifies the duration that objects need to be
+ // retained. Retention duration must be greater than zero and less than
+ // 100 years. Note that enforcement of retention periods less than a day
+ // is not guaranteed. Such periods should only be used for testing
+ // purposes.
+ RetentionPeriod time.Duration
+
+ // EffectiveTime is the time from which the policy was enforced and
+ // effective. This field is read-only.
+ EffectiveTime time.Time
+
+ // IsLocked describes whether the bucket is locked. Once locked, an
+ // object retention policy cannot be modified.
+ // This field is read-only.
+ IsLocked bool
+}
+
+const (
+ // RFC3339 date with only the date segment, used for CreatedBefore in LifecycleRule.
+ rfc3339Date = "2006-01-02"
+
+ // DeleteAction is a lifecycle action that deletes a live and/or archived
+ // objects. Takes precedence over SetStorageClass actions.
+ DeleteAction = "Delete"
+
+ // SetStorageClassAction changes the storage class of live and/or archived
+ // objects.
+ SetStorageClassAction = "SetStorageClass"
+)
+
+// LifecycleRule is a lifecycle configuration rule.
+//
+// When all the configured conditions are met by an object in the bucket, the
+// configured action will automatically be taken on that object.
+type LifecycleRule struct {
+ // Action is the action to take when all of the associated conditions are
+ // met.
+ Action LifecycleAction
+
+ // Condition is the set of conditions that must be met for the associated
+ // action to be taken.
+ Condition LifecycleCondition
+}
+
+// LifecycleAction is a lifecycle configuration action.
+type LifecycleAction struct {
+ // Type is the type of action to take on matching objects.
+ //
+ // Acceptable values are "Delete" to delete matching objects and
+ // "SetStorageClass" to set the storage class defined in StorageClass on
+ // matching objects.
+ Type string
+
+ // StorageClass is the storage class to set on matching objects if the Action
+ // is "SetStorageClass".
+ StorageClass string
+}
+
+// Liveness specifies whether the object is live or not.
+type Liveness int
+
+const (
+ // LiveAndArchived includes both live and archived objects.
+ LiveAndArchived Liveness = iota
+ // Live specifies that the object is still live.
+ Live
+ // Archived specifies that the object is archived.
+ Archived
+)
+
+// LifecycleCondition is a set of conditions used to match objects and take an
+// action automatically.
+//
+// All configured conditions must be met for the associated action to be taken.
+type LifecycleCondition struct {
+ // AgeInDays is the age of the object in days.
+ AgeInDays int64
+
+ // CreatedBefore is the time the object was created.
+ //
+ // This condition is satisfied when an object is created before midnight of
+ // the specified date in UTC.
+ CreatedBefore time.Time
+
+ // Liveness specifies the object's liveness. Relevant only for versioned objects
+ Liveness Liveness
+
+ // MatchesStorageClasses is the condition matching the object's storage
+ // class.
+ //
+ // Values include "MULTI_REGIONAL", "REGIONAL", "NEARLINE", "COLDLINE",
+ // "STANDARD", and "DURABLE_REDUCED_AVAILABILITY".
+ MatchesStorageClasses []string
+
+ // NumNewerVersions is the condition matching objects with a number of newer versions.
+ //
+ // If the value is N, this condition is satisfied when there are at least N
+ // versions (including the live version) newer than this version of the
+ // object.
+ NumNewerVersions int64
+}
+
+// BucketLogging holds the bucket's logging configuration, which defines the
+// destination bucket and optional name prefix for the current bucket's
+// logs.
+type BucketLogging struct {
+ // The destination bucket where the current bucket's logs
+ // should be placed.
+ LogBucket string
+
+ // A prefix for log object names.
+ LogObjectPrefix string
+}
+
+// BucketWebsite holds the bucket's website configuration, controlling how the
+// service behaves when accessing bucket contents as a web site. See
+// https://cloud.google.com/storage/docs/static-website for more information.
+type BucketWebsite struct {
+ // If the requested object path is missing, the service will ensure the path has
+ // a trailing '/', append this suffix, and attempt to retrieve the resulting
+ // object. This allows the creation of index.html objects to represent directory
+ // pages.
+ MainPageSuffix string
+
+ // If the requested object path is missing, and any mainPageSuffix object is
+ // missing, if applicable, the service will return the named object from this
+ // bucket as the content for a 404 Not Found result.
+ NotFoundPage string
+}
+
+func newBucket(b *raw.Bucket) (*BucketAttrs, error) {
+ if b == nil {
+ return nil, nil
+ }
+ rp, err := toRetentionPolicy(b.RetentionPolicy)
+ if err != nil {
+ return nil, err
+ }
+ return &BucketAttrs{
+ Name: b.Name,
+ Location: b.Location,
+ MetaGeneration: b.Metageneration,
+ DefaultEventBasedHold: b.DefaultEventBasedHold,
+ StorageClass: b.StorageClass,
+ Created: convertTime(b.TimeCreated),
+ VersioningEnabled: b.Versioning != nil && b.Versioning.Enabled,
+ ACL: toBucketACLRules(b.Acl),
+ DefaultObjectACL: toObjectACLRules(b.DefaultObjectAcl),
+ Labels: b.Labels,
+ RequesterPays: b.Billing != nil && b.Billing.RequesterPays,
+ Lifecycle: toLifecycle(b.Lifecycle),
+ RetentionPolicy: rp,
+ CORS: toCORS(b.Cors),
+ Encryption: toBucketEncryption(b.Encryption),
+ Logging: toBucketLogging(b.Logging),
+ Website: toBucketWebsite(b.Website),
+ }, nil
+}
+
+// toRawBucket copies the editable attribute from b to the raw library's Bucket type.
+func (b *BucketAttrs) toRawBucket() *raw.Bucket {
+ // Copy label map.
+ var labels map[string]string
+ if len(b.Labels) > 0 {
+ labels = make(map[string]string, len(b.Labels))
+ for k, v := range b.Labels {
+ labels[k] = v
+ }
+ }
+ // Ignore VersioningEnabled if it is false. This is OK because
+ // we only call this method when creating a bucket, and by default
+ // new buckets have versioning off.
+ var v *raw.BucketVersioning
+ if b.VersioningEnabled {
+ v = &raw.BucketVersioning{Enabled: true}
+ }
+ var bb *raw.BucketBilling
+ if b.RequesterPays {
+ bb = &raw.BucketBilling{RequesterPays: true}
+ }
+ return &raw.Bucket{
+ Name: b.Name,
+ Location: b.Location,
+ StorageClass: b.StorageClass,
+ Acl: toRawBucketACL(b.ACL),
+ DefaultObjectAcl: toRawObjectACL(b.DefaultObjectACL),
+ Versioning: v,
+ Labels: labels,
+ Billing: bb,
+ Lifecycle: toRawLifecycle(b.Lifecycle),
+ RetentionPolicy: b.RetentionPolicy.toRawRetentionPolicy(),
+ Cors: toRawCORS(b.CORS),
+ Encryption: b.Encryption.toRawBucketEncryption(),
+ Logging: b.Logging.toRawBucketLogging(),
+ Website: b.Website.toRawBucketWebsite(),
+ }
+}
+
+// CORS is the bucket's Cross-Origin Resource Sharing (CORS) configuration.
+type CORS struct {
+ // MaxAge is the value to return in the Access-Control-Max-Age
+ // header used in preflight responses.
+ MaxAge time.Duration
+
+ // Methods is the list of HTTP methods on which to include CORS response
+ // headers, (GET, OPTIONS, POST, etc) Note: "*" is permitted in the list
+ // of methods, and means "any method".
+ Methods []string
+
+ // Origins is the list of Origins eligible to receive CORS response
+ // headers. Note: "*" is permitted in the list of origins, and means
+ // "any Origin".
+ Origins []string
+
+ // ResponseHeaders is the list of HTTP headers other than the simple
+ // response headers to give permission for the user-agent to share
+ // across domains.
+ ResponseHeaders []string
+}
+
+// BucketEncryption is a bucket's encryption configuration.
+type BucketEncryption struct {
+ // A Cloud KMS key name, in the form
+ // projects/P/locations/L/keyRings/R/cryptoKeys/K, that will be used to encrypt
+ // objects inserted into this bucket, if no encryption method is specified.
+ // The key's location must be the same as the bucket's.
+ DefaultKMSKeyName string
+}
+
+// BucketAttrsToUpdate define the attributes to update during an Update call.
+type BucketAttrsToUpdate struct {
+ // If set, updates whether the bucket uses versioning.
+ VersioningEnabled optional.Bool
+
+ // If set, updates whether the bucket is a Requester Pays bucket.
+ RequesterPays optional.Bool
+
+ // DefaultEventBasedHold is the default value for event-based hold on
+ // newly created objects in this bucket.
+ DefaultEventBasedHold optional.Bool
+
+ // If set, updates the retention policy of the bucket. Using
+ // RetentionPolicy.RetentionPeriod = 0 will delete the existing policy.
+ //
+ // This feature is in private alpha release. It is not currently available to
+ // most customers. It might be changed in backwards-incompatible ways and is not
+ // subject to any SLA or deprecation policy.
+ RetentionPolicy *RetentionPolicy
+
+ // If set, replaces the CORS configuration with a new configuration.
+ // An empty (rather than nil) slice causes all CORS policies to be removed.
+ CORS []CORS
+
+ // If set, replaces the encryption configuration of the bucket. Using
+ // BucketEncryption.DefaultKMSKeyName = "" will delete the existing
+ // configuration.
+ Encryption *BucketEncryption
+
+ // If set, replaces the lifecycle configuration of the bucket.
+ Lifecycle *Lifecycle
+
+ // If set, replaces the logging configuration of the bucket.
+ Logging *BucketLogging
+
+ // If set, replaces the website configuration of the bucket.
+ Website *BucketWebsite
+
+ // If not empty, applies a predefined set of access controls.
+ // See https://cloud.google.com/storage/docs/json_api/v1/buckets/patch.
+ PredefinedACL string
+
+ // If not empty, applies a predefined set of default object access controls.
+ // See https://cloud.google.com/storage/docs/json_api/v1/buckets/patch.
+ PredefinedDefaultObjectACL string
+
+ setLabels map[string]string
+ deleteLabels map[string]bool
+}
+
+// SetLabel causes a label to be added or modified when ua is used
+// in a call to Bucket.Update.
+func (ua *BucketAttrsToUpdate) SetLabel(name, value string) {
+ if ua.setLabels == nil {
+ ua.setLabels = map[string]string{}
+ }
+ ua.setLabels[name] = value
+}
+
+// DeleteLabel causes a label to be deleted when ua is used in a
+// call to Bucket.Update.
+func (ua *BucketAttrsToUpdate) DeleteLabel(name string) {
+ if ua.deleteLabels == nil {
+ ua.deleteLabels = map[string]bool{}
+ }
+ ua.deleteLabels[name] = true
+}
+
+func (ua *BucketAttrsToUpdate) toRawBucket() *raw.Bucket {
+ rb := &raw.Bucket{}
+ if ua.CORS != nil {
+ rb.Cors = toRawCORS(ua.CORS)
+ rb.ForceSendFields = append(rb.ForceSendFields, "Cors")
+ }
+ if ua.DefaultEventBasedHold != nil {
+ rb.DefaultEventBasedHold = optional.ToBool(ua.DefaultEventBasedHold)
+ rb.ForceSendFields = append(rb.ForceSendFields, "DefaultEventBasedHold")
+ }
+ if ua.RetentionPolicy != nil {
+ if ua.RetentionPolicy.RetentionPeriod == 0 {
+ rb.NullFields = append(rb.NullFields, "RetentionPolicy")
+ rb.RetentionPolicy = nil
+ } else {
+ rb.RetentionPolicy = ua.RetentionPolicy.toRawRetentionPolicy()
+ }
+ }
+ if ua.VersioningEnabled != nil {
+ rb.Versioning = &raw.BucketVersioning{
+ Enabled: optional.ToBool(ua.VersioningEnabled),
+ ForceSendFields: []string{"Enabled"},
+ }
+ }
+ if ua.RequesterPays != nil {
+ rb.Billing = &raw.BucketBilling{
+ RequesterPays: optional.ToBool(ua.RequesterPays),
+ ForceSendFields: []string{"RequesterPays"},
+ }
+ }
+ if ua.Encryption != nil {
+ if ua.Encryption.DefaultKMSKeyName == "" {
+ rb.NullFields = append(rb.NullFields, "Encryption")
+ rb.Encryption = nil
+ } else {
+ rb.Encryption = ua.Encryption.toRawBucketEncryption()
+ }
+ }
+ if ua.Lifecycle != nil {
+ rb.Lifecycle = toRawLifecycle(*ua.Lifecycle)
+ }
+ if ua.Logging != nil {
+ if *ua.Logging == (BucketLogging{}) {
+ rb.NullFields = append(rb.NullFields, "Logging")
+ rb.Logging = nil
+ } else {
+ rb.Logging = ua.Logging.toRawBucketLogging()
+ }
+ }
+ if ua.Website != nil {
+ if *ua.Website == (BucketWebsite{}) {
+ rb.NullFields = append(rb.NullFields, "Website")
+ rb.Website = nil
+ } else {
+ rb.Website = ua.Website.toRawBucketWebsite()
+ }
+ }
+ if ua.PredefinedACL != "" {
+ // Clear ACL or the call will fail.
+ rb.Acl = nil
+ rb.ForceSendFields = append(rb.ForceSendFields, "Acl")
+ }
+ if ua.PredefinedDefaultObjectACL != "" {
+ // Clear ACLs or the call will fail.
+ rb.DefaultObjectAcl = nil
+ rb.ForceSendFields = append(rb.ForceSendFields, "DefaultObjectAcl")
+ }
+ if ua.setLabels != nil || ua.deleteLabels != nil {
+ rb.Labels = map[string]string{}
+ for k, v := range ua.setLabels {
+ rb.Labels[k] = v
+ }
+ if len(rb.Labels) == 0 && len(ua.deleteLabels) > 0 {
+ rb.ForceSendFields = append(rb.ForceSendFields, "Labels")
+ }
+ for l := range ua.deleteLabels {
+ rb.NullFields = append(rb.NullFields, "Labels."+l)
+ }
+ }
+ return rb
+}
+
+// If returns a new BucketHandle that applies a set of preconditions.
+// Preconditions already set on the BucketHandle are ignored.
+// Operations on the new handle will return an error if the preconditions are not
+// satisfied. The only valid preconditions for buckets are MetagenerationMatch
+// and MetagenerationNotMatch.
+func (b *BucketHandle) If(conds BucketConditions) *BucketHandle {
+ b2 := *b
+ b2.conds = &conds
+ return &b2
+}
+
+// BucketConditions constrain bucket methods to act on specific metagenerations.
+//
+// The zero value is an empty set of constraints.
+type BucketConditions struct {
+ // MetagenerationMatch specifies that the bucket must have the given
+ // metageneration for the operation to occur.
+ // If MetagenerationMatch is zero, it has no effect.
+ MetagenerationMatch int64
+
+ // MetagenerationNotMatch specifies that the bucket must not have the given
+ // metageneration for the operation to occur.
+ // If MetagenerationNotMatch is zero, it has no effect.
+ MetagenerationNotMatch int64
+}
+
+func (c *BucketConditions) validate(method string) error {
+ if *c == (BucketConditions{}) {
+ return fmt.Errorf("storage: %s: empty conditions", method)
+ }
+ if c.MetagenerationMatch != 0 && c.MetagenerationNotMatch != 0 {
+ return fmt.Errorf("storage: %s: multiple conditions specified for metageneration", method)
+ }
+ return nil
+}
+
+// UserProject returns a new BucketHandle that passes the project ID as the user
+// project for all subsequent calls. Calls with a user project will be billed to that
+// project rather than to the bucket's owning project.
+//
+// A user project is required for all operations on Requester Pays buckets.
+func (b *BucketHandle) UserProject(projectID string) *BucketHandle {
+ b2 := *b
+ b2.userProject = projectID
+ b2.acl.userProject = projectID
+ b2.defaultObjectACL.userProject = projectID
+ return &b2
+}
+
+// LockRetentionPolicy locks a bucket's retention policy until a previously-configured
+// RetentionPeriod past the EffectiveTime. Note that if RetentionPeriod is set to less
+// than a day, the retention policy is treated as a development configuration and locking
+// will have no effect. The BucketHandle must have a metageneration condition that
+// matches the bucket's metageneration. See BucketHandle.If.
+//
+// This feature is in private alpha release. It is not currently available to
+// most customers. It might be changed in backwards-incompatible ways and is not
+// subject to any SLA or deprecation policy.
+func (b *BucketHandle) LockRetentionPolicy(ctx context.Context) error {
+ var metageneration int64
+ if b.conds != nil {
+ metageneration = b.conds.MetagenerationMatch
+ }
+ req := b.c.raw.Buckets.LockRetentionPolicy(b.name, metageneration)
+ _, err := req.Context(ctx).Do()
+ return err
+}
+
+// applyBucketConds modifies the provided call using the conditions in conds.
+// call is something that quacks like a *raw.WhateverCall.
+func applyBucketConds(method string, conds *BucketConditions, call interface{}) error {
+ if conds == nil {
+ return nil
+ }
+ if err := conds.validate(method); err != nil {
+ return err
+ }
+ cval := reflect.ValueOf(call)
+ switch {
+ case conds.MetagenerationMatch != 0:
+ if !setConditionField(cval, "IfMetagenerationMatch", conds.MetagenerationMatch) {
+ return fmt.Errorf("storage: %s: ifMetagenerationMatch not supported", method)
+ }
+ case conds.MetagenerationNotMatch != 0:
+ if !setConditionField(cval, "IfMetagenerationNotMatch", conds.MetagenerationNotMatch) {
+ return fmt.Errorf("storage: %s: ifMetagenerationNotMatch not supported", method)
+ }
+ }
+ return nil
+}
+
+func (rp *RetentionPolicy) toRawRetentionPolicy() *raw.BucketRetentionPolicy {
+ if rp == nil {
+ return nil
+ }
+ return &raw.BucketRetentionPolicy{
+ RetentionPeriod: int64(rp.RetentionPeriod / time.Second),
+ }
+}
+
+func toRetentionPolicy(rp *raw.BucketRetentionPolicy) (*RetentionPolicy, error) {
+ if rp == nil {
+ return nil, nil
+ }
+ t, err := time.Parse(time.RFC3339, rp.EffectiveTime)
+ if err != nil {
+ return nil, err
+ }
+ return &RetentionPolicy{
+ RetentionPeriod: time.Duration(rp.RetentionPeriod) * time.Second,
+ EffectiveTime: t,
+ IsLocked: rp.IsLocked,
+ }, nil
+}
+
+func toRawCORS(c []CORS) []*raw.BucketCors {
+ var out []*raw.BucketCors
+ for _, v := range c {
+ out = append(out, &raw.BucketCors{
+ MaxAgeSeconds: int64(v.MaxAge / time.Second),
+ Method: v.Methods,
+ Origin: v.Origins,
+ ResponseHeader: v.ResponseHeaders,
+ })
+ }
+ return out
+}
+
+func toCORS(rc []*raw.BucketCors) []CORS {
+ var out []CORS
+ for _, v := range rc {
+ out = append(out, CORS{
+ MaxAge: time.Duration(v.MaxAgeSeconds) * time.Second,
+ Methods: v.Method,
+ Origins: v.Origin,
+ ResponseHeaders: v.ResponseHeader,
+ })
+ }
+ return out
+}
+
+func toRawLifecycle(l Lifecycle) *raw.BucketLifecycle {
+ var rl raw.BucketLifecycle
+ if len(l.Rules) == 0 {
+ return nil
+ }
+ for _, r := range l.Rules {
+ rr := &raw.BucketLifecycleRule{
+ Action: &raw.BucketLifecycleRuleAction{
+ Type: r.Action.Type,
+ StorageClass: r.Action.StorageClass,
+ },
+ Condition: &raw.BucketLifecycleRuleCondition{
+ Age: r.Condition.AgeInDays,
+ MatchesStorageClass: r.Condition.MatchesStorageClasses,
+ NumNewerVersions: r.Condition.NumNewerVersions,
+ },
+ }
+
+ switch r.Condition.Liveness {
+ case LiveAndArchived:
+ rr.Condition.IsLive = nil
+ case Live:
+ rr.Condition.IsLive = googleapi.Bool(true)
+ case Archived:
+ rr.Condition.IsLive = googleapi.Bool(false)
+ }
+
+ if !r.Condition.CreatedBefore.IsZero() {
+ rr.Condition.CreatedBefore = r.Condition.CreatedBefore.Format(rfc3339Date)
+ }
+ rl.Rule = append(rl.Rule, rr)
+ }
+ return &rl
+}
+
+func toLifecycle(rl *raw.BucketLifecycle) Lifecycle {
+ var l Lifecycle
+ if rl == nil {
+ return l
+ }
+ for _, rr := range rl.Rule {
+ r := LifecycleRule{
+ Action: LifecycleAction{
+ Type: rr.Action.Type,
+ StorageClass: rr.Action.StorageClass,
+ },
+ Condition: LifecycleCondition{
+ AgeInDays: rr.Condition.Age,
+ MatchesStorageClasses: rr.Condition.MatchesStorageClass,
+ NumNewerVersions: rr.Condition.NumNewerVersions,
+ },
+ }
+
+ switch {
+ case rr.Condition.IsLive == nil:
+ r.Condition.Liveness = LiveAndArchived
+ case *rr.Condition.IsLive == true:
+ r.Condition.Liveness = Live
+ case *rr.Condition.IsLive == false:
+ r.Condition.Liveness = Archived
+ }
+
+ if rr.Condition.CreatedBefore != "" {
+ r.Condition.CreatedBefore, _ = time.Parse(rfc3339Date, rr.Condition.CreatedBefore)
+ }
+ l.Rules = append(l.Rules, r)
+ }
+ return l
+}
+
+func (e *BucketEncryption) toRawBucketEncryption() *raw.BucketEncryption {
+ if e == nil {
+ return nil
+ }
+ return &raw.BucketEncryption{
+ DefaultKmsKeyName: e.DefaultKMSKeyName,
+ }
+}
+
+func toBucketEncryption(e *raw.BucketEncryption) *BucketEncryption {
+ if e == nil {
+ return nil
+ }
+ return &BucketEncryption{DefaultKMSKeyName: e.DefaultKmsKeyName}
+}
+
+func (b *BucketLogging) toRawBucketLogging() *raw.BucketLogging {
+ if b == nil {
+ return nil
+ }
+ return &raw.BucketLogging{
+ LogBucket: b.LogBucket,
+ LogObjectPrefix: b.LogObjectPrefix,
+ }
+}
+
+func toBucketLogging(b *raw.BucketLogging) *BucketLogging {
+ if b == nil {
+ return nil
+ }
+ return &BucketLogging{
+ LogBucket: b.LogBucket,
+ LogObjectPrefix: b.LogObjectPrefix,
+ }
+}
+
+func (w *BucketWebsite) toRawBucketWebsite() *raw.BucketWebsite {
+ if w == nil {
+ return nil
+ }
+ return &raw.BucketWebsite{
+ MainPageSuffix: w.MainPageSuffix,
+ NotFoundPage: w.NotFoundPage,
+ }
+}
+
+func toBucketWebsite(w *raw.BucketWebsite) *BucketWebsite {
+ if w == nil {
+ return nil
+ }
+ return &BucketWebsite{
+ MainPageSuffix: w.MainPageSuffix,
+ NotFoundPage: w.NotFoundPage,
+ }
+}
+
+// Objects returns an iterator over the objects in the bucket that match the Query q.
+// If q is nil, no filtering is done.
+func (b *BucketHandle) Objects(ctx context.Context, q *Query) *ObjectIterator {
+ it := &ObjectIterator{
+ ctx: ctx,
+ bucket: b,
+ }
+ it.pageInfo, it.nextFunc = iterator.NewPageInfo(
+ it.fetch,
+ func() int { return len(it.items) },
+ func() interface{} { b := it.items; it.items = nil; return b })
+ if q != nil {
+ it.query = *q
+ }
+ return it
+}
+
+// An ObjectIterator is an iterator over ObjectAttrs.
+type ObjectIterator struct {
+ ctx context.Context
+ bucket *BucketHandle
+ query Query
+ pageInfo *iterator.PageInfo
+ nextFunc func() error
+ items []*ObjectAttrs
+}
+
+// PageInfo supports pagination. See the google.golang.org/api/iterator package for details.
+func (it *ObjectIterator) PageInfo() *iterator.PageInfo { return it.pageInfo }
+
+// Next returns the next result. Its second return value is iterator.Done if
+// there are no more results. Once Next returns iterator.Done, all subsequent
+// calls will return iterator.Done.
+//
+// If Query.Delimiter is non-empty, some of the ObjectAttrs returned by Next will
+// have a non-empty Prefix field, and a zero value for all other fields. These
+// represent prefixes.
+func (it *ObjectIterator) Next() (*ObjectAttrs, error) {
+ if err := it.nextFunc(); err != nil {
+ return nil, err
+ }
+ item := it.items[0]
+ it.items = it.items[1:]
+ return item, nil
+}
+
+func (it *ObjectIterator) fetch(pageSize int, pageToken string) (string, error) {
+ req := it.bucket.c.raw.Objects.List(it.bucket.name)
+ setClientHeader(req.Header())
+ req.Projection("full")
+ req.Delimiter(it.query.Delimiter)
+ req.Prefix(it.query.Prefix)
+ req.Versions(it.query.Versions)
+ req.PageToken(pageToken)
+ if it.bucket.userProject != "" {
+ req.UserProject(it.bucket.userProject)
+ }
+ if pageSize > 0 {
+ req.MaxResults(int64(pageSize))
+ }
+ var resp *raw.Objects
+ var err error
+ err = runWithRetry(it.ctx, func() error {
+ resp, err = req.Context(it.ctx).Do()
+ return err
+ })
+ if err != nil {
+ if e, ok := err.(*googleapi.Error); ok && e.Code == http.StatusNotFound {
+ err = ErrBucketNotExist
+ }
+ return "", err
+ }
+ for _, item := range resp.Items {
+ it.items = append(it.items, newObject(item))
+ }
+ for _, prefix := range resp.Prefixes {
+ it.items = append(it.items, &ObjectAttrs{Prefix: prefix})
+ }
+ return resp.NextPageToken, nil
+}
+
+// Buckets returns an iterator over the buckets in the project. You may
+// optionally set the iterator's Prefix field to restrict the list to buckets
+// whose names begin with the prefix. By default, all buckets in the project
+// are returned.
+func (c *Client) Buckets(ctx context.Context, projectID string) *BucketIterator {
+ it := &BucketIterator{
+ ctx: ctx,
+ client: c,
+ projectID: projectID,
+ }
+ it.pageInfo, it.nextFunc = iterator.NewPageInfo(
+ it.fetch,
+ func() int { return len(it.buckets) },
+ func() interface{} { b := it.buckets; it.buckets = nil; return b })
+ return it
+}
+
+// A BucketIterator is an iterator over BucketAttrs.
+type BucketIterator struct {
+ // Prefix restricts the iterator to buckets whose names begin with it.
+ Prefix string
+
+ ctx context.Context
+ client *Client
+ projectID string
+ buckets []*BucketAttrs
+ pageInfo *iterator.PageInfo
+ nextFunc func() error
+}
+
+// Next returns the next result. Its second return value is iterator.Done if
+// there are no more results. Once Next returns iterator.Done, all subsequent
+// calls will return iterator.Done.
+func (it *BucketIterator) Next() (*BucketAttrs, error) {
+ if err := it.nextFunc(); err != nil {
+ return nil, err
+ }
+ b := it.buckets[0]
+ it.buckets = it.buckets[1:]
+ return b, nil
+}
+
+// PageInfo supports pagination. See the google.golang.org/api/iterator package for details.
+func (it *BucketIterator) PageInfo() *iterator.PageInfo { return it.pageInfo }
+
+func (it *BucketIterator) fetch(pageSize int, pageToken string) (token string, err error) {
+ req := it.client.raw.Buckets.List(it.projectID)
+ setClientHeader(req.Header())
+ req.Projection("full")
+ req.Prefix(it.Prefix)
+ req.PageToken(pageToken)
+ if pageSize > 0 {
+ req.MaxResults(int64(pageSize))
+ }
+ var resp *raw.Buckets
+ err = runWithRetry(it.ctx, func() error {
+ resp, err = req.Context(it.ctx).Do()
+ return err
+ })
+ if err != nil {
+ return "", err
+ }
+ for _, item := range resp.Items {
+ b, err := newBucket(item)
+ if err != nil {
+ return "", err
+ }
+ it.buckets = append(it.buckets, b)
+ }
+ return resp.NextPageToken, nil
+}
diff --git a/vendor/cloud.google.com/go/storage/copy.go b/vendor/cloud.google.com/go/storage/copy.go
new file mode 100644
index 000000000..52162e72d
--- /dev/null
+++ b/vendor/cloud.google.com/go/storage/copy.go
@@ -0,0 +1,228 @@
+// Copyright 2016 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package storage
+
+import (
+ "context"
+ "errors"
+ "fmt"
+
+ "cloud.google.com/go/internal/trace"
+ raw "google.golang.org/api/storage/v1"
+)
+
+// CopierFrom creates a Copier that can copy src to dst.
+// You can immediately call Run on the returned Copier, or
+// you can configure it first.
+//
+// For Requester Pays buckets, the user project of dst is billed, unless it is empty,
+// in which case the user project of src is billed.
+func (dst *ObjectHandle) CopierFrom(src *ObjectHandle) *Copier {
+ return &Copier{dst: dst, src: src}
+}
+
+// A Copier copies a source object to a destination.
+type Copier struct {
+ // ObjectAttrs are optional attributes to set on the destination object.
+ // Any attributes must be initialized before any calls on the Copier. Nil
+ // or zero-valued attributes are ignored.
+ ObjectAttrs
+
+ // RewriteToken can be set before calling Run to resume a copy
+ // operation. After Run returns a non-nil error, RewriteToken will
+ // have been updated to contain the value needed to resume the copy.
+ RewriteToken string
+
+ // ProgressFunc can be used to monitor the progress of a multi-RPC copy
+ // operation. If ProgressFunc is not nil and copying requires multiple
+ // calls to the underlying service (see
+ // https://cloud.google.com/storage/docs/json_api/v1/objects/rewrite), then
+ // ProgressFunc will be invoked after each call with the number of bytes of
+ // content copied so far and the total size in bytes of the source object.
+ //
+ // ProgressFunc is intended to make upload progress available to the
+ // application. For example, the implementation of ProgressFunc may update
+ // a progress bar in the application's UI, or log the result of
+ // float64(copiedBytes)/float64(totalBytes).
+ //
+ // ProgressFunc should return quickly without blocking.
+ ProgressFunc func(copiedBytes, totalBytes uint64)
+
+ // The Cloud KMS key, in the form projects/P/locations/L/keyRings/R/cryptoKeys/K,
+ // that will be used to encrypt the object. Overrides the object's KMSKeyName, if
+ // any.
+ //
+ // Providing both a DestinationKMSKeyName and a customer-supplied encryption key
+ // (via ObjectHandle.Key) on the destination object will result in an error when
+ // Run is called.
+ DestinationKMSKeyName string
+
+ dst, src *ObjectHandle
+}
+
+// Run performs the copy.
+func (c *Copier) Run(ctx context.Context) (attrs *ObjectAttrs, err error) {
+ ctx = trace.StartSpan(ctx, "cloud.google.com/go/storage.Copier.Run")
+ defer func() { trace.EndSpan(ctx, err) }()
+
+ if err := c.src.validate(); err != nil {
+ return nil, err
+ }
+ if err := c.dst.validate(); err != nil {
+ return nil, err
+ }
+ if c.DestinationKMSKeyName != "" && c.dst.encryptionKey != nil {
+ return nil, errors.New("storage: cannot use DestinationKMSKeyName with a customer-supplied encryption key")
+ }
+ // Convert destination attributes to raw form, omitting the bucket.
+ // If the bucket is included but name or content-type aren't, the service
+ // returns a 400 with "Required" as the only message. Omitting the bucket
+ // does not cause any problems.
+ rawObject := c.ObjectAttrs.toRawObject("")
+ for {
+ res, err := c.callRewrite(ctx, rawObject)
+ if err != nil {
+ return nil, err
+ }
+ if c.ProgressFunc != nil {
+ c.ProgressFunc(uint64(res.TotalBytesRewritten), uint64(res.ObjectSize))
+ }
+ if res.Done { // Finished successfully.
+ return newObject(res.Resource), nil
+ }
+ }
+}
+
+func (c *Copier) callRewrite(ctx context.Context, rawObj *raw.Object) (*raw.RewriteResponse, error) {
+ call := c.dst.c.raw.Objects.Rewrite(c.src.bucket, c.src.object, c.dst.bucket, c.dst.object, rawObj)
+
+ call.Context(ctx).Projection("full")
+ if c.RewriteToken != "" {
+ call.RewriteToken(c.RewriteToken)
+ }
+ if c.DestinationKMSKeyName != "" {
+ call.DestinationKmsKeyName(c.DestinationKMSKeyName)
+ }
+ if c.PredefinedACL != "" {
+ call.DestinationPredefinedAcl(c.PredefinedACL)
+ }
+ if err := applyConds("Copy destination", c.dst.gen, c.dst.conds, call); err != nil {
+ return nil, err
+ }
+ if c.dst.userProject != "" {
+ call.UserProject(c.dst.userProject)
+ } else if c.src.userProject != "" {
+ call.UserProject(c.src.userProject)
+ }
+ if err := applySourceConds(c.src.gen, c.src.conds, call); err != nil {
+ return nil, err
+ }
+ if err := setEncryptionHeaders(call.Header(), c.dst.encryptionKey, false); err != nil {
+ return nil, err
+ }
+ if err := setEncryptionHeaders(call.Header(), c.src.encryptionKey, true); err != nil {
+ return nil, err
+ }
+ var res *raw.RewriteResponse
+ var err error
+ setClientHeader(call.Header())
+ err = runWithRetry(ctx, func() error { res, err = call.Do(); return err })
+ if err != nil {
+ return nil, err
+ }
+ c.RewriteToken = res.RewriteToken
+ return res, nil
+}
+
+// ComposerFrom creates a Composer that can compose srcs into dst.
+// You can immediately call Run on the returned Composer, or you can
+// configure it first.
+//
+// The encryption key for the destination object will be used to decrypt all
+// source objects and encrypt the destination object. It is an error
+// to specify an encryption key for any of the source objects.
+func (dst *ObjectHandle) ComposerFrom(srcs ...*ObjectHandle) *Composer {
+ return &Composer{dst: dst, srcs: srcs}
+}
+
+// A Composer composes source objects into a destination object.
+//
+// For Requester Pays buckets, the user project of dst is billed.
+type Composer struct {
+ // ObjectAttrs are optional attributes to set on the destination object.
+ // Any attributes must be initialized before any calls on the Composer. Nil
+ // or zero-valued attributes are ignored.
+ ObjectAttrs
+
+ dst *ObjectHandle
+ srcs []*ObjectHandle
+}
+
+// Run performs the compose operation.
+func (c *Composer) Run(ctx context.Context) (attrs *ObjectAttrs, err error) {
+ ctx = trace.StartSpan(ctx, "cloud.google.com/go/storage.Composer.Run")
+ defer func() { trace.EndSpan(ctx, err) }()
+
+ if err := c.dst.validate(); err != nil {
+ return nil, err
+ }
+ if len(c.srcs) == 0 {
+ return nil, errors.New("storage: at least one source object must be specified")
+ }
+
+ req := &raw.ComposeRequest{}
+ // Compose requires a non-empty Destination, so we always set it,
+ // even if the caller-provided ObjectAttrs is the zero value.
+ req.Destination = c.ObjectAttrs.toRawObject(c.dst.bucket)
+ for _, src := range c.srcs {
+ if err := src.validate(); err != nil {
+ return nil, err
+ }
+ if src.bucket != c.dst.bucket {
+ return nil, fmt.Errorf("storage: all source objects must be in bucket %q, found %q", c.dst.bucket, src.bucket)
+ }
+ if src.encryptionKey != nil {
+ return nil, fmt.Errorf("storage: compose source %s.%s must not have encryption key", src.bucket, src.object)
+ }
+ srcObj := &raw.ComposeRequestSourceObjects{
+ Name: src.object,
+ }
+ if err := applyConds("ComposeFrom source", src.gen, src.conds, composeSourceObj{srcObj}); err != nil {
+ return nil, err
+ }
+ req.SourceObjects = append(req.SourceObjects, srcObj)
+ }
+
+ call := c.dst.c.raw.Objects.Compose(c.dst.bucket, c.dst.object, req).Context(ctx)
+ if err := applyConds("ComposeFrom destination", c.dst.gen, c.dst.conds, call); err != nil {
+ return nil, err
+ }
+ if c.dst.userProject != "" {
+ call.UserProject(c.dst.userProject)
+ }
+ if c.PredefinedACL != "" {
+ call.DestinationPredefinedAcl(c.PredefinedACL)
+ }
+ if err := setEncryptionHeaders(call.Header(), c.dst.encryptionKey, false); err != nil {
+ return nil, err
+ }
+ var obj *raw.Object
+ setClientHeader(call.Header())
+ err = runWithRetry(ctx, func() error { obj, err = call.Do(); return err })
+ if err != nil {
+ return nil, err
+ }
+ return newObject(obj), nil
+}
diff --git a/vendor/cloud.google.com/go/storage/doc.go b/vendor/cloud.google.com/go/storage/doc.go
new file mode 100644
index 000000000..e277f1d95
--- /dev/null
+++ b/vendor/cloud.google.com/go/storage/doc.go
@@ -0,0 +1,176 @@
+// Copyright 2016 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/*
+Package storage provides an easy way to work with Google Cloud Storage.
+Google Cloud Storage stores data in named objects, which are grouped into buckets.
+
+More information about Google Cloud Storage is available at
+https://cloud.google.com/storage/docs.
+
+See https://godoc.org/cloud.google.com/go for authentication, timeouts,
+connection pooling and similar aspects of this package.
+
+All of the methods of this package use exponential backoff to retry calls that fail
+with certain errors, as described in
+https://cloud.google.com/storage/docs/exponential-backoff. Retrying continues
+indefinitely unless the controlling context is canceled or the client is closed. See
+context.WithTimeout and context.WithCancel.
+
+
+Creating a Client
+
+To start working with this package, create a client:
+
+ ctx := context.Background()
+ client, err := storage.NewClient(ctx)
+ if err != nil {
+ // TODO: Handle error.
+ }
+
+The client will use your default application credentials.
+
+If you only wish to access public data, you can create
+an unauthenticated client with
+
+ client, err := storage.NewClient(ctx, option.WithoutAuthentication())
+
+Buckets
+
+A Google Cloud Storage bucket is a collection of objects. To work with a
+bucket, make a bucket handle:
+
+ bkt := client.Bucket(bucketName)
+
+A handle is a reference to a bucket. You can have a handle even if the
+bucket doesn't exist yet. To create a bucket in Google Cloud Storage,
+call Create on the handle:
+
+ if err := bkt.Create(ctx, projectID, nil); err != nil {
+ // TODO: Handle error.
+ }
+
+Note that although buckets are associated with projects, bucket names are
+global across all projects.
+
+Each bucket has associated metadata, represented in this package by
+BucketAttrs. The third argument to BucketHandle.Create allows you to set
+the initial BucketAttrs of a bucket. To retrieve a bucket's attributes, use
+Attrs:
+
+ attrs, err := bkt.Attrs(ctx)
+ if err != nil {
+ // TODO: Handle error.
+ }
+ fmt.Printf("bucket %s, created at %s, is located in %s with storage class %s\n",
+ attrs.Name, attrs.Created, attrs.Location, attrs.StorageClass)
+
+Objects
+
+An object holds arbitrary data as a sequence of bytes, like a file. You
+refer to objects using a handle, just as with buckets, but unlike buckets
+you don't explicitly create an object. Instead, the first time you write
+to an object it will be created. You can use the standard Go io.Reader
+and io.Writer interfaces to read and write object data:
+
+ obj := bkt.Object("data")
+ // Write something to obj.
+ // w implements io.Writer.
+ w := obj.NewWriter(ctx)
+ // Write some text to obj. This will either create the object or overwrite whatever is there already.
+ if _, err := fmt.Fprintf(w, "This object contains text.\n"); err != nil {
+ // TODO: Handle error.
+ }
+ // Close, just like writing a file.
+ if err := w.Close(); err != nil {
+ // TODO: Handle error.
+ }
+
+ // Read it back.
+ r, err := obj.NewReader(ctx)
+ if err != nil {
+ // TODO: Handle error.
+ }
+ defer r.Close()
+ if _, err := io.Copy(os.Stdout, r); err != nil {
+ // TODO: Handle error.
+ }
+ // Prints "This object contains text."
+
+Objects also have attributes, which you can fetch with Attrs:
+
+ objAttrs, err := obj.Attrs(ctx)
+ if err != nil {
+ // TODO: Handle error.
+ }
+ fmt.Printf("object %s has size %d and can be read using %s\n",
+ objAttrs.Name, objAttrs.Size, objAttrs.MediaLink)
+
+ACLs
+
+Both objects and buckets have ACLs (Access Control Lists). An ACL is a list of
+ACLRules, each of which specifies the role of a user, group or project. ACLs
+are suitable for fine-grained control, but you may prefer using IAM to control
+access at the project level (see
+https://cloud.google.com/storage/docs/access-control/iam).
+
+To list the ACLs of a bucket or object, obtain an ACLHandle and call its List method:
+
+ acls, err := obj.ACL().List(ctx)
+ if err != nil {
+ // TODO: Handle error.
+ }
+ for _, rule := range acls {
+ fmt.Printf("%s has role %s\n", rule.Entity, rule.Role)
+ }
+
+You can also set and delete ACLs.
+
+Conditions
+
+Every object has a generation and a metageneration. The generation changes
+whenever the content changes, and the metageneration changes whenever the
+metadata changes. Conditions let you check these values before an operation;
+the operation only executes if the conditions match. You can use conditions to
+prevent race conditions in read-modify-write operations.
+
+For example, say you've read an object's metadata into objAttrs. Now
+you want to write to that object, but only if its contents haven't changed
+since you read it. Here is how to express that:
+
+ w = obj.If(storage.Conditions{GenerationMatch: objAttrs.Generation}).NewWriter(ctx)
+ // Proceed with writing as above.
+
+Signed URLs
+
+You can obtain a URL that lets anyone read or write an object for a limited time.
+You don't need to create a client to do this. See the documentation of
+SignedURL for details.
+
+ url, err := storage.SignedURL(bucketName, "shared-object", opts)
+ if err != nil {
+ // TODO: Handle error.
+ }
+ fmt.Println(url)
+
+Errors
+
+Errors returned by this client are often of the type [`googleapi.Error`](https://godoc.org/google.golang.org/api/googleapi#Error).
+These errors can be introspected for more information by type asserting to the richer `googleapi.Error` type. For example:
+
+ if e, ok := err.(*googleapi.Error); ok {
+ if e.Code = 409 { ... }
+ }
+*/
+package storage // import "cloud.google.com/go/storage"
diff --git a/vendor/cloud.google.com/go/storage/go110.go b/vendor/cloud.google.com/go/storage/go110.go
new file mode 100644
index 000000000..206813f0c
--- /dev/null
+++ b/vendor/cloud.google.com/go/storage/go110.go
@@ -0,0 +1,32 @@
+// Copyright 2017 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// +build go1.10
+
+package storage
+
+import "google.golang.org/api/googleapi"
+
+func shouldRetry(err error) bool {
+ switch e := err.(type) {
+ case *googleapi.Error:
+ // Retry on 429 and 5xx, according to
+ // https://cloud.google.com/storage/docs/exponential-backoff.
+ return e.Code == 429 || (e.Code >= 500 && e.Code < 600)
+ case interface{ Temporary() bool }:
+ return e.Temporary()
+ default:
+ return false
+ }
+}
diff --git a/vendor/cloud.google.com/go/storage/iam.go b/vendor/cloud.google.com/go/storage/iam.go
new file mode 100644
index 000000000..9d9360671
--- /dev/null
+++ b/vendor/cloud.google.com/go/storage/iam.go
@@ -0,0 +1,130 @@
+// Copyright 2017 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package storage
+
+import (
+ "context"
+
+ "cloud.google.com/go/iam"
+ "cloud.google.com/go/internal/trace"
+ raw "google.golang.org/api/storage/v1"
+ iampb "google.golang.org/genproto/googleapis/iam/v1"
+)
+
+// IAM provides access to IAM access control for the bucket.
+func (b *BucketHandle) IAM() *iam.Handle {
+ return iam.InternalNewHandleClient(&iamClient{
+ raw: b.c.raw,
+ userProject: b.userProject,
+ }, b.name)
+}
+
+// iamClient implements the iam.client interface.
+type iamClient struct {
+ raw *raw.Service
+ userProject string
+}
+
+func (c *iamClient) Get(ctx context.Context, resource string) (p *iampb.Policy, err error) {
+ ctx = trace.StartSpan(ctx, "cloud.google.com/go/storage.IAM.Get")
+ defer func() { trace.EndSpan(ctx, err) }()
+
+ call := c.raw.Buckets.GetIamPolicy(resource)
+ setClientHeader(call.Header())
+ if c.userProject != "" {
+ call.UserProject(c.userProject)
+ }
+ var rp *raw.Policy
+ err = runWithRetry(ctx, func() error {
+ rp, err = call.Context(ctx).Do()
+ return err
+ })
+ if err != nil {
+ return nil, err
+ }
+ return iamFromStoragePolicy(rp), nil
+}
+
+func (c *iamClient) Set(ctx context.Context, resource string, p *iampb.Policy) (err error) {
+ ctx = trace.StartSpan(ctx, "cloud.google.com/go/storage.IAM.Set")
+ defer func() { trace.EndSpan(ctx, err) }()
+
+ rp := iamToStoragePolicy(p)
+ call := c.raw.Buckets.SetIamPolicy(resource, rp)
+ setClientHeader(call.Header())
+ if c.userProject != "" {
+ call.UserProject(c.userProject)
+ }
+ return runWithRetry(ctx, func() error {
+ _, err := call.Context(ctx).Do()
+ return err
+ })
+}
+
+func (c *iamClient) Test(ctx context.Context, resource string, perms []string) (permissions []string, err error) {
+ ctx = trace.StartSpan(ctx, "cloud.google.com/go/storage.IAM.Test")
+ defer func() { trace.EndSpan(ctx, err) }()
+
+ call := c.raw.Buckets.TestIamPermissions(resource, perms)
+ setClientHeader(call.Header())
+ if c.userProject != "" {
+ call.UserProject(c.userProject)
+ }
+ var res *raw.TestIamPermissionsResponse
+ err = runWithRetry(ctx, func() error {
+ res, err = call.Context(ctx).Do()
+ return err
+ })
+ if err != nil {
+ return nil, err
+ }
+ return res.Permissions, nil
+}
+
+func iamToStoragePolicy(ip *iampb.Policy) *raw.Policy {
+ return &raw.Policy{
+ Bindings: iamToStorageBindings(ip.Bindings),
+ Etag: string(ip.Etag),
+ }
+}
+
+func iamToStorageBindings(ibs []*iampb.Binding) []*raw.PolicyBindings {
+ var rbs []*raw.PolicyBindings
+ for _, ib := range ibs {
+ rbs = append(rbs, &raw.PolicyBindings{
+ Role: ib.Role,
+ Members: ib.Members,
+ })
+ }
+ return rbs
+}
+
+func iamFromStoragePolicy(rp *raw.Policy) *iampb.Policy {
+ return &iampb.Policy{
+ Bindings: iamFromStorageBindings(rp.Bindings),
+ Etag: []byte(rp.Etag),
+ }
+}
+
+func iamFromStorageBindings(rbs []*raw.PolicyBindings) []*iampb.Binding {
+ var ibs []*iampb.Binding
+ for _, rb := range rbs {
+ ibs = append(ibs, &iampb.Binding{
+ Role: rb.Role,
+ Members: rb.Members,
+ })
+ }
+ return ibs
+}
diff --git a/vendor/cloud.google.com/go/storage/invoke.go b/vendor/cloud.google.com/go/storage/invoke.go
new file mode 100644
index 000000000..0a03f1101
--- /dev/null
+++ b/vendor/cloud.google.com/go/storage/invoke.go
@@ -0,0 +1,37 @@
+// Copyright 2014 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package storage
+
+import (
+ "context"
+
+ "cloud.google.com/go/internal"
+ gax "github.com/googleapis/gax-go"
+)
+
+// runWithRetry calls the function until it returns nil or a non-retryable error, or
+// the context is done.
+func runWithRetry(ctx context.Context, call func() error) error {
+ return internal.Retry(ctx, gax.Backoff{}, func() (stop bool, err error) {
+ err = call()
+ if err == nil {
+ return true, nil
+ }
+ if shouldRetry(err) {
+ return false, nil
+ }
+ return true, err
+ })
+}
diff --git a/vendor/cloud.google.com/go/storage/not_go110.go b/vendor/cloud.google.com/go/storage/not_go110.go
new file mode 100644
index 000000000..66fa45bea
--- /dev/null
+++ b/vendor/cloud.google.com/go/storage/not_go110.go
@@ -0,0 +1,42 @@
+// Copyright 2017 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// +build !go1.10
+
+package storage
+
+import (
+ "net/url"
+ "strings"
+
+ "google.golang.org/api/googleapi"
+)
+
+func shouldRetry(err error) bool {
+ switch e := err.(type) {
+ case *googleapi.Error:
+ // Retry on 429 and 5xx, according to
+ // https://cloud.google.com/storage/docs/exponential-backoff.
+ return e.Code == 429 || (e.Code >= 500 && e.Code < 600)
+ case *url.Error:
+ // Retry on REFUSED_STREAM.
+ // Unfortunately the error type is unexported, so we resort to string
+ // matching.
+ return strings.Contains(e.Error(), "REFUSED_STREAM")
+ case interface{ Temporary() bool }:
+ return e.Temporary()
+ default:
+ return false
+ }
+}
diff --git a/vendor/cloud.google.com/go/storage/notifications.go b/vendor/cloud.google.com/go/storage/notifications.go
new file mode 100644
index 000000000..84619b6d5
--- /dev/null
+++ b/vendor/cloud.google.com/go/storage/notifications.go
@@ -0,0 +1,188 @@
+// Copyright 2017 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package storage
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "regexp"
+
+ "cloud.google.com/go/internal/trace"
+ raw "google.golang.org/api/storage/v1"
+)
+
+// A Notification describes how to send Cloud PubSub messages when certain
+// events occur in a bucket.
+type Notification struct {
+ //The ID of the notification.
+ ID string
+
+ // The ID of the topic to which this subscription publishes.
+ TopicID string
+
+ // The ID of the project to which the topic belongs.
+ TopicProjectID string
+
+ // Only send notifications about listed event types. If empty, send notifications
+ // for all event types.
+ // See https://cloud.google.com/storage/docs/pubsub-notifications#events.
+ EventTypes []string
+
+ // If present, only apply this notification configuration to object names that
+ // begin with this prefix.
+ ObjectNamePrefix string
+
+ // An optional list of additional attributes to attach to each Cloud PubSub
+ // message published for this notification subscription.
+ CustomAttributes map[string]string
+
+ // The contents of the message payload.
+ // See https://cloud.google.com/storage/docs/pubsub-notifications#payload.
+ PayloadFormat string
+}
+
+// Values for Notification.PayloadFormat.
+const (
+ // Send no payload with notification messages.
+ NoPayload = "NONE"
+
+ // Send object metadata as JSON with notification messages.
+ JSONPayload = "JSON_API_V1"
+)
+
+// Values for Notification.EventTypes.
+const (
+ // Event that occurs when an object is successfully created.
+ ObjectFinalizeEvent = "OBJECT_FINALIZE"
+
+ // Event that occurs when the metadata of an existing object changes.
+ ObjectMetadataUpdateEvent = "OBJECT_METADATA_UPDATE"
+
+ // Event that occurs when an object is permanently deleted.
+ ObjectDeleteEvent = "OBJECT_DELETE"
+
+ // Event that occurs when the live version of an object becomes an
+ // archived version.
+ ObjectArchiveEvent = "OBJECT_ARCHIVE"
+)
+
+func toNotification(rn *raw.Notification) *Notification {
+ n := &Notification{
+ ID: rn.Id,
+ EventTypes: rn.EventTypes,
+ ObjectNamePrefix: rn.ObjectNamePrefix,
+ CustomAttributes: rn.CustomAttributes,
+ PayloadFormat: rn.PayloadFormat,
+ }
+ n.TopicProjectID, n.TopicID = parseNotificationTopic(rn.Topic)
+ return n
+}
+
+var topicRE = regexp.MustCompile("^//pubsub.googleapis.com/projects/([^/]+)/topics/([^/]+)")
+
+// parseNotificationTopic extracts the project and topic IDs from from the full
+// resource name returned by the service. If the name is malformed, it returns
+// "?" for both IDs.
+func parseNotificationTopic(nt string) (projectID, topicID string) {
+ matches := topicRE.FindStringSubmatch(nt)
+ if matches == nil {
+ return "?", "?"
+ }
+ return matches[1], matches[2]
+}
+
+func toRawNotification(n *Notification) *raw.Notification {
+ return &raw.Notification{
+ Id: n.ID,
+ Topic: fmt.Sprintf("//pubsub.googleapis.com/projects/%s/topics/%s",
+ n.TopicProjectID, n.TopicID),
+ EventTypes: n.EventTypes,
+ ObjectNamePrefix: n.ObjectNamePrefix,
+ CustomAttributes: n.CustomAttributes,
+ PayloadFormat: string(n.PayloadFormat),
+ }
+}
+
+// AddNotification adds a notification to b. You must set n's TopicProjectID, TopicID
+// and PayloadFormat, and must not set its ID. The other fields are all optional. The
+// returned Notification's ID can be used to refer to it.
+func (b *BucketHandle) AddNotification(ctx context.Context, n *Notification) (ret *Notification, err error) {
+ ctx = trace.StartSpan(ctx, "cloud.google.com/go/storage.Bucket.AddNotification")
+ defer func() { trace.EndSpan(ctx, err) }()
+
+ if n.ID != "" {
+ return nil, errors.New("storage: AddNotification: ID must not be set")
+ }
+ if n.TopicProjectID == "" {
+ return nil, errors.New("storage: AddNotification: missing TopicProjectID")
+ }
+ if n.TopicID == "" {
+ return nil, errors.New("storage: AddNotification: missing TopicID")
+ }
+ call := b.c.raw.Notifications.Insert(b.name, toRawNotification(n))
+ setClientHeader(call.Header())
+ if b.userProject != "" {
+ call.UserProject(b.userProject)
+ }
+ rn, err := call.Context(ctx).Do()
+ if err != nil {
+ return nil, err
+ }
+ return toNotification(rn), nil
+}
+
+// Notifications returns all the Notifications configured for this bucket, as a map
+// indexed by notification ID.
+func (b *BucketHandle) Notifications(ctx context.Context) (n map[string]*Notification, err error) {
+ ctx = trace.StartSpan(ctx, "cloud.google.com/go/storage.Bucket.Notifications")
+ defer func() { trace.EndSpan(ctx, err) }()
+
+ call := b.c.raw.Notifications.List(b.name)
+ setClientHeader(call.Header())
+ if b.userProject != "" {
+ call.UserProject(b.userProject)
+ }
+ var res *raw.Notifications
+ err = runWithRetry(ctx, func() error {
+ res, err = call.Context(ctx).Do()
+ return err
+ })
+ if err != nil {
+ return nil, err
+ }
+ return notificationsToMap(res.Items), nil
+}
+
+func notificationsToMap(rns []*raw.Notification) map[string]*Notification {
+ m := map[string]*Notification{}
+ for _, rn := range rns {
+ m[rn.Id] = toNotification(rn)
+ }
+ return m
+}
+
+// DeleteNotification deletes the notification with the given ID.
+func (b *BucketHandle) DeleteNotification(ctx context.Context, id string) (err error) {
+ ctx = trace.StartSpan(ctx, "cloud.google.com/go/storage.Bucket.DeleteNotification")
+ defer func() { trace.EndSpan(ctx, err) }()
+
+ call := b.c.raw.Notifications.Delete(b.name, id)
+ setClientHeader(call.Header())
+ if b.userProject != "" {
+ call.UserProject(b.userProject)
+ }
+ return call.Context(ctx).Do()
+}
diff --git a/vendor/cloud.google.com/go/storage/reader.go b/vendor/cloud.google.com/go/storage/reader.go
new file mode 100644
index 000000000..50f381f91
--- /dev/null
+++ b/vendor/cloud.google.com/go/storage/reader.go
@@ -0,0 +1,385 @@
+// Copyright 2016 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package storage
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "hash/crc32"
+ "io"
+ "io/ioutil"
+ "net/http"
+ "net/url"
+ "reflect"
+ "strconv"
+ "strings"
+ "time"
+
+ "cloud.google.com/go/internal/trace"
+ "google.golang.org/api/googleapi"
+)
+
+var crc32cTable = crc32.MakeTable(crc32.Castagnoli)
+
+// ReaderObjectAttrs are attributes about the object being read. These are populated
+// during the New call. This struct only holds a subset of object attributes: to
+// get the full set of attributes, use ObjectHandle.Attrs.
+//
+// Each field is read-only.
+type ReaderObjectAttrs struct {
+ // Size is the length of the object's content.
+ Size int64
+
+ // ContentType is the MIME type of the object's content.
+ ContentType string
+
+ // ContentEncoding is the encoding of the object's content.
+ ContentEncoding string
+
+ // CacheControl specifies whether and for how long browser and Internet
+ // caches are allowed to cache your objects.
+ CacheControl string
+
+ // LastModified is the time that the object was last modified.
+ LastModified time.Time
+
+ // Generation is the generation number of the object's content.
+ Generation int64
+
+ // Metageneration is the version of the metadata for this object at
+ // this generation. This field is used for preconditions and for
+ // detecting changes in metadata. A metageneration number is only
+ // meaningful in the context of a particular generation of a
+ // particular object.
+ Metageneration int64
+}
+
+// NewReader creates a new Reader to read the contents of the
+// object.
+// ErrObjectNotExist will be returned if the object is not found.
+//
+// The caller must call Close on the returned Reader when done reading.
+func (o *ObjectHandle) NewReader(ctx context.Context) (*Reader, error) {
+ return o.NewRangeReader(ctx, 0, -1)
+}
+
+// NewRangeReader reads part of an object, reading at most length bytes
+// starting at the given offset. If length is negative, the object is read
+// until the end.
+func (o *ObjectHandle) NewRangeReader(ctx context.Context, offset, length int64) (r *Reader, err error) {
+ ctx = trace.StartSpan(ctx, "cloud.google.com/go/storage.Object.NewRangeReader")
+ defer func() { trace.EndSpan(ctx, err) }()
+
+ if err := o.validate(); err != nil {
+ return nil, err
+ }
+ if offset < 0 {
+ return nil, fmt.Errorf("storage: invalid offset %d < 0", offset)
+ }
+ if o.conds != nil {
+ if err := o.conds.validate("NewRangeReader"); err != nil {
+ return nil, err
+ }
+ }
+ u := &url.URL{
+ Scheme: "https",
+ Host: "storage.googleapis.com",
+ Path: fmt.Sprintf("/%s/%s", o.bucket, o.object),
+ }
+ verb := "GET"
+ if length == 0 {
+ verb = "HEAD"
+ }
+ req, err := http.NewRequest(verb, u.String(), nil)
+ if err != nil {
+ return nil, err
+ }
+ req = req.WithContext(ctx)
+ if o.userProject != "" {
+ req.Header.Set("X-Goog-User-Project", o.userProject)
+ }
+ if o.readCompressed {
+ req.Header.Set("Accept-Encoding", "gzip")
+ }
+ if err := setEncryptionHeaders(req.Header, o.encryptionKey, false); err != nil {
+ return nil, err
+ }
+
+ gen := o.gen
+
+ // Define a function that initiates a Read with offset and length, assuming we
+ // have already read seen bytes.
+ reopen := func(seen int64) (*http.Response, error) {
+ start := offset + seen
+ if length < 0 && start > 0 {
+ req.Header.Set("Range", fmt.Sprintf("bytes=%d-", start))
+ } else if length > 0 {
+ // The end character isn't affected by how many bytes we've seen.
+ req.Header.Set("Range", fmt.Sprintf("bytes=%d-%d", start, offset+length-1))
+ }
+ // We wait to assign conditions here because the generation number can change in between reopen() runs.
+ req.URL.RawQuery = conditionsQuery(gen, o.conds)
+ var res *http.Response
+ err = runWithRetry(ctx, func() error {
+ res, err = o.c.hc.Do(req)
+ if err != nil {
+ return err
+ }
+ if res.StatusCode == http.StatusNotFound {
+ res.Body.Close()
+ return ErrObjectNotExist
+ }
+ if res.StatusCode < 200 || res.StatusCode > 299 {
+ body, _ := ioutil.ReadAll(res.Body)
+ res.Body.Close()
+ return &googleapi.Error{
+ Code: res.StatusCode,
+ Header: res.Header,
+ Body: string(body),
+ }
+ }
+ if start > 0 && length != 0 && res.StatusCode != http.StatusPartialContent {
+ res.Body.Close()
+ return errors.New("storage: partial request not satisfied")
+ }
+ // If a generation hasn't been specified, and this is the first response we get, let's record the
+ // generation. In future requests we'll use this generation as a precondition to avoid data races.
+ if gen < 0 && res.Header.Get("X-Goog-Generation") != "" {
+ gen64, err := strconv.ParseInt(res.Header.Get("X-Goog-Generation"), 10, 64)
+ if err != nil {
+ return err
+ }
+ gen = gen64
+ }
+ return nil
+ })
+ if err != nil {
+ return nil, err
+ }
+ return res, nil
+ }
+
+ res, err := reopen(0)
+ if err != nil {
+ return nil, err
+ }
+ var (
+ size int64 // total size of object, even if a range was requested.
+ checkCRC bool
+ crc uint32
+ )
+ if res.StatusCode == http.StatusPartialContent {
+ cr := strings.TrimSpace(res.Header.Get("Content-Range"))
+ if !strings.HasPrefix(cr, "bytes ") || !strings.Contains(cr, "/") {
+
+ return nil, fmt.Errorf("storage: invalid Content-Range %q", cr)
+ }
+ size, err = strconv.ParseInt(cr[strings.LastIndex(cr, "/")+1:], 10, 64)
+ if err != nil {
+ return nil, fmt.Errorf("storage: invalid Content-Range %q", cr)
+ }
+ } else {
+ size = res.ContentLength
+ // Check the CRC iff all of the following hold:
+ // - We asked for content (length != 0).
+ // - We got all the content (status != PartialContent).
+ // - The server sent a CRC header.
+ // - The Go http stack did not uncompress the file.
+ // - We were not served compressed data that was uncompressed on download.
+ // The problem with the last two cases is that the CRC will not match -- GCS
+ // computes it on the compressed contents, but we compute it on the
+ // uncompressed contents.
+ if length != 0 && !res.Uncompressed && !uncompressedByServer(res) {
+ crc, checkCRC = parseCRC32c(res)
+ }
+ }
+
+ remain := res.ContentLength
+ body := res.Body
+ if length == 0 {
+ remain = 0
+ body.Close()
+ body = emptyBody
+ }
+ var metaGen int64
+ if res.Header.Get("X-Goog-Generation") != "" {
+ metaGen, err = strconv.ParseInt(res.Header.Get("X-Goog-Metageneration"), 10, 64)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ var lm time.Time
+ if res.Header.Get("Last-Modified") != "" {
+ lm, err = http.ParseTime(res.Header.Get("Last-Modified"))
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ attrs := ReaderObjectAttrs{
+ Size: size,
+ ContentType: res.Header.Get("Content-Type"),
+ ContentEncoding: res.Header.Get("Content-Encoding"),
+ CacheControl: res.Header.Get("Cache-Control"),
+ LastModified: lm,
+ Generation: gen,
+ Metageneration: metaGen,
+ }
+ return &Reader{
+ Attrs: attrs,
+ body: body,
+ size: size,
+ remain: remain,
+ wantCRC: crc,
+ checkCRC: checkCRC,
+ reopen: reopen,
+ }, nil
+}
+
+func uncompressedByServer(res *http.Response) bool {
+ // If the data is stored as gzip but is not encoded as gzip, then it
+ // was uncompressed by the server.
+ return res.Header.Get("X-Goog-Stored-Content-Encoding") == "gzip" &&
+ res.Header.Get("Content-Encoding") != "gzip"
+}
+
+func parseCRC32c(res *http.Response) (uint32, bool) {
+ const prefix = "crc32c="
+ for _, spec := range res.Header["X-Goog-Hash"] {
+ if strings.HasPrefix(spec, prefix) {
+ c, err := decodeUint32(spec[len(prefix):])
+ if err == nil {
+ return c, true
+ }
+ }
+ }
+ return 0, false
+}
+
+var emptyBody = ioutil.NopCloser(strings.NewReader(""))
+
+// Reader reads a Cloud Storage object.
+// It implements io.Reader.
+//
+// Typically, a Reader computes the CRC of the downloaded content and compares it to
+// the stored CRC, returning an error from Read if there is a mismatch. This integrity check
+// is skipped if transcoding occurs. See https://cloud.google.com/storage/docs/transcoding.
+type Reader struct {
+ Attrs ReaderObjectAttrs
+ body io.ReadCloser
+ seen, remain, size int64
+ checkCRC bool // should we check the CRC?
+ wantCRC uint32 // the CRC32c value the server sent in the header
+ gotCRC uint32 // running crc
+ reopen func(seen int64) (*http.Response, error)
+}
+
+// Close closes the Reader. It must be called when done reading.
+func (r *Reader) Close() error {
+ return r.body.Close()
+}
+
+func (r *Reader) Read(p []byte) (int, error) {
+ n, err := r.readWithRetry(p)
+ if r.remain != -1 {
+ r.remain -= int64(n)
+ }
+ if r.checkCRC {
+ r.gotCRC = crc32.Update(r.gotCRC, crc32cTable, p[:n])
+ // Check CRC here. It would be natural to check it in Close, but
+ // everybody defers Close on the assumption that it doesn't return
+ // anything worth looking at.
+ if err == io.EOF {
+ if r.gotCRC != r.wantCRC {
+ return n, fmt.Errorf("storage: bad CRC on read: got %d, want %d",
+ r.gotCRC, r.wantCRC)
+ }
+ }
+ }
+ return n, err
+}
+
+func (r *Reader) readWithRetry(p []byte) (int, error) {
+ n := 0
+ for len(p[n:]) > 0 {
+ m, err := r.body.Read(p[n:])
+ n += m
+ r.seen += int64(m)
+ if !shouldRetryRead(err) {
+ return n, err
+ }
+ // Read failed, but we will try again. Send a ranged read request that takes
+ // into account the number of bytes we've already seen.
+ res, err := r.reopen(r.seen)
+ if err != nil {
+ // reopen already retries
+ return n, err
+ }
+ r.body.Close()
+ r.body = res.Body
+ }
+ return n, nil
+}
+
+func shouldRetryRead(err error) bool {
+ if err == nil {
+ return false
+ }
+ return strings.HasSuffix(err.Error(), "INTERNAL_ERROR") && strings.Contains(reflect.TypeOf(err).String(), "http2")
+}
+
+// Size returns the size of the object in bytes.
+// The returned value is always the same and is not affected by
+// calls to Read or Close.
+//
+// Deprecated: use Reader.Attrs.Size.
+func (r *Reader) Size() int64 {
+ return r.Attrs.Size
+}
+
+// Remain returns the number of bytes left to read, or -1 if unknown.
+func (r *Reader) Remain() int64 {
+ return r.remain
+}
+
+// ContentType returns the content type of the object.
+//
+// Deprecated: use Reader.Attrs.ContentType.
+func (r *Reader) ContentType() string {
+ return r.Attrs.ContentType
+}
+
+// ContentEncoding returns the content encoding of the object.
+//
+// Deprecated: use Reader.Attrs.ContentEncoding.
+func (r *Reader) ContentEncoding() string {
+ return r.Attrs.ContentEncoding
+}
+
+// CacheControl returns the cache control of the object.
+//
+// Deprecated: use Reader.Attrs.CacheControl.
+func (r *Reader) CacheControl() string {
+ return r.Attrs.CacheControl
+}
+
+// LastModified returns the value of the Last-Modified header.
+//
+// Deprecated: use Reader.Attrs.LastModified.
+func (r *Reader) LastModified() (time.Time, error) {
+ return r.Attrs.LastModified, nil
+}
diff --git a/vendor/cloud.google.com/go/storage/storage.go b/vendor/cloud.google.com/go/storage/storage.go
new file mode 100644
index 000000000..4b4d62eeb
--- /dev/null
+++ b/vendor/cloud.google.com/go/storage/storage.go
@@ -0,0 +1,1123 @@
+// Copyright 2014 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package storage
+
+import (
+ "bytes"
+ "context"
+ "crypto"
+ "crypto/rand"
+ "crypto/rsa"
+ "crypto/sha256"
+ "crypto/x509"
+ "encoding/base64"
+ "encoding/pem"
+ "errors"
+ "fmt"
+ "io"
+ "net/http"
+ "net/url"
+ "reflect"
+ "regexp"
+ "sort"
+ "strconv"
+ "strings"
+ "time"
+ "unicode/utf8"
+
+ "cloud.google.com/go/internal/optional"
+ "cloud.google.com/go/internal/trace"
+ "cloud.google.com/go/internal/version"
+ "google.golang.org/api/googleapi"
+ "google.golang.org/api/option"
+ raw "google.golang.org/api/storage/v1"
+ htransport "google.golang.org/api/transport/http"
+)
+
+var (
+ // ErrBucketNotExist indicates that the bucket does not exist.
+ ErrBucketNotExist = errors.New("storage: bucket doesn't exist")
+ // ErrObjectNotExist indicates that the object does not exist.
+ ErrObjectNotExist = errors.New("storage: object doesn't exist")
+)
+
+const userAgent = "gcloud-golang-storage/20151204"
+
+const (
+ // ScopeFullControl grants permissions to manage your
+ // data and permissions in Google Cloud Storage.
+ ScopeFullControl = raw.DevstorageFullControlScope
+
+ // ScopeReadOnly grants permissions to
+ // view your data in Google Cloud Storage.
+ ScopeReadOnly = raw.DevstorageReadOnlyScope
+
+ // ScopeReadWrite grants permissions to manage your
+ // data in Google Cloud Storage.
+ ScopeReadWrite = raw.DevstorageReadWriteScope
+)
+
+var xGoogHeader = fmt.Sprintf("gl-go/%s gccl/%s", version.Go(), version.Repo)
+
+func setClientHeader(headers http.Header) {
+ headers.Set("x-goog-api-client", xGoogHeader)
+}
+
+// Client is a client for interacting with Google Cloud Storage.
+//
+// Clients should be reused instead of created as needed.
+// The methods of Client are safe for concurrent use by multiple goroutines.
+type Client struct {
+ hc *http.Client
+ raw *raw.Service
+}
+
+// NewClient creates a new Google Cloud Storage client.
+// The default scope is ScopeFullControl. To use a different scope, like ScopeReadOnly, use option.WithScopes.
+func NewClient(ctx context.Context, opts ...option.ClientOption) (*Client, error) {
+ o := []option.ClientOption{
+ option.WithScopes(ScopeFullControl),
+ option.WithUserAgent(userAgent),
+ }
+ opts = append(o, opts...)
+ hc, ep, err := htransport.NewClient(ctx, opts...)
+ if err != nil {
+ return nil, fmt.Errorf("dialing: %v", err)
+ }
+ rawService, err := raw.New(hc)
+ if err != nil {
+ return nil, fmt.Errorf("storage client: %v", err)
+ }
+ if ep != "" {
+ rawService.BasePath = ep
+ }
+ return &Client{
+ hc: hc,
+ raw: rawService,
+ }, nil
+}
+
+// Close closes the Client.
+//
+// Close need not be called at program exit.
+func (c *Client) Close() error {
+ // Set fields to nil so that subsequent uses will panic.
+ c.hc = nil
+ c.raw = nil
+ return nil
+}
+
+// SignedURLOptions allows you to restrict the access to the signed URL.
+type SignedURLOptions struct {
+ // GoogleAccessID represents the authorizer of the signed URL generation.
+ // It is typically the Google service account client email address from
+ // the Google Developers Console in the form of "xxx@developer.gserviceaccount.com".
+ // Required.
+ GoogleAccessID string
+
+ // PrivateKey is the Google service account private key. It is obtainable
+ // from the Google Developers Console.
+ // At https://console.developers.google.com/project/<your-project-id>/apiui/credential,
+ // create a service account client ID or reuse one of your existing service account
+ // credentials. Click on the "Generate new P12 key" to generate and download
+ // a new private key. Once you download the P12 file, use the following command
+ // to convert it into a PEM file.
+ //
+ // $ openssl pkcs12 -in key.p12 -passin pass:notasecret -out key.pem -nodes
+ //
+ // Provide the contents of the PEM file as a byte slice.
+ // Exactly one of PrivateKey or SignBytes must be non-nil.
+ PrivateKey []byte
+
+ // SignBytes is a function for implementing custom signing.
+ // If your application is running on Google App Engine, you can use appengine's internal signing function:
+ // ctx := appengine.NewContext(request)
+ // acc, _ := appengine.ServiceAccount(ctx)
+ // url, err := SignedURL("bucket", "object", &SignedURLOptions{
+ // GoogleAccessID: acc,
+ // SignBytes: func(b []byte) ([]byte, error) {
+ // _, signedBytes, err := appengine.SignBytes(ctx, b)
+ // return signedBytes, err
+ // },
+ // // etc.
+ // })
+ //
+ // Exactly one of PrivateKey or SignBytes must be non-nil.
+ SignBytes func([]byte) ([]byte, error)
+
+ // Method is the HTTP method to be used with the signed URL.
+ // Signed URLs can be used with GET, HEAD, PUT, and DELETE requests.
+ // Required.
+ Method string
+
+ // Expires is the expiration time on the signed URL. It must be
+ // a datetime in the future.
+ // Required.
+ Expires time.Time
+
+ // ContentType is the content type header the client must provide
+ // to use the generated signed URL.
+ // Optional.
+ ContentType string
+
+ // Headers is a list of extension headers the client must provide
+ // in order to use the generated signed URL.
+ // Optional.
+ Headers []string
+
+ // MD5 is the base64 encoded MD5 checksum of the file.
+ // If provided, the client should provide the exact value on the request
+ // header in order to use the signed URL.
+ // Optional.
+ MD5 string
+}
+
+var (
+ canonicalHeaderRegexp = regexp.MustCompile(`(?i)^(x-goog-[^:]+):(.*)?$`)
+ excludedCanonicalHeaders = map[string]bool{
+ "x-goog-encryption-key": true,
+ "x-goog-encryption-key-sha256": true,
+ }
+)
+
+// sanitizeHeaders applies the specifications for canonical extension headers at
+// https://cloud.google.com/storage/docs/access-control/signed-urls#about-canonical-extension-headers.
+func sanitizeHeaders(hdrs []string) []string {
+ headerMap := map[string][]string{}
+ for _, hdr := range hdrs {
+ // No leading or trailing whitespaces.
+ sanitizedHeader := strings.TrimSpace(hdr)
+
+ // Only keep canonical headers, discard any others.
+ headerMatches := canonicalHeaderRegexp.FindStringSubmatch(sanitizedHeader)
+ if len(headerMatches) == 0 {
+ continue
+ }
+
+ header := strings.ToLower(strings.TrimSpace(headerMatches[1]))
+ if excludedCanonicalHeaders[headerMatches[1]] {
+ // Do not keep any deliberately excluded canonical headers when signing.
+ continue
+ }
+ value := strings.TrimSpace(headerMatches[2])
+ if len(value) > 0 {
+ // Remove duplicate headers by appending the values of duplicates
+ // in their order of appearance.
+ headerMap[header] = append(headerMap[header], value)
+ }
+ }
+
+ var sanitizedHeaders []string
+ for header, values := range headerMap {
+ // There should be no spaces around the colon separating the
+ // header name from the header value or around the values
+ // themselves. The values should be separated by commas.
+ // NOTE: The semantics for headers without a value are not clear.
+ // However from specifications these should be edge-cases
+ // anyway and we should assume that there will be no
+ // canonical headers using empty values. Any such headers
+ // are discarded at the regexp stage above.
+ sanitizedHeaders = append(
+ sanitizedHeaders,
+ fmt.Sprintf("%s:%s", header, strings.Join(values, ",")),
+ )
+ }
+ sort.Strings(sanitizedHeaders)
+ return sanitizedHeaders
+}
+
+// SignedURL returns a URL for the specified object. Signed URLs allow
+// the users access to a restricted resource for a limited time without having a
+// Google account or signing in. For more information about the signed
+// URLs, see https://cloud.google.com/storage/docs/accesscontrol#Signed-URLs.
+func SignedURL(bucket, name string, opts *SignedURLOptions) (string, error) {
+ if opts == nil {
+ return "", errors.New("storage: missing required SignedURLOptions")
+ }
+ if opts.GoogleAccessID == "" {
+ return "", errors.New("storage: missing required GoogleAccessID")
+ }
+ if (opts.PrivateKey == nil) == (opts.SignBytes == nil) {
+ return "", errors.New("storage: exactly one of PrivateKey or SignedBytes must be set")
+ }
+ if opts.Method == "" {
+ return "", errors.New("storage: missing required method option")
+ }
+ if opts.Expires.IsZero() {
+ return "", errors.New("storage: missing required expires option")
+ }
+ if opts.MD5 != "" {
+ md5, err := base64.StdEncoding.DecodeString(opts.MD5)
+ if err != nil || len(md5) != 16 {
+ return "", errors.New("storage: invalid MD5 checksum")
+ }
+ }
+ opts.Headers = sanitizeHeaders(opts.Headers)
+
+ signBytes := opts.SignBytes
+ if opts.PrivateKey != nil {
+ key, err := parseKey(opts.PrivateKey)
+ if err != nil {
+ return "", err
+ }
+ signBytes = func(b []byte) ([]byte, error) {
+ sum := sha256.Sum256(b)
+ return rsa.SignPKCS1v15(
+ rand.Reader,
+ key,
+ crypto.SHA256,
+ sum[:],
+ )
+ }
+ }
+
+ u := &url.URL{
+ Path: fmt.Sprintf("/%s/%s", bucket, name),
+ }
+
+ buf := &bytes.Buffer{}
+ fmt.Fprintf(buf, "%s\n", opts.Method)
+ fmt.Fprintf(buf, "%s\n", opts.MD5)
+ fmt.Fprintf(buf, "%s\n", opts.ContentType)
+ fmt.Fprintf(buf, "%d\n", opts.Expires.Unix())
+ if len(opts.Headers) > 0 {
+ fmt.Fprintf(buf, "%s\n", strings.Join(opts.Headers, "\n"))
+ }
+ fmt.Fprintf(buf, "%s", u.String())
+
+ b, err := signBytes(buf.Bytes())
+ if err != nil {
+ return "", err
+ }
+ encoded := base64.StdEncoding.EncodeToString(b)
+ u.Scheme = "https"
+ u.Host = "storage.googleapis.com"
+ q := u.Query()
+ q.Set("GoogleAccessId", opts.GoogleAccessID)
+ q.Set("Expires", fmt.Sprintf("%d", opts.Expires.Unix()))
+ q.Set("Signature", string(encoded))
+ u.RawQuery = q.Encode()
+ return u.String(), nil
+}
+
+// ObjectHandle provides operations on an object in a Google Cloud Storage bucket.
+// Use BucketHandle.Object to get a handle.
+type ObjectHandle struct {
+ c *Client
+ bucket string
+ object string
+ acl ACLHandle
+ gen int64 // a negative value indicates latest
+ conds *Conditions
+ encryptionKey []byte // AES-256 key
+ userProject string // for requester-pays buckets
+ readCompressed bool // Accept-Encoding: gzip
+}
+
+// ACL provides access to the object's access control list.
+// This controls who can read and write this object.
+// This call does not perform any network operations.
+func (o *ObjectHandle) ACL() *ACLHandle {
+ return &o.acl
+}
+
+// Generation returns a new ObjectHandle that operates on a specific generation
+// of the object.
+// By default, the handle operates on the latest generation. Not
+// all operations work when given a specific generation; check the API
+// endpoints at https://cloud.google.com/storage/docs/json_api/ for details.
+func (o *ObjectHandle) Generation(gen int64) *ObjectHandle {
+ o2 := *o
+ o2.gen = gen
+ return &o2
+}
+
+// If returns a new ObjectHandle that applies a set of preconditions.
+// Preconditions already set on the ObjectHandle are ignored.
+// Operations on the new handle will return an error if the preconditions are not
+// satisfied. See https://cloud.google.com/storage/docs/generations-preconditions
+// for more details.
+func (o *ObjectHandle) If(conds Conditions) *ObjectHandle {
+ o2 := *o
+ o2.conds = &conds
+ return &o2
+}
+
+// Key returns a new ObjectHandle that uses the supplied encryption
+// key to encrypt and decrypt the object's contents.
+//
+// Encryption key must be a 32-byte AES-256 key.
+// See https://cloud.google.com/storage/docs/encryption for details.
+func (o *ObjectHandle) Key(encryptionKey []byte) *ObjectHandle {
+ o2 := *o
+ o2.encryptionKey = encryptionKey
+ return &o2
+}
+
+// Attrs returns meta information about the object.
+// ErrObjectNotExist will be returned if the object is not found.
+func (o *ObjectHandle) Attrs(ctx context.Context) (attrs *ObjectAttrs, err error) {
+ ctx = trace.StartSpan(ctx, "cloud.google.com/go/storage.Object.Attrs")
+ defer func() { trace.EndSpan(ctx, err) }()
+
+ if err := o.validate(); err != nil {
+ return nil, err
+ }
+ call := o.c.raw.Objects.Get(o.bucket, o.object).Projection("full").Context(ctx)
+ if err := applyConds("Attrs", o.gen, o.conds, call); err != nil {
+ return nil, err
+ }
+ if o.userProject != "" {
+ call.UserProject(o.userProject)
+ }
+ if err := setEncryptionHeaders(call.Header(), o.encryptionKey, false); err != nil {
+ return nil, err
+ }
+ var obj *raw.Object
+ setClientHeader(call.Header())
+ err = runWithRetry(ctx, func() error { obj, err = call.Do(); return err })
+ if e, ok := err.(*googleapi.Error); ok && e.Code == http.StatusNotFound {
+ return nil, ErrObjectNotExist
+ }
+ if err != nil {
+ return nil, err
+ }
+ return newObject(obj), nil
+}
+
+// Update updates an object with the provided attributes.
+// All zero-value attributes are ignored.
+// ErrObjectNotExist will be returned if the object is not found.
+func (o *ObjectHandle) Update(ctx context.Context, uattrs ObjectAttrsToUpdate) (oa *ObjectAttrs, err error) {
+ ctx = trace.StartSpan(ctx, "cloud.google.com/go/storage.Object.Update")
+ defer func() { trace.EndSpan(ctx, err) }()
+
+ if err := o.validate(); err != nil {
+ return nil, err
+ }
+ var attrs ObjectAttrs
+ // Lists of fields to send, and set to null, in the JSON.
+ var forceSendFields, nullFields []string
+ if uattrs.ContentType != nil {
+ attrs.ContentType = optional.ToString(uattrs.ContentType)
+ // For ContentType, sending the empty string is a no-op.
+ // Instead we send a null.
+ if attrs.ContentType == "" {
+ nullFields = append(nullFields, "ContentType")
+ } else {
+ forceSendFields = append(forceSendFields, "ContentType")
+ }
+ }
+ if uattrs.ContentLanguage != nil {
+ attrs.ContentLanguage = optional.ToString(uattrs.ContentLanguage)
+ // For ContentLanguage it's an error to send the empty string.
+ // Instead we send a null.
+ if attrs.ContentLanguage == "" {
+ nullFields = append(nullFields, "ContentLanguage")
+ } else {
+ forceSendFields = append(forceSendFields, "ContentLanguage")
+ }
+ }
+ if uattrs.ContentEncoding != nil {
+ attrs.ContentEncoding = optional.ToString(uattrs.ContentEncoding)
+ forceSendFields = append(forceSendFields, "ContentEncoding")
+ }
+ if uattrs.ContentDisposition != nil {
+ attrs.ContentDisposition = optional.ToString(uattrs.ContentDisposition)
+ forceSendFields = append(forceSendFields, "ContentDisposition")
+ }
+ if uattrs.CacheControl != nil {
+ attrs.CacheControl = optional.ToString(uattrs.CacheControl)
+ forceSendFields = append(forceSendFields, "CacheControl")
+ }
+ if uattrs.EventBasedHold != nil {
+ attrs.EventBasedHold = optional.ToBool(uattrs.EventBasedHold)
+ forceSendFields = append(forceSendFields, "EventBasedHold")
+ }
+ if uattrs.TemporaryHold != nil {
+ attrs.TemporaryHold = optional.ToBool(uattrs.TemporaryHold)
+ forceSendFields = append(forceSendFields, "TemporaryHold")
+ }
+ if uattrs.Metadata != nil {
+ attrs.Metadata = uattrs.Metadata
+ if len(attrs.Metadata) == 0 {
+ // Sending the empty map is a no-op. We send null instead.
+ nullFields = append(nullFields, "Metadata")
+ } else {
+ forceSendFields = append(forceSendFields, "Metadata")
+ }
+ }
+ if uattrs.ACL != nil {
+ attrs.ACL = uattrs.ACL
+ // It's an error to attempt to delete the ACL, so
+ // we don't append to nullFields here.
+ forceSendFields = append(forceSendFields, "Acl")
+ }
+ rawObj := attrs.toRawObject(o.bucket)
+ rawObj.ForceSendFields = forceSendFields
+ rawObj.NullFields = nullFields
+ call := o.c.raw.Objects.Patch(o.bucket, o.object, rawObj).Projection("full").Context(ctx)
+ if err := applyConds("Update", o.gen, o.conds, call); err != nil {
+ return nil, err
+ }
+ if o.userProject != "" {
+ call.UserProject(o.userProject)
+ }
+ if uattrs.PredefinedACL != "" {
+ call.PredefinedAcl(uattrs.PredefinedACL)
+ }
+ if err := setEncryptionHeaders(call.Header(), o.encryptionKey, false); err != nil {
+ return nil, err
+ }
+ var obj *raw.Object
+ setClientHeader(call.Header())
+ err = runWithRetry(ctx, func() error { obj, err = call.Do(); return err })
+ if e, ok := err.(*googleapi.Error); ok && e.Code == http.StatusNotFound {
+ return nil, ErrObjectNotExist
+ }
+ if err != nil {
+ return nil, err
+ }
+ return newObject(obj), nil
+}
+
+// BucketName returns the name of the bucket.
+func (o *ObjectHandle) BucketName() string {
+ return o.bucket
+}
+
+// ObjectName returns the name of the object.
+func (o *ObjectHandle) ObjectName() string {
+ return o.object
+}
+
+// ObjectAttrsToUpdate is used to update the attributes of an object.
+// Only fields set to non-nil values will be updated.
+// Set a field to its zero value to delete it.
+//
+// For example, to change ContentType and delete ContentEncoding and
+// Metadata, use
+// ObjectAttrsToUpdate{
+// ContentType: "text/html",
+// ContentEncoding: "",
+// Metadata: map[string]string{},
+// }
+type ObjectAttrsToUpdate struct {
+ EventBasedHold optional.Bool
+ TemporaryHold optional.Bool
+ ContentType optional.String
+ ContentLanguage optional.String
+ ContentEncoding optional.String
+ ContentDisposition optional.String
+ CacheControl optional.String
+ Metadata map[string]string // set to map[string]string{} to delete
+ ACL []ACLRule
+
+ // If not empty, applies a predefined set of access controls. ACL must be nil.
+ // See https://cloud.google.com/storage/docs/json_api/v1/objects/patch.
+ PredefinedACL string
+}
+
+// Delete deletes the single specified object.
+func (o *ObjectHandle) Delete(ctx context.Context) error {
+ if err := o.validate(); err != nil {
+ return err
+ }
+ call := o.c.raw.Objects.Delete(o.bucket, o.object).Context(ctx)
+ if err := applyConds("Delete", o.gen, o.conds, call); err != nil {
+ return err
+ }
+ if o.userProject != "" {
+ call.UserProject(o.userProject)
+ }
+ // Encryption doesn't apply to Delete.
+ setClientHeader(call.Header())
+ err := runWithRetry(ctx, func() error { return call.Do() })
+ switch e := err.(type) {
+ case nil:
+ return nil
+ case *googleapi.Error:
+ if e.Code == http.StatusNotFound {
+ return ErrObjectNotExist
+ }
+ }
+ return err
+}
+
+// ReadCompressed when true causes the read to happen without decompressing.
+func (o *ObjectHandle) ReadCompressed(compressed bool) *ObjectHandle {
+ o2 := *o
+ o2.readCompressed = compressed
+ return &o2
+}
+
+// NewWriter returns a storage Writer that writes to the GCS object
+// associated with this ObjectHandle.
+//
+// A new object will be created unless an object with this name already exists.
+// Otherwise any previous object with the same name will be replaced.
+// The object will not be available (and any previous object will remain)
+// until Close has been called.
+//
+// Attributes can be set on the object by modifying the returned Writer's
+// ObjectAttrs field before the first call to Write. If no ContentType
+// attribute is specified, the content type will be automatically sniffed
+// using net/http.DetectContentType.
+//
+// It is the caller's responsibility to call Close when writing is done. To
+// stop writing without saving the data, cancel the context.
+func (o *ObjectHandle) NewWriter(ctx context.Context) *Writer {
+ return &Writer{
+ ctx: ctx,
+ o: o,
+ donec: make(chan struct{}),
+ ObjectAttrs: ObjectAttrs{Name: o.object},
+ ChunkSize: googleapi.DefaultUploadChunkSize,
+ }
+}
+
+func (o *ObjectHandle) validate() error {
+ if o.bucket == "" {
+ return errors.New("storage: bucket name is empty")
+ }
+ if o.object == "" {
+ return errors.New("storage: object name is empty")
+ }
+ if !utf8.ValidString(o.object) {
+ return fmt.Errorf("storage: object name %q is not valid UTF-8", o.object)
+ }
+ return nil
+}
+
+// parseKey converts the binary contents of a private key file to an
+// *rsa.PrivateKey. It detects whether the private key is in a PEM container or
+// not. If so, it extracts the private key from PEM container before
+// conversion. It only supports PEM containers with no passphrase.
+func parseKey(key []byte) (*rsa.PrivateKey, error) {
+ if block, _ := pem.Decode(key); block != nil {
+ key = block.Bytes
+ }
+ parsedKey, err := x509.ParsePKCS8PrivateKey(key)
+ if err != nil {
+ parsedKey, err = x509.ParsePKCS1PrivateKey(key)
+ if err != nil {
+ return nil, err
+ }
+ }
+ parsed, ok := parsedKey.(*rsa.PrivateKey)
+ if !ok {
+ return nil, errors.New("oauth2: private key is invalid")
+ }
+ return parsed, nil
+}
+
+// toRawObject copies the editable attributes from o to the raw library's Object type.
+func (o *ObjectAttrs) toRawObject(bucket string) *raw.Object {
+ var ret string
+ if !o.RetentionExpirationTime.IsZero() {
+ ret = o.RetentionExpirationTime.Format(time.RFC3339)
+ }
+ return &raw.Object{
+ Bucket: bucket,
+ Name: o.Name,
+ EventBasedHold: o.EventBasedHold,
+ TemporaryHold: o.TemporaryHold,
+ RetentionExpirationTime: ret,
+ ContentType: o.ContentType,
+ ContentEncoding: o.ContentEncoding,
+ ContentLanguage: o.ContentLanguage,
+ CacheControl: o.CacheControl,
+ ContentDisposition: o.ContentDisposition,
+ StorageClass: o.StorageClass,
+ Acl: toRawObjectACL(o.ACL),
+ Metadata: o.Metadata,
+ }
+}
+
+// ObjectAttrs represents the metadata for a Google Cloud Storage (GCS) object.
+type ObjectAttrs struct {
+ // Bucket is the name of the bucket containing this GCS object.
+ // This field is read-only.
+ Bucket string
+
+ // Name is the name of the object within the bucket.
+ // This field is read-only.
+ Name string
+
+ // ContentType is the MIME type of the object's content.
+ ContentType string
+
+ // ContentLanguage is the content language of the object's content.
+ ContentLanguage string
+
+ // CacheControl is the Cache-Control header to be sent in the response
+ // headers when serving the object data.
+ CacheControl string
+
+ // EventBasedHold specifies whether an object is under event-based hold. New
+ // objects created in a bucket whose DefaultEventBasedHold is set will
+ // default to that value.
+ EventBasedHold bool
+
+ // TemporaryHold specifies whether an object is under temporary hold. While
+ // this flag is set to true, the object is protected against deletion and
+ // overwrites.
+ TemporaryHold bool
+
+ // RetentionExpirationTime is a server-determined value that specifies the
+ // earliest time that the object's retention period expires.
+ // This is a read-only field.
+ RetentionExpirationTime time.Time
+
+ // ACL is the list of access control rules for the object.
+ ACL []ACLRule
+
+ // If not empty, applies a predefined set of access controls. It should be set
+ // only when writing, copying or composing an object. When copying or composing,
+ // it acts as the destinationPredefinedAcl parameter.
+ // PredefinedACL is always empty for ObjectAttrs returned from the service.
+ // See https://cloud.google.com/storage/docs/json_api/v1/objects/insert
+ // for valid values.
+ PredefinedACL string
+
+ // Owner is the owner of the object. This field is read-only.
+ //
+ // If non-zero, it is in the form of "user-<userId>".
+ Owner string
+
+ // Size is the length of the object's content. This field is read-only.
+ Size int64
+
+ // ContentEncoding is the encoding of the object's content.
+ ContentEncoding string
+
+ // ContentDisposition is the optional Content-Disposition header of the object
+ // sent in the response headers.
+ ContentDisposition string
+
+ // MD5 is the MD5 hash of the object's content. This field is read-only,
+ // except when used from a Writer. If set on a Writer, the uploaded
+ // data is rejected if its MD5 hash does not match this field.
+ MD5 []byte
+
+ // CRC32C is the CRC32 checksum of the object's content using
+ // the Castagnoli93 polynomial. This field is read-only, except when
+ // used from a Writer. If set on a Writer and Writer.SendCRC32C
+ // is true, the uploaded data is rejected if its CRC32c hash does not
+ // match this field.
+ CRC32C uint32
+
+ // MediaLink is an URL to the object's content. This field is read-only.
+ MediaLink string
+
+ // Metadata represents user-provided metadata, in key/value pairs.
+ // It can be nil if no metadata is provided.
+ Metadata map[string]string
+
+ // Generation is the generation number of the object's content.
+ // This field is read-only.
+ Generation int64
+
+ // Metageneration is the version of the metadata for this
+ // object at this generation. This field is used for preconditions
+ // and for detecting changes in metadata. A metageneration number
+ // is only meaningful in the context of a particular generation
+ // of a particular object. This field is read-only.
+ Metageneration int64
+
+ // StorageClass is the storage class of the object.
+ // This value defines how objects in the bucket are stored and
+ // determines the SLA and the cost of storage. Typical values are
+ // "MULTI_REGIONAL", "REGIONAL", "NEARLINE", "COLDLINE", "STANDARD"
+ // and "DURABLE_REDUCED_AVAILABILITY".
+ // It defaults to "STANDARD", which is equivalent to "MULTI_REGIONAL"
+ // or "REGIONAL" depending on the bucket's location settings.
+ StorageClass string
+
+ // Created is the time the object was created. This field is read-only.
+ Created time.Time
+
+ // Deleted is the time the object was deleted.
+ // If not deleted, it is the zero value. This field is read-only.
+ Deleted time.Time
+
+ // Updated is the creation or modification time of the object.
+ // For buckets with versioning enabled, changing an object's
+ // metadata does not change this property. This field is read-only.
+ Updated time.Time
+
+ // CustomerKeySHA256 is the base64-encoded SHA-256 hash of the
+ // customer-supplied encryption key for the object. It is empty if there is
+ // no customer-supplied encryption key.
+ // See // https://cloud.google.com/storage/docs/encryption for more about
+ // encryption in Google Cloud Storage.
+ CustomerKeySHA256 string
+
+ // Cloud KMS key name, in the form
+ // projects/P/locations/L/keyRings/R/cryptoKeys/K, used to encrypt this object,
+ // if the object is encrypted by such a key.
+ //
+ // Providing both a KMSKeyName and a customer-supplied encryption key (via
+ // ObjectHandle.Key) will result in an error when writing an object.
+ KMSKeyName string
+
+ // Prefix is set only for ObjectAttrs which represent synthetic "directory
+ // entries" when iterating over buckets using Query.Delimiter. See
+ // ObjectIterator.Next. When set, no other fields in ObjectAttrs will be
+ // populated.
+ Prefix string
+}
+
+// convertTime converts a time in RFC3339 format to time.Time.
+// If any error occurs in parsing, the zero-value time.Time is silently returned.
+func convertTime(t string) time.Time {
+ var r time.Time
+ if t != "" {
+ r, _ = time.Parse(time.RFC3339, t)
+ }
+ return r
+}
+
+func newObject(o *raw.Object) *ObjectAttrs {
+ if o == nil {
+ return nil
+ }
+ owner := ""
+ if o.Owner != nil {
+ owner = o.Owner.Entity
+ }
+ md5, _ := base64.StdEncoding.DecodeString(o.Md5Hash)
+ crc32c, _ := decodeUint32(o.Crc32c)
+ var sha256 string
+ if o.CustomerEncryption != nil {
+ sha256 = o.CustomerEncryption.KeySha256
+ }
+ return &ObjectAttrs{
+ Bucket: o.Bucket,
+ Name: o.Name,
+ ContentType: o.ContentType,
+ ContentLanguage: o.ContentLanguage,
+ CacheControl: o.CacheControl,
+ EventBasedHold: o.EventBasedHold,
+ TemporaryHold: o.TemporaryHold,
+ RetentionExpirationTime: convertTime(o.RetentionExpirationTime),
+ ACL: toObjectACLRules(o.Acl),
+ Owner: owner,
+ ContentEncoding: o.ContentEncoding,
+ ContentDisposition: o.ContentDisposition,
+ Size: int64(o.Size),
+ MD5: md5,
+ CRC32C: crc32c,
+ MediaLink: o.MediaLink,
+ Metadata: o.Metadata,
+ Generation: o.Generation,
+ Metageneration: o.Metageneration,
+ StorageClass: o.StorageClass,
+ CustomerKeySHA256: sha256,
+ KMSKeyName: o.KmsKeyName,
+ Created: convertTime(o.TimeCreated),
+ Deleted: convertTime(o.TimeDeleted),
+ Updated: convertTime(o.Updated),
+ }
+}
+
+// Decode a uint32 encoded in Base64 in big-endian byte order.
+func decodeUint32(b64 string) (uint32, error) {
+ d, err := base64.StdEncoding.DecodeString(b64)
+ if err != nil {
+ return 0, err
+ }
+ if len(d) != 4 {
+ return 0, fmt.Errorf("storage: %q does not encode a 32-bit value", d)
+ }
+ return uint32(d[0])<<24 + uint32(d[1])<<16 + uint32(d[2])<<8 + uint32(d[3]), nil
+}
+
+// Encode a uint32 as Base64 in big-endian byte order.
+func encodeUint32(u uint32) string {
+ b := []byte{byte(u >> 24), byte(u >> 16), byte(u >> 8), byte(u)}
+ return base64.StdEncoding.EncodeToString(b)
+}
+
+// Query represents a query to filter objects from a bucket.
+type Query struct {
+ // Delimiter returns results in a directory-like fashion.
+ // Results will contain only objects whose names, aside from the
+ // prefix, do not contain delimiter. Objects whose names,
+ // aside from the prefix, contain delimiter will have their name,
+ // truncated after the delimiter, returned in prefixes.
+ // Duplicate prefixes are omitted.
+ // Optional.
+ Delimiter string
+
+ // Prefix is the prefix filter to query objects
+ // whose names begin with this prefix.
+ // Optional.
+ Prefix string
+
+ // Versions indicates whether multiple versions of the same
+ // object will be included in the results.
+ Versions bool
+}
+
+// contentTyper implements ContentTyper to enable an
+// io.ReadCloser to specify its MIME type.
+type contentTyper struct {
+ io.Reader
+ t string
+}
+
+func (c *contentTyper) ContentType() string {
+ return c.t
+}
+
+// Conditions constrain methods to act on specific generations of
+// objects.
+//
+// The zero value is an empty set of constraints. Not all conditions or
+// combinations of conditions are applicable to all methods.
+// See https://cloud.google.com/storage/docs/generations-preconditions
+// for details on how these operate.
+type Conditions struct {
+ // Generation constraints.
+ // At most one of the following can be set to a non-zero value.
+
+ // GenerationMatch specifies that the object must have the given generation
+ // for the operation to occur.
+ // If GenerationMatch is zero, it has no effect.
+ // Use DoesNotExist to specify that the object does not exist in the bucket.
+ GenerationMatch int64
+
+ // GenerationNotMatch specifies that the object must not have the given
+ // generation for the operation to occur.
+ // If GenerationNotMatch is zero, it has no effect.
+ GenerationNotMatch int64
+
+ // DoesNotExist specifies that the object must not exist in the bucket for
+ // the operation to occur.
+ // If DoesNotExist is false, it has no effect.
+ DoesNotExist bool
+
+ // Metadata generation constraints.
+ // At most one of the following can be set to a non-zero value.
+
+ // MetagenerationMatch specifies that the object must have the given
+ // metageneration for the operation to occur.
+ // If MetagenerationMatch is zero, it has no effect.
+ MetagenerationMatch int64
+
+ // MetagenerationNotMatch specifies that the object must not have the given
+ // metageneration for the operation to occur.
+ // If MetagenerationNotMatch is zero, it has no effect.
+ MetagenerationNotMatch int64
+}
+
+func (c *Conditions) validate(method string) error {
+ if *c == (Conditions{}) {
+ return fmt.Errorf("storage: %s: empty conditions", method)
+ }
+ if !c.isGenerationValid() {
+ return fmt.Errorf("storage: %s: multiple conditions specified for generation", method)
+ }
+ if !c.isMetagenerationValid() {
+ return fmt.Errorf("storage: %s: multiple conditions specified for metageneration", method)
+ }
+ return nil
+}
+
+func (c *Conditions) isGenerationValid() bool {
+ n := 0
+ if c.GenerationMatch != 0 {
+ n++
+ }
+ if c.GenerationNotMatch != 0 {
+ n++
+ }
+ if c.DoesNotExist {
+ n++
+ }
+ return n <= 1
+}
+
+func (c *Conditions) isMetagenerationValid() bool {
+ return c.MetagenerationMatch == 0 || c.MetagenerationNotMatch == 0
+}
+
+// applyConds modifies the provided call using the conditions in conds.
+// call is something that quacks like a *raw.WhateverCall.
+func applyConds(method string, gen int64, conds *Conditions, call interface{}) error {
+ cval := reflect.ValueOf(call)
+ if gen >= 0 {
+ if !setConditionField(cval, "Generation", gen) {
+ return fmt.Errorf("storage: %s: generation not supported", method)
+ }
+ }
+ if conds == nil {
+ return nil
+ }
+ if err := conds.validate(method); err != nil {
+ return err
+ }
+ switch {
+ case conds.GenerationMatch != 0:
+ if !setConditionField(cval, "IfGenerationMatch", conds.GenerationMatch) {
+ return fmt.Errorf("storage: %s: ifGenerationMatch not supported", method)
+ }
+ case conds.GenerationNotMatch != 0:
+ if !setConditionField(cval, "IfGenerationNotMatch", conds.GenerationNotMatch) {
+ return fmt.Errorf("storage: %s: ifGenerationNotMatch not supported", method)
+ }
+ case conds.DoesNotExist:
+ if !setConditionField(cval, "IfGenerationMatch", int64(0)) {
+ return fmt.Errorf("storage: %s: DoesNotExist not supported", method)
+ }
+ }
+ switch {
+ case conds.MetagenerationMatch != 0:
+ if !setConditionField(cval, "IfMetagenerationMatch", conds.MetagenerationMatch) {
+ return fmt.Errorf("storage: %s: ifMetagenerationMatch not supported", method)
+ }
+ case conds.MetagenerationNotMatch != 0:
+ if !setConditionField(cval, "IfMetagenerationNotMatch", conds.MetagenerationNotMatch) {
+ return fmt.Errorf("storage: %s: ifMetagenerationNotMatch not supported", method)
+ }
+ }
+ return nil
+}
+
+func applySourceConds(gen int64, conds *Conditions, call *raw.ObjectsRewriteCall) error {
+ if gen >= 0 {
+ call.SourceGeneration(gen)
+ }
+ if conds == nil {
+ return nil
+ }
+ if err := conds.validate("CopyTo source"); err != nil {
+ return err
+ }
+ switch {
+ case conds.GenerationMatch != 0:
+ call.IfSourceGenerationMatch(conds.GenerationMatch)
+ case conds.GenerationNotMatch != 0:
+ call.IfSourceGenerationNotMatch(conds.GenerationNotMatch)
+ case conds.DoesNotExist:
+ call.IfSourceGenerationMatch(0)
+ }
+ switch {
+ case conds.MetagenerationMatch != 0:
+ call.IfSourceMetagenerationMatch(conds.MetagenerationMatch)
+ case conds.MetagenerationNotMatch != 0:
+ call.IfSourceMetagenerationNotMatch(conds.MetagenerationNotMatch)
+ }
+ return nil
+}
+
+// setConditionField sets a field on a *raw.WhateverCall.
+// We can't use anonymous interfaces because the return type is
+// different, since the field setters are builders.
+func setConditionField(call reflect.Value, name string, value interface{}) bool {
+ m := call.MethodByName(name)
+ if !m.IsValid() {
+ return false
+ }
+ m.Call([]reflect.Value{reflect.ValueOf(value)})
+ return true
+}
+
+// conditionsQuery returns the generation and conditions as a URL query
+// string suitable for URL.RawQuery. It assumes that the conditions
+// have been validated.
+func conditionsQuery(gen int64, conds *Conditions) string {
+ // URL escapes are elided because integer strings are URL-safe.
+ var buf []byte
+
+ appendParam := func(s string, n int64) {
+ if len(buf) > 0 {
+ buf = append(buf, '&')
+ }
+ buf = append(buf, s...)
+ buf = strconv.AppendInt(buf, n, 10)
+ }
+
+ if gen >= 0 {
+ appendParam("generation=", gen)
+ }
+ if conds == nil {
+ return string(buf)
+ }
+ switch {
+ case conds.GenerationMatch != 0:
+ appendParam("ifGenerationMatch=", conds.GenerationMatch)
+ case conds.GenerationNotMatch != 0:
+ appendParam("ifGenerationNotMatch=", conds.GenerationNotMatch)
+ case conds.DoesNotExist:
+ appendParam("ifGenerationMatch=", 0)
+ }
+ switch {
+ case conds.MetagenerationMatch != 0:
+ appendParam("ifMetagenerationMatch=", conds.MetagenerationMatch)
+ case conds.MetagenerationNotMatch != 0:
+ appendParam("ifMetagenerationNotMatch=", conds.MetagenerationNotMatch)
+ }
+ return string(buf)
+}
+
+// composeSourceObj wraps a *raw.ComposeRequestSourceObjects, but adds the methods
+// that modifyCall searches for by name.
+type composeSourceObj struct {
+ src *raw.ComposeRequestSourceObjects
+}
+
+func (c composeSourceObj) Generation(gen int64) {
+ c.src.Generation = gen
+}
+
+func (c composeSourceObj) IfGenerationMatch(gen int64) {
+ // It's safe to overwrite ObjectPreconditions, since its only field is
+ // IfGenerationMatch.
+ c.src.ObjectPreconditions = &raw.ComposeRequestSourceObjectsObjectPreconditions{
+ IfGenerationMatch: gen,
+ }
+}
+
+func setEncryptionHeaders(headers http.Header, key []byte, copySource bool) error {
+ if key == nil {
+ return nil
+ }
+ // TODO(jbd): Ask the API team to return a more user-friendly error
+ // and avoid doing this check at the client level.
+ if len(key) != 32 {
+ return errors.New("storage: not a 32-byte AES-256 key")
+ }
+ var cs string
+ if copySource {
+ cs = "copy-source-"
+ }
+ headers.Set("x-goog-"+cs+"encryption-algorithm", "AES256")
+ headers.Set("x-goog-"+cs+"encryption-key", base64.StdEncoding.EncodeToString(key))
+ keyHash := sha256.Sum256(key)
+ headers.Set("x-goog-"+cs+"encryption-key-sha256", base64.StdEncoding.EncodeToString(keyHash[:]))
+ return nil
+}
+
+// ServiceAccount fetches the email address of the given project's Google Cloud Storage service account.
+func (c *Client) ServiceAccount(ctx context.Context, projectID string) (string, error) {
+ r := c.raw.Projects.ServiceAccount.Get(projectID)
+ res, err := r.Context(ctx).Do()
+ if err != nil {
+ return "", err
+ }
+ return res.EmailAddress, nil
+}
diff --git a/vendor/cloud.google.com/go/storage/storage.replay b/vendor/cloud.google.com/go/storage/storage.replay
new file mode 100644
index 000000000..079b162e0
--- /dev/null
+++ b/vendor/cloud.google.com/go/storage/storage.replay
@@ -0,0 +1,53540 @@
+{
+ "Initial": "IjIwMTgtMDktMjdUMTI6MjM6NTAuOTExODYzNjRaIg==",
+ "Version": "0.1",
+ "Entries": [
+ {
+ "ID": "4a867507b0f3dbee",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/storage/v1/b?alt=json\u0026prettyPrint=false\u0026project=dulcet-port-762",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "60"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "324cf8b8639b6b4631e5c4cafd0e2c16/986732864287226636;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b?alt=json\u0026prettyPrint=false\u0026project=dulcet-port-762"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJuYW1lIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIn0K"
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "426"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:23:52 GMT"
+ ],
+ "Etag": [
+ "CAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051331000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrdk3:4341,/bns/yr/borg/yr/bns/blobstore2/bitpusher/44.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=18usW9v6OMTvkAPC4IGgCQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/44.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/44:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWUNKdzJzd0Q5dnlBOGFHdHN2YzZ3MzJpem1SRXNRUWZaZl94RkpWbU84VFRyeEJfc2ZaRkZsdjBhUlRLZC1zLWtJc2pLcWd6ZGVJejkwZGMtUFlSVFZQVTdrTkNJbHllUmVhSlRldU9sb1YyWl94aFdFQkoxNGN2VHhyZDl4Uk03RFViN0tra09hd1NlVkdqLWU0V2FZU0ZOTW16U1dDS3NSZUtDTUhaRDFEc1g3djM3RmZGMmw1RXcwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UpcHZthlQWJ5OdoRGpk5Js3AAogojVNWvlmo_v3oIqaVxRiH0Y5STeX-fVrzNltY06kjYMaSo3O9iTiJWw3AvtVVLy8UA"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjM6NTIuMzU1WiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjIzOjUyLjM1NVoiLCJtZXRhZ2VuZXJhdGlvbiI6IjEiLCJsb2NhdGlvbiI6IlVTIiwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJldGFnIjoiQ0FFPSJ9"
+ }
+ },
+ {
+ "ID": "ba85864b53e935df",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/storage/v1/b?alt=json\u0026prettyPrint=false\u0026project=dulcet-port-762",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "60"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "cbd945887a7e22a66506ae96bde01c15/4926593637547890840;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b?alt=json\u0026prettyPrint=false\u0026project=dulcet-port-762"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJuYW1lIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAyIn0K"
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "426"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:23:53 GMT"
+ ],
+ "Etag": [
+ "CAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051332000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrc82:4164,/bns/yw/borg/yw/bns/blobstore2/bitpusher/49.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=2MusW73YLMOwhgT23rH4CQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yw/borg/yw/bns/blobstore2/bitpusher/49.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yw/borg/yw/bns/blobstore2/bitpusher/49:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRYkFaSE11YVZ6S2lnNDcyVW5lcUNPRzBMMmlCekJVY0NGaTB1c3o4ekE0Uk5kQ1A5aW1wbE1vcTcyVlQzLUJlVlhUaU9Mb0F0VURYRHpwb0lYZkpMMjVTZzFYTk9KZ1dJbV9QNHlaV0pGY1hHNFMxeGxnbDlmMkpXRkRUbjFfLTdweHFYNGJudndGM0JXTzZ5Y1ROdWtqX3NqS29kanRJMW9HQTBnbmVTM0RaMF9HX1B0bWpmSFlYanMwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UoGCVnjOfC9cVkP546g8csLoUI7KRTsrnTDPV2wpbnLpOKwP6qKGpLkqkFg0Vp1ez-KuxdvHzgxloaoqFZ3GjWVzOYtZA"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMiIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMiIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDIiLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjM6NTMuMTYyWiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjIzOjUzLjE2MloiLCJtZXRhZ2VuZXJhdGlvbiI6IjEiLCJsb2NhdGlvbiI6IlVTIiwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJldGFnIjoiQ0FFPSJ9"
+ }
+ },
+ {
+ "ID": "486bc9edab67455b",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0002?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "336221695c86fb5324eaf6a7d4e2082c/6516722971421670967;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0002?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0, must-revalidate, no-transform"
+ ],
+ "Content-Length": [
+ "2353"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:23:53 GMT"
+ ],
+ "Etag": [
+ "CAE="
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:23:53 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051333000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrqe25:4313,/bns/yr/borg/yr/bns/blobstore2/bitpusher/9.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=2cusW4yhGLLm4QS0iZ9I"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/9.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/9:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRYkFaSE11YVZ6S2lnNDcyVW5lcUNPRzBMMmlCekJVY0NGaTB1c3o4ekE0Uk5kQ1A5aW1wbE1vcTcyVlQzLUJlVlhUaU9Mb0F0VURYRHpwb0lYZkpMMjVTZzFYTk9KZ1dJbV9QNHlaV0pGY1hHNFMxeGxnbDlmMkpXRkRUbjFfLTdweHFYNGJudndGM0JXTzZ5Y1ROdWtqX3NqS29kanRJMW9HQTBnbmVTM0RaMF9HX1B0bWpmSFlYanMwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UqvlMRQ1xVQ4ay63D5G54td8G9spIJDhN4kzGHZvTEW8sdjRs4_h5P6FVP_xUKNsLv38Rt6frdE6DohTYKJzwvZ78xSdQ"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMiIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMiIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDIiLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjM6NTMuMTYyWiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjIzOjUzLjE2MloiLCJtZXRhZ2VuZXJhdGlvbiI6IjEiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMi9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMi9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDIiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMi9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDIvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMiIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDQUU9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDIvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAyL2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDIiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNBRT0ifV0sImRlZmF1bHRPYmplY3RBY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0FFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0FFPSJ9XSwib3duZXIiOnsiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUifSwibG9jYXRpb24iOiJVUyIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwiZXRhZyI6IkNBRT0ifQ=="
+ }
+ },
+ {
+ "ID": "18c04b894e7914ca",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0002?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "99cc7479d127b305fe0a7955f514551c/8107134871193920470;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0002?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 204,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "0"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:23:54 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051332000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrjm12:4359,/bns/yv/borg/yv/bns/blobstore2/bitpusher/250.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=2cusW_-dM9X8gQS2j5UY"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/250.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/250:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRYkFaSE11YVZ6S2lnNDcyVW5lcUNPRzBMMmlCekJVY0NGaTB1c3o4ekE0Uk5kQ1A5aW1wbE1vcTcyVlQzLUJlVlhUaU9Mb0F0VURYRHpwb0lYZkpMMjVTZzFYTk9KZ1dJbV9QNHlaV0pGY1hHNFMxeGxnbDlmMkpXRkRUbjFfLTdweHFYNGJudndGM0JXTzZ5Y1ROdWtqX3NqS29kanRJMW9HQTBnbmVTM0RaMF9HX1B0bWpmSFlYanMwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Upwbe_KfHSmvQWFmYWTIHi1QxfU6aaP320Hi2YakvoHiu9eV6n6yebxLDKyLyKL6GKAaXGv1GJpYo-cx8S2qNo8kqpI0Q"
+ ]
+ },
+ "Body": ""
+ }
+ },
+ {
+ "ID": "3f65476279d8f2a4",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/storage/v1/b?alt=json\u0026prettyPrint=false\u0026project=dulcet-port-762",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "543"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "811fa6ca0d68c12f4f50698dff145469/9697546775244360052;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b?alt=json\u0026prettyPrint=false\u0026project=dulcet-port-762"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJsYWJlbHMiOnsiZW1wdHkiOiIiLCJsMSI6InYxIn0sImxpZmVjeWNsZSI6eyJydWxlIjpbeyJhY3Rpb24iOnsic3RvcmFnZUNsYXNzIjoiTkVBUkxJTkUiLCJ0eXBlIjoiU2V0U3RvcmFnZUNsYXNzIn0sImNvbmRpdGlvbiI6eyJhZ2UiOjEwLCJjcmVhdGVkQmVmb3JlIjoiMjAxNy0wMS0wMSIsImlzTGl2ZSI6ZmFsc2UsIm1hdGNoZXNTdG9yYWdlQ2xhc3MiOlsiTVVMVElfUkVHSU9OQUwiLCJTVEFOREFSRCJdLCJudW1OZXdlclZlcnNpb25zIjozfX0seyJhY3Rpb24iOnsidHlwZSI6IkRlbGV0ZSJ9LCJjb25kaXRpb24iOnsiYWdlIjozMCwiY3JlYXRlZEJlZm9yZSI6IjIwMTctMDEtMDEiLCJpc0xpdmUiOnRydWUsIm1hdGNoZXNTdG9yYWdlQ2xhc3MiOlsiTkVBUkxJTkUiXSwibnVtTmV3ZXJWZXJzaW9ucyI6MTB9fV19LCJsb2NhdGlvbiI6IlVTIiwibmFtZSI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMiIsInN0b3JhZ2VDbGFzcyI6Ik5FQVJMSU5FIiwidmVyc2lvbmluZyI6eyJlbmFibGVkIjp0cnVlfX0K"
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "867"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:23:54 GMT"
+ ],
+ "Etag": [
+ "CAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051332000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrak11:4291,/bns/yw/borg/yw/bns/blobstore2/bitpusher/50.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=2susW6jMDsHAhATs75PIDA"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yw/borg/yw/bns/blobstore2/bitpusher/50.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yw/borg/yw/bns/blobstore2/bitpusher/50:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRYkFaSE11YVZ6S2lnNDcyVW5lcUNPRzBMMmlCekJVY0NGaTB1c3o4ekE0Uk5kQ1A5aW1wbE1vcTcyVlQzLUJlVlhUaU9Mb0F0VURYRHpwb0lYZkpMMjVTZzFYTk9KZ1dJbV9QNHlaV0pGY1hHNFMxeGxnbDlmMkpXRkRUbjFfLTdweHFYNGJudndGM0JXTzZ5Y1ROdWtqX3NqS29kanRJMW9HQTBnbmVTM0RaMF9HX1B0bWpmSFlYanMwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UrCe3wG3NZcYEUACuZktBQLRW8Eg5sflTKX7uRVrmzCJuksbsdtl6DtdqUJwPAyaemH-HkA-RDCjA0STJNKBXwv1k1w6w"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMiIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMiIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDIiLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjM6NTQuNjY2WiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjIzOjU0LjY2NloiLCJtZXRhZ2VuZXJhdGlvbiI6IjEiLCJsb2NhdGlvbiI6IlVTIiwidmVyc2lvbmluZyI6eyJlbmFibGVkIjp0cnVlfSwibGlmZWN5Y2xlIjp7InJ1bGUiOlt7ImFjdGlvbiI6eyJ0eXBlIjoiU2V0U3RvcmFnZUNsYXNzIiwic3RvcmFnZUNsYXNzIjoiTkVBUkxJTkUifSwiY29uZGl0aW9uIjp7ImFnZSI6MTAsImNyZWF0ZWRCZWZvcmUiOiIyMDE3LTAxLTAxIiwiaXNMaXZlIjpmYWxzZSwibWF0Y2hlc1N0b3JhZ2VDbGFzcyI6WyJNVUxUSV9SRUdJT05BTCIsIlNUQU5EQVJEIl0sIm51bU5ld2VyVmVyc2lvbnMiOjN9fSx7ImFjdGlvbiI6eyJ0eXBlIjoiRGVsZXRlIn0sImNvbmRpdGlvbiI6eyJhZ2UiOjMwLCJjcmVhdGVkQmVmb3JlIjoiMjAxNy0wMS0wMSIsImlzTGl2ZSI6dHJ1ZSwibWF0Y2hlc1N0b3JhZ2VDbGFzcyI6WyJORUFSTElORSJdLCJudW1OZXdlclZlcnNpb25zIjoxMH19XX0sImxhYmVscyI6eyJsMSI6InYxIiwiZW1wdHkiOiIifSwic3RvcmFnZUNsYXNzIjoiTkVBUkxJTkUiLCJldGFnIjoiQ0FFPSJ9"
+ }
+ },
+ {
+ "ID": "959d26ad1031b8fe",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0002?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "591e17a835f0e96a9eefadf22d09a1ee/11287958679311511059;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0002?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0, must-revalidate, no-transform"
+ ],
+ "Content-Length": [
+ "2794"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:23:55 GMT"
+ ],
+ "Etag": [
+ "CAE="
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:23:55 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051334000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vnss7:4006,/bns/yx/borg/yx/bns/blobstore2/bitpusher/121.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=2susW6OUNMuRzgLBuZuAAQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yx/borg/yx/bns/blobstore2/bitpusher/121.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yx/borg/yx/bns/blobstore2/bitpusher/121:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRYkFaSE11YVZ6S2lnNDcyVW5lcUNPRzBMMmlCekJVY0NGaTB1c3o4ekE0Uk5kQ1A5aW1wbE1vcTcyVlQzLUJlVlhUaU9Mb0F0VURYRHpwb0lYZkpMMjVTZzFYTk9KZ1dJbV9QNHlaV0pGY1hHNFMxeGxnbDlmMkpXRkRUbjFfLTdweHFYNGJudndGM0JXTzZ5Y1ROdWtqX3NqS29kanRJMW9HQTBnbmVTM0RaMF9HX1B0bWpmSFlYanMwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UpesIKnG6nWNHsdZuWGkdrt7L_1eeDmsUHLIRTQMb_9EX567zcXF2uU50jLaVK4WZtH0ZO0rG2RWY-20o1Y3aJCImfm_w"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMiIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMiIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDIiLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjM6NTQuNjY2WiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjIzOjU0LjY2NloiLCJtZXRhZ2VuZXJhdGlvbiI6IjEiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMi9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMi9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDIiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMi9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDIvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMiIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDQUU9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDIvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAyL2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDIiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNBRT0ifV0sImRlZmF1bHRPYmplY3RBY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0FFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0FFPSJ9XSwib3duZXIiOnsiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUifSwibG9jYXRpb24iOiJVUyIsInZlcnNpb25pbmciOnsiZW5hYmxlZCI6dHJ1ZX0sImxpZmVjeWNsZSI6eyJydWxlIjpbeyJhY3Rpb24iOnsidHlwZSI6IlNldFN0b3JhZ2VDbGFzcyIsInN0b3JhZ2VDbGFzcyI6Ik5FQVJMSU5FIn0sImNvbmRpdGlvbiI6eyJhZ2UiOjEwLCJjcmVhdGVkQmVmb3JlIjoiMjAxNy0wMS0wMSIsImlzTGl2ZSI6ZmFsc2UsIm1hdGNoZXNTdG9yYWdlQ2xhc3MiOlsiTVVMVElfUkVHSU9OQUwiLCJTVEFOREFSRCJdLCJudW1OZXdlclZlcnNpb25zIjozfX0seyJhY3Rpb24iOnsidHlwZSI6IkRlbGV0ZSJ9LCJjb25kaXRpb24iOnsiYWdlIjozMCwiY3JlYXRlZEJlZm9yZSI6IjIwMTctMDEtMDEiLCJpc0xpdmUiOnRydWUsIm1hdGNoZXNTdG9yYWdlQ2xhc3MiOlsiTkVBUkxJTkUiXSwibnVtTmV3ZXJWZXJzaW9ucyI6MTB9fV19LCJsYWJlbHMiOnsibDEiOiJ2MSIsImVtcHR5IjoiIn0sInN0b3JhZ2VDbGFzcyI6Ik5FQVJMSU5FIiwiZXRhZyI6IkNBRT0ifQ=="
+ }
+ },
+ {
+ "ID": "5c5a9394a6df293c",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0002?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "5fc569e90e1807b37ae8b7e2261abfd9/12878089108385240242;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0002?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 204,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "0"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:23:55 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051332000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrgg80:4282,/bns/yr/borg/yr/bns/blobstore2/bitpusher/65.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=28usW7GPB4SGkASB5ob4BQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/65.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/65:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRYkFaSE11YVZ6S2lnNDcyVW5lcUNPRzBMMmlCekJVY0NGaTB1c3o4ekE0Uk5kQ1A5aW1wbE1vcTcyVlQzLUJlVlhUaU9Mb0F0VURYRHpwb0lYZkpMMjVTZzFYTk9KZ1dJbV9QNHlaV0pGY1hHNFMxeGxnbDlmMkpXRkRUbjFfLTdweHFYNGJudndGM0JXTzZ5Y1ROdWtqX3NqS29kanRJMW9HQTBnbmVTM0RaMF9HX1B0bWpmSFlYanMwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UpCJff1tEGhyDbHTx3PppR8ezK_fjgJCuPocttNzHKB98UqFv38y6-CrTard9dk51CY0fizSV9S8XaEMBMpevmhBShQSQ"
+ ]
+ },
+ "Body": ""
+ }
+ },
+ {
+ "ID": "e4ab887b5dddc69b",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "8715d6d92b86b13e7fba448ddf7d3604/14468499912957606224;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0, must-revalidate, no-transform"
+ ],
+ "Content-Length": [
+ "2353"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:23:55 GMT"
+ ],
+ "Etag": [
+ "CAE="
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:23:55 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051335000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrv189:4445,/bns/yv/borg/yv/bns/blobstore2/bitpusher/374.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=28usW47vJY3yggSq27_4CQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/374.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/374:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRYkJ1dHF6dE1zd2lVYzFqbFhQblk4Zk1vWTU0dzJzYmZicXh1bEFiRjdFVkZTVWFCY3liY3hyY1RmRXFuX0tCOTYxZ2pONXJrYzFseHJtUGV1YnZMY2JQUVlrYjA4bnFVOGN5UVE0VDlGdy1UdTNSV2dhbWdnVDU3bl80YnpwWDU3ZjZycDJ0ejcyWXgxQnc5c2ppQmtOWlJIcGhMbEpuRHFKRC1IaXF4RllzUWpld3Ewc3RiWDRzQ2MwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Upt9LBuQWdif5NPssRtVxoi9j0KQELZ1rCKjIN56roTgjIH7mZ0A1ZHDuPB6c4XdqIgoZprVYGMT7pFQEGD08luMOkKlw"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjM6NTIuMzU1WiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjIzOjUyLjM1NVoiLCJtZXRhZ2VuZXJhdGlvbiI6IjEiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDQUU9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNBRT0ifV0sImRlZmF1bHRPYmplY3RBY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0FFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0FFPSJ9XSwib3duZXIiOnsiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUifSwibG9jYXRpb24iOiJVUyIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwiZXRhZyI6IkNBRT0ifQ=="
+ }
+ },
+ {
+ "ID": "9fe8f52448faf49d",
+ "Request": {
+ "Method": "PATCH",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "3"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "ebc497d92bd029c51a5c96b957211d37/16058911817007980527;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "e30K"
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "2353"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:23:57 GMT"
+ ],
+ "Etag": [
+ "CAI="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051336000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrbq123:4158,/bns/yw/borg/yw/bns/blobstore2/bitpusher/161.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=28usW7OEOI-2N_7Un8gF"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yw/borg/yw/bns/blobstore2/bitpusher/161.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yw/borg/yw/bns/blobstore2/bitpusher/161:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATpxChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4CtK4wESxgF5YTI5LmMuRW93QkpRYkJ1dHF6dE1zd2lVYzFqbFhQblk4Zk1vWTU0dzJzYmZicXh1bEFiRjdFVkZTVWFCY3liY3hyY1RmRXFuX0tCOTYxZ2pONXJrYzFseHJtUGV1YnZMY2JQUVlrYjA4bnFVOGN5UVE0VDlGdy1UdTNSV2dhbWdnVDU3bl80YnpwWDU3ZjZycDJ0ejcyWXgxQnc5c2ppQmtOWlJIcGhMbEpuRHFKRC1IaXF4RllzUWpld3Ewc3RiWDRzQ2MwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UqOH7YWz4uHeB7Zu_HYqn6JkWYP_j5bSoYFsj7yER0-RUIcDaA3Bv3eYs-dj8feSewfT-dR1pQWwMV8yE_E_oap5YU9zw"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjM6NTIuMzU1WiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjIzOjU3LjQyN1oiLCJtZXRhZ2VuZXJhdGlvbiI6IjIiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBST0ifSx7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDQUk9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNBST0ifV0sImRlZmF1bHRPYmplY3RBY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBST0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0FJPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0FJPSJ9XSwib3duZXIiOnsiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUifSwibG9jYXRpb24iOiJVUyIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwiZXRhZyI6IkNBST0ifQ=="
+ }
+ },
+ {
+ "ID": "44db27d29c1e0abe",
+ "Request": {
+ "Method": "PATCH",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "64"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "8c93187dec5f14a9c6a2260dfd519d5d/17649323716780229774;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJsYWJlbHMiOnsiZW1wdHkiOiIiLCJsMSI6InYxIn0sInZlcnNpb25pbmciOnsiZW5hYmxlZCI6dHJ1ZX19Cg=="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "2415"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:23:58 GMT"
+ ],
+ "Etag": [
+ "CAM="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051336000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrmm26:4177,/bns/yv/borg/yv/bns/blobstore2/bitpusher/211.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=3cusW9DxJsfWgwSThbvoBw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/211.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/211:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATpxChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4CtK4wESxgF5YTI5LmMuRW93QkpRYkJ1dHF6dE1zd2lVYzFqbFhQblk4Zk1vWTU0dzJzYmZicXh1bEFiRjdFVkZTVWFCY3liY3hyY1RmRXFuX0tCOTYxZ2pONXJrYzFseHJtUGV1YnZMY2JQUVlrYjA4bnFVOGN5UVE0VDlGdy1UdTNSV2dhbWdnVDU3bl80YnpwWDU3ZjZycDJ0ejcyWXgxQnc5c2ppQmtOWlJIcGhMbEpuRHFKRC1IaXF4RllzUWpld3Ewc3RiWDRzQ2MwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Upvu77QBhzvRw1piNR-X93WTmdCSybBSWbAm_HIAco5vSyg0E3M69iewocziGyHJBL7GVmnNIcGAeyxETWYUuRlS2z5TQ"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjM6NTIuMzU1WiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjIzOjU4LjcyM1oiLCJtZXRhZ2VuZXJhdGlvbiI6IjMiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBTT0ifSx7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDQU09In0seyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNBTT0ifV0sImRlZmF1bHRPYmplY3RBY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBTT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0FNPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0FNPSJ9XSwib3duZXIiOnsiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUifSwibG9jYXRpb24iOiJVUyIsInZlcnNpb25pbmciOnsiZW5hYmxlZCI6dHJ1ZX0sImxhYmVscyI6eyJlbXB0eSI6IiIsImwxIjoidjEifSwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJldGFnIjoiQ0FNPSJ9"
+ }
+ },
+ {
+ "ID": "f51861aaca48496f",
+ "Request": {
+ "Method": "PATCH",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "93"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "06ae89cc69c52d58c7caa6672fbf6225/720935056889784876;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJsYWJlbHMiOnsiYWJzZW50IjpudWxsLCJlbXB0eSI6bnVsbCwibDEiOiJ2MiIsIm5ldyI6Im5ldyJ9LCJ2ZXJzaW9uaW5nIjp7ImVuYWJsZWQiOmZhbHNlfX0K"
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "2417"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:00 GMT"
+ ],
+ "Etag": [
+ "CAQ="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051336000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrpw19:4348,/bns/yw/borg/yw/bns/blobstore2/bitpusher/40.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=3susW7z_OIvFhgSUoLf4Ag"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yw/borg/yw/bns/blobstore2/bitpusher/40.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yw/borg/yw/bns/blobstore2/bitpusher/40:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATpxChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4CtK4wESxgF5YTI5LmMuRW93QkpRYkJ1dHF6dE1zd2lVYzFqbFhQblk4Zk1vWTU0dzJzYmZicXh1bEFiRjdFVkZTVWFCY3liY3hyY1RmRXFuX0tCOTYxZ2pONXJrYzFseHJtUGV1YnZMY2JQUVlrYjA4bnFVOGN5UVE0VDlGdy1UdTNSV2dhbWdnVDU3bl80YnpwWDU3ZjZycDJ0ejcyWXgxQnc5c2ppQmtOWlJIcGhMbEpuRHFKRC1IaXF4RllzUWpld3Ewc3RiWDRzQ2MwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UqjrhFVd9uFgXPlY_Y-sPlqWx_zSWqwKmIwnXnWUQ02LsnvtCgpyuv71-now-QWBq_fdOf_GVkWzaBEje5_8W2gQliO-Q"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjM6NTIuMzU1WiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjAwLjMyMloiLCJtZXRhZ2VuZXJhdGlvbiI6IjQiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBUT0ifSx7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDQVE9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNBUT0ifV0sImRlZmF1bHRPYmplY3RBY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBUT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0FRPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0FRPSJ9XSwib3duZXIiOnsiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUifSwibG9jYXRpb24iOiJVUyIsInZlcnNpb25pbmciOnsiZW5hYmxlZCI6ZmFsc2V9LCJsYWJlbHMiOnsibDEiOiJ2MiIsIm5ldyI6Im5ldyJ9LCJzdG9yYWdlQ2xhc3MiOiJTVEFOREFSRCIsImV0YWciOiJDQVE9In0="
+ }
+ },
+ {
+ "ID": "b64b55060955d79c",
+ "Request": {
+ "Method": "PATCH",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "77"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "303b222cd26f932b6132314f2ae7055e/2311346960956936139;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJsaWZlY3ljbGUiOnsicnVsZSI6W3siYWN0aW9uIjp7InR5cGUiOiJEZWxldGUifSwiY29uZGl0aW9uIjp7ImFnZSI6MzB9fV19fQo="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "2492"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:02 GMT"
+ ],
+ "Etag": [
+ "CAU="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051336000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrjp9:4258,/bns/yv/borg/yv/bns/blobstore2/bitpusher/58.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=4MusW77VIJOOgQTGxbr4Cg"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/58.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/58:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATpxChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4CtK4wESxgF5YTI5LmMuRW93QkpRYkJ1dHF6dE1zd2lVYzFqbFhQblk4Zk1vWTU0dzJzYmZicXh1bEFiRjdFVkZTVWFCY3liY3hyY1RmRXFuX0tCOTYxZ2pONXJrYzFseHJtUGV1YnZMY2JQUVlrYjA4bnFVOGN5UVE0VDlGdy1UdTNSV2dhbWdnVDU3bl80YnpwWDU3ZjZycDJ0ejcyWXgxQnc5c2ppQmtOWlJIcGhMbEpuRHFKRC1IaXF4RllzUWpld3Ewc3RiWDRzQ2MwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Uo-IbtKMtWZK12VIWm36H83fcYySjH7jSBOoH02cdECp8fasNymRIEHTBg4xzPYF2DtVWoKVAzpHVWxLGUvyVf3imyL8QGR-cuBgIoN4s32gE6AgY0"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjM6NTIuMzU1WiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjAyLjEyOVoiLCJtZXRhZ2VuZXJhdGlvbiI6IjUiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBVT0ifSx7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDQVU9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNBVT0ifV0sImRlZmF1bHRPYmplY3RBY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBVT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0FVPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0FVPSJ9XSwib3duZXIiOnsiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUifSwibG9jYXRpb24iOiJVUyIsInZlcnNpb25pbmciOnsiZW5hYmxlZCI6ZmFsc2V9LCJsaWZlY3ljbGUiOnsicnVsZSI6W3siYWN0aW9uIjp7InR5cGUiOiJEZWxldGUifSwiY29uZGl0aW9uIjp7ImFnZSI6MzB9fV19LCJsYWJlbHMiOnsibDEiOiJ2MiIsIm5ldyI6Im5ldyJ9LCJzdG9yYWdlQ2xhc3MiOiJTVEFOREFSRCIsImV0YWciOiJDQVU9In0="
+ }
+ },
+ {
+ "ID": "214ff250647b9b45",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Type": [
+ "multipart/related; boundary=ddc31edea4b16a31d614ee7de096bb732d74bb8c75462aad8a02b6dd0098"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "c63fd227fd0ef1001c1768b1dee0d0f7/3142440424904434202;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "LS1kZGMzMWVkZWE0YjE2YTMxZDYxNGVlN2RlMDk2YmI3MzJkNzRiYjhjNzU0NjJhYWQ4YTAyYjZkZDAwOTgNCkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vanNvbg0KDQp7ImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbiIsIm5hbWUiOiJjb25kZGVsIn0KDQotLWRkYzMxZWRlYTRiMTZhMzFkNjE0ZWU3ZGUwOTZiYjczMmQ3NGJiOGM3NTQ2MmFhZDhhMDJiNmRkMDA5OA0KQ29udGVudC1UeXBlOiB0ZXh0L3BsYWluDQoNCmZvbw0KLS1kZGMzMWVkZWE0YjE2YTMxZDYxNGVlN2RlMDk2YmI3MzJkNzRiYjhjNzU0NjJhYWQ4YTAyYjZkZDAwOTgtLQ0K"
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3254"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:02 GMT"
+ ],
+ "Etag": [
+ "CICps9CW290CEAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051342000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrlh82:4312,/bns/yv/borg/yv/bns/blobstore2/bitpusher/384.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=4susW5GSGtiiggSxqYa4Dw"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/384.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/384:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWXY2MTJyUVRiNE1ZWEtqdTZPQnktbmItdVBNRDJaTWRzU01HMFpSR3hiSUNwbUhWbXVFRlVEYjNkTURQUjc1OFJLMUtDNmEtZllTQWE5RWNYMXNaSlY3M0xWLXRnRmNOZFphckJMak9JSWRJRG5vSG4ySzcwTHpLdXhZNzBBSWU1TlFzU0F3WWIwLWU1WHlKZDk4WFlQLXBBT2tTVzBraFdXblVlZnpmYzExdWZUeHZnN2llS0hTWGswBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_single_post_uploads"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UqfAXKlaBbrgYFw53CCPGs3Fc_7Oyg0ltyrmvfu-XsEw3WBnui0YnKufuulHx-futBxiHniFMJLM6i2SHoPuvKFI2mmOQ"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jb25kZGVsLzE1MzgwNTEwNDI3NTk4MDgiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9jb25kZGVsIiwibmFtZSI6ImNvbmRkZWwiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0Mjc1OTgwOCIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbiIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDowMi43NThaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MDIuNzU4WiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjAyLjc1OFoiLCJzaXplIjoiMyIsIm1kNUhhc2giOiJyTDBZMjB6QytGenQ3MlZQek1TazJBPT0iLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vY29uZGRlbD9nZW5lcmF0aW9uPTE1MzgwNTEwNDI3NTk4MDgmYWx0PW1lZGlhIiwiYWNsIjpbeyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvY29uZGRlbC8xNTM4MDUxMDQyNzU5ODA4L3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vY29uZGRlbC9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJjb25kZGVsIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNDI3NTk4MDgiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNJQ3BzOUNXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jb25kZGVsLzE1MzgwNTEwNDI3NTk4MDgvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vY29uZGRlbC9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiY29uZGRlbCIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDQyNzU5ODA4IiwiZW50aXR5IjoicHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6ImVkaXRvcnMifSwiZXRhZyI6IkNJQ3BzOUNXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jb25kZGVsLzE1MzgwNTEwNDI3NTk4MDgvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vY29uZGRlbC9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiY29uZGRlbCIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDQyNzU5ODA4IiwiZW50aXR5IjoicHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6IlJFQURFUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJ2aWV3ZXJzIn0sImV0YWciOiJDSUNwczlDVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvY29uZGRlbC8xNTM4MDUxMDQyNzU5ODA4L3VzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9jb25kZGVsL2FjbC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiY29uZGRlbCIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDQyNzU5ODA4IiwiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInJvbGUiOiJPV05FUiIsImVtYWlsIjoiMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJldGFnIjoiQ0lDcHM5Q1cyOTBDRUFFPSJ9XSwib3duZXIiOnsiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSJ9LCJjcmMzMmMiOiJ6OFN1SFE9PSIsImV0YWciOiJDSUNwczlDVzI5MENFQUU9In0="
+ }
+ },
+ {
+ "ID": "6dbba13fcd47d71f",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/conddel?alt=json\u0026generation=1538051042759807\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "3b8bffeb25986a949f398d3644170d39/3901757765529302121;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/conddel?alt=json\u0026generation=1538051042759807\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 404,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0"
+ ],
+ "Content-Length": [
+ "12141"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:02 GMT"
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:24:02 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051342000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrcf20:4198,/bns/yr/borg/yr/bns/blobstore2/bitpusher/0.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=4susW6KXNsSxkATZ74bIAQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/0.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/0:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWXY2MTJyUVRiNE1ZWEtqdTZPQnktbmItdVBNRDJaTWRzU01HMFpSR3hiSUNwbUhWbXVFRlVEYjNkTURQUjc1OFJLMUtDNmEtZllTQWE5RWNYMXNaSlY3M0xWLXRnRmNOZFphckJMak9JSWRJRG5vSG4ySzcwTHpLdXhZNzBBSWU1TlFzU0F3WWIwLWU1WHlKZDk4WFlQLXBBT2tTVzBraFdXblVlZnpmYzExdWZUeHZnN2llS0hTWGswBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Upload-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UqwKNtC0lvvXvOJjHGNLri9TO3nTa-DXd6rZS0MXi720b899Swzs8NBB5krLGaiWnNU-xfLgFxZkpEx1KGeC5pOwR2jhg"
+ ]
+ },
+ "Body": "eyJlcnJvciI6eyJlcnJvcnMiOlt7ImRvbWFpbiI6Imdsb2JhbCIsInJlYXNvbiI6Im5vdEZvdW5kIiwibWVzc2FnZSI6Ik5vIHN1Y2ggb2JqZWN0OiBnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvY29uZGRlbCIsImRlYnVnSW5mbyI6ImNvbS5nb29nbGUubmV0LnJwYzMuUnBjRXhjZXB0aW9uOiBjbG91ZC5iaWdzdG9yZS5SZXNwb25zZUNvZGUuRXJyb3JDb2RlOjpPQkpFQ1RfTk9UX0ZPVU5EOiBObyBzdWNoIG9iamVjdDogZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2NvbmRkZWxcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udG9ScGMzRXhjZXB0aW9uKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MTM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuRGVsZXRlT2JqZWN0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChEZWxldGVPYmplY3QuamF2YTo3Nylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5vYmplY3RzLkRlbGV0ZU9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoRGVsZXRlT2JqZWN0LmphdmE6MjMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5PYmplY3RzRGVsZWdhdG9yLmRlbGV0ZShPYmplY3RzRGVsZWdhdG9yLmphdmE6MTEzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5ScGNSZWNlaXZlci5sYW1iZGEkcHJvY2Vzc1JlcXVlc3RBc3luYyQ0KFJwY1JlY2VpdmVyLmphdmE6MjAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5Bc3luY0V4ZWN1dG9yLmxhbWJkYSRzdWJtaXQkMChBc3luY0V4ZWN1dG9yLmphdmE6MjcyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoQ29udGV4dFJ1bm5hYmxlLmphdmE6NTApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlJDEucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM5KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo3Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5FeGVjdXRvcnMkUnVubmFibGVBZGFwdGVyLmNhbGwoRXhlY3V0b3JzLmphdmE6NTExKVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5GdXR1cmVUYXNrLnJ1bihGdXR1cmVUYXNrLmphdmE6MjY2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IucnVuV29ya2VyKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjExNDkpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvciRXb3JrZXIucnVuKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjYyNClcblx0YXQgamF2YS5sYW5nLlRocmVhZC5ydW4oVGhyZWFkLmphdmE6NzQ4KVxuQ2F1c2VkIGJ5OiBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbjogTm8gc3VjaCBvYmplY3Q6IGdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jb25kZGVsXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93T25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjI5MClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMSlcblx0Li4uIDE3IG1vcmVcblxuY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUuRmF1bHQ6IEltbXV0YWJsZUVycm9yRGVmaW5pdGlvbntiYXNlPU5PVF9GT1VORCwgY2F0ZWdvcnk9VVNFUl9FUlJPUiwgY2F1c2U9bnVsbCwgZGVidWdJbmZvPWNvbS5nb29nbGUubmV0LnJwYzMuUnBjRXhjZXB0aW9uOiBjbG91ZC5iaWdzdG9yZS5SZXNwb25zZUNvZGUuRXJyb3JDb2RlOjpPQkpFQ1RfTk9UX0ZPVU5EOiBObyBzdWNoIG9iamVjdDogZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2NvbmRkZWxcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udG9ScGMzRXhjZXB0aW9uKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MTM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuRGVsZXRlT2JqZWN0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChEZWxldGVPYmplY3QuamF2YTo3Nylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5vYmplY3RzLkRlbGV0ZU9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoRGVsZXRlT2JqZWN0LmphdmE6MjMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5PYmplY3RzRGVsZWdhdG9yLmRlbGV0ZShPYmplY3RzRGVsZWdhdG9yLmphdmE6MTEzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5ScGNSZWNlaXZlci5sYW1iZGEkcHJvY2Vzc1JlcXVlc3RBc3luYyQ0KFJwY1JlY2VpdmVyLmphdmE6MjAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5Bc3luY0V4ZWN1dG9yLmxhbWJkYSRzdWJtaXQkMChBc3luY0V4ZWN1dG9yLmphdmE6MjcyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoQ29udGV4dFJ1bm5hYmxlLmphdmE6NTApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlJDEucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM5KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo3Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5FeGVjdXRvcnMkUnVubmFibGVBZGFwdGVyLmNhbGwoRXhlY3V0b3JzLmphdmE6NTExKVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5GdXR1cmVUYXNrLnJ1bihGdXR1cmVUYXNrLmphdmE6MjY2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IucnVuV29ya2VyKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjExNDkpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvciRXb3JrZXIucnVuKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjYyNClcblx0YXQgamF2YS5sYW5nLlRocmVhZC5ydW4oVGhyZWFkLmphdmE6NzQ4KVxuQ2F1c2VkIGJ5OiBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbjogTm8gc3VjaCBvYmplY3Q6IGdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jb25kZGVsXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93T25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjI5MClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMSlcblx0Li4uIDE3IG1vcmVcbiwgZG9tYWluPWdsb2JhbCwgZXh0ZW5kZWRIZWxwPW51bGwsIGh0dHBIZWFkZXJzPXt9LCBodHRwU3RhdHVzPW5vdEZvdW5kLCBpbnRlcm5hbFJlYXNvbj1SZWFzb257YXJndW1lbnRzPXt9LCBjYXVzZT1udWxsLCBjb2RlPWdkYXRhLkNvcmVFcnJvckRvbWFpbi5OT1RfRk9VTkQsIGNyZWF0ZWRCeUJhY2tlbmQ9dHJ1ZSwgZGVidWdNZXNzYWdlPWNvbS5nb29nbGUubmV0LnJwYzMuUnBjRXhjZXB0aW9uOiBjbG91ZC5iaWdzdG9yZS5SZXNwb25zZUNvZGUuRXJyb3JDb2RlOjpPQkpFQ1RfTk9UX0ZPVU5EOiBObyBzdWNoIG9iamVjdDogZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2NvbmRkZWxcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udG9ScGMzRXhjZXB0aW9uKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MTM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuRGVsZXRlT2JqZWN0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChEZWxldGVPYmplY3QuamF2YTo3Nylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5vYmplY3RzLkRlbGV0ZU9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoRGVsZXRlT2JqZWN0LmphdmE6MjMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5PYmplY3RzRGVsZWdhdG9yLmRlbGV0ZShPYmplY3RzRGVsZWdhdG9yLmphdmE6MTEzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5ScGNSZWNlaXZlci5sYW1iZGEkcHJvY2Vzc1JlcXVlc3RBc3luYyQ0KFJwY1JlY2VpdmVyLmphdmE6MjAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5Bc3luY0V4ZWN1dG9yLmxhbWJkYSRzdWJtaXQkMChBc3luY0V4ZWN1dG9yLmphdmE6MjcyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoQ29udGV4dFJ1bm5hYmxlLmphdmE6NTApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlJDEucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM5KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo3Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5FeGVjdXRvcnMkUnVubmFibGVBZGFwdGVyLmNhbGwoRXhlY3V0b3JzLmphdmE6NTExKVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5GdXR1cmVUYXNrLnJ1bihGdXR1cmVUYXNrLmphdmE6MjY2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IucnVuV29ya2VyKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjExNDkpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvciRXb3JrZXIucnVuKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjYyNClcblx0YXQgamF2YS5sYW5nLlRocmVhZC5ydW4oVGhyZWFkLmphdmE6NzQ4KVxuQ2F1c2VkIGJ5OiBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbjogTm8gc3VjaCBvYmplY3Q6IGdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jb25kZGVsXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93T25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjI5MClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMSlcblx0Li4uIDE3IG1vcmVcbiwgZXJyb3JQcm90b0NvZGU9Tk9UX0ZPVU5ELCBlcnJvclByb3RvRG9tYWluPWdkYXRhLkNvcmVFcnJvckRvbWFpbiwgZmlsdGVyZWRNZXNzYWdlPW51bGwsIGxvY2F0aW9uPWVudGl0eS5yZXNvdXJjZV9pZC5uYW1lLCBtZXNzYWdlPU5vIHN1Y2ggb2JqZWN0OiBnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvY29uZGRlbCwgdW5uYW1lZEFyZ3VtZW50cz1bXX0sIGxvY2F0aW9uPWVudGl0eS5yZXNvdXJjZV9pZC5uYW1lLCBtZXNzYWdlPU5vIHN1Y2ggb2JqZWN0OiBnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvY29uZGRlbCwgcmVhc29uPW5vdEZvdW5kLCBycGNDb2RlPTQwNH0gTm8gc3VjaCBvYmplY3Q6IGdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jb25kZGVsOiBjb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6T0JKRUNUX05PVF9GT1VORDogTm8gc3VjaCBvYmplY3Q6IGdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jb25kZGVsXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRvUnBjM0V4Y2VwdGlvbihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjEzNSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5vYmplY3RzLkRlbGV0ZU9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoRGVsZXRlT2JqZWN0LmphdmE6NzcpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5EZWxldGVPYmplY3QuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKERlbGV0ZU9iamVjdC5qYXZhOjIzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmZyYW1ld29yay5SZXF1ZXN0SGFuZGxlci5oYW5kbGUoUmVxdWVzdEhhbmRsZXIuamF2YToyOTQpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uT2JqZWN0c0RlbGVnYXRvci5kZWxldGUoT2JqZWN0c0RlbGVnYXRvci5qYXZhOjExMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uUnBjUmVjZWl2ZXIubGFtYmRhJHByb2Nlc3NSZXF1ZXN0QXN5bmMkNChScGNSZWNlaXZlci5qYXZhOjIwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uQXN5bmNFeGVjdXRvci5sYW1iZGEkc3VibWl0JDAoQXN5bmNFeGVjdXRvci5qYXZhOjI3Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KENvbnRleHRSdW5uYWJsZS5qYXZhOjUwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZSQxLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozOSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NzIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozNilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRXhlY3V0b3JzJFJ1bm5hYmxlQWRhcHRlci5jYWxsKEV4ZWN1dG9ycy5qYXZhOjUxMSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRnV0dXJlVGFzay5ydW4oRnV0dXJlVGFzay5qYXZhOjI2Nilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yLnJ1bldvcmtlcihUaHJlYWRQb29sRXhlY3V0b3IuamF2YToxMTQ5KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IkV29ya2VyLnJ1bihUaHJlYWRQb29sRXhlY3V0b3IuamF2YTo2MjQpXG5cdGF0IGphdmEubGFuZy5UaHJlYWQucnVuKFRocmVhZC5qYXZhOjc0OClcbkNhdXNlZCBieTogY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb246IE5vIHN1Y2ggb2JqZWN0OiBnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvY29uZGRlbFxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxNyBtb3JlXG5cblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUuRXJyb3JDb2xsZWN0b3IudG9GYXVsdChFcnJvckNvbGxlY3Rvci5qYXZhOjU0KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIucmVzdC5hZGFwdGVyLnJvc3kuUm9zeUVycm9yQ29udmVydGVyLnRvRmF1bHQoUm9zeUVycm9yQ29udmVydGVyLmphdmE6NjcpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5yZXN0LmFkYXB0ZXIucm9zeS5Sb3N5SGFuZGxlciQyLmNhbGwoUm9zeUhhbmRsZXIuamF2YToyNTgpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5yZXN0LmFkYXB0ZXIucm9zeS5Sb3N5SGFuZGxlciQyLmNhbGwoUm9zeUhhbmRsZXIuamF2YToyMzgpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLnV0aWwuQ2FsbGFibGVGdXR1cmUucnVuKENhbGxhYmxlRnV0dXJlLmphdmE6NjIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5EaXJlY3RFeGVjdXRvci5leGVjdXRlKERpcmVjdEV4ZWN1dG9yLmphdmE6MzApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5leGVjdXRlTGlzdGVuZXIoQWJzdHJhY3RGdXR1cmUuamF2YToxMTQzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuY29tcGxldGUoQWJzdHJhY3RGdXR1cmUuamF2YTo5NjMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5zZXQoQWJzdHJhY3RGdXR1cmUuamF2YTo3MzEpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLnV0aWwuQ2FsbGFibGVGdXR1cmUucnVuKENhbGxhYmxlRnV0dXJlLmphdmE6NjIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5EaXJlY3RFeGVjdXRvci5leGVjdXRlKERpcmVjdEV4ZWN1dG9yLmphdmE6MzApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5leGVjdXRlTGlzdGVuZXIoQWJzdHJhY3RGdXR1cmUuamF2YToxMTQzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuY29tcGxldGUoQWJzdHJhY3RGdXR1cmUuamF2YTo5NjMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5zZXQoQWJzdHJhY3RGdXR1cmUuamF2YTo3MzEpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLnV0aWwuQ2FsbGFibGVGdXR1cmUucnVuKENhbGxhYmxlRnV0dXJlLmphdmE6NjIpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci50aHJlYWQuVGhyZWFkVHJhY2tlcnMkVGhyZWFkVHJhY2tpbmdSdW5uYWJsZS5ydW4oVGhyZWFkVHJhY2tlcnMuamF2YToxMjYpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkVHJhY2VDb250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KFRyYWNlQ29udGV4dC5qYXZhOjQ1NSlcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnNlcnZlci5Db21tb25Nb2R1bGUkQ29udGV4dENhcnJ5aW5nRXhlY3V0b3JTZXJ2aWNlJDEucnVuSW5Db250ZXh0KENvbW1vbk1vZHVsZS5qYXZhOjg0Nilcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRUcmFjZUNvbnRleHRSdW5uYWJsZSQxLnJ1bihUcmFjZUNvbnRleHQuamF2YTo0NjIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkQWJzdHJhY3RUcmFjZUNvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKFRyYWNlQ29udGV4dC5qYXZhOjMyMSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRBYnN0cmFjdFRyYWNlQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChUcmFjZUNvbnRleHQuamF2YTozMTMpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkVHJhY2VDb250ZXh0UnVubmFibGUucnVuKFRyYWNlQ29udGV4dC5qYXZhOjQ1OSlcblx0YXQgY29tLmdvb2dsZS5nc2UuaW50ZXJuYWwuRGlzcGF0Y2hRdWV1ZUltcGwkV29ya2VyVGhyZWFkLnJ1bihEaXNwYXRjaFF1ZXVlSW1wbC5qYXZhOjQwMylcbiJ9XSwiY29kZSI6NDA0LCJtZXNzYWdlIjoiTm8gc3VjaCBvYmplY3Q6IGdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jb25kZGVsIn19"
+ }
+ },
+ {
+ "ID": "dc490fa6bbb48c34",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/conddel?alt=json\u0026ifMetagenerationMatch=2\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "0e0594c6a559ad76638088af4a82573c/4732851225181833145;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/conddel?alt=json\u0026ifMetagenerationMatch=2\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 412,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0"
+ ],
+ "Content-Length": [
+ "11943"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:03 GMT"
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:24:03 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051342000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrlh82:4312,/bns/yw/borg/yw/bns/blobstore2/bitpusher/115.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=4susW6SoPI-jhQTSyrfwDA"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yw/borg/yw/bns/blobstore2/bitpusher/115.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yw/borg/yw/bns/blobstore2/bitpusher/115:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWXY2MTJyUVRiNE1ZWEtqdTZPQnktbmItdVBNRDJaTWRzU01HMFpSR3hiSUNwbUhWbXVFRlVEYjNkTURQUjc1OFJLMUtDNmEtZllTQWE5RWNYMXNaSlY3M0xWLXRnRmNOZFphckJMak9JSWRJRG5vSG4ySzcwTHpLdXhZNzBBSWU1TlFzU0F3WWIwLWU1WHlKZDk4WFlQLXBBT2tTVzBraFdXblVlZnpmYzExdWZUeHZnN2llS0hTWGswBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Upload-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UpW9PNlTnX1_YvdYKwOuxuOLQ-G9xx8dVMlb7UazrnA4HBJpJsWjEmrvJ67r6x6o2wfh82shQUEuCJjClvBiQayN7R-Tg"
+ ]
+ },
+ "Body": "eyJlcnJvciI6eyJlcnJvcnMiOlt7ImRvbWFpbiI6Imdsb2JhbCIsInJlYXNvbiI6ImNvbmRpdGlvbk5vdE1ldCIsIm1lc3NhZ2UiOiJQcmVjb25kaXRpb24gRmFpbGVkIiwibG9jYXRpb25UeXBlIjoiaGVhZGVyIiwibG9jYXRpb24iOiJJZi1NYXRjaCIsImRlYnVnSW5mbyI6ImNvbS5nb29nbGUubmV0LnJwYzMuUnBjRXhjZXB0aW9uOiBjbG91ZC5iaWdzdG9yZS5SZXNwb25zZUNvZGUuRXJyb3JDb2RlOjpJTkNPUlJFQ1RfTUVUQV9HRU5FUkFUSU9OX1NQRUNJRklFRDogRXhwZWN0ZWQgbWV0YWRhdGEgZ2VuZXJhdGlvbiB0byBtYXRjaCAyLCBidXQgYWN0dWFsIHZhbHVlIHdhcyAxLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5EZWxldGVPYmplY3QuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKERlbGV0ZU9iamVjdC5qYXZhOjc3KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuRGVsZXRlT2JqZWN0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChEZWxldGVPYmplY3QuamF2YToyMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLk9iamVjdHNEZWxlZ2F0b3IuZGVsZXRlKE9iamVjdHNEZWxlZ2F0b3IuamF2YToxMTMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBFeHBlY3RlZCBtZXRhZGF0YSBnZW5lcmF0aW9uIHRvIG1hdGNoIDIsIGJ1dCBhY3R1YWwgdmFsdWUgd2FzIDEuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93T25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjI5Mylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMSlcblx0Li4uIDE3IG1vcmVcblxuY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUuRmF1bHQ6IEltbXV0YWJsZUVycm9yRGVmaW5pdGlvbntiYXNlPVBSRUNPTkRJVElPTl9GQUlMRUQsIGNhdGVnb3J5PVVTRVJfRVJST1IsIGNhdXNlPW51bGwsIGRlYnVnSW5mbz1jb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6SU5DT1JSRUNUX01FVEFfR0VORVJBVElPTl9TUEVDSUZJRUQ6IEV4cGVjdGVkIG1ldGFkYXRhIGdlbmVyYXRpb24gdG8gbWF0Y2ggMiwgYnV0IGFjdHVhbCB2YWx1ZSB3YXMgMS5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udG9ScGMzRXhjZXB0aW9uKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MTM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuRGVsZXRlT2JqZWN0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChEZWxldGVPYmplY3QuamF2YTo3Nylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5vYmplY3RzLkRlbGV0ZU9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoRGVsZXRlT2JqZWN0LmphdmE6MjMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5PYmplY3RzRGVsZWdhdG9yLmRlbGV0ZShPYmplY3RzRGVsZWdhdG9yLmphdmE6MTEzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5ScGNSZWNlaXZlci5sYW1iZGEkcHJvY2Vzc1JlcXVlc3RBc3luYyQ0KFJwY1JlY2VpdmVyLmphdmE6MjAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5Bc3luY0V4ZWN1dG9yLmxhbWJkYSRzdWJtaXQkMChBc3luY0V4ZWN1dG9yLmphdmE6MjcyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoQ29udGV4dFJ1bm5hYmxlLmphdmE6NTApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlJDEucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM5KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo3Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5FeGVjdXRvcnMkUnVubmFibGVBZGFwdGVyLmNhbGwoRXhlY3V0b3JzLmphdmE6NTExKVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5GdXR1cmVUYXNrLnJ1bihGdXR1cmVUYXNrLmphdmE6MjY2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IucnVuV29ya2VyKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjExNDkpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvciRXb3JrZXIucnVuKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjYyNClcblx0YXQgamF2YS5sYW5nLlRocmVhZC5ydW4oVGhyZWFkLmphdmE6NzQ4KVxuQ2F1c2VkIGJ5OiBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbjogRXhwZWN0ZWQgbWV0YWRhdGEgZ2VuZXJhdGlvbiB0byBtYXRjaCAyLCBidXQgYWN0dWFsIHZhbHVlIHdhcyAxLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxNyBtb3JlXG4sIGRvbWFpbj1nbG9iYWwsIGV4dGVuZGVkSGVscD1udWxsLCBodHRwSGVhZGVycz17fSwgaHR0cFN0YXR1cz1wcmVjb25kaXRpb25GYWlsZWQsIGludGVybmFsUmVhc29uPVJlYXNvbnthcmd1bWVudHM9e30sIGNhdXNlPW51bGwsIGNvZGU9Z2RhdGEuQ29yZUVycm9yRG9tYWluLkNPTkRJVElPTl9OT1RfTUVULCBjcmVhdGVkQnlCYWNrZW5kPXRydWUsIGRlYnVnTWVzc2FnZT1jb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6SU5DT1JSRUNUX01FVEFfR0VORVJBVElPTl9TUEVDSUZJRUQ6IEV4cGVjdGVkIG1ldGFkYXRhIGdlbmVyYXRpb24gdG8gbWF0Y2ggMiwgYnV0IGFjdHVhbCB2YWx1ZSB3YXMgMS5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udG9ScGMzRXhjZXB0aW9uKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MTM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuRGVsZXRlT2JqZWN0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChEZWxldGVPYmplY3QuamF2YTo3Nylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5vYmplY3RzLkRlbGV0ZU9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoRGVsZXRlT2JqZWN0LmphdmE6MjMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5PYmplY3RzRGVsZWdhdG9yLmRlbGV0ZShPYmplY3RzRGVsZWdhdG9yLmphdmE6MTEzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5ScGNSZWNlaXZlci5sYW1iZGEkcHJvY2Vzc1JlcXVlc3RBc3luYyQ0KFJwY1JlY2VpdmVyLmphdmE6MjAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5Bc3luY0V4ZWN1dG9yLmxhbWJkYSRzdWJtaXQkMChBc3luY0V4ZWN1dG9yLmphdmE6MjcyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoQ29udGV4dFJ1bm5hYmxlLmphdmE6NTApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlJDEucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM5KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo3Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5FeGVjdXRvcnMkUnVubmFibGVBZGFwdGVyLmNhbGwoRXhlY3V0b3JzLmphdmE6NTExKVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5GdXR1cmVUYXNrLnJ1bihGdXR1cmVUYXNrLmphdmE6MjY2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IucnVuV29ya2VyKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjExNDkpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvciRXb3JrZXIucnVuKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjYyNClcblx0YXQgamF2YS5sYW5nLlRocmVhZC5ydW4oVGhyZWFkLmphdmE6NzQ4KVxuQ2F1c2VkIGJ5OiBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbjogRXhwZWN0ZWQgbWV0YWRhdGEgZ2VuZXJhdGlvbiB0byBtYXRjaCAyLCBidXQgYWN0dWFsIHZhbHVlIHdhcyAxLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxNyBtb3JlXG4sIGVycm9yUHJvdG9Db2RlPUNPTkRJVElPTl9OT1RfTUVULCBlcnJvclByb3RvRG9tYWluPWdkYXRhLkNvcmVFcnJvckRvbWFpbiwgZmlsdGVyZWRNZXNzYWdlPW51bGwsIGxvY2F0aW9uPW51bGwsIG1lc3NhZ2U9bnVsbCwgdW5uYW1lZEFyZ3VtZW50cz1bXX0sIGxvY2F0aW9uPWhlYWRlcnMuSWYtTWF0Y2gsIG1lc3NhZ2U9UHJlY29uZGl0aW9uIEZhaWxlZCwgcmVhc29uPWNvbmRpdGlvbk5vdE1ldCwgcnBjQ29kZT00MTJ9IFByZWNvbmRpdGlvbiBGYWlsZWQ6IGNvbS5nb29nbGUubmV0LnJwYzMuUnBjRXhjZXB0aW9uOiBjbG91ZC5iaWdzdG9yZS5SZXNwb25zZUNvZGUuRXJyb3JDb2RlOjpJTkNPUlJFQ1RfTUVUQV9HRU5FUkFUSU9OX1NQRUNJRklFRDogRXhwZWN0ZWQgbWV0YWRhdGEgZ2VuZXJhdGlvbiB0byBtYXRjaCAyLCBidXQgYWN0dWFsIHZhbHVlIHdhcyAxLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5EZWxldGVPYmplY3QuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKERlbGV0ZU9iamVjdC5qYXZhOjc3KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuRGVsZXRlT2JqZWN0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChEZWxldGVPYmplY3QuamF2YToyMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLk9iamVjdHNEZWxlZ2F0b3IuZGVsZXRlKE9iamVjdHNEZWxlZ2F0b3IuamF2YToxMTMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBFeHBlY3RlZCBtZXRhZGF0YSBnZW5lcmF0aW9uIHRvIG1hdGNoIDIsIGJ1dCBhY3R1YWwgdmFsdWUgd2FzIDEuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93T25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjI5Mylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMSlcblx0Li4uIDE3IG1vcmVcblxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS5FcnJvckNvbGxlY3Rvci50b0ZhdWx0KEVycm9yQ29sbGVjdG9yLmphdmE6NTQpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5yZXN0LmFkYXB0ZXIucm9zeS5Sb3N5RXJyb3JDb252ZXJ0ZXIudG9GYXVsdChSb3N5RXJyb3JDb252ZXJ0ZXIuamF2YTo2Nylcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnJlc3QuYWRhcHRlci5yb3N5LlJvc3lIYW5kbGVyJDIuY2FsbChSb3N5SGFuZGxlci5qYXZhOjI1OClcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnJlc3QuYWRhcHRlci5yb3N5LlJvc3lIYW5kbGVyJDIuY2FsbChSb3N5SGFuZGxlci5qYXZhOjIzOClcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkRpcmVjdEV4ZWN1dG9yLmV4ZWN1dGUoRGlyZWN0RXhlY3V0b3IuamF2YTozMClcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmV4ZWN1dGVMaXN0ZW5lcihBYnN0cmFjdEZ1dHVyZS5qYXZhOjExNDMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5jb21wbGV0ZShBYnN0cmFjdEZ1dHVyZS5qYXZhOjk2Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLnNldChBYnN0cmFjdEZ1dHVyZS5qYXZhOjczMSlcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkRpcmVjdEV4ZWN1dG9yLmV4ZWN1dGUoRGlyZWN0RXhlY3V0b3IuamF2YTozMClcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmV4ZWN1dGVMaXN0ZW5lcihBYnN0cmFjdEZ1dHVyZS5qYXZhOjExNDMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5jb21wbGV0ZShBYnN0cmFjdEZ1dHVyZS5qYXZhOjk2Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLnNldChBYnN0cmFjdEZ1dHVyZS5qYXZhOjczMSlcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnRocmVhZC5UaHJlYWRUcmFja2VycyRUaHJlYWRUcmFja2luZ1J1bm5hYmxlLnJ1bihUaHJlYWRUcmFja2Vycy5qYXZhOjEyNilcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRUcmFjZUNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoVHJhY2VDb250ZXh0LmphdmE6NDU1KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuc2VydmVyLkNvbW1vbk1vZHVsZSRDb250ZXh0Q2FycnlpbmdFeGVjdXRvclNlcnZpY2UkMS5ydW5JbkNvbnRleHQoQ29tbW9uTW9kdWxlLmphdmE6ODQ2KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JFRyYWNlQ29udGV4dFJ1bm5hYmxlJDEucnVuKFRyYWNlQ29udGV4dC5qYXZhOjQ2Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRBYnN0cmFjdFRyYWNlQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoVHJhY2VDb250ZXh0LmphdmE6MzIxKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JEFic3RyYWN0VHJhY2VDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KFRyYWNlQ29udGV4dC5qYXZhOjMxMylcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRUcmFjZUNvbnRleHRSdW5uYWJsZS5ydW4oVHJhY2VDb250ZXh0LmphdmE6NDU5KVxuXHRhdCBjb20uZ29vZ2xlLmdzZS5pbnRlcm5hbC5EaXNwYXRjaFF1ZXVlSW1wbCRXb3JrZXJUaHJlYWQucnVuKERpc3BhdGNoUXVldWVJbXBsLmphdmE6NDAzKVxuIn1dLCJjb2RlIjo0MTIsIm1lc3NhZ2UiOiJQcmVjb25kaXRpb24gRmFpbGVkIn19"
+ }
+ },
+ {
+ "ID": "7b4d64f669c0333c",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/conddel?alt=json\u0026ifMetagenerationNotMatch=1\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "1f52dac0b93933518d0bdbf98d760edf/5491888194603031048;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/conddel?alt=json\u0026ifMetagenerationNotMatch=1\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 304,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0"
+ ],
+ "Content-Length": [
+ "0"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:03 GMT"
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:24:03 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051342000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrhr16:4228,/bns/yw/borg/yw/bns/blobstore2/bitpusher/147.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=48usW-HOEMnxhQTc04vYDA"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yw/borg/yw/bns/blobstore2/bitpusher/147.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yw/borg/yw/bns/blobstore2/bitpusher/147:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWXY2MTJyUVRiNE1ZWEtqdTZPQnktbmItdVBNRDJaTWRzU01HMFpSR3hiSUNwbUhWbXVFRlVEYjNkTURQUjc1OFJLMUtDNmEtZllTQWE5RWNYMXNaSlY3M0xWLXRnRmNOZFphckJMak9JSWRJRG5vSG4ySzcwTHpLdXhZNzBBSWU1TlFzU0F3WWIwLWU1WHlKZDk4WFlQLXBBT2tTVzBraFdXblVlZnpmYzExdWZUeHZnN2llS0hTWGswBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UqXbCw-65-mGU7N9rqCcQdeR9L7gyLR3middMRmDYhL4PflAyi-fWZKa2_Hn6fC_MmZNwUUJhhbQiptY53-x322rayLLA"
+ ]
+ },
+ "Body": ""
+ }
+ },
+ {
+ "ID": "3a3d4e799b1d4ff1",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/conddel?alt=json\u0026generation=1538051042759808\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "3614b8bee4c582fd5d488e1e6b9c6a83/6323263129232272727;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/conddel?alt=json\u0026generation=1538051042759808\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 204,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "0"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:03 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051342000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrih14:4363,/bns/yw/borg/yw/bns/blobstore2/bitpusher/63.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=48usW5qOI4fuN9ytj-AL"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yw/borg/yw/bns/blobstore2/bitpusher/63.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yw/borg/yw/bns/blobstore2/bitpusher/63:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWXY2MTJyUVRiNE1ZWEtqdTZPQnktbmItdVBNRDJaTWRzU01HMFpSR3hiSUNwbUhWbXVFRlVEYjNkTURQUjc1OFJLMUtDNmEtZllTQWE5RWNYMXNaSlY3M0xWLXRnRmNOZFphckJMak9JSWRJRG5vSG4ySzcwTHpLdXhZNzBBSWU1TlFzU0F3WWIwLWU1WHlKZDk4WFlQLXBBT2tTVzBraFdXblVlZnpmYzExdWZUeHZnN2llS0hTWGswBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UoJHiQpNZ-qEzatUz59hED1GW-yo-BCmNHyDwotCZGRLIkp6_KPIVZkVrtmVVKlKI-NqP7C1VOZCKWq1JSFxSk32uIAcw"
+ ]
+ },
+ "Body": ""
+ }
+ },
+ {
+ "ID": "a09383dd9bc5920c",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Type": [
+ "multipart/related; boundary=7834c061d4a46c74dc809f40f72ea21bc28430ca21d42af796b7c56f7090"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "29f22ce3f51c65ee421feee1bd46b233/7082300098670182311;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "LS03ODM0YzA2MWQ0YTQ2Yzc0ZGM4MDlmNDBmNzJlYTIxYmMyODQzMGNhMjFkNDJhZjc5NmI3YzU2ZjcwOTANCkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vanNvbg0KDQp7ImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsImNhY2hlQ29udHJvbCI6InB1YmxpYywgbWF4LWFnZT02MCIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbiIsIm5hbWUiOiJvYmoxIn0KDQotLTc4MzRjMDYxZDRhNDZjNzRkYzgwOWY0MGY3MmVhMjFiYzI4NDMwY2EyMWQ0MmFmNzk2YjdjNTZmNzA5MA0KQ29udGVudC1UeXBlOiB0ZXh0L3BsYWluDQoNChu2BO3eJ9HctT16IRSaVJ8NCi0tNzgzNGMwNjFkNGE0NmM3NGRjODA5ZjQwZjcyZWEyMWJjMjg0MzBjYTIxZDQyYWY3OTZiN2M1NmY3MDkwLS0NCg=="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3243"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:04 GMT"
+ ],
+ "Etag": [
+ "CI7Bn9GW290CEAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051344000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrjm12:4359,/bns/yv/borg/yv/bns/blobstore2/bitpusher/50.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=5MusW-JakcuzBviUvZAD"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/50.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/50:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRYnFLZDRCTjBkdm9mZm9PZVZZS0p1VDRROFVJT3NhUTljbFFvbW42UElpcDBpenczVUc1ZHZUMVZlZE1OWGp3cHJDNUUyam9FUUZwbldFellKMWd5Tlp1T3o4dy16UUMxaXAtb3VNMjdkM0JqNGR4SmNfUDVYRXRjeHNYWVN3LXNuNXEtcXpLZ1NvM3BKMGx4Ym9YaGNlZHBiR2t6VGVSdlc5QnVxZDFESV9pbE84ZEFXSDVOLVJnNDQwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_single_post_uploads"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UqZK45KDcXNpqKxs7RM4nR3KIPATeLgKgB8XtPJRm8ykneziFgQBwXknvRchuyv76v14eoyX1QNT6vGNYl16Tcg_5AEWw"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmoxLzE1MzgwNTEwNDQ1MzIzNjYiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9vYmoxIiwibmFtZSI6Im9iajEiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NDUzMjM2NiIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbiIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDowNC41MzJaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MDQuNTMyWiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjA0LjUzMloiLCJzaXplIjoiMTYiLCJtZDVIYXNoIjoiN3dVRkg4bUREd0hGWXFvN29seGRQZz09IiwibWVkaWFMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vZG93bmxvYWQvc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iajE/Z2VuZXJhdGlvbj0xNTM4MDUxMDQ0NTMyMzY2JmFsdD1tZWRpYSIsImNhY2hlQ29udHJvbCI6InB1YmxpYywgbWF4LWFnZT02MCIsImFjbCI6W3sia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL29iajEvMTUzODA1MTA0NDUzMjM2Ni9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iajEvYWNsL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0Ijoib2JqMSIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDQ0NTMyMzY2IiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDSTdCbjlHVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqMS8xNTM4MDUxMDQ0NTMyMzY2L3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iajEvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Im9iajEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NDUzMjM2NiIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDSTdCbjlHVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqMS8xNTM4MDUxMDQ0NTMyMzY2L3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iajEvYWNsL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Im9iajEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NDUzMjM2NiIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0k3Qm45R1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL29iajEvMTUzODA1MTA0NDUzMjM2Ni91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vb2JqMS9hY2wvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Im9iajEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NDUzMjM2NiIsImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJyb2xlIjoiT1dORVIiLCJlbWFpbCI6IjM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiZXRhZyI6IkNJN0JuOUdXMjkwQ0VBRT0ifV0sIm93bmVyIjp7ImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20ifSwiY3JjMzJjIjoiKzdSMTFnPT0iLCJldGFnIjoiQ0k3Qm45R1cyOTBDRUFFPSJ9"
+ }
+ },
+ {
+ "ID": "415cbbb4c411d828",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Type": [
+ "multipart/related; boundary=51ce82224b1617abfd90683ffa66b3773319b1a8364c2f78256a0cfc75c1"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "73bdb84b0db761fac19f7226ea21ad8b/7913393562617680630;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "LS01MWNlODIyMjRiMTYxN2FiZmQ5MDY4M2ZmYTY2YjM3NzMzMTliMWE4MzY0YzJmNzgyNTZhMGNmYzc1YzENCkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vanNvbg0KDQp7ImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsImNhY2hlQ29udHJvbCI6InB1YmxpYywgbWF4LWFnZT02MCIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbiIsIm5hbWUiOiJvYmoyIn0KDQotLTUxY2U4MjIyNGIxNjE3YWJmZDkwNjgzZmZhNjZiMzc3MzMxOWIxYTgzNjRjMmY3ODI1NmEwY2ZjNzVjMQ0KQ29udGVudC1UeXBlOiB0ZXh0L3BsYWluDQoNCsPZcNJccaSrouZ5qGqfKcMNCi0tNTFjZTgyMjI0YjE2MTdhYmZkOTA2ODNmZmE2NmIzNzczMzE5YjFhODM2NGMyZjc4MjU2YTBjZmM3NWMxLS0NCg=="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3243"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:05 GMT"
+ ],
+ "Etag": [
+ "CNeSxNGW290CEAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051344000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vnna19:4148,/bns/yx/borg/yx/bns/blobstore2/bitpusher/15.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=5MusW8WsL8bPzwLJ_o3YCA"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yx/borg/yx/bns/blobstore2/bitpusher/15.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yx/borg/yx/bns/blobstore2/bitpusher/15:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRYnFLZDRCTjBkdm9mZm9PZVZZS0p1VDRROFVJT3NhUTljbFFvbW42UElpcDBpenczVUc1ZHZUMVZlZE1OWGp3cHJDNUUyam9FUUZwbldFellKMWd5Tlp1T3o4dy16UUMxaXAtb3VNMjdkM0JqNGR4SmNfUDVYRXRjeHNYWVN3LXNuNXEtcXpLZ1NvM3BKMGx4Ym9YaGNlZHBiR2t6VGVSdlc5QnVxZDFESV9pbE84ZEFXSDVOLVJnNDQwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_single_post_uploads"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Up2wgYdgpOZhxiQEfC9zZYmEfyDtJdlztDtjrpklLhwzZZlQFaOHUULevuaKs257Y9xrXUNEZ1BHjxOk8Dt_vUcduWQpA"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmoyLzE1MzgwNTEwNDUxMzI2MzEiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9vYmoyIiwibmFtZSI6Im9iajIiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NTEzMjYzMSIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbiIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDowNS4xMzJaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MDUuMTMyWiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjA1LjEzMloiLCJzaXplIjoiMTYiLCJtZDVIYXNoIjoiaDY0bVlxSjJPNTRqcnhHT0pOeUd4UT09IiwibWVkaWFMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vZG93bmxvYWQvc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iajI/Z2VuZXJhdGlvbj0xNTM4MDUxMDQ1MTMyNjMxJmFsdD1tZWRpYSIsImNhY2hlQ29udHJvbCI6InB1YmxpYywgbWF4LWFnZT02MCIsImFjbCI6W3sia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL29iajIvMTUzODA1MTA0NTEzMjYzMS9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iajIvYWNsL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0Ijoib2JqMiIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDQ1MTMyNjMxIiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDTmVTeE5HVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqMi8xNTM4MDUxMDQ1MTMyNjMxL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iajIvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Im9iajIiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NTEzMjYzMSIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDTmVTeE5HVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqMi8xNTM4MDUxMDQ1MTMyNjMxL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iajIvYWNsL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Im9iajIiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NTEzMjYzMSIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ05lU3hOR1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL29iajIvMTUzODA1MTA0NTEzMjYzMS91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vb2JqMi9hY2wvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Im9iajIiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NTEzMjYzMSIsImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJyb2xlIjoiT1dORVIiLCJlbWFpbCI6IjM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiZXRhZyI6IkNOZVN4TkdXMjkwQ0VBRT0ifV0sIm93bmVyIjp7ImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20ifSwiY3JjMzJjIjoiM0RLRHFnPT0iLCJldGFnIjoiQ05lU3hOR1cyOTBDRUFFPSJ9"
+ }
+ },
+ {
+ "ID": "f67034946dd9c5a8",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Type": [
+ "multipart/related; boundary=090845640f43d87c92783246d30b6758c9a71a1c48bf1fa3f421832a1a1d"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "35e219d1230ad747c0ffbd9bacfec0b6/8672712002720621893;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "LS0wOTA4NDU2NDBmNDNkODdjOTI3ODMyNDZkMzBiNjc1OGM5YTcxYTFjNDhiZjFmYTNmNDIxODMyYTFhMWQNCkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vanNvbg0KDQp7ImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsImNhY2hlQ29udHJvbCI6InB1YmxpYywgbWF4LWFnZT02MCIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbiIsIm5hbWUiOiJvYmovd2l0aC9zbGFzaGVzIn0KDQotLTA5MDg0NTY0MGY0M2Q4N2M5Mjc4MzI0NmQzMGI2NzU4YzlhNzFhMWM0OGJmMWZhM2Y0MjE4MzJhMWExZA0KQ29udGVudC1UeXBlOiB0ZXh0L3BsYWluDQoNClj7FIqgnZiH3EyVHy/zHpENCi0tMDkwODQ1NjQwZjQzZDg3YzkyNzgzMjQ2ZDMwYjY3NThjOWE3MWExYzQ4YmYxZmEzZjQyMTgzMmExYTFkLS0NCg=="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3459"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:05 GMT"
+ ],
+ "Etag": [
+ "CL6q4tGW290CEAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051344000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vril72:4228,/bns/yr/borg/yr/bns/blobstore2/bitpusher/35.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=5cusW6rBFpDv4QSx-464CQ"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/35.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/35:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRYnFLZDRCTjBkdm9mZm9PZVZZS0p1VDRROFVJT3NhUTljbFFvbW42UElpcDBpenczVUc1ZHZUMVZlZE1OWGp3cHJDNUUyam9FUUZwbldFellKMWd5Tlp1T3o4dy16UUMxaXAtb3VNMjdkM0JqNGR4SmNfUDVYRXRjeHNYWVN3LXNuNXEtcXpLZ1NvM3BKMGx4Ym9YaGNlZHBiR2t6VGVSdlc5QnVxZDFESV9pbE84ZEFXSDVOLVJnNDQwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_single_post_uploads"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UqAi9M8gXtYgNBppM0_5Qy48gHgCeBJ2rQNhX_bVIUqNMThN5aQcO9mO1s4tsGd860po8SPIq6U8i8Tp2c-QFHY0S36-Q"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmovd2l0aC9zbGFzaGVzLzE1MzgwNTEwNDU2MjcxOTgiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9vYmolMkZ3aXRoJTJGc2xhc2hlcyIsIm5hbWUiOiJvYmovd2l0aC9zbGFzaGVzIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNDU2MjcxOTgiLCJtZXRhZ2VuZXJhdGlvbiI6IjEiLCJjb250ZW50VHlwZSI6InRleHQvcGxhaW4iLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MDUuNjI3WiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjA1LjYyN1oiLCJzdG9yYWdlQ2xhc3MiOiJTVEFOREFSRCIsInRpbWVTdG9yYWdlQ2xhc3NVcGRhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDowNS42MjdaIiwic2l6ZSI6IjE2IiwibWQ1SGFzaCI6Iis3bVZuNkxUd0RuVjN0Zy9wQ3Jpb3c9PSIsIm1lZGlhTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2Rvd25sb2FkL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9vYmolMkZ3aXRoJTJGc2xhc2hlcz9nZW5lcmF0aW9uPTE1MzgwNTEwNDU2MjcxOTgmYWx0PW1lZGlhIiwiY2FjaGVDb250cm9sIjoicHVibGljLCBtYXgtYWdlPTYwIiwiYWNsIjpbeyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqL3dpdGgvc2xhc2hlcy8xNTM4MDUxMDQ1NjI3MTk4L3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vb2JqJTJGd2l0aCUyRnNsYXNoZXMvYWNsL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0Ijoib2JqL3dpdGgvc2xhc2hlcyIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDQ1NjI3MTk4IiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDTDZxNHRHVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqL3dpdGgvc2xhc2hlcy8xNTM4MDUxMDQ1NjI3MTk4L3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iaiUyRndpdGglMkZzbGFzaGVzL2FjbC9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJvYmovd2l0aC9zbGFzaGVzIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNDU2MjcxOTgiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0w2cTR0R1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL29iai93aXRoL3NsYXNoZXMvMTUzODA1MTA0NTYyNzE5OC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9vYmolMkZ3aXRoJTJGc2xhc2hlcy9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0Ijoib2JqL3dpdGgvc2xhc2hlcyIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDQ1NjI3MTk4IiwiZW50aXR5IjoicHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6IlJFQURFUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJ2aWV3ZXJzIn0sImV0YWciOiJDTDZxNHRHVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqL3dpdGgvc2xhc2hlcy8xNTM4MDUxMDQ1NjI3MTk4L3VzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9vYmolMkZ3aXRoJTJGc2xhc2hlcy9hY2wvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Im9iai93aXRoL3NsYXNoZXMiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NTYyNzE5OCIsImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJyb2xlIjoiT1dORVIiLCJlbWFpbCI6IjM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiZXRhZyI6IkNMNnE0dEdXMjkwQ0VBRT0ifV0sIm93bmVyIjp7ImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20ifSwiY3JjMzJjIjoia1NzV1FnPT0iLCJldGFnIjoiQ0w2cTR0R1cyOTBDRUFFPSJ9"
+ }
+ },
+ {
+ "ID": "db2ba221d4332295",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/obj%2Fwith%2Fslashes?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "55f8bad62f3127c0ef5fccc806d398c4/10263123902492871396;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/obj%2Fwith%2Fslashes?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3459"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:05 GMT"
+ ],
+ "Etag": [
+ "CL6q4tGW290CEAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051345000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vnob6:4175,/bns/yx/borg/yx/bns/blobstore2/bitpusher/60.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=5cusW472MoG_zALtjKnABA"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yx/borg/yx/bns/blobstore2/bitpusher/60.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yx/borg/yx/bns/blobstore2/bitpusher/60:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRYnFLZDRCTjBkdm9mZm9PZVZZS0p1VDRROFVJT3NhUTljbFFvbW42UElpcDBpenczVUc1ZHZUMVZlZE1OWGp3cHJDNUUyam9FUUZwbldFellKMWd5Tlp1T3o4dy16UUMxaXAtb3VNMjdkM0JqNGR4SmNfUDVYRXRjeHNYWVN3LXNuNXEtcXpLZ1NvM3BKMGx4Ym9YaGNlZHBiR2t6VGVSdlc5QnVxZDFESV9pbE84ZEFXSDVOLVJnNDQwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UrrNXgt6uywwej2qFhVm9mxQCs98f0CyuSuOI3cx9Dstby13tllyGHQ1Gsz00qGk2VQyvqv9OnpgVqajrJsHYhsCvoiDg"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmovd2l0aC9zbGFzaGVzLzE1MzgwNTEwNDU2MjcxOTgiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9vYmolMkZ3aXRoJTJGc2xhc2hlcyIsIm5hbWUiOiJvYmovd2l0aC9zbGFzaGVzIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNDU2MjcxOTgiLCJtZXRhZ2VuZXJhdGlvbiI6IjEiLCJjb250ZW50VHlwZSI6InRleHQvcGxhaW4iLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MDUuNjI3WiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjA1LjYyN1oiLCJzdG9yYWdlQ2xhc3MiOiJTVEFOREFSRCIsInRpbWVTdG9yYWdlQ2xhc3NVcGRhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDowNS42MjdaIiwic2l6ZSI6IjE2IiwibWQ1SGFzaCI6Iis3bVZuNkxUd0RuVjN0Zy9wQ3Jpb3c9PSIsIm1lZGlhTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2Rvd25sb2FkL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9vYmolMkZ3aXRoJTJGc2xhc2hlcz9nZW5lcmF0aW9uPTE1MzgwNTEwNDU2MjcxOTgmYWx0PW1lZGlhIiwiY2FjaGVDb250cm9sIjoicHVibGljLCBtYXgtYWdlPTYwIiwiYWNsIjpbeyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqL3dpdGgvc2xhc2hlcy8xNTM4MDUxMDQ1NjI3MTk4L3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vb2JqJTJGd2l0aCUyRnNsYXNoZXMvYWNsL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0Ijoib2JqL3dpdGgvc2xhc2hlcyIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDQ1NjI3MTk4IiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDTDZxNHRHVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqL3dpdGgvc2xhc2hlcy8xNTM4MDUxMDQ1NjI3MTk4L3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iaiUyRndpdGglMkZzbGFzaGVzL2FjbC9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJvYmovd2l0aC9zbGFzaGVzIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNDU2MjcxOTgiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0w2cTR0R1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL29iai93aXRoL3NsYXNoZXMvMTUzODA1MTA0NTYyNzE5OC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9vYmolMkZ3aXRoJTJGc2xhc2hlcy9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0Ijoib2JqL3dpdGgvc2xhc2hlcyIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDQ1NjI3MTk4IiwiZW50aXR5IjoicHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6IlJFQURFUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJ2aWV3ZXJzIn0sImV0YWciOiJDTDZxNHRHVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqL3dpdGgvc2xhc2hlcy8xNTM4MDUxMDQ1NjI3MTk4L3VzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9vYmolMkZ3aXRoJTJGc2xhc2hlcy9hY2wvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Im9iai93aXRoL3NsYXNoZXMiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NTYyNzE5OCIsImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJyb2xlIjoiT1dORVIiLCJlbWFpbCI6IjM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiZXRhZyI6IkNMNnE0dEdXMjkwQ0VBRT0ifV0sIm93bmVyIjp7ImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20ifSwiY3JjMzJjIjoia1NzV1FnPT0iLCJldGFnIjoiQ0w2cTR0R1cyOTBDRUFFPSJ9"
+ }
+ },
+ {
+ "ID": "dc21ca1708a6ecef",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/obj1?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "959f74f11da0fe031209c5ee56fc9a65/11853253236366651523;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/obj1?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3243"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:06 GMT"
+ ],
+ "Etag": [
+ "CI7Bn9GW290CEAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051345000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrat7:4174,/bns/yv/borg/yv/bns/blobstore2/bitpusher/349.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=5cusW4DVOdPXgATL46nICA"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/349.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/349:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRYnFLZDRCTjBkdm9mZm9PZVZZS0p1VDRROFVJT3NhUTljbFFvbW42UElpcDBpenczVUc1ZHZUMVZlZE1OWGp3cHJDNUUyam9FUUZwbldFellKMWd5Tlp1T3o4dy16UUMxaXAtb3VNMjdkM0JqNGR4SmNfUDVYRXRjeHNYWVN3LXNuNXEtcXpLZ1NvM3BKMGx4Ym9YaGNlZHBiR2t6VGVSdlc5QnVxZDFESV9pbE84ZEFXSDVOLVJnNDQwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Uqglj1Cm20uhsQlokYmNGcuPEqqziisZ8SNgl_7G8Wsygq5_8LpH3AzZgZGyMjI3ollcwmB_Fu3jr2EmRVk1Nr0sEPg5A"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmoxLzE1MzgwNTEwNDQ1MzIzNjYiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9vYmoxIiwibmFtZSI6Im9iajEiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NDUzMjM2NiIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbiIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDowNC41MzJaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MDQuNTMyWiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjA0LjUzMloiLCJzaXplIjoiMTYiLCJtZDVIYXNoIjoiN3dVRkg4bUREd0hGWXFvN29seGRQZz09IiwibWVkaWFMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vZG93bmxvYWQvc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iajE/Z2VuZXJhdGlvbj0xNTM4MDUxMDQ0NTMyMzY2JmFsdD1tZWRpYSIsImNhY2hlQ29udHJvbCI6InB1YmxpYywgbWF4LWFnZT02MCIsImFjbCI6W3sia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL29iajEvMTUzODA1MTA0NDUzMjM2Ni9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iajEvYWNsL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0Ijoib2JqMSIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDQ0NTMyMzY2IiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDSTdCbjlHVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqMS8xNTM4MDUxMDQ0NTMyMzY2L3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iajEvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Im9iajEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NDUzMjM2NiIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDSTdCbjlHVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqMS8xNTM4MDUxMDQ0NTMyMzY2L3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iajEvYWNsL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Im9iajEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NDUzMjM2NiIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0k3Qm45R1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL29iajEvMTUzODA1MTA0NDUzMjM2Ni91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vb2JqMS9hY2wvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Im9iajEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NDUzMjM2NiIsImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJyb2xlIjoiT1dORVIiLCJlbWFpbCI6IjM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiZXRhZyI6IkNJN0JuOUdXMjkwQ0VBRT0ifV0sIm93bmVyIjp7ImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20ifSwiY3JjMzJjIjoiKzdSMTFnPT0iLCJldGFnIjoiQ0k3Qm45R1cyOTBDRUFFPSJ9"
+ }
+ },
+ {
+ "ID": "fd29f689761e4b31",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/obj2?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "5ef1744d10c7648379162c035275d3ce/13443665140433868065;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/obj2?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3243"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:06 GMT"
+ ],
+ "Etag": [
+ "CNeSxNGW290CEAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051345000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrjd27:4293,/bns/yw/borg/yw/bns/blobstore2/bitpusher/199.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=5susW-XiAsi7N6meoOAN"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yw/borg/yw/bns/blobstore2/bitpusher/199.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yw/borg/yw/bns/blobstore2/bitpusher/199:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRYnFLZDRCTjBkdm9mZm9PZVZZS0p1VDRROFVJT3NhUTljbFFvbW42UElpcDBpenczVUc1ZHZUMVZlZE1OWGp3cHJDNUUyam9FUUZwbldFellKMWd5Tlp1T3o4dy16UUMxaXAtb3VNMjdkM0JqNGR4SmNfUDVYRXRjeHNYWVN3LXNuNXEtcXpLZ1NvM3BKMGx4Ym9YaGNlZHBiR2t6VGVSdlc5QnVxZDFESV9pbE84ZEFXSDVOLVJnNDQwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UqgmMt-wtS-BgBfPzVeYLqOCQ0Qmx2zZ1U1FHnzAkejIWwPi4nApt9w5rDFHnWQ1IcBGrR-SRfChmDHctco-1F1ILIAKQ"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmoyLzE1MzgwNTEwNDUxMzI2MzEiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9vYmoyIiwibmFtZSI6Im9iajIiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NTEzMjYzMSIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbiIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDowNS4xMzJaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MDUuMTMyWiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjA1LjEzMloiLCJzaXplIjoiMTYiLCJtZDVIYXNoIjoiaDY0bVlxSjJPNTRqcnhHT0pOeUd4UT09IiwibWVkaWFMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vZG93bmxvYWQvc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iajI/Z2VuZXJhdGlvbj0xNTM4MDUxMDQ1MTMyNjMxJmFsdD1tZWRpYSIsImNhY2hlQ29udHJvbCI6InB1YmxpYywgbWF4LWFnZT02MCIsImFjbCI6W3sia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL29iajIvMTUzODA1MTA0NTEzMjYzMS9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iajIvYWNsL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0Ijoib2JqMiIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDQ1MTMyNjMxIiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDTmVTeE5HVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqMi8xNTM4MDUxMDQ1MTMyNjMxL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iajIvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Im9iajIiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NTEzMjYzMSIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDTmVTeE5HVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqMi8xNTM4MDUxMDQ1MTMyNjMxL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iajIvYWNsL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Im9iajIiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NTEzMjYzMSIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ05lU3hOR1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL29iajIvMTUzODA1MTA0NTEzMjYzMS91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vb2JqMi9hY2wvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Im9iajIiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NTEzMjYzMSIsImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJyb2xlIjoiT1dORVIiLCJlbWFpbCI6IjM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiZXRhZyI6IkNOZVN4TkdXMjkwQ0VBRT0ifV0sIm93bmVyIjp7ImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20ifSwiY3JjMzJjIjoiM0RLRHFnPT0iLCJldGFnIjoiQ05lU3hOR1cyOTBDRUFFPSJ9"
+ }
+ },
+ {
+ "ID": "3a99a037e206464a",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026delimiter=\u0026pageToken=\u0026prefix=obj\u0026prettyPrint=false\u0026projection=full\u0026versions=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "a25e5213318efa4ed40e3e176bf3f0a8/14202702109855000689;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026delimiter=\u0026pageToken=\u0026prefix=obj\u0026prettyPrint=false\u0026projection=full\u0026versions=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0, must-revalidate, no-transform"
+ ],
+ "Content-Length": [
+ "9984"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:06 GMT"
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:24:06 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051345000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vnfg189:4335,/bns/yx/borg/yx/bns/blobstore2/bitpusher/126.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=5susW4qoB4yRzgKW0YXoBw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yx/borg/yx/bns/blobstore2/bitpusher/126.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yx/borg/yx/bns/blobstore2/bitpusher/126:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRYnFLZDRCTjBkdm9mZm9PZVZZS0p1VDRROFVJT3NhUTljbFFvbW42UElpcDBpenczVUc1ZHZUMVZlZE1OWGp3cHJDNUUyam9FUUZwbldFellKMWd5Tlp1T3o4dy16UUMxaXAtb3VNMjdkM0JqNGR4SmNfUDVYRXRjeHNYWVN3LXNuNXEtcXpLZ1NvM3BKMGx4Ym9YaGNlZHBiR2t6VGVSdlc5QnVxZDFESV9pbE84ZEFXSDVOLVJnNDQwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Uq8-aSvhpGNPv1tZlVtCWggTQXXV-f_thkZHH9rzlZP4_417Hx7jMyrGCez1n-6RObqAxU6Ykn6e93l54fIxaqB2KyWNg"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3RzIiwiaXRlbXMiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL29iai93aXRoL3NsYXNoZXMvMTUzODA1MTA0NTYyNzE5OCIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iaiUyRndpdGglMkZzbGFzaGVzIiwibmFtZSI6Im9iai93aXRoL3NsYXNoZXMiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NTYyNzE5OCIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbiIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDowNS42MjdaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MDUuNjI3WiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjA1LjYyN1oiLCJzaXplIjoiMTYiLCJtZDVIYXNoIjoiKzdtVm42TFR3RG5WM3RnL3BDcmlvdz09IiwibWVkaWFMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vZG93bmxvYWQvc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iaiUyRndpdGglMkZzbGFzaGVzP2dlbmVyYXRpb249MTUzODA1MTA0NTYyNzE5OCZhbHQ9bWVkaWEiLCJjYWNoZUNvbnRyb2wiOiJwdWJsaWMsIG1heC1hZ2U9NjAiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmovd2l0aC9zbGFzaGVzLzE1MzgwNTEwNDU2MjcxOTgvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9vYmolMkZ3aXRoJTJGc2xhc2hlcy9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJvYmovd2l0aC9zbGFzaGVzIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNDU2MjcxOTgiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNMNnE0dEdXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmovd2l0aC9zbGFzaGVzLzE1MzgwNTEwNDU2MjcxOTgvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vb2JqJTJGd2l0aCUyRnNsYXNoZXMvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Im9iai93aXRoL3NsYXNoZXMiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NTYyNzE5OCIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDTDZxNHRHVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqL3dpdGgvc2xhc2hlcy8xNTM4MDUxMDQ1NjI3MTk4L3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iaiUyRndpdGglMkZzbGFzaGVzL2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJvYmovd2l0aC9zbGFzaGVzIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNDU2MjcxOTgiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNMNnE0dEdXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmovd2l0aC9zbGFzaGVzLzE1MzgwNTEwNDU2MjcxOTgvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iaiUyRndpdGglMkZzbGFzaGVzL2FjbC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0Ijoib2JqL3dpdGgvc2xhc2hlcyIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDQ1NjI3MTk4IiwiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInJvbGUiOiJPV05FUiIsImVtYWlsIjoiMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJldGFnIjoiQ0w2cTR0R1cyOTBDRUFFPSJ9XSwib3duZXIiOnsiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSJ9LCJjcmMzMmMiOiJrU3NXUWc9PSIsImV0YWciOiJDTDZxNHRHVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmoxLzE1MzgwNTEwNDQ1MzIzNjYiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9vYmoxIiwibmFtZSI6Im9iajEiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NDUzMjM2NiIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbiIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDowNC41MzJaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MDQuNTMyWiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjA0LjUzMloiLCJzaXplIjoiMTYiLCJtZDVIYXNoIjoiN3dVRkg4bUREd0hGWXFvN29seGRQZz09IiwibWVkaWFMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vZG93bmxvYWQvc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iajE/Z2VuZXJhdGlvbj0xNTM4MDUxMDQ0NTMyMzY2JmFsdD1tZWRpYSIsImNhY2hlQ29udHJvbCI6InB1YmxpYywgbWF4LWFnZT02MCIsImFjbCI6W3sia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL29iajEvMTUzODA1MTA0NDUzMjM2Ni9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iajEvYWNsL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0Ijoib2JqMSIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDQ0NTMyMzY2IiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDSTdCbjlHVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqMS8xNTM4MDUxMDQ0NTMyMzY2L3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iajEvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Im9iajEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NDUzMjM2NiIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDSTdCbjlHVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqMS8xNTM4MDUxMDQ0NTMyMzY2L3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iajEvYWNsL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Im9iajEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NDUzMjM2NiIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0k3Qm45R1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL29iajEvMTUzODA1MTA0NDUzMjM2Ni91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vb2JqMS9hY2wvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Im9iajEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NDUzMjM2NiIsImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJyb2xlIjoiT1dORVIiLCJlbWFpbCI6IjM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiZXRhZyI6IkNJN0JuOUdXMjkwQ0VBRT0ifV0sIm93bmVyIjp7ImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20ifSwiY3JjMzJjIjoiKzdSMTFnPT0iLCJldGFnIjoiQ0k3Qm45R1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0IiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqMi8xNTM4MDUxMDQ1MTMyNjMxIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vb2JqMiIsIm5hbWUiOiJvYmoyIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNDUxMzI2MzEiLCJtZXRhZ2VuZXJhdGlvbiI6IjEiLCJjb250ZW50VHlwZSI6InRleHQvcGxhaW4iLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MDUuMTMyWiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjA1LjEzMloiLCJzdG9yYWdlQ2xhc3MiOiJTVEFOREFSRCIsInRpbWVTdG9yYWdlQ2xhc3NVcGRhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDowNS4xMzJaIiwic2l6ZSI6IjE2IiwibWQ1SGFzaCI6Img2NG1ZcUoyTzU0anJ4R09KTnlHeFE9PSIsIm1lZGlhTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2Rvd25sb2FkL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9vYmoyP2dlbmVyYXRpb249MTUzODA1MTA0NTEzMjYzMSZhbHQ9bWVkaWEiLCJjYWNoZUNvbnRyb2wiOiJwdWJsaWMsIG1heC1hZ2U9NjAiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmoyLzE1MzgwNTEwNDUxMzI2MzEvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9vYmoyL2FjbC9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Im9iajIiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NTEzMjYzMSIsImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6Im93bmVycyJ9LCJldGFnIjoiQ05lU3hOR1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL29iajIvMTUzODA1MTA0NTEzMjYzMS9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9vYmoyL2FjbC9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJvYmoyIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNDUxMzI2MzEiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ05lU3hOR1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL29iajIvMTUzODA1MTA0NTEzMjYzMS9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9vYmoyL2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJvYmoyIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNDUxMzI2MzEiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNOZVN4TkdXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmoyLzE1MzgwNTEwNDUxMzI2MzEvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iajIvYWNsL3VzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJvYmoyIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNDUxMzI2MzEiLCJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwicm9sZSI6Ik9XTkVSIiwiZW1haWwiOiIzNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImV0YWciOiJDTmVTeE5HVzI5MENFQUU9In1dLCJvd25lciI6eyJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIn0sImNyYzMyYyI6IjNES0RxZz09IiwiZXRhZyI6IkNOZVN4TkdXMjkwQ0VBRT0ifV19"
+ }
+ },
+ {
+ "ID": "87bd688d342c7b80",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026delimiter=\u0026maxResults=1\u0026pageToken=\u0026prefix=obj\u0026prettyPrint=false\u0026projection=full\u0026versions=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "ac7c5ab79ebed4a783e660562aa2bb30/15034077040189340608;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026delimiter=\u0026maxResults=1\u0026pageToken=\u0026prefix=obj\u0026prettyPrint=false\u0026projection=full\u0026versions=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0, must-revalidate, no-transform"
+ ],
+ "Content-Length": [
+ "3539"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:06 GMT"
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:24:06 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051345000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vref6:4304,/bns/yr/borg/yr/bns/blobstore2/bitpusher/7.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=5susW9n6H6WLkAT2zYCwBA"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/7.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/7:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRYnFLZDRCTjBkdm9mZm9PZVZZS0p1VDRROFVJT3NhUTljbFFvbW42UElpcDBpenczVUc1ZHZUMVZlZE1OWGp3cHJDNUUyam9FUUZwbldFellKMWd5Tlp1T3o4dy16UUMxaXAtb3VNMjdkM0JqNGR4SmNfUDVYRXRjeHNYWVN3LXNuNXEtcXpLZ1NvM3BKMGx4Ym9YaGNlZHBiR2t6VGVSdlc5QnVxZDFESV9pbE84ZEFXSDVOLVJnNDQwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UodVTmI8-rEEYuBuGV3NiJB5_ZJMdLVpSon2_dvC4U7PFLgToJlhr6reTs3-Fy_euNgshBmySmDhaywOqXEM45PX4Pj4Q"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3RzIiwibmV4dFBhZ2VUb2tlbiI6IkNoQnZZbW92ZDJsMGFDOXpiR0Z6YUdWeiIsIml0ZW1zIjpbeyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmovd2l0aC9zbGFzaGVzLzE1MzgwNTEwNDU2MjcxOTgiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9vYmolMkZ3aXRoJTJGc2xhc2hlcyIsIm5hbWUiOiJvYmovd2l0aC9zbGFzaGVzIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNDU2MjcxOTgiLCJtZXRhZ2VuZXJhdGlvbiI6IjEiLCJjb250ZW50VHlwZSI6InRleHQvcGxhaW4iLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MDUuNjI3WiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjA1LjYyN1oiLCJzdG9yYWdlQ2xhc3MiOiJTVEFOREFSRCIsInRpbWVTdG9yYWdlQ2xhc3NVcGRhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDowNS42MjdaIiwic2l6ZSI6IjE2IiwibWQ1SGFzaCI6Iis3bVZuNkxUd0RuVjN0Zy9wQ3Jpb3c9PSIsIm1lZGlhTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2Rvd25sb2FkL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9vYmolMkZ3aXRoJTJGc2xhc2hlcz9nZW5lcmF0aW9uPTE1MzgwNTEwNDU2MjcxOTgmYWx0PW1lZGlhIiwiY2FjaGVDb250cm9sIjoicHVibGljLCBtYXgtYWdlPTYwIiwiYWNsIjpbeyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqL3dpdGgvc2xhc2hlcy8xNTM4MDUxMDQ1NjI3MTk4L3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vb2JqJTJGd2l0aCUyRnNsYXNoZXMvYWNsL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0Ijoib2JqL3dpdGgvc2xhc2hlcyIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDQ1NjI3MTk4IiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDTDZxNHRHVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqL3dpdGgvc2xhc2hlcy8xNTM4MDUxMDQ1NjI3MTk4L3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iaiUyRndpdGglMkZzbGFzaGVzL2FjbC9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJvYmovd2l0aC9zbGFzaGVzIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNDU2MjcxOTgiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0w2cTR0R1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL29iai93aXRoL3NsYXNoZXMvMTUzODA1MTA0NTYyNzE5OC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9vYmolMkZ3aXRoJTJGc2xhc2hlcy9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0Ijoib2JqL3dpdGgvc2xhc2hlcyIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDQ1NjI3MTk4IiwiZW50aXR5IjoicHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6IlJFQURFUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJ2aWV3ZXJzIn0sImV0YWciOiJDTDZxNHRHVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqL3dpdGgvc2xhc2hlcy8xNTM4MDUxMDQ1NjI3MTk4L3VzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9vYmolMkZ3aXRoJTJGc2xhc2hlcy9hY2wvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Im9iai93aXRoL3NsYXNoZXMiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NTYyNzE5OCIsImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJyb2xlIjoiT1dORVIiLCJlbWFpbCI6IjM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiZXRhZyI6IkNMNnE0dEdXMjkwQ0VBRT0ifV0sIm93bmVyIjp7ImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20ifSwiY3JjMzJjIjoia1NzV1FnPT0iLCJldGFnIjoiQ0w2cTR0R1cyOTBDRUFFPSJ9XX0="
+ }
+ },
+ {
+ "ID": "7b63dd3875d7c28c",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026delimiter=\u0026maxResults=1\u0026pageToken=ChBvYmovd2l0aC9zbGFzaGVz\u0026prefix=obj\u0026prettyPrint=false\u0026projection=full\u0026versions=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "937f7093bd739fcc09bb93cd0d47a9da/15793114009610538511;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026delimiter=\u0026maxResults=1\u0026pageToken=ChBvYmovd2l0aC9zbGFzaGVz\u0026prefix=obj\u0026prettyPrint=false\u0026projection=full\u0026versions=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0, must-revalidate, no-transform"
+ ],
+ "Content-Length": [
+ "3307"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:07 GMT"
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:24:07 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051345000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrmt5:4328,/bns/yv/borg/yv/bns/blobstore2/bitpusher/272.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=5susW5u9OIWYNtLmguAE"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/272.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/272:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRYnFLZDRCTjBkdm9mZm9PZVZZS0p1VDRROFVJT3NhUTljbFFvbW42UElpcDBpenczVUc1ZHZUMVZlZE1OWGp3cHJDNUUyam9FUUZwbldFellKMWd5Tlp1T3o4dy16UUMxaXAtb3VNMjdkM0JqNGR4SmNfUDVYRXRjeHNYWVN3LXNuNXEtcXpLZ1NvM3BKMGx4Ym9YaGNlZHBiR2t6VGVSdlc5QnVxZDFESV9pbE84ZEFXSDVOLVJnNDQwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UrviMDK5gl_QwiDaGX3mzHAHBar0t6nLEe_ZgxZFdBvPDPwZoNEb0G5YHcmXZ3oxTt2tZcg58WXTi5sLL3cdKn52R-rww"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3RzIiwibmV4dFBhZ2VUb2tlbiI6IkNnUnZZbW94IiwiaXRlbXMiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL29iajEvMTUzODA1MTA0NDUzMjM2NiIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iajEiLCJuYW1lIjoib2JqMSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDQ0NTMyMzY2IiwibWV0YWdlbmVyYXRpb24iOiIxIiwiY29udGVudFR5cGUiOiJ0ZXh0L3BsYWluIiwidGltZUNyZWF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjA0LjUzMloiLCJ1cGRhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDowNC41MzJaIiwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJ0aW1lU3RvcmFnZUNsYXNzVXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MDQuNTMyWiIsInNpemUiOiIxNiIsIm1kNUhhc2giOiI3d1VGSDhtRER3SEZZcW83b2x4ZFBnPT0iLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vb2JqMT9nZW5lcmF0aW9uPTE1MzgwNTEwNDQ1MzIzNjYmYWx0PW1lZGlhIiwiY2FjaGVDb250cm9sIjoicHVibGljLCBtYXgtYWdlPTYwIiwiYWNsIjpbeyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqMS8xNTM4MDUxMDQ0NTMyMzY2L3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vb2JqMS9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJvYmoxIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNDQ1MzIzNjYiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNJN0JuOUdXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmoxLzE1MzgwNTEwNDQ1MzIzNjYvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vb2JqMS9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0Ijoib2JqMSIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDQ0NTMyMzY2IiwiZW50aXR5IjoicHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6ImVkaXRvcnMifSwiZXRhZyI6IkNJN0JuOUdXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmoxLzE1MzgwNTEwNDQ1MzIzNjYvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vb2JqMS9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0Ijoib2JqMSIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDQ0NTMyMzY2IiwiZW50aXR5IjoicHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6IlJFQURFUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJ2aWV3ZXJzIn0sImV0YWciOiJDSTdCbjlHVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqMS8xNTM4MDUxMDQ0NTMyMzY2L3VzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9vYmoxL2FjbC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0Ijoib2JqMSIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDQ0NTMyMzY2IiwiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInJvbGUiOiJPV05FUiIsImVtYWlsIjoiMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJldGFnIjoiQ0k3Qm45R1cyOTBDRUFFPSJ9XSwib3duZXIiOnsiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSJ9LCJjcmMzMmMiOiIrN1IxMWc9PSIsImV0YWciOiJDSTdCbjlHVzI5MENFQUU9In1dfQ=="
+ }
+ },
+ {
+ "ID": "59779a32ce3325d0",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026delimiter=\u0026maxResults=1\u0026pageToken=CgRvYmox\u0026prefix=obj\u0026prettyPrint=false\u0026projection=full\u0026versions=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "d06f76647120968faf6801e7f847bcc2/16624207473574748255;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026delimiter=\u0026maxResults=1\u0026pageToken=CgRvYmox\u0026prefix=obj\u0026prettyPrint=false\u0026projection=full\u0026versions=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0, must-revalidate, no-transform"
+ ],
+ "Content-Length": [
+ "3280"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:07 GMT"
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:24:07 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051345000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrdz80:4263,/bns/yr/borg/yr/bns/blobstore2/bitpusher/117.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=58usW6y2E8KnkASClZioBg"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/117.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/117:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRYnFLZDRCTjBkdm9mZm9PZVZZS0p1VDRROFVJT3NhUTljbFFvbW42UElpcDBpenczVUc1ZHZUMVZlZE1OWGp3cHJDNUUyam9FUUZwbldFellKMWd5Tlp1T3o4dy16UUMxaXAtb3VNMjdkM0JqNGR4SmNfUDVYRXRjeHNYWVN3LXNuNXEtcXpLZ1NvM3BKMGx4Ym9YaGNlZHBiR2t6VGVSdlc5QnVxZDFESV9pbE84ZEFXSDVOLVJnNDQwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Uq40wlm8PHg-66CKFvxN1syf6zO6TMU7Xj-aJ7JDRDW9tYTHZL1z-WYOQaoHQzcI9BoMQyck1-Q3_V0qsPeeOAqdja9DA"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3RzIiwiaXRlbXMiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL29iajIvMTUzODA1MTA0NTEzMjYzMSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iajIiLCJuYW1lIjoib2JqMiIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDQ1MTMyNjMxIiwibWV0YWdlbmVyYXRpb24iOiIxIiwiY29udGVudFR5cGUiOiJ0ZXh0L3BsYWluIiwidGltZUNyZWF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjA1LjEzMloiLCJ1cGRhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDowNS4xMzJaIiwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJ0aW1lU3RvcmFnZUNsYXNzVXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MDUuMTMyWiIsInNpemUiOiIxNiIsIm1kNUhhc2giOiJoNjRtWXFKMk81NGpyeEdPSk55R3hRPT0iLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vb2JqMj9nZW5lcmF0aW9uPTE1MzgwNTEwNDUxMzI2MzEmYWx0PW1lZGlhIiwiY2FjaGVDb250cm9sIjoicHVibGljLCBtYXgtYWdlPTYwIiwiYWNsIjpbeyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqMi8xNTM4MDUxMDQ1MTMyNjMxL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vb2JqMi9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJvYmoyIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNDUxMzI2MzEiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNOZVN4TkdXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmoyLzE1MzgwNTEwNDUxMzI2MzEvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vb2JqMi9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0Ijoib2JqMiIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDQ1MTMyNjMxIiwiZW50aXR5IjoicHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6ImVkaXRvcnMifSwiZXRhZyI6IkNOZVN4TkdXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmoyLzE1MzgwNTEwNDUxMzI2MzEvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vb2JqMi9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0Ijoib2JqMiIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDQ1MTMyNjMxIiwiZW50aXR5IjoicHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6IlJFQURFUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJ2aWV3ZXJzIn0sImV0YWciOiJDTmVTeE5HVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqMi8xNTM4MDUxMDQ1MTMyNjMxL3VzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9vYmoyL2FjbC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0Ijoib2JqMiIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDQ1MTMyNjMxIiwiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInJvbGUiOiJPV05FUiIsImVtYWlsIjoiMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJldGFnIjoiQ05lU3hOR1cyOTBDRUFFPSJ9XSwib3duZXIiOnsiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSJ9LCJjcmMzMmMiOiIzREtEcWc9PSIsImV0YWciOiJDTmVTeE5HVzI5MENFQUU9In1dfQ=="
+ }
+ },
+ {
+ "ID": "46a89f8b19abcfdf",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026delimiter=\u0026maxResults=1\u0026pageToken=\u0026prefix=obj\u0026prettyPrint=false\u0026projection=full\u0026versions=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "ce942d957abe25aa51aff8c6a8902b6b/17383525913677689774;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026delimiter=\u0026maxResults=1\u0026pageToken=\u0026prefix=obj\u0026prettyPrint=false\u0026projection=full\u0026versions=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0, must-revalidate, no-transform"
+ ],
+ "Content-Length": [
+ "3539"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:07 GMT"
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:24:07 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051345000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrbs9:4050,/bns/yw/borg/yw/bns/blobstore2/bitpusher/189.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=58usW4OzH9X4hASTgpuYBA"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yw/borg/yw/bns/blobstore2/bitpusher/189.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yw/borg/yw/bns/blobstore2/bitpusher/189:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRYnFLZDRCTjBkdm9mZm9PZVZZS0p1VDRROFVJT3NhUTljbFFvbW42UElpcDBpenczVUc1ZHZUMVZlZE1OWGp3cHJDNUUyam9FUUZwbldFellKMWd5Tlp1T3o4dy16UUMxaXAtb3VNMjdkM0JqNGR4SmNfUDVYRXRjeHNYWVN3LXNuNXEtcXpLZ1NvM3BKMGx4Ym9YaGNlZHBiR2t6VGVSdlc5QnVxZDFESV9pbE84ZEFXSDVOLVJnNDQwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UpQMRp8raCulwW2LTGhYSz7tHVHxIJbJ2q8npzOrKBD6muvVlF2UE51EYCDu_VrFVYkI0Vif55kF4HrCCcrG1sIMrNAqA"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3RzIiwibmV4dFBhZ2VUb2tlbiI6IkNoQnZZbW92ZDJsMGFDOXpiR0Z6YUdWeiIsIml0ZW1zIjpbeyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmovd2l0aC9zbGFzaGVzLzE1MzgwNTEwNDU2MjcxOTgiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9vYmolMkZ3aXRoJTJGc2xhc2hlcyIsIm5hbWUiOiJvYmovd2l0aC9zbGFzaGVzIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNDU2MjcxOTgiLCJtZXRhZ2VuZXJhdGlvbiI6IjEiLCJjb250ZW50VHlwZSI6InRleHQvcGxhaW4iLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MDUuNjI3WiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjA1LjYyN1oiLCJzdG9yYWdlQ2xhc3MiOiJTVEFOREFSRCIsInRpbWVTdG9yYWdlQ2xhc3NVcGRhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDowNS42MjdaIiwic2l6ZSI6IjE2IiwibWQ1SGFzaCI6Iis3bVZuNkxUd0RuVjN0Zy9wQ3Jpb3c9PSIsIm1lZGlhTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2Rvd25sb2FkL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9vYmolMkZ3aXRoJTJGc2xhc2hlcz9nZW5lcmF0aW9uPTE1MzgwNTEwNDU2MjcxOTgmYWx0PW1lZGlhIiwiY2FjaGVDb250cm9sIjoicHVibGljLCBtYXgtYWdlPTYwIiwiYWNsIjpbeyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqL3dpdGgvc2xhc2hlcy8xNTM4MDUxMDQ1NjI3MTk4L3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vb2JqJTJGd2l0aCUyRnNsYXNoZXMvYWNsL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0Ijoib2JqL3dpdGgvc2xhc2hlcyIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDQ1NjI3MTk4IiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDTDZxNHRHVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqL3dpdGgvc2xhc2hlcy8xNTM4MDUxMDQ1NjI3MTk4L3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iaiUyRndpdGglMkZzbGFzaGVzL2FjbC9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJvYmovd2l0aC9zbGFzaGVzIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNDU2MjcxOTgiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0w2cTR0R1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL29iai93aXRoL3NsYXNoZXMvMTUzODA1MTA0NTYyNzE5OC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9vYmolMkZ3aXRoJTJGc2xhc2hlcy9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0Ijoib2JqL3dpdGgvc2xhc2hlcyIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDQ1NjI3MTk4IiwiZW50aXR5IjoicHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6IlJFQURFUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJ2aWV3ZXJzIn0sImV0YWciOiJDTDZxNHRHVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqL3dpdGgvc2xhc2hlcy8xNTM4MDUxMDQ1NjI3MTk4L3VzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9vYmolMkZ3aXRoJTJGc2xhc2hlcy9hY2wvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Im9iai93aXRoL3NsYXNoZXMiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NTYyNzE5OCIsImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJyb2xlIjoiT1dORVIiLCJlbWFpbCI6IjM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiZXRhZyI6IkNMNnE0dEdXMjkwQ0VBRT0ifV0sIm93bmVyIjp7ImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20ifSwiY3JjMzJjIjoia1NzV1FnPT0iLCJldGFnIjoiQ0w2cTR0R1cyOTBDRUFFPSJ9XX0="
+ }
+ },
+ {
+ "ID": "4af251bb107b46bd",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026delimiter=\u0026maxResults=1\u0026pageToken=ChBvYmovd2l0aC9zbGFzaGVz\u0026prefix=obj\u0026prettyPrint=false\u0026projection=full\u0026versions=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "61ba81076b6b0450edaa3960a50b144b/18214619377625188093;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026delimiter=\u0026maxResults=1\u0026pageToken=ChBvYmovd2l0aC9zbGFzaGVz\u0026prefix=obj\u0026prettyPrint=false\u0026projection=full\u0026versions=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0, must-revalidate, no-transform"
+ ],
+ "Content-Length": [
+ "3307"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:08 GMT"
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:24:08 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051345000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vnbn6:4287,/bns/yx/borg/yx/bns/blobstore2/bitpusher/64.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=58usW8eJOMeMzQK1zJDgDA"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yx/borg/yx/bns/blobstore2/bitpusher/64.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yx/borg/yx/bns/blobstore2/bitpusher/64:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRYnFLZDRCTjBkdm9mZm9PZVZZS0p1VDRROFVJT3NhUTljbFFvbW42UElpcDBpenczVUc1ZHZUMVZlZE1OWGp3cHJDNUUyam9FUUZwbldFellKMWd5Tlp1T3o4dy16UUMxaXAtb3VNMjdkM0JqNGR4SmNfUDVYRXRjeHNYWVN3LXNuNXEtcXpLZ1NvM3BKMGx4Ym9YaGNlZHBiR2t6VGVSdlc5QnVxZDFESV9pbE84ZEFXSDVOLVJnNDQwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Uoi7JdVKHjUAAoH_OUZ1lBy-m08Ahe2SVpkEcrEN8fXfs2-GztOUpsnFM0j4d2DWAVN_wpcAi2bZB8SZ9gaEORasVy2Bw"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3RzIiwibmV4dFBhZ2VUb2tlbiI6IkNnUnZZbW94IiwiaXRlbXMiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL29iajEvMTUzODA1MTA0NDUzMjM2NiIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iajEiLCJuYW1lIjoib2JqMSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDQ0NTMyMzY2IiwibWV0YWdlbmVyYXRpb24iOiIxIiwiY29udGVudFR5cGUiOiJ0ZXh0L3BsYWluIiwidGltZUNyZWF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjA0LjUzMloiLCJ1cGRhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDowNC41MzJaIiwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJ0aW1lU3RvcmFnZUNsYXNzVXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MDQuNTMyWiIsInNpemUiOiIxNiIsIm1kNUhhc2giOiI3d1VGSDhtRER3SEZZcW83b2x4ZFBnPT0iLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vb2JqMT9nZW5lcmF0aW9uPTE1MzgwNTEwNDQ1MzIzNjYmYWx0PW1lZGlhIiwiY2FjaGVDb250cm9sIjoicHVibGljLCBtYXgtYWdlPTYwIiwiYWNsIjpbeyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqMS8xNTM4MDUxMDQ0NTMyMzY2L3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vb2JqMS9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJvYmoxIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNDQ1MzIzNjYiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNJN0JuOUdXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmoxLzE1MzgwNTEwNDQ1MzIzNjYvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vb2JqMS9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0Ijoib2JqMSIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDQ0NTMyMzY2IiwiZW50aXR5IjoicHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6ImVkaXRvcnMifSwiZXRhZyI6IkNJN0JuOUdXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmoxLzE1MzgwNTEwNDQ1MzIzNjYvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vb2JqMS9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0Ijoib2JqMSIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDQ0NTMyMzY2IiwiZW50aXR5IjoicHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6IlJFQURFUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJ2aWV3ZXJzIn0sImV0YWciOiJDSTdCbjlHVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqMS8xNTM4MDUxMDQ0NTMyMzY2L3VzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9vYmoxL2FjbC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0Ijoib2JqMSIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDQ0NTMyMzY2IiwiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInJvbGUiOiJPV05FUiIsImVtYWlsIjoiMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJldGFnIjoiQ0k3Qm45R1cyOTBDRUFFPSJ9XSwib3duZXIiOnsiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSJ9LCJjcmMzMmMiOiIrN1IxMWc9PSIsImV0YWciOiJDSTdCbjlHVzI5MENFQUU9In1dfQ=="
+ }
+ },
+ {
+ "ID": "60d1026a4e479c3a",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026delimiter=\u0026maxResults=1\u0026pageToken=CgRvYmox\u0026prefix=obj\u0026prettyPrint=false\u0026projection=full\u0026versions=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "efd38d87265a668abdf5e34ef236c3d7/527475218995222861;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026delimiter=\u0026maxResults=1\u0026pageToken=CgRvYmox\u0026prefix=obj\u0026prettyPrint=false\u0026projection=full\u0026versions=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0, must-revalidate, no-transform"
+ ],
+ "Content-Length": [
+ "3280"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:08 GMT"
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:24:08 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051345000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrbp63:4132,/bns/yr/borg/yr/bns/blobstore2/bitpusher/1.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=6MusW4fdE4eTkATnw5OYAQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/1.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/1:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRYnFLZDRCTjBkdm9mZm9PZVZZS0p1VDRROFVJT3NhUTljbFFvbW42UElpcDBpenczVUc1ZHZUMVZlZE1OWGp3cHJDNUUyam9FUUZwbldFellKMWd5Tlp1T3o4dy16UUMxaXAtb3VNMjdkM0JqNGR4SmNfUDVYRXRjeHNYWVN3LXNuNXEtcXpLZ1NvM3BKMGx4Ym9YaGNlZHBiR2t6VGVSdlc5QnVxZDFESV9pbE84ZEFXSDVOLVJnNDQwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UooQI_nQGXwTtfxZywLyy4MI3ZXK3zGGOxqVcN34fwGrkHZvYi96r1Wo-XBskmWVEGXA_QFGBrdOVDNoW-oQ2ruqqXFQw"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3RzIiwiaXRlbXMiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL29iajIvMTUzODA1MTA0NTEzMjYzMSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iajIiLCJuYW1lIjoib2JqMiIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDQ1MTMyNjMxIiwibWV0YWdlbmVyYXRpb24iOiIxIiwiY29udGVudFR5cGUiOiJ0ZXh0L3BsYWluIiwidGltZUNyZWF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjA1LjEzMloiLCJ1cGRhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDowNS4xMzJaIiwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJ0aW1lU3RvcmFnZUNsYXNzVXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MDUuMTMyWiIsInNpemUiOiIxNiIsIm1kNUhhc2giOiJoNjRtWXFKMk81NGpyeEdPSk55R3hRPT0iLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vb2JqMj9nZW5lcmF0aW9uPTE1MzgwNTEwNDUxMzI2MzEmYWx0PW1lZGlhIiwiY2FjaGVDb250cm9sIjoicHVibGljLCBtYXgtYWdlPTYwIiwiYWNsIjpbeyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqMi8xNTM4MDUxMDQ1MTMyNjMxL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vb2JqMi9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJvYmoyIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNDUxMzI2MzEiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNOZVN4TkdXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmoyLzE1MzgwNTEwNDUxMzI2MzEvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vb2JqMi9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0Ijoib2JqMiIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDQ1MTMyNjMxIiwiZW50aXR5IjoicHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6ImVkaXRvcnMifSwiZXRhZyI6IkNOZVN4TkdXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmoyLzE1MzgwNTEwNDUxMzI2MzEvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vb2JqMi9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0Ijoib2JqMiIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDQ1MTMyNjMxIiwiZW50aXR5IjoicHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6IlJFQURFUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJ2aWV3ZXJzIn0sImV0YWciOiJDTmVTeE5HVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqMi8xNTM4MDUxMDQ1MTMyNjMxL3VzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9vYmoyL2FjbC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0Ijoib2JqMiIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDQ1MTMyNjMxIiwiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInJvbGUiOiJPV05FUiIsImVtYWlsIjoiMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJldGFnIjoiQ05lU3hOR1cyOTBDRUFFPSJ9XSwib3duZXIiOnsiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSJ9LCJjcmMzMmMiOiIzREtEcWc9PSIsImV0YWciOiJDTmVTeE5HVzI5MENFQUU9In1dfQ=="
+ }
+ },
+ {
+ "ID": "d8d0c6f8532afe45",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026delimiter=\u0026maxResults=2\u0026pageToken=\u0026prefix=obj\u0026prettyPrint=false\u0026projection=full\u0026versions=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "23aa59ef8b1a656a7a57764481f249e3/1358567583464647580;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026delimiter=\u0026maxResults=2\u0026pageToken=\u0026prefix=obj\u0026prettyPrint=false\u0026projection=full\u0026versions=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0, must-revalidate, no-transform"
+ ],
+ "Content-Length": [
+ "6767"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:09 GMT"
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:24:09 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051345000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrd1:4212,/bns/yv/borg/yv/bns/blobstore2/bitpusher/270.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=6MusW6ytLIykNvW7uMAB"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/270.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/270:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRYnFLZDRCTjBkdm9mZm9PZVZZS0p1VDRROFVJT3NhUTljbFFvbW42UElpcDBpenczVUc1ZHZUMVZlZE1OWGp3cHJDNUUyam9FUUZwbldFellKMWd5Tlp1T3o4dy16UUMxaXAtb3VNMjdkM0JqNGR4SmNfUDVYRXRjeHNYWVN3LXNuNXEtcXpLZ1NvM3BKMGx4Ym9YaGNlZHBiR2t6VGVSdlc5QnVxZDFESV9pbE84ZEFXSDVOLVJnNDQwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UqHH0Mn1RwMLRxs4f-RMGTZOM5qbCkUl9e7I3Lom4_LvmRJYFMuxPiPCLqx21QFNhAu6O32MjvHzGYk-Oce_hQ1ILQzoQ"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3RzIiwibmV4dFBhZ2VUb2tlbiI6IkNnUnZZbW94IiwiaXRlbXMiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL29iai93aXRoL3NsYXNoZXMvMTUzODA1MTA0NTYyNzE5OCIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iaiUyRndpdGglMkZzbGFzaGVzIiwibmFtZSI6Im9iai93aXRoL3NsYXNoZXMiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NTYyNzE5OCIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbiIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDowNS42MjdaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MDUuNjI3WiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjA1LjYyN1oiLCJzaXplIjoiMTYiLCJtZDVIYXNoIjoiKzdtVm42TFR3RG5WM3RnL3BDcmlvdz09IiwibWVkaWFMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vZG93bmxvYWQvc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iaiUyRndpdGglMkZzbGFzaGVzP2dlbmVyYXRpb249MTUzODA1MTA0NTYyNzE5OCZhbHQ9bWVkaWEiLCJjYWNoZUNvbnRyb2wiOiJwdWJsaWMsIG1heC1hZ2U9NjAiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmovd2l0aC9zbGFzaGVzLzE1MzgwNTEwNDU2MjcxOTgvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9vYmolMkZ3aXRoJTJGc2xhc2hlcy9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJvYmovd2l0aC9zbGFzaGVzIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNDU2MjcxOTgiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNMNnE0dEdXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmovd2l0aC9zbGFzaGVzLzE1MzgwNTEwNDU2MjcxOTgvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vb2JqJTJGd2l0aCUyRnNsYXNoZXMvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Im9iai93aXRoL3NsYXNoZXMiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NTYyNzE5OCIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDTDZxNHRHVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqL3dpdGgvc2xhc2hlcy8xNTM4MDUxMDQ1NjI3MTk4L3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iaiUyRndpdGglMkZzbGFzaGVzL2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJvYmovd2l0aC9zbGFzaGVzIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNDU2MjcxOTgiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNMNnE0dEdXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmovd2l0aC9zbGFzaGVzLzE1MzgwNTEwNDU2MjcxOTgvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iaiUyRndpdGglMkZzbGFzaGVzL2FjbC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0Ijoib2JqL3dpdGgvc2xhc2hlcyIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDQ1NjI3MTk4IiwiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInJvbGUiOiJPV05FUiIsImVtYWlsIjoiMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJldGFnIjoiQ0w2cTR0R1cyOTBDRUFFPSJ9XSwib3duZXIiOnsiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSJ9LCJjcmMzMmMiOiJrU3NXUWc9PSIsImV0YWciOiJDTDZxNHRHVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmoxLzE1MzgwNTEwNDQ1MzIzNjYiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9vYmoxIiwibmFtZSI6Im9iajEiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NDUzMjM2NiIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbiIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDowNC41MzJaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MDQuNTMyWiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjA0LjUzMloiLCJzaXplIjoiMTYiLCJtZDVIYXNoIjoiN3dVRkg4bUREd0hGWXFvN29seGRQZz09IiwibWVkaWFMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vZG93bmxvYWQvc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iajE/Z2VuZXJhdGlvbj0xNTM4MDUxMDQ0NTMyMzY2JmFsdD1tZWRpYSIsImNhY2hlQ29udHJvbCI6InB1YmxpYywgbWF4LWFnZT02MCIsImFjbCI6W3sia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL29iajEvMTUzODA1MTA0NDUzMjM2Ni9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iajEvYWNsL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0Ijoib2JqMSIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDQ0NTMyMzY2IiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDSTdCbjlHVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqMS8xNTM4MDUxMDQ0NTMyMzY2L3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iajEvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Im9iajEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NDUzMjM2NiIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDSTdCbjlHVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqMS8xNTM4MDUxMDQ0NTMyMzY2L3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iajEvYWNsL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Im9iajEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NDUzMjM2NiIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0k3Qm45R1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL29iajEvMTUzODA1MTA0NDUzMjM2Ni91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vb2JqMS9hY2wvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Im9iajEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NDUzMjM2NiIsImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJyb2xlIjoiT1dORVIiLCJlbWFpbCI6IjM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiZXRhZyI6IkNJN0JuOUdXMjkwQ0VBRT0ifV0sIm93bmVyIjp7ImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20ifSwiY3JjMzJjIjoiKzdSMTFnPT0iLCJldGFnIjoiQ0k3Qm45R1cyOTBDRUFFPSJ9XX0="
+ }
+ },
+ {
+ "ID": "f3574d5c0c1dda72",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026delimiter=\u0026maxResults=2\u0026pageToken=CgRvYmox\u0026prefix=obj\u0026prettyPrint=false\u0026projection=full\u0026versions=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "bb79afa8303a06e95456399e4c28d835/2117604548590943979;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026delimiter=\u0026maxResults=2\u0026pageToken=CgRvYmox\u0026prefix=obj\u0026prettyPrint=false\u0026projection=full\u0026versions=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0, must-revalidate, no-transform"
+ ],
+ "Content-Length": [
+ "3280"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:09 GMT"
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:24:09 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051345000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrub8:4298,/bns/yv/borg/yv/bns/blobstore2/bitpusher/178.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=6cusW_K_B8TIggSEmZeoDA"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/178.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/178:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRYnFLZDRCTjBkdm9mZm9PZVZZS0p1VDRROFVJT3NhUTljbFFvbW42UElpcDBpenczVUc1ZHZUMVZlZE1OWGp3cHJDNUUyam9FUUZwbldFellKMWd5Tlp1T3o4dy16UUMxaXAtb3VNMjdkM0JqNGR4SmNfUDVYRXRjeHNYWVN3LXNuNXEtcXpLZ1NvM3BKMGx4Ym9YaGNlZHBiR2t6VGVSdlc5QnVxZDFESV9pbE84ZEFXSDVOLVJnNDQwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UrOkBdaiMksr3Jzhg2qzo2Y0Z8zDuc8pB6dc1y4WcrURwCdoy16OrCLApc-xnSLoDqbIb6Qo3DspgAOuKPTwweB3uT-iQ"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3RzIiwiaXRlbXMiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL29iajIvMTUzODA1MTA0NTEzMjYzMSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iajIiLCJuYW1lIjoib2JqMiIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDQ1MTMyNjMxIiwibWV0YWdlbmVyYXRpb24iOiIxIiwiY29udGVudFR5cGUiOiJ0ZXh0L3BsYWluIiwidGltZUNyZWF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjA1LjEzMloiLCJ1cGRhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDowNS4xMzJaIiwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJ0aW1lU3RvcmFnZUNsYXNzVXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MDUuMTMyWiIsInNpemUiOiIxNiIsIm1kNUhhc2giOiJoNjRtWXFKMk81NGpyeEdPSk55R3hRPT0iLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vb2JqMj9nZW5lcmF0aW9uPTE1MzgwNTEwNDUxMzI2MzEmYWx0PW1lZGlhIiwiY2FjaGVDb250cm9sIjoicHVibGljLCBtYXgtYWdlPTYwIiwiYWNsIjpbeyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqMi8xNTM4MDUxMDQ1MTMyNjMxL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vb2JqMi9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJvYmoyIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNDUxMzI2MzEiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNOZVN4TkdXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmoyLzE1MzgwNTEwNDUxMzI2MzEvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vb2JqMi9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0Ijoib2JqMiIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDQ1MTMyNjMxIiwiZW50aXR5IjoicHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6ImVkaXRvcnMifSwiZXRhZyI6IkNOZVN4TkdXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmoyLzE1MzgwNTEwNDUxMzI2MzEvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vb2JqMi9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0Ijoib2JqMiIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDQ1MTMyNjMxIiwiZW50aXR5IjoicHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6IlJFQURFUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJ2aWV3ZXJzIn0sImV0YWciOiJDTmVTeE5HVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqMi8xNTM4MDUxMDQ1MTMyNjMxL3VzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9vYmoyL2FjbC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0Ijoib2JqMiIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDQ1MTMyNjMxIiwiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInJvbGUiOiJPV05FUiIsImVtYWlsIjoiMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJldGFnIjoiQ05lU3hOR1cyOTBDRUFFPSJ9XSwib3duZXIiOnsiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSJ9LCJjcmMzMmMiOiIzREtEcWc9PSIsImV0YWciOiJDTmVTeE5HVzI5MENFQUU9In1dfQ=="
+ }
+ },
+ {
+ "ID": "f2f711bb69faeb45",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026delimiter=\u0026maxResults=2\u0026pageToken=\u0026prefix=obj\u0026prettyPrint=false\u0026projection=full\u0026versions=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "9f42f8b63cd1e8a51789f59550f90a39/2948979483220119867;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026delimiter=\u0026maxResults=2\u0026pageToken=\u0026prefix=obj\u0026prettyPrint=false\u0026projection=full\u0026versions=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0, must-revalidate, no-transform"
+ ],
+ "Content-Length": [
+ "6767"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:09 GMT"
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:24:09 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051345000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrbp63:4132,/bns/yv/borg/yv/bns/blobstore2/bitpusher/140.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=6cusW_faH5KCgwS2iqKgDw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/140.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/140:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRYnFLZDRCTjBkdm9mZm9PZVZZS0p1VDRROFVJT3NhUTljbFFvbW42UElpcDBpenczVUc1ZHZUMVZlZE1OWGp3cHJDNUUyam9FUUZwbldFellKMWd5Tlp1T3o4dy16UUMxaXAtb3VNMjdkM0JqNGR4SmNfUDVYRXRjeHNYWVN3LXNuNXEtcXpLZ1NvM3BKMGx4Ym9YaGNlZHBiR2t6VGVSdlc5QnVxZDFESV9pbE84ZEFXSDVOLVJnNDQwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UpR3T9vRuVsBcJqCxFkxMS1393TLzXnM1FmvP76TVSQezRyyfupQfblGucwkpaj_g19hxNbevh1tp8ZTfn1r2Bc4_fikA"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3RzIiwibmV4dFBhZ2VUb2tlbiI6IkNnUnZZbW94IiwiaXRlbXMiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL29iai93aXRoL3NsYXNoZXMvMTUzODA1MTA0NTYyNzE5OCIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iaiUyRndpdGglMkZzbGFzaGVzIiwibmFtZSI6Im9iai93aXRoL3NsYXNoZXMiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NTYyNzE5OCIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbiIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDowNS42MjdaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MDUuNjI3WiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjA1LjYyN1oiLCJzaXplIjoiMTYiLCJtZDVIYXNoIjoiKzdtVm42TFR3RG5WM3RnL3BDcmlvdz09IiwibWVkaWFMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vZG93bmxvYWQvc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iaiUyRndpdGglMkZzbGFzaGVzP2dlbmVyYXRpb249MTUzODA1MTA0NTYyNzE5OCZhbHQ9bWVkaWEiLCJjYWNoZUNvbnRyb2wiOiJwdWJsaWMsIG1heC1hZ2U9NjAiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmovd2l0aC9zbGFzaGVzLzE1MzgwNTEwNDU2MjcxOTgvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9vYmolMkZ3aXRoJTJGc2xhc2hlcy9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJvYmovd2l0aC9zbGFzaGVzIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNDU2MjcxOTgiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNMNnE0dEdXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmovd2l0aC9zbGFzaGVzLzE1MzgwNTEwNDU2MjcxOTgvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vb2JqJTJGd2l0aCUyRnNsYXNoZXMvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Im9iai93aXRoL3NsYXNoZXMiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NTYyNzE5OCIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDTDZxNHRHVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqL3dpdGgvc2xhc2hlcy8xNTM4MDUxMDQ1NjI3MTk4L3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iaiUyRndpdGglMkZzbGFzaGVzL2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJvYmovd2l0aC9zbGFzaGVzIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNDU2MjcxOTgiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNMNnE0dEdXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmovd2l0aC9zbGFzaGVzLzE1MzgwNTEwNDU2MjcxOTgvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iaiUyRndpdGglMkZzbGFzaGVzL2FjbC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0Ijoib2JqL3dpdGgvc2xhc2hlcyIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDQ1NjI3MTk4IiwiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInJvbGUiOiJPV05FUiIsImVtYWlsIjoiMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJldGFnIjoiQ0w2cTR0R1cyOTBDRUFFPSJ9XSwib3duZXIiOnsiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSJ9LCJjcmMzMmMiOiJrU3NXUWc9PSIsImV0YWciOiJDTDZxNHRHVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmoxLzE1MzgwNTEwNDQ1MzIzNjYiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9vYmoxIiwibmFtZSI6Im9iajEiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NDUzMjM2NiIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbiIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDowNC41MzJaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MDQuNTMyWiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjA0LjUzMloiLCJzaXplIjoiMTYiLCJtZDVIYXNoIjoiN3dVRkg4bUREd0hGWXFvN29seGRQZz09IiwibWVkaWFMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vZG93bmxvYWQvc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iajE/Z2VuZXJhdGlvbj0xNTM4MDUxMDQ0NTMyMzY2JmFsdD1tZWRpYSIsImNhY2hlQ29udHJvbCI6InB1YmxpYywgbWF4LWFnZT02MCIsImFjbCI6W3sia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL29iajEvMTUzODA1MTA0NDUzMjM2Ni9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iajEvYWNsL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0Ijoib2JqMSIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDQ0NTMyMzY2IiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDSTdCbjlHVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqMS8xNTM4MDUxMDQ0NTMyMzY2L3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iajEvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Im9iajEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NDUzMjM2NiIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDSTdCbjlHVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqMS8xNTM4MDUxMDQ0NTMyMzY2L3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iajEvYWNsL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Im9iajEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NDUzMjM2NiIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0k3Qm45R1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL29iajEvMTUzODA1MTA0NDUzMjM2Ni91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vb2JqMS9hY2wvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Im9iajEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NDUzMjM2NiIsImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJyb2xlIjoiT1dORVIiLCJlbWFpbCI6IjM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiZXRhZyI6IkNJN0JuOUdXMjkwQ0VBRT0ifV0sIm93bmVyIjp7ImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20ifSwiY3JjMzJjIjoiKzdSMTFnPT0iLCJldGFnIjoiQ0k3Qm45R1cyOTBDRUFFPSJ9XX0="
+ }
+ },
+ {
+ "ID": "8808fafb9637c238",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026delimiter=\u0026maxResults=2\u0026pageToken=CgRvYmox\u0026prefix=obj\u0026prettyPrint=false\u0026projection=full\u0026versions=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "a783f696c9821dde0fd569cacc970f59/3708016452658094986;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026delimiter=\u0026maxResults=2\u0026pageToken=CgRvYmox\u0026prefix=obj\u0026prettyPrint=false\u0026projection=full\u0026versions=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0, must-revalidate, no-transform"
+ ],
+ "Content-Length": [
+ "3280"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:10 GMT"
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:24:10 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051345000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrlh9:4090,/bns/yr/borg/yr/bns/blobstore2/bitpusher/84.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=6cusW6PyOczukAPMwpbQAw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/84.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/84:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRYnFLZDRCTjBkdm9mZm9PZVZZS0p1VDRROFVJT3NhUTljbFFvbW42UElpcDBpenczVUc1ZHZUMVZlZE1OWGp3cHJDNUUyam9FUUZwbldFellKMWd5Tlp1T3o4dy16UUMxaXAtb3VNMjdkM0JqNGR4SmNfUDVYRXRjeHNYWVN3LXNuNXEtcXpLZ1NvM3BKMGx4Ym9YaGNlZHBiR2t6VGVSdlc5QnVxZDFESV9pbE84ZEFXSDVOLVJnNDQwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UoiYRTaEq7pO9cBg2viegrNBjlBrmXfkEMJiWvA6FcAMx4uUrVvCmUdM93Uhqx9YmCu6E3EXlUUzXOssXx0WjUTvGIrtQ"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3RzIiwiaXRlbXMiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL29iajIvMTUzODA1MTA0NTEzMjYzMSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iajIiLCJuYW1lIjoib2JqMiIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDQ1MTMyNjMxIiwibWV0YWdlbmVyYXRpb24iOiIxIiwiY29udGVudFR5cGUiOiJ0ZXh0L3BsYWluIiwidGltZUNyZWF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjA1LjEzMloiLCJ1cGRhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDowNS4xMzJaIiwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJ0aW1lU3RvcmFnZUNsYXNzVXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MDUuMTMyWiIsInNpemUiOiIxNiIsIm1kNUhhc2giOiJoNjRtWXFKMk81NGpyeEdPSk55R3hRPT0iLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vb2JqMj9nZW5lcmF0aW9uPTE1MzgwNTEwNDUxMzI2MzEmYWx0PW1lZGlhIiwiY2FjaGVDb250cm9sIjoicHVibGljLCBtYXgtYWdlPTYwIiwiYWNsIjpbeyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqMi8xNTM4MDUxMDQ1MTMyNjMxL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vb2JqMi9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJvYmoyIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNDUxMzI2MzEiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNOZVN4TkdXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmoyLzE1MzgwNTEwNDUxMzI2MzEvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vb2JqMi9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0Ijoib2JqMiIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDQ1MTMyNjMxIiwiZW50aXR5IjoicHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6ImVkaXRvcnMifSwiZXRhZyI6IkNOZVN4TkdXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmoyLzE1MzgwNTEwNDUxMzI2MzEvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vb2JqMi9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0Ijoib2JqMiIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDQ1MTMyNjMxIiwiZW50aXR5IjoicHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6IlJFQURFUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJ2aWV3ZXJzIn0sImV0YWciOiJDTmVTeE5HVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqMi8xNTM4MDUxMDQ1MTMyNjMxL3VzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9vYmoyL2FjbC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0Ijoib2JqMiIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDQ1MTMyNjMxIiwiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInJvbGUiOiJPV05FUiIsImVtYWlsIjoiMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJldGFnIjoiQ05lU3hOR1cyOTBDRUFFPSJ9XSwib3duZXIiOnsiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSJ9LCJjcmMzMmMiOiIzREtEcWc9PSIsImV0YWciOiJDTmVTeE5HVzI5MENFQUU9In1dfQ=="
+ }
+ },
+ {
+ "ID": "177ae0685adc2ee1",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026delimiter=\u0026maxResults=3\u0026pageToken=\u0026prefix=obj\u0026prettyPrint=false\u0026projection=full\u0026versions=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "5f216de33683069c9803469708b404e9/4539109916605593305;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026delimiter=\u0026maxResults=3\u0026pageToken=\u0026prefix=obj\u0026prettyPrint=false\u0026projection=full\u0026versions=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0, must-revalidate, no-transform"
+ ],
+ "Content-Length": [
+ "9984"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:10 GMT"
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:24:10 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051345000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vreb18:4023,/bns/yr/borg/yr/bns/blobstore2/bitpusher/12.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=6susW8W5E9COkATL9oqABA"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/12.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/12:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRYnFLZDRCTjBkdm9mZm9PZVZZS0p1VDRROFVJT3NhUTljbFFvbW42UElpcDBpenczVUc1ZHZUMVZlZE1OWGp3cHJDNUUyam9FUUZwbldFellKMWd5Tlp1T3o4dy16UUMxaXAtb3VNMjdkM0JqNGR4SmNfUDVYRXRjeHNYWVN3LXNuNXEtcXpLZ1NvM3BKMGx4Ym9YaGNlZHBiR2t6VGVSdlc5QnVxZDFESV9pbE84ZEFXSDVOLVJnNDQwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UrxfEZ8Nc3yr1LWDWGqnj6D1KUzIsYSBf26j_M5guMAuvNENKt2tnFliV-C-5T7Y7GZ2oz11YTDoU3V2iiJnXoWOT7tgA"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3RzIiwiaXRlbXMiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL29iai93aXRoL3NsYXNoZXMvMTUzODA1MTA0NTYyNzE5OCIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iaiUyRndpdGglMkZzbGFzaGVzIiwibmFtZSI6Im9iai93aXRoL3NsYXNoZXMiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NTYyNzE5OCIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbiIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDowNS42MjdaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MDUuNjI3WiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjA1LjYyN1oiLCJzaXplIjoiMTYiLCJtZDVIYXNoIjoiKzdtVm42TFR3RG5WM3RnL3BDcmlvdz09IiwibWVkaWFMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vZG93bmxvYWQvc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iaiUyRndpdGglMkZzbGFzaGVzP2dlbmVyYXRpb249MTUzODA1MTA0NTYyNzE5OCZhbHQ9bWVkaWEiLCJjYWNoZUNvbnRyb2wiOiJwdWJsaWMsIG1heC1hZ2U9NjAiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmovd2l0aC9zbGFzaGVzLzE1MzgwNTEwNDU2MjcxOTgvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9vYmolMkZ3aXRoJTJGc2xhc2hlcy9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJvYmovd2l0aC9zbGFzaGVzIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNDU2MjcxOTgiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNMNnE0dEdXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmovd2l0aC9zbGFzaGVzLzE1MzgwNTEwNDU2MjcxOTgvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vb2JqJTJGd2l0aCUyRnNsYXNoZXMvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Im9iai93aXRoL3NsYXNoZXMiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NTYyNzE5OCIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDTDZxNHRHVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqL3dpdGgvc2xhc2hlcy8xNTM4MDUxMDQ1NjI3MTk4L3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iaiUyRndpdGglMkZzbGFzaGVzL2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJvYmovd2l0aC9zbGFzaGVzIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNDU2MjcxOTgiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNMNnE0dEdXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmovd2l0aC9zbGFzaGVzLzE1MzgwNTEwNDU2MjcxOTgvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iaiUyRndpdGglMkZzbGFzaGVzL2FjbC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0Ijoib2JqL3dpdGgvc2xhc2hlcyIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDQ1NjI3MTk4IiwiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInJvbGUiOiJPV05FUiIsImVtYWlsIjoiMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJldGFnIjoiQ0w2cTR0R1cyOTBDRUFFPSJ9XSwib3duZXIiOnsiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSJ9LCJjcmMzMmMiOiJrU3NXUWc9PSIsImV0YWciOiJDTDZxNHRHVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmoxLzE1MzgwNTEwNDQ1MzIzNjYiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9vYmoxIiwibmFtZSI6Im9iajEiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NDUzMjM2NiIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbiIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDowNC41MzJaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MDQuNTMyWiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjA0LjUzMloiLCJzaXplIjoiMTYiLCJtZDVIYXNoIjoiN3dVRkg4bUREd0hGWXFvN29seGRQZz09IiwibWVkaWFMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vZG93bmxvYWQvc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iajE/Z2VuZXJhdGlvbj0xNTM4MDUxMDQ0NTMyMzY2JmFsdD1tZWRpYSIsImNhY2hlQ29udHJvbCI6InB1YmxpYywgbWF4LWFnZT02MCIsImFjbCI6W3sia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL29iajEvMTUzODA1MTA0NDUzMjM2Ni9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iajEvYWNsL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0Ijoib2JqMSIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDQ0NTMyMzY2IiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDSTdCbjlHVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqMS8xNTM4MDUxMDQ0NTMyMzY2L3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iajEvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Im9iajEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NDUzMjM2NiIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDSTdCbjlHVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqMS8xNTM4MDUxMDQ0NTMyMzY2L3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iajEvYWNsL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Im9iajEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NDUzMjM2NiIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0k3Qm45R1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL29iajEvMTUzODA1MTA0NDUzMjM2Ni91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vb2JqMS9hY2wvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Im9iajEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NDUzMjM2NiIsImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJyb2xlIjoiT1dORVIiLCJlbWFpbCI6IjM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiZXRhZyI6IkNJN0JuOUdXMjkwQ0VBRT0ifV0sIm93bmVyIjp7ImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20ifSwiY3JjMzJjIjoiKzdSMTFnPT0iLCJldGFnIjoiQ0k3Qm45R1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0IiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqMi8xNTM4MDUxMDQ1MTMyNjMxIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vb2JqMiIsIm5hbWUiOiJvYmoyIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNDUxMzI2MzEiLCJtZXRhZ2VuZXJhdGlvbiI6IjEiLCJjb250ZW50VHlwZSI6InRleHQvcGxhaW4iLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MDUuMTMyWiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjA1LjEzMloiLCJzdG9yYWdlQ2xhc3MiOiJTVEFOREFSRCIsInRpbWVTdG9yYWdlQ2xhc3NVcGRhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDowNS4xMzJaIiwic2l6ZSI6IjE2IiwibWQ1SGFzaCI6Img2NG1ZcUoyTzU0anJ4R09KTnlHeFE9PSIsIm1lZGlhTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2Rvd25sb2FkL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9vYmoyP2dlbmVyYXRpb249MTUzODA1MTA0NTEzMjYzMSZhbHQ9bWVkaWEiLCJjYWNoZUNvbnRyb2wiOiJwdWJsaWMsIG1heC1hZ2U9NjAiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmoyLzE1MzgwNTEwNDUxMzI2MzEvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9vYmoyL2FjbC9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Im9iajIiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NTEzMjYzMSIsImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6Im93bmVycyJ9LCJldGFnIjoiQ05lU3hOR1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL29iajIvMTUzODA1MTA0NTEzMjYzMS9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9vYmoyL2FjbC9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJvYmoyIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNDUxMzI2MzEiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ05lU3hOR1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL29iajIvMTUzODA1MTA0NTEzMjYzMS9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9vYmoyL2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJvYmoyIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNDUxMzI2MzEiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNOZVN4TkdXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmoyLzE1MzgwNTEwNDUxMzI2MzEvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iajIvYWNsL3VzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJvYmoyIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNDUxMzI2MzEiLCJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwicm9sZSI6Ik9XTkVSIiwiZW1haWwiOiIzNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImV0YWciOiJDTmVTeE5HVzI5MENFQUU9In1dLCJvd25lciI6eyJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIn0sImNyYzMyYyI6IjNES0RxZz09IiwiZXRhZyI6IkNOZVN4TkdXMjkwQ0VBRT0ifV19"
+ }
+ },
+ {
+ "ID": "4c5d5ec2f5ac82a1",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026delimiter=\u0026maxResults=3\u0026pageToken=\u0026prefix=obj\u0026prettyPrint=false\u0026projection=full\u0026versions=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "290553f278ed99d3bfaaa4e200ee8a41/5298428356708469033;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026delimiter=\u0026maxResults=3\u0026pageToken=\u0026prefix=obj\u0026prettyPrint=false\u0026projection=full\u0026versions=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0, must-revalidate, no-transform"
+ ],
+ "Content-Length": [
+ "9984"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:11 GMT"
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:24:11 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051345000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrvu4:4011,/bns/yw/borg/yw/bns/blobstore2/bitpusher/68.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=6susW9aYLIHrhATap5foAw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yw/borg/yw/bns/blobstore2/bitpusher/68.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yw/borg/yw/bns/blobstore2/bitpusher/68:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRYnFLZDRCTjBkdm9mZm9PZVZZS0p1VDRROFVJT3NhUTljbFFvbW42UElpcDBpenczVUc1ZHZUMVZlZE1OWGp3cHJDNUUyam9FUUZwbldFellKMWd5Tlp1T3o4dy16UUMxaXAtb3VNMjdkM0JqNGR4SmNfUDVYRXRjeHNYWVN3LXNuNXEtcXpLZ1NvM3BKMGx4Ym9YaGNlZHBiR2t6VGVSdlc5QnVxZDFESV9pbE84ZEFXSDVOLVJnNDQwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UqqTZWUEdY633nBYemRmInVkovwfiLLhIYWVskV7mfCjnjlUvTl5hlDPCd2sCOQGKvDPLnR0g6w_Kak_vUGtjET-5a5WA"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3RzIiwiaXRlbXMiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL29iai93aXRoL3NsYXNoZXMvMTUzODA1MTA0NTYyNzE5OCIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iaiUyRndpdGglMkZzbGFzaGVzIiwibmFtZSI6Im9iai93aXRoL3NsYXNoZXMiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NTYyNzE5OCIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbiIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDowNS42MjdaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MDUuNjI3WiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjA1LjYyN1oiLCJzaXplIjoiMTYiLCJtZDVIYXNoIjoiKzdtVm42TFR3RG5WM3RnL3BDcmlvdz09IiwibWVkaWFMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vZG93bmxvYWQvc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iaiUyRndpdGglMkZzbGFzaGVzP2dlbmVyYXRpb249MTUzODA1MTA0NTYyNzE5OCZhbHQ9bWVkaWEiLCJjYWNoZUNvbnRyb2wiOiJwdWJsaWMsIG1heC1hZ2U9NjAiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmovd2l0aC9zbGFzaGVzLzE1MzgwNTEwNDU2MjcxOTgvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9vYmolMkZ3aXRoJTJGc2xhc2hlcy9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJvYmovd2l0aC9zbGFzaGVzIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNDU2MjcxOTgiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNMNnE0dEdXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmovd2l0aC9zbGFzaGVzLzE1MzgwNTEwNDU2MjcxOTgvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vb2JqJTJGd2l0aCUyRnNsYXNoZXMvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Im9iai93aXRoL3NsYXNoZXMiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NTYyNzE5OCIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDTDZxNHRHVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqL3dpdGgvc2xhc2hlcy8xNTM4MDUxMDQ1NjI3MTk4L3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iaiUyRndpdGglMkZzbGFzaGVzL2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJvYmovd2l0aC9zbGFzaGVzIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNDU2MjcxOTgiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNMNnE0dEdXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmovd2l0aC9zbGFzaGVzLzE1MzgwNTEwNDU2MjcxOTgvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iaiUyRndpdGglMkZzbGFzaGVzL2FjbC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0Ijoib2JqL3dpdGgvc2xhc2hlcyIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDQ1NjI3MTk4IiwiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInJvbGUiOiJPV05FUiIsImVtYWlsIjoiMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJldGFnIjoiQ0w2cTR0R1cyOTBDRUFFPSJ9XSwib3duZXIiOnsiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSJ9LCJjcmMzMmMiOiJrU3NXUWc9PSIsImV0YWciOiJDTDZxNHRHVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmoxLzE1MzgwNTEwNDQ1MzIzNjYiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9vYmoxIiwibmFtZSI6Im9iajEiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NDUzMjM2NiIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbiIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDowNC41MzJaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MDQuNTMyWiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjA0LjUzMloiLCJzaXplIjoiMTYiLCJtZDVIYXNoIjoiN3dVRkg4bUREd0hGWXFvN29seGRQZz09IiwibWVkaWFMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vZG93bmxvYWQvc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iajE/Z2VuZXJhdGlvbj0xNTM4MDUxMDQ0NTMyMzY2JmFsdD1tZWRpYSIsImNhY2hlQ29udHJvbCI6InB1YmxpYywgbWF4LWFnZT02MCIsImFjbCI6W3sia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL29iajEvMTUzODA1MTA0NDUzMjM2Ni9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iajEvYWNsL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0Ijoib2JqMSIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDQ0NTMyMzY2IiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDSTdCbjlHVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqMS8xNTM4MDUxMDQ0NTMyMzY2L3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iajEvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Im9iajEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NDUzMjM2NiIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDSTdCbjlHVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqMS8xNTM4MDUxMDQ0NTMyMzY2L3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iajEvYWNsL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Im9iajEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NDUzMjM2NiIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0k3Qm45R1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL29iajEvMTUzODA1MTA0NDUzMjM2Ni91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vb2JqMS9hY2wvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Im9iajEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NDUzMjM2NiIsImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJyb2xlIjoiT1dORVIiLCJlbWFpbCI6IjM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiZXRhZyI6IkNJN0JuOUdXMjkwQ0VBRT0ifV0sIm93bmVyIjp7ImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20ifSwiY3JjMzJjIjoiKzdSMTFnPT0iLCJldGFnIjoiQ0k3Qm45R1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0IiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqMi8xNTM4MDUxMDQ1MTMyNjMxIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vb2JqMiIsIm5hbWUiOiJvYmoyIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNDUxMzI2MzEiLCJtZXRhZ2VuZXJhdGlvbiI6IjEiLCJjb250ZW50VHlwZSI6InRleHQvcGxhaW4iLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MDUuMTMyWiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjA1LjEzMloiLCJzdG9yYWdlQ2xhc3MiOiJTVEFOREFSRCIsInRpbWVTdG9yYWdlQ2xhc3NVcGRhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDowNS4xMzJaIiwic2l6ZSI6IjE2IiwibWQ1SGFzaCI6Img2NG1ZcUoyTzU0anJ4R09KTnlHeFE9PSIsIm1lZGlhTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2Rvd25sb2FkL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9vYmoyP2dlbmVyYXRpb249MTUzODA1MTA0NTEzMjYzMSZhbHQ9bWVkaWEiLCJjYWNoZUNvbnRyb2wiOiJwdWJsaWMsIG1heC1hZ2U9NjAiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmoyLzE1MzgwNTEwNDUxMzI2MzEvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9vYmoyL2FjbC9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Im9iajIiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NTEzMjYzMSIsImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6Im93bmVycyJ9LCJldGFnIjoiQ05lU3hOR1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL29iajIvMTUzODA1MTA0NTEzMjYzMS9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9vYmoyL2FjbC9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJvYmoyIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNDUxMzI2MzEiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ05lU3hOR1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL29iajIvMTUzODA1MTA0NTEzMjYzMS9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9vYmoyL2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJvYmoyIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNDUxMzI2MzEiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNOZVN4TkdXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmoyLzE1MzgwNTEwNDUxMzI2MzEvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iajIvYWNsL3VzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJvYmoyIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNDUxMzI2MzEiLCJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwicm9sZSI6Ik9XTkVSIiwiZW1haWwiOiIzNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImV0YWciOiJDTmVTeE5HVzI5MENFQUU9In1dLCJvd25lciI6eyJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIn0sImNyYzMyYyI6IjNES0RxZz09IiwiZXRhZyI6IkNOZVN4TkdXMjkwQ0VBRT0ifV19"
+ }
+ },
+ {
+ "ID": "dbf2b3beca4073fe",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026delimiter=\u0026maxResults=13\u0026pageToken=\u0026prefix=obj\u0026prettyPrint=false\u0026projection=full\u0026versions=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "d4daed5dc66c10342d5068cd5717a2ab/6057465326129667192;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026delimiter=\u0026maxResults=13\u0026pageToken=\u0026prefix=obj\u0026prettyPrint=false\u0026projection=full\u0026versions=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0, must-revalidate, no-transform"
+ ],
+ "Content-Length": [
+ "9984"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:11 GMT"
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:24:11 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051345000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrnb2:4089,/bns/yv/borg/yv/bns/blobstore2/bitpusher/59.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=68usW_LfB8jAggTmnbjABA"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/59.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/59:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRYnFLZDRCTjBkdm9mZm9PZVZZS0p1VDRROFVJT3NhUTljbFFvbW42UElpcDBpenczVUc1ZHZUMVZlZE1OWGp3cHJDNUUyam9FUUZwbldFellKMWd5Tlp1T3o4dy16UUMxaXAtb3VNMjdkM0JqNGR4SmNfUDVYRXRjeHNYWVN3LXNuNXEtcXpLZ1NvM3BKMGx4Ym9YaGNlZHBiR2t6VGVSdlc5QnVxZDFESV9pbE84ZEFXSDVOLVJnNDQwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UpVhzCQ4FNrnsz83C_F7ZJW_zkPRALyju0_LUrPz4dA0kD5-W_YcNRRB5ipUN8YDQ2ZOVdJeF9f5Ead7ZrYd-yS_oOJrw"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3RzIiwiaXRlbXMiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL29iai93aXRoL3NsYXNoZXMvMTUzODA1MTA0NTYyNzE5OCIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iaiUyRndpdGglMkZzbGFzaGVzIiwibmFtZSI6Im9iai93aXRoL3NsYXNoZXMiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NTYyNzE5OCIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbiIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDowNS42MjdaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MDUuNjI3WiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjA1LjYyN1oiLCJzaXplIjoiMTYiLCJtZDVIYXNoIjoiKzdtVm42TFR3RG5WM3RnL3BDcmlvdz09IiwibWVkaWFMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vZG93bmxvYWQvc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iaiUyRndpdGglMkZzbGFzaGVzP2dlbmVyYXRpb249MTUzODA1MTA0NTYyNzE5OCZhbHQ9bWVkaWEiLCJjYWNoZUNvbnRyb2wiOiJwdWJsaWMsIG1heC1hZ2U9NjAiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmovd2l0aC9zbGFzaGVzLzE1MzgwNTEwNDU2MjcxOTgvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9vYmolMkZ3aXRoJTJGc2xhc2hlcy9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJvYmovd2l0aC9zbGFzaGVzIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNDU2MjcxOTgiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNMNnE0dEdXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmovd2l0aC9zbGFzaGVzLzE1MzgwNTEwNDU2MjcxOTgvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vb2JqJTJGd2l0aCUyRnNsYXNoZXMvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Im9iai93aXRoL3NsYXNoZXMiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NTYyNzE5OCIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDTDZxNHRHVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqL3dpdGgvc2xhc2hlcy8xNTM4MDUxMDQ1NjI3MTk4L3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iaiUyRndpdGglMkZzbGFzaGVzL2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJvYmovd2l0aC9zbGFzaGVzIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNDU2MjcxOTgiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNMNnE0dEdXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmovd2l0aC9zbGFzaGVzLzE1MzgwNTEwNDU2MjcxOTgvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iaiUyRndpdGglMkZzbGFzaGVzL2FjbC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0Ijoib2JqL3dpdGgvc2xhc2hlcyIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDQ1NjI3MTk4IiwiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInJvbGUiOiJPV05FUiIsImVtYWlsIjoiMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJldGFnIjoiQ0w2cTR0R1cyOTBDRUFFPSJ9XSwib3duZXIiOnsiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSJ9LCJjcmMzMmMiOiJrU3NXUWc9PSIsImV0YWciOiJDTDZxNHRHVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmoxLzE1MzgwNTEwNDQ1MzIzNjYiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9vYmoxIiwibmFtZSI6Im9iajEiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NDUzMjM2NiIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbiIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDowNC41MzJaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MDQuNTMyWiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjA0LjUzMloiLCJzaXplIjoiMTYiLCJtZDVIYXNoIjoiN3dVRkg4bUREd0hGWXFvN29seGRQZz09IiwibWVkaWFMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vZG93bmxvYWQvc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iajE/Z2VuZXJhdGlvbj0xNTM4MDUxMDQ0NTMyMzY2JmFsdD1tZWRpYSIsImNhY2hlQ29udHJvbCI6InB1YmxpYywgbWF4LWFnZT02MCIsImFjbCI6W3sia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL29iajEvMTUzODA1MTA0NDUzMjM2Ni9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iajEvYWNsL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0Ijoib2JqMSIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDQ0NTMyMzY2IiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDSTdCbjlHVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqMS8xNTM4MDUxMDQ0NTMyMzY2L3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iajEvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Im9iajEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NDUzMjM2NiIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDSTdCbjlHVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqMS8xNTM4MDUxMDQ0NTMyMzY2L3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iajEvYWNsL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Im9iajEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NDUzMjM2NiIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0k3Qm45R1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL29iajEvMTUzODA1MTA0NDUzMjM2Ni91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vb2JqMS9hY2wvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Im9iajEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NDUzMjM2NiIsImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJyb2xlIjoiT1dORVIiLCJlbWFpbCI6IjM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiZXRhZyI6IkNJN0JuOUdXMjkwQ0VBRT0ifV0sIm93bmVyIjp7ImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20ifSwiY3JjMzJjIjoiKzdSMTFnPT0iLCJldGFnIjoiQ0k3Qm45R1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0IiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqMi8xNTM4MDUxMDQ1MTMyNjMxIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vb2JqMiIsIm5hbWUiOiJvYmoyIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNDUxMzI2MzEiLCJtZXRhZ2VuZXJhdGlvbiI6IjEiLCJjb250ZW50VHlwZSI6InRleHQvcGxhaW4iLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MDUuMTMyWiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjA1LjEzMloiLCJzdG9yYWdlQ2xhc3MiOiJTVEFOREFSRCIsInRpbWVTdG9yYWdlQ2xhc3NVcGRhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDowNS4xMzJaIiwic2l6ZSI6IjE2IiwibWQ1SGFzaCI6Img2NG1ZcUoyTzU0anJ4R09KTnlHeFE9PSIsIm1lZGlhTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2Rvd25sb2FkL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9vYmoyP2dlbmVyYXRpb249MTUzODA1MTA0NTEzMjYzMSZhbHQ9bWVkaWEiLCJjYWNoZUNvbnRyb2wiOiJwdWJsaWMsIG1heC1hZ2U9NjAiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmoyLzE1MzgwNTEwNDUxMzI2MzEvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9vYmoyL2FjbC9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Im9iajIiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NTEzMjYzMSIsImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6Im93bmVycyJ9LCJldGFnIjoiQ05lU3hOR1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL29iajIvMTUzODA1MTA0NTEzMjYzMS9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9vYmoyL2FjbC9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJvYmoyIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNDUxMzI2MzEiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ05lU3hOR1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL29iajIvMTUzODA1MTA0NTEzMjYzMS9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9vYmoyL2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJvYmoyIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNDUxMzI2MzEiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNOZVN4TkdXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmoyLzE1MzgwNTEwNDUxMzI2MzEvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iajIvYWNsL3VzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJvYmoyIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNDUxMzI2MzEiLCJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwicm9sZSI6Ik9XTkVSIiwiZW1haWwiOiIzNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImV0YWciOiJDTmVTeE5HVzI5MENFQUU9In1dLCJvd25lciI6eyJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIn0sImNyYzMyYyI6IjNES0RxZz09IiwiZXRhZyI6IkNOZVN4TkdXMjkwQ0VBRT0ifV19"
+ }
+ },
+ {
+ "ID": "e8813cef66890896",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026delimiter=\u0026maxResults=13\u0026pageToken=\u0026prefix=obj\u0026prettyPrint=false\u0026projection=full\u0026versions=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "62aa9d0cab4f9a0da9ef03336c517f21/6888558790093942471;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026delimiter=\u0026maxResults=13\u0026pageToken=\u0026prefix=obj\u0026prettyPrint=false\u0026projection=full\u0026versions=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0, must-revalidate, no-transform"
+ ],
+ "Content-Length": [
+ "9984"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:11 GMT"
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:24:11 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051345000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vnlz21:4176,/bns/yx/borg/yx/bns/blobstore2/bitpusher/98.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=68usW_HzH5C5zwK1qK7ABg"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yx/borg/yx/bns/blobstore2/bitpusher/98.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yx/borg/yx/bns/blobstore2/bitpusher/98:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRYnFLZDRCTjBkdm9mZm9PZVZZS0p1VDRROFVJT3NhUTljbFFvbW42UElpcDBpenczVUc1ZHZUMVZlZE1OWGp3cHJDNUUyam9FUUZwbldFellKMWd5Tlp1T3o4dy16UUMxaXAtb3VNMjdkM0JqNGR4SmNfUDVYRXRjeHNYWVN3LXNuNXEtcXpLZ1NvM3BKMGx4Ym9YaGNlZHBiR2t6VGVSdlc5QnVxZDFESV9pbE84ZEFXSDVOLVJnNDQwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UrkNNiEw_PwZc-Zf2lHJ96tTZm1AUqfzqSG48wX2_Lyzi-K-RPTcM4QEfUyXYjSKbb_SWOe1xSTGRQBMnW95mGmeG8pAQ"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3RzIiwiaXRlbXMiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL29iai93aXRoL3NsYXNoZXMvMTUzODA1MTA0NTYyNzE5OCIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iaiUyRndpdGglMkZzbGFzaGVzIiwibmFtZSI6Im9iai93aXRoL3NsYXNoZXMiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NTYyNzE5OCIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbiIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDowNS42MjdaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MDUuNjI3WiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjA1LjYyN1oiLCJzaXplIjoiMTYiLCJtZDVIYXNoIjoiKzdtVm42TFR3RG5WM3RnL3BDcmlvdz09IiwibWVkaWFMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vZG93bmxvYWQvc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iaiUyRndpdGglMkZzbGFzaGVzP2dlbmVyYXRpb249MTUzODA1MTA0NTYyNzE5OCZhbHQ9bWVkaWEiLCJjYWNoZUNvbnRyb2wiOiJwdWJsaWMsIG1heC1hZ2U9NjAiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmovd2l0aC9zbGFzaGVzLzE1MzgwNTEwNDU2MjcxOTgvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9vYmolMkZ3aXRoJTJGc2xhc2hlcy9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJvYmovd2l0aC9zbGFzaGVzIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNDU2MjcxOTgiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNMNnE0dEdXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmovd2l0aC9zbGFzaGVzLzE1MzgwNTEwNDU2MjcxOTgvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vb2JqJTJGd2l0aCUyRnNsYXNoZXMvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Im9iai93aXRoL3NsYXNoZXMiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NTYyNzE5OCIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDTDZxNHRHVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqL3dpdGgvc2xhc2hlcy8xNTM4MDUxMDQ1NjI3MTk4L3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iaiUyRndpdGglMkZzbGFzaGVzL2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJvYmovd2l0aC9zbGFzaGVzIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNDU2MjcxOTgiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNMNnE0dEdXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmovd2l0aC9zbGFzaGVzLzE1MzgwNTEwNDU2MjcxOTgvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iaiUyRndpdGglMkZzbGFzaGVzL2FjbC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0Ijoib2JqL3dpdGgvc2xhc2hlcyIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDQ1NjI3MTk4IiwiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInJvbGUiOiJPV05FUiIsImVtYWlsIjoiMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJldGFnIjoiQ0w2cTR0R1cyOTBDRUFFPSJ9XSwib3duZXIiOnsiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSJ9LCJjcmMzMmMiOiJrU3NXUWc9PSIsImV0YWciOiJDTDZxNHRHVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmoxLzE1MzgwNTEwNDQ1MzIzNjYiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9vYmoxIiwibmFtZSI6Im9iajEiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NDUzMjM2NiIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbiIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDowNC41MzJaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MDQuNTMyWiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjA0LjUzMloiLCJzaXplIjoiMTYiLCJtZDVIYXNoIjoiN3dVRkg4bUREd0hGWXFvN29seGRQZz09IiwibWVkaWFMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vZG93bmxvYWQvc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iajE/Z2VuZXJhdGlvbj0xNTM4MDUxMDQ0NTMyMzY2JmFsdD1tZWRpYSIsImNhY2hlQ29udHJvbCI6InB1YmxpYywgbWF4LWFnZT02MCIsImFjbCI6W3sia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL29iajEvMTUzODA1MTA0NDUzMjM2Ni9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iajEvYWNsL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0Ijoib2JqMSIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDQ0NTMyMzY2IiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDSTdCbjlHVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqMS8xNTM4MDUxMDQ0NTMyMzY2L3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iajEvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Im9iajEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NDUzMjM2NiIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDSTdCbjlHVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqMS8xNTM4MDUxMDQ0NTMyMzY2L3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iajEvYWNsL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Im9iajEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NDUzMjM2NiIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0k3Qm45R1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL29iajEvMTUzODA1MTA0NDUzMjM2Ni91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vb2JqMS9hY2wvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Im9iajEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NDUzMjM2NiIsImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJyb2xlIjoiT1dORVIiLCJlbWFpbCI6IjM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiZXRhZyI6IkNJN0JuOUdXMjkwQ0VBRT0ifV0sIm93bmVyIjp7ImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20ifSwiY3JjMzJjIjoiKzdSMTFnPT0iLCJldGFnIjoiQ0k3Qm45R1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0IiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqMi8xNTM4MDUxMDQ1MTMyNjMxIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vb2JqMiIsIm5hbWUiOiJvYmoyIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNDUxMzI2MzEiLCJtZXRhZ2VuZXJhdGlvbiI6IjEiLCJjb250ZW50VHlwZSI6InRleHQvcGxhaW4iLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MDUuMTMyWiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjA1LjEzMloiLCJzdG9yYWdlQ2xhc3MiOiJTVEFOREFSRCIsInRpbWVTdG9yYWdlQ2xhc3NVcGRhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDowNS4xMzJaIiwic2l6ZSI6IjE2IiwibWQ1SGFzaCI6Img2NG1ZcUoyTzU0anJ4R09KTnlHeFE9PSIsIm1lZGlhTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2Rvd25sb2FkL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9vYmoyP2dlbmVyYXRpb249MTUzODA1MTA0NTEzMjYzMSZhbHQ9bWVkaWEiLCJjYWNoZUNvbnRyb2wiOiJwdWJsaWMsIG1heC1hZ2U9NjAiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmoyLzE1MzgwNTEwNDUxMzI2MzEvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9vYmoyL2FjbC9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Im9iajIiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NTEzMjYzMSIsImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6Im93bmVycyJ9LCJldGFnIjoiQ05lU3hOR1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL29iajIvMTUzODA1MTA0NTEzMjYzMS9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9vYmoyL2FjbC9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJvYmoyIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNDUxMzI2MzEiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ05lU3hOR1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL29iajIvMTUzODA1MTA0NTEzMjYzMS9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9vYmoyL2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJvYmoyIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNDUxMzI2MzEiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNOZVN4TkdXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmoyLzE1MzgwNTEwNDUxMzI2MzEvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iajIvYWNsL3VzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJvYmoyIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNDUxMzI2MzEiLCJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwicm9sZSI6Ik9XTkVSIiwiZW1haWwiOiIzNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImV0YWciOiJDTmVTeE5HVzI5MENFQUU9In1dLCJvd25lciI6eyJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIn0sImNyYzMyYyI6IjNES0RxZz09IiwiZXRhZyI6IkNOZVN4TkdXMjkwQ0VBRT0ifV19"
+ }
+ },
+ {
+ "ID": "d8438a79406c3ee7",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://storage.googleapis.com/go-integration-test-20180927-44630911863640-0001/obj1",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "Go-http-client/1.1"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "e34a37eefc5f30bda40070484796f0c8/8478970689849414758;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "storage.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://storage.googleapis.com/go-integration-test-20180927-44630911863640-0001/obj1"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Accept-Ranges": [
+ "bytes"
+ ],
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "public, max-age=60"
+ ],
+ "Content-Length": [
+ "16"
+ ],
+ "Content-Type": [
+ "text/plain"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:12 GMT"
+ ],
+ "Etag": [
+ "\"ef05051fc9830f01c562aa3ba25c5d3e\""
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:25:12 GMT"
+ ],
+ "Last-Modified": [
+ "Thu, 27 Sep 2018 12:24:04 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "X-Goog-Expiration": [
+ "Sat, 27 Oct 2018 12:24:04 GMT"
+ ],
+ "X-Goog-Generation": [
+ "1538051044532366"
+ ],
+ "X-Goog-Hash": [
+ "crc32c=+7R11g==",
+ "md5=7wUFH8mDDwHFYqo7olxdPg=="
+ ],
+ "X-Goog-Metageneration": [
+ "1"
+ ],
+ "X-Goog-Storage-Class": [
+ "STANDARD"
+ ],
+ "X-Goog-Stored-Content-Encoding": [
+ "identity"
+ ],
+ "X-Goog-Stored-Content-Length": [
+ "16"
+ ],
+ "X-Google-Backends": [
+ "/bns/xh/borg/xh/bns/cloud-storage/prod-cloud-storage-frontend.frontend/36,/bns/xh/borg/xh/bns/blobstore2/bitpusher/67.scotty,aclgag19:443"
+ ],
+ "X-Google-Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=68usW-PjO8atswaMgIygCQ"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "aclgag19:443,/bns/xh/borg/xh/bns/blobstore2/bitpusher/67.scotty,aclgag19:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/xh/borg/xh/bns/blobstore2/bitpusher/67:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBJ"
+ ],
+ "X-Google-Storage-Location": [
+ "US"
+ ],
+ "X-Guploader-Customer": [
+ "cloud-storage"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UoN20jwQv6iqBStn8N8_-tHO-IskyynbFbYmE1mHi1U9xJb6Y2n3w85qIy_ia8QkIr7pFOugsjvxJjlyeGqhAvDrPmvpQ"
+ ]
+ },
+ "Body": "G7YE7d4n0dy1PXohFJpUnw=="
+ }
+ },
+ {
+ "ID": "fd51799008bfea12",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://storage.googleapis.com/go-integration-test-20180927-44630911863640-0001/obj1",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "Go-http-client/1.1"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "b351f3135416bf5a89a34b654a1b3303/10069381494421780740;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "storage.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://storage.googleapis.com/go-integration-test-20180927-44630911863640-0001/obj1"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Accept-Ranges": [
+ "bytes"
+ ],
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "public, max-age=60"
+ ],
+ "Content-Length": [
+ "16"
+ ],
+ "Content-Type": [
+ "text/plain"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:12 GMT"
+ ],
+ "Etag": [
+ "\"ef05051fc9830f01c562aa3ba25c5d3e\""
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:25:12 GMT"
+ ],
+ "Last-Modified": [
+ "Thu, 27 Sep 2018 12:24:04 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "X-Goog-Expiration": [
+ "Sat, 27 Oct 2018 12:24:04 GMT"
+ ],
+ "X-Goog-Generation": [
+ "1538051044532366"
+ ],
+ "X-Goog-Hash": [
+ "crc32c=+7R11g==",
+ "md5=7wUFH8mDDwHFYqo7olxdPg=="
+ ],
+ "X-Goog-Metageneration": [
+ "1"
+ ],
+ "X-Goog-Storage-Class": [
+ "STANDARD"
+ ],
+ "X-Goog-Stored-Content-Encoding": [
+ "identity"
+ ],
+ "X-Goog-Stored-Content-Length": [
+ "16"
+ ],
+ "X-Google-Backends": [
+ "/bns/xh/borg/xh/bns/cloud-storage/prod-cloud-storage-frontend.frontend/25,/bns/xh/borg/xh/bns/blobstore2/bitpusher/80.scotty,aclgag19:443"
+ ],
+ "X-Google-Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=7MusW9CDCs6kswbMy5uwDQ"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "aclgag19:443,/bns/xh/borg/xh/bns/blobstore2/bitpusher/80.scotty,aclgag19:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/xh/borg/xh/bns/blobstore2/bitpusher/80:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBJ"
+ ],
+ "X-Google-Storage-Location": [
+ "US"
+ ],
+ "X-Guploader-Customer": [
+ "cloud-storage"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Uo5sFr6jrRtig10NXjMHaOuCabFiHZyrLqEZXpEdYTzqQD2zOhEp6iVt_78e54QX32MpRWEinlwSQbwTIdqrl9IOW_eUQ"
+ ]
+ },
+ "Body": "G7YE7d4n0dy1PXohFJpUnw=="
+ }
+ },
+ {
+ "ID": "6c56bc3a2067d53c",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://storage.googleapis.com/go-integration-test-20180927-44630911863640-0001/obj2",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "Go-http-client/1.1"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "fbdec27742a732b75803ee6a32401901/11659793398472155043;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "storage.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://storage.googleapis.com/go-integration-test-20180927-44630911863640-0001/obj2"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Accept-Ranges": [
+ "bytes"
+ ],
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "public, max-age=60"
+ ],
+ "Content-Length": [
+ "16"
+ ],
+ "Content-Type": [
+ "text/plain"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:12 GMT"
+ ],
+ "Etag": [
+ "\"87ae2662a2763b9e23af118e24dc86c5\""
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:25:12 GMT"
+ ],
+ "Last-Modified": [
+ "Thu, 27 Sep 2018 12:24:05 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "X-Goog-Expiration": [
+ "Sat, 27 Oct 2018 12:24:05 GMT"
+ ],
+ "X-Goog-Generation": [
+ "1538051045132631"
+ ],
+ "X-Goog-Hash": [
+ "crc32c=3DKDqg==",
+ "md5=h64mYqJ2O54jrxGOJNyGxQ=="
+ ],
+ "X-Goog-Metageneration": [
+ "1"
+ ],
+ "X-Goog-Storage-Class": [
+ "STANDARD"
+ ],
+ "X-Goog-Stored-Content-Encoding": [
+ "identity"
+ ],
+ "X-Goog-Stored-Content-Length": [
+ "16"
+ ],
+ "X-Google-Backends": [
+ "/bns/xh/borg/xh/bns/cloud-storage/prod-cloud-storage-frontend.frontend/8,/bns/xh/borg/xh/bns/blobstore2/bitpusher/28.scotty,aclgag19:443"
+ ],
+ "X-Google-Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=7MusW4aSDYuhswbl1qKYBg"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "aclgag19:443,/bns/xh/borg/xh/bns/blobstore2/bitpusher/28.scotty,aclgag19:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/xh/borg/xh/bns/blobstore2/bitpusher/28:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBJ"
+ ],
+ "X-Google-Storage-Location": [
+ "US"
+ ],
+ "X-Guploader-Customer": [
+ "cloud-storage"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UpfFy79R8hO4AoIDRUlP96iSXUSqB11GvlDhxq4NcGDXbTVxdErTejn5DnMjFhugLOAuP-p9uQDPyFy4be5vpakmpIg0w"
+ ]
+ },
+ "Body": "w9lw0lxxpKui5nmoap8pww=="
+ }
+ },
+ {
+ "ID": "e68e0aa406a7ace6",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://storage.googleapis.com/go-integration-test-20180927-44630911863640-0001/obj2",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "Go-http-client/1.1"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "436c06c3631f6877cb6b0adeb4d42c30/13249923827562660930;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "storage.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://storage.googleapis.com/go-integration-test-20180927-44630911863640-0001/obj2"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Accept-Ranges": [
+ "bytes"
+ ],
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "public, max-age=60"
+ ],
+ "Content-Length": [
+ "16"
+ ],
+ "Content-Type": [
+ "text/plain"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:12 GMT"
+ ],
+ "Etag": [
+ "\"87ae2662a2763b9e23af118e24dc86c5\""
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:25:12 GMT"
+ ],
+ "Last-Modified": [
+ "Thu, 27 Sep 2018 12:24:05 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "X-Goog-Expiration": [
+ "Sat, 27 Oct 2018 12:24:05 GMT"
+ ],
+ "X-Goog-Generation": [
+ "1538051045132631"
+ ],
+ "X-Goog-Hash": [
+ "crc32c=3DKDqg==",
+ "md5=h64mYqJ2O54jrxGOJNyGxQ=="
+ ],
+ "X-Goog-Metageneration": [
+ "1"
+ ],
+ "X-Goog-Storage-Class": [
+ "STANDARD"
+ ],
+ "X-Goog-Stored-Content-Encoding": [
+ "identity"
+ ],
+ "X-Goog-Stored-Content-Length": [
+ "16"
+ ],
+ "X-Google-Backends": [
+ "/bns/xh/borg/xh/bns/cloud-storage/prod-cloud-storage-frontend.frontend/10,/bns/xh/borg/xh/bns/blobstore2/bitpusher/86.scotty,aclgag19:443"
+ ],
+ "X-Google-Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=7MusW7OVE-6oswaP1oK4DA"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "aclgag19:443,/bns/xh/borg/xh/bns/blobstore2/bitpusher/86.scotty,aclgag19:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/xh/borg/xh/bns/blobstore2/bitpusher/86:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBJ"
+ ],
+ "X-Google-Storage-Location": [
+ "US"
+ ],
+ "X-Guploader-Customer": [
+ "cloud-storage"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UrkIt55pMPwjOM5myY8ijTv9lEmVrnGGv9NO_S-cG3qqvbRihzY7EKU2bhQVR1P9es7xJ7zsET3Av7yqTQ05O7kSs8vHA"
+ ]
+ },
+ "Body": "w9lw0lxxpKui5nmoap8pww=="
+ }
+ },
+ {
+ "ID": "0908749e71e23161",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://storage.googleapis.com/go-integration-test-20180927-44630911863640-0001/obj/with/slashes",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "Go-http-client/1.1"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "46b71c05144a5810a4f56acc0f1e1817/14840335731613100768;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "storage.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://storage.googleapis.com/go-integration-test-20180927-44630911863640-0001/obj/with/slashes"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Accept-Ranges": [
+ "bytes"
+ ],
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "public, max-age=60"
+ ],
+ "Content-Length": [
+ "16"
+ ],
+ "Content-Type": [
+ "text/plain"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:12 GMT"
+ ],
+ "Etag": [
+ "\"fbb9959fa2d3c039d5ded83fa42ae2a3\""
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:25:12 GMT"
+ ],
+ "Last-Modified": [
+ "Thu, 27 Sep 2018 12:24:05 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "X-Goog-Expiration": [
+ "Sat, 27 Oct 2018 12:24:05 GMT"
+ ],
+ "X-Goog-Generation": [
+ "1538051045627198"
+ ],
+ "X-Goog-Hash": [
+ "crc32c=kSsWQg==",
+ "md5=+7mVn6LTwDnV3tg/pCriow=="
+ ],
+ "X-Goog-Metageneration": [
+ "1"
+ ],
+ "X-Goog-Storage-Class": [
+ "STANDARD"
+ ],
+ "X-Goog-Stored-Content-Encoding": [
+ "identity"
+ ],
+ "X-Goog-Stored-Content-Length": [
+ "16"
+ ],
+ "X-Google-Backends": [
+ "/bns/xh/borg/xh/bns/cloud-storage/prod-cloud-storage-frontend.frontend/34,/bns/xh/borg/xh/bns/blobstore2/bitpusher/64.scotty,aclgag19:443"
+ ],
+ "X-Google-Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=7MusW5yxFsKmswayqIGIDg"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "aclgag19:443,/bns/xh/borg/xh/bns/blobstore2/bitpusher/64.scotty,aclgag19:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/xh/borg/xh/bns/blobstore2/bitpusher/64:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBJ"
+ ],
+ "X-Google-Storage-Location": [
+ "US"
+ ],
+ "X-Guploader-Customer": [
+ "cloud-storage"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Uo7UsAfQNdMNAdb2cU08Ktr6iNP4KbzoyHv46mQTZhM3d4zXlwFI8AcTFAPnQBWXJ_AUMDTKPS3LKGs617c7Shqv8l-rg"
+ ]
+ },
+ "Body": "WPsUiqCdmIfcTJUfL/MekQ=="
+ }
+ },
+ {
+ "ID": "3a6945ba8c54d3d0",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://storage.googleapis.com/go-integration-test-20180927-44630911863640-0001/obj/with/slashes",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "Go-http-client/1.1"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "e18289f7643f0221c20d31d88e440330/16358691141153951615;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "storage.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://storage.googleapis.com/go-integration-test-20180927-44630911863640-0001/obj/with/slashes"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Accept-Ranges": [
+ "bytes"
+ ],
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "public, max-age=60"
+ ],
+ "Content-Length": [
+ "16"
+ ],
+ "Content-Type": [
+ "text/plain"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:12 GMT"
+ ],
+ "Etag": [
+ "\"fbb9959fa2d3c039d5ded83fa42ae2a3\""
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:25:12 GMT"
+ ],
+ "Last-Modified": [
+ "Thu, 27 Sep 2018 12:24:05 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "X-Goog-Expiration": [
+ "Sat, 27 Oct 2018 12:24:05 GMT"
+ ],
+ "X-Goog-Generation": [
+ "1538051045627198"
+ ],
+ "X-Goog-Hash": [
+ "crc32c=kSsWQg==",
+ "md5=+7mVn6LTwDnV3tg/pCriow=="
+ ],
+ "X-Goog-Metageneration": [
+ "1"
+ ],
+ "X-Goog-Storage-Class": [
+ "STANDARD"
+ ],
+ "X-Goog-Stored-Content-Encoding": [
+ "identity"
+ ],
+ "X-Goog-Stored-Content-Length": [
+ "16"
+ ],
+ "X-Google-Backends": [
+ "/bns/xh/borg/xh/bns/cloud-storage/prod-cloud-storage-frontend.frontend/10,/bns/xh/borg/xh/bns/blobstore2/bitpusher/62.scotty,aclgag19:443"
+ ],
+ "X-Google-Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=7MusW9KVHMSmswaLopWwDA"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "aclgag19:443,/bns/xh/borg/xh/bns/blobstore2/bitpusher/62.scotty,aclgag19:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/xh/borg/xh/bns/blobstore2/bitpusher/62:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBJ"
+ ],
+ "X-Google-Storage-Location": [
+ "US"
+ ],
+ "X-Guploader-Customer": [
+ "cloud-storage"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Uq1_6wNvDu73BRMfGjIe95yVvDDKtlIqWWmlfUxcAWUAI5ZYPk8bBJS5SzvrFzdt-g5gRdnfa1S1wWBolex4S0h4SuWRQ"
+ ]
+ },
+ "Body": "WPsUiqCdmIfcTJUfL/MekQ=="
+ }
+ },
+ {
+ "ID": "55395569801967d3",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://storage.googleapis.com/go-integration-test-20180927-44630911863640-0001/obj1",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Range": [
+ "bytes=0-15"
+ ],
+ "User-Agent": [
+ "Go-http-client/1.1"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "835d9af2500c84822019536da352936f/17948820470732829982;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "storage.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://storage.googleapis.com/go-integration-test-20180927-44630911863640-0001/obj1"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Accept-Ranges": [
+ "bytes"
+ ],
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "public, max-age=60"
+ ],
+ "Content-Length": [
+ "16"
+ ],
+ "Content-Type": [
+ "text/plain"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:12 GMT"
+ ],
+ "Etag": [
+ "\"ef05051fc9830f01c562aa3ba25c5d3e\""
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:25:12 GMT"
+ ],
+ "Last-Modified": [
+ "Thu, 27 Sep 2018 12:24:04 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "X-Goog-Expiration": [
+ "Sat, 27 Oct 2018 12:24:04 GMT"
+ ],
+ "X-Goog-Generation": [
+ "1538051044532366"
+ ],
+ "X-Goog-Hash": [
+ "crc32c=+7R11g==",
+ "md5=7wUFH8mDDwHFYqo7olxdPg=="
+ ],
+ "X-Goog-Metageneration": [
+ "1"
+ ],
+ "X-Goog-Storage-Class": [
+ "STANDARD"
+ ],
+ "X-Goog-Stored-Content-Encoding": [
+ "identity"
+ ],
+ "X-Goog-Stored-Content-Length": [
+ "16"
+ ],
+ "X-Google-Backends": [
+ "/bns/xh/borg/xh/bns/cloud-storage/prod-cloud-storage-frontend.frontend/6,/bns/xh/borg/xh/bns/blobstore2/bitpusher/52.scotty,aclgag19:443"
+ ],
+ "X-Google-Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=7MusW6XiH7Cqswa-pIPADw"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "aclgag19:443,/bns/xh/borg/xh/bns/blobstore2/bitpusher/52.scotty,aclgag19:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/xh/borg/xh/bns/blobstore2/bitpusher/52:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBJ"
+ ],
+ "X-Google-Storage-Location": [
+ "US"
+ ],
+ "X-Guploader-Customer": [
+ "cloud-storage"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Ur7qd9oilYQm2rBqGKum--l_-DYiYr2wxV2HJ9nTGE4RjGaDoqeOfB5G5nmQkUR3Tq5M6AzVrwD5yKlNjiyN4-R2MFMNA"
+ ]
+ },
+ "Body": "G7YE7d4n0dy1PXohFJpUnw=="
+ }
+ },
+ {
+ "ID": "d869b9305381b8dc",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://storage.googleapis.com/go-integration-test-20180927-44630911863640-0001/obj1",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Range": [
+ "bytes=0-7"
+ ],
+ "User-Agent": [
+ "Go-http-client/1.1"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "4402daf1c2931122ca6c23a4457c8567/1092769776067205820;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "storage.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://storage.googleapis.com/go-integration-test-20180927-44630911863640-0001/obj1"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 206,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Accept-Ranges": [
+ "bytes"
+ ],
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "public, max-age=60"
+ ],
+ "Content-Length": [
+ "8"
+ ],
+ "Content-Range": [
+ "bytes 0-7/16"
+ ],
+ "Content-Type": [
+ "text/plain"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:12 GMT"
+ ],
+ "Etag": [
+ "\"ef05051fc9830f01c562aa3ba25c5d3e\""
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:25:12 GMT"
+ ],
+ "Last-Modified": [
+ "Thu, 27 Sep 2018 12:24:04 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "X-Goog-Expiration": [
+ "Sat, 27 Oct 2018 12:24:04 GMT"
+ ],
+ "X-Goog-Generation": [
+ "1538051044532366"
+ ],
+ "X-Goog-Hash": [
+ "crc32c=+7R11g==",
+ "md5=7wUFH8mDDwHFYqo7olxdPg=="
+ ],
+ "X-Goog-Metageneration": [
+ "1"
+ ],
+ "X-Goog-Storage-Class": [
+ "STANDARD"
+ ],
+ "X-Goog-Stored-Content-Encoding": [
+ "identity"
+ ],
+ "X-Goog-Stored-Content-Length": [
+ "16"
+ ],
+ "X-Google-Backends": [
+ "/bns/xh/borg/xh/bns/cloud-storage/prod-cloud-storage-frontend.frontend/15,/bns/xh/borg/xh/bns/blobstore2/bitpusher/39.scotty,aclgag19:443"
+ ],
+ "X-Google-Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=7MusW5uYIouoswbSkZD4Bg"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "aclgag19:443,/bns/xh/borg/xh/bns/blobstore2/bitpusher/39.scotty,aclgag19:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/xh/borg/xh/bns/blobstore2/bitpusher/39:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBJ"
+ ],
+ "X-Google-Storage-Location": [
+ "US"
+ ],
+ "X-Guploader-Customer": [
+ "cloud-storage"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Ur7al2tIDOVB8w1OYnq2HBh8-8N1uPecM3R2P83XNw62Pj2fwUZJ5gH9hLQ6Jcyl8MA_3jTwOes2TDZayRnvMI8GTe6ng"
+ ]
+ },
+ "Body": "G7YE7d4n0dw="
+ }
+ },
+ {
+ "ID": "0a535e86355c12ac",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://storage.googleapis.com/go-integration-test-20180927-44630911863640-0001/obj1",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Range": [
+ "bytes=8-23"
+ ],
+ "User-Agent": [
+ "Go-http-client/1.1"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "b0441aa4a7eab03a43e60c8b286ebd0f/2683181680117579867;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "storage.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://storage.googleapis.com/go-integration-test-20180927-44630911863640-0001/obj1"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 206,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Accept-Ranges": [
+ "bytes"
+ ],
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "public, max-age=60"
+ ],
+ "Content-Length": [
+ "8"
+ ],
+ "Content-Range": [
+ "bytes 8-15/16"
+ ],
+ "Content-Type": [
+ "text/plain"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:12 GMT"
+ ],
+ "Etag": [
+ "\"ef05051fc9830f01c562aa3ba25c5d3e\""
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:25:12 GMT"
+ ],
+ "Last-Modified": [
+ "Thu, 27 Sep 2018 12:24:04 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "X-Goog-Expiration": [
+ "Sat, 27 Oct 2018 12:24:04 GMT"
+ ],
+ "X-Goog-Generation": [
+ "1538051044532366"
+ ],
+ "X-Goog-Hash": [
+ "crc32c=+7R11g==",
+ "md5=7wUFH8mDDwHFYqo7olxdPg=="
+ ],
+ "X-Goog-Metageneration": [
+ "1"
+ ],
+ "X-Goog-Storage-Class": [
+ "STANDARD"
+ ],
+ "X-Goog-Stored-Content-Encoding": [
+ "identity"
+ ],
+ "X-Goog-Stored-Content-Length": [
+ "16"
+ ],
+ "X-Google-Backends": [
+ "/bns/xh/borg/xh/bns/cloud-storage/prod-cloud-storage-frontend.frontend/3,/bns/xh/borg/xh/bns/blobstore2/bitpusher/55.scotty,aclgag19:443"
+ ],
+ "X-Google-Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=7MusW-L2JO2kswaT64GQDQ"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "aclgag19:443,/bns/xh/borg/xh/bns/blobstore2/bitpusher/55.scotty,aclgag19:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/xh/borg/xh/bns/blobstore2/bitpusher/55:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBJ"
+ ],
+ "X-Google-Storage-Location": [
+ "US"
+ ],
+ "X-Guploader-Customer": [
+ "cloud-storage"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UrmRn0K293XJuaEyQYPoTS5Bbd-uKT12V8mzmrOYMj5aMCOa6ndse3iLY_TY5wzWyI4I38vJ3A0G6T7MTHHfrIxetCXaw"
+ ]
+ },
+ "Body": "tT16IRSaVJ8="
+ }
+ },
+ {
+ "ID": "ad1c8f3bf07175cb",
+ "Request": {
+ "Method": "HEAD",
+ "URL": "https://storage.googleapis.com/go-integration-test-20180927-44630911863640-0001/obj1",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "Go-http-client/1.1"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "d6872a13ef19e6aded259a214ad6449e/4273593584184731130;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "storage.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://storage.googleapis.com/go-integration-test-20180927-44630911863640-0001/obj1"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Accept-Ranges": [
+ "bytes"
+ ],
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "public, max-age=60"
+ ],
+ "Content-Length": [
+ "16"
+ ],
+ "Content-Type": [
+ "text/plain"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:12 GMT"
+ ],
+ "Etag": [
+ "\"ef05051fc9830f01c562aa3ba25c5d3e\""
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:25:12 GMT"
+ ],
+ "Last-Modified": [
+ "Thu, 27 Sep 2018 12:24:04 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "X-Goog-Expiration": [
+ "Sat, 27 Oct 2018 12:24:04 GMT"
+ ],
+ "X-Goog-Generation": [
+ "1538051044532366"
+ ],
+ "X-Goog-Hash": [
+ "crc32c=+7R11g==",
+ "md5=7wUFH8mDDwHFYqo7olxdPg=="
+ ],
+ "X-Goog-Metageneration": [
+ "1"
+ ],
+ "X-Goog-Storage-Class": [
+ "STANDARD"
+ ],
+ "X-Goog-Stored-Content-Encoding": [
+ "identity"
+ ],
+ "X-Goog-Stored-Content-Length": [
+ "16"
+ ],
+ "X-Google-Backends": [
+ "/bns/xh/borg/xh/bns/cloud-storage/prod-cloud-storage-frontend.frontend/35,/bns/xh/borg/xh/bns/blobstore2/bitpusher/59.scotty,aclgag19:443"
+ ],
+ "X-Google-Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=7MusW-XcJ4OhswbwjYa4Bw"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "aclgag19:443,/bns/xh/borg/xh/bns/blobstore2/bitpusher/59.scotty,aclgag19:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/xh/borg/xh/bns/blobstore2/bitpusher/59:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBJ"
+ ],
+ "X-Google-Storage-Location": [
+ "US"
+ ],
+ "X-Guploader-Customer": [
+ "cloud-storage"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UrOJk9tHBq0OUCi9A8y0xXe7IslqrVOVGYdH5Mbp-7Snhb8xEW8qc8GIb9lIWnFCETqHRZh7ONRc1Xzf5HG9W0jws0QSA"
+ ]
+ },
+ "Body": ""
+ }
+ },
+ {
+ "ID": "3c4f9ce008c97f86",
+ "Request": {
+ "Method": "HEAD",
+ "URL": "https://storage.googleapis.com/go-integration-test-20180927-44630911863640-0001/obj1",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "Go-http-client/1.1"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "72e113b79d3ca5d01ad7071131993c6b/5863724013258525592;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "storage.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://storage.googleapis.com/go-integration-test-20180927-44630911863640-0001/obj1"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Accept-Ranges": [
+ "bytes"
+ ],
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "public, max-age=60"
+ ],
+ "Content-Length": [
+ "16"
+ ],
+ "Content-Type": [
+ "text/plain"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:12 GMT"
+ ],
+ "Etag": [
+ "\"ef05051fc9830f01c562aa3ba25c5d3e\""
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:25:12 GMT"
+ ],
+ "Last-Modified": [
+ "Thu, 27 Sep 2018 12:24:04 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "X-Goog-Expiration": [
+ "Sat, 27 Oct 2018 12:24:04 GMT"
+ ],
+ "X-Goog-Generation": [
+ "1538051044532366"
+ ],
+ "X-Goog-Hash": [
+ "crc32c=+7R11g==",
+ "md5=7wUFH8mDDwHFYqo7olxdPg=="
+ ],
+ "X-Goog-Metageneration": [
+ "1"
+ ],
+ "X-Goog-Storage-Class": [
+ "STANDARD"
+ ],
+ "X-Goog-Stored-Content-Encoding": [
+ "identity"
+ ],
+ "X-Goog-Stored-Content-Length": [
+ "16"
+ ],
+ "X-Google-Backends": [
+ "/bns/xh/borg/xh/bns/cloud-storage/prod-cloud-storage-frontend.frontend/21,/bns/xh/borg/xh/bns/blobstore2/bitpusher/2.scotty,aclgag19:443"
+ ],
+ "X-Google-Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=7MusW9GTKo6kswbkhYKoAQ"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "aclgag19:443,/bns/xh/borg/xh/bns/blobstore2/bitpusher/2.scotty,aclgag19:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/xh/borg/xh/bns/blobstore2/bitpusher/2:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBJ"
+ ],
+ "X-Google-Storage-Location": [
+ "US"
+ ],
+ "X-Guploader-Customer": [
+ "cloud-storage"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Ura7_vBiJ9u_QXx62sETf4NCB8WaOdF-C-fdKE7JvfU4jceQVdFuFPknKkVLmlPbkF6-w60s3MPUSr_WZEW6hi7welwbg"
+ ]
+ },
+ "Body": ""
+ }
+ },
+ {
+ "ID": "649ec0e8258f8230",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://storage.googleapis.com/go-integration-test-20180927-44630911863640-0001/obj1",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Range": [
+ "bytes=8-"
+ ],
+ "User-Agent": [
+ "Go-http-client/1.1"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "312d714b782e4823e2766239e9764a82/7454134817830826039;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "storage.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://storage.googleapis.com/go-integration-test-20180927-44630911863640-0001/obj1"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 206,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Accept-Ranges": [
+ "bytes"
+ ],
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "public, max-age=60"
+ ],
+ "Content-Length": [
+ "8"
+ ],
+ "Content-Range": [
+ "bytes 8-15/16"
+ ],
+ "Content-Type": [
+ "text/plain"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:12 GMT"
+ ],
+ "Etag": [
+ "\"ef05051fc9830f01c562aa3ba25c5d3e\""
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:25:12 GMT"
+ ],
+ "Last-Modified": [
+ "Thu, 27 Sep 2018 12:24:04 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "X-Goog-Expiration": [
+ "Sat, 27 Oct 2018 12:24:04 GMT"
+ ],
+ "X-Goog-Generation": [
+ "1538051044532366"
+ ],
+ "X-Goog-Hash": [
+ "crc32c=+7R11g==",
+ "md5=7wUFH8mDDwHFYqo7olxdPg=="
+ ],
+ "X-Goog-Metageneration": [
+ "1"
+ ],
+ "X-Goog-Storage-Class": [
+ "STANDARD"
+ ],
+ "X-Goog-Stored-Content-Encoding": [
+ "identity"
+ ],
+ "X-Goog-Stored-Content-Length": [
+ "16"
+ ],
+ "X-Google-Backends": [
+ "/bns/xh/borg/xh/bns/cloud-storage/prod-cloud-storage-frontend.frontend/24,/bns/xh/borg/xh/bns/blobstore2/bitpusher/26.scotty,aclgag19:443"
+ ],
+ "X-Google-Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=7MusW8nZLOusswbax6LwDA"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "aclgag19:443,/bns/xh/borg/xh/bns/blobstore2/bitpusher/26.scotty,aclgag19:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/xh/borg/xh/bns/blobstore2/bitpusher/26:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBJ"
+ ],
+ "X-Google-Storage-Location": [
+ "US"
+ ],
+ "X-Guploader-Customer": [
+ "cloud-storage"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UpK-jwiYqScQfGxJj6D6ewVKGX-nZjT0EmiiH4Tfi66bSPjtZh5-kVGuI6Ckly3VoTzW_sJD6d_YuMNo3fLYyALhrBNyA"
+ ]
+ },
+ "Body": "tT16IRSaVJ8="
+ }
+ },
+ {
+ "ID": "be676a0036e215e9",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://storage.googleapis.com/go-integration-test-20180927-44630911863640-0001/obj1",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Range": [
+ "bytes=0-31"
+ ],
+ "User-Agent": [
+ "Go-http-client/1.1"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "f92a4564cfdb1f40093f36bf14fcf5ab/9044546721881200342;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "storage.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://storage.googleapis.com/go-integration-test-20180927-44630911863640-0001/obj1"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Accept-Ranges": [
+ "bytes"
+ ],
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "public, max-age=60"
+ ],
+ "Content-Length": [
+ "16"
+ ],
+ "Content-Type": [
+ "text/plain"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:12 GMT"
+ ],
+ "Etag": [
+ "\"ef05051fc9830f01c562aa3ba25c5d3e\""
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:25:12 GMT"
+ ],
+ "Last-Modified": [
+ "Thu, 27 Sep 2018 12:24:04 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "X-Goog-Expiration": [
+ "Sat, 27 Oct 2018 12:24:04 GMT"
+ ],
+ "X-Goog-Generation": [
+ "1538051044532366"
+ ],
+ "X-Goog-Hash": [
+ "crc32c=+7R11g==",
+ "md5=7wUFH8mDDwHFYqo7olxdPg=="
+ ],
+ "X-Goog-Metageneration": [
+ "1"
+ ],
+ "X-Goog-Storage-Class": [
+ "STANDARD"
+ ],
+ "X-Goog-Stored-Content-Encoding": [
+ "identity"
+ ],
+ "X-Goog-Stored-Content-Length": [
+ "16"
+ ],
+ "X-Google-Backends": [
+ "/bns/xh/borg/xh/bns/cloud-storage/prod-cloud-storage-frontend.frontend/9,/bns/xh/borg/xh/bns/blobstore2/bitpusher/21.scotty,aclgag19:443"
+ ],
+ "X-Google-Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=7MusW4m5L8msswb5q6WgAg"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "aclgag19:443,/bns/xh/borg/xh/bns/blobstore2/bitpusher/21.scotty,aclgag19:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/xh/borg/xh/bns/blobstore2/bitpusher/21:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBJ"
+ ],
+ "X-Google-Storage-Location": [
+ "US"
+ ],
+ "X-Guploader-Customer": [
+ "cloud-storage"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UppB6wgT197zLhkNdO97CZkj9y76ysWm6rz4qIrigBJOHEncPQvnSZDWNtkK6WWA1RmDPZuTTbqvJNssVtWwNLVMAAUxA"
+ ]
+ },
+ "Body": "G7YE7d4n0dy1PXohFJpUnw=="
+ }
+ },
+ {
+ "ID": "563f2298ed35180b",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://storage.googleapis.com/go-integration-test-20180927-44630911863640-0001/obj1",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Range": [
+ "bytes=32-41"
+ ],
+ "User-Agent": [
+ "Go-http-client/1.1"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "2cf3892a10fb83adcb8a69720664c6a0/10634958621653515124;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "storage.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://storage.googleapis.com/go-integration-test-20180927-44630911863640-0001/obj1"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 416,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Accept-Ranges": [
+ "bytes"
+ ],
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "public, max-age=60"
+ ],
+ "Content-Length": [
+ "167"
+ ],
+ "Content-Type": [
+ "application/xml; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:12 GMT"
+ ],
+ "Etag": [
+ "\"ef05051fc9830f01c562aa3ba25c5d3e\""
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:25:12 GMT"
+ ],
+ "Last-Modified": [
+ "Thu, 27 Sep 2018 12:24:04 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "X-Goog-Expiration": [
+ "Sat, 27 Oct 2018 12:24:04 GMT"
+ ],
+ "X-Goog-Generation": [
+ "1538051044532366"
+ ],
+ "X-Goog-Hash": [
+ "crc32c=+7R11g==",
+ "md5=7wUFH8mDDwHFYqo7olxdPg=="
+ ],
+ "X-Goog-Metageneration": [
+ "1"
+ ],
+ "X-Goog-Storage-Class": [
+ "STANDARD"
+ ],
+ "X-Goog-Stored-Content-Encoding": [
+ "identity"
+ ],
+ "X-Goog-Stored-Content-Length": [
+ "16"
+ ],
+ "X-Google-Backends": [
+ "/bns/xh/borg/xh/bns/cloud-storage/prod-cloud-storage-frontend.frontend/34,/bns/xh/borg/xh/bns/blobstore2/bitpusher/56.scotty,aclgag19:443"
+ ],
+ "X-Google-Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=7MusW5XDMoqlswbzlYawCw"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "aclgag19:443,/bns/xh/borg/xh/bns/blobstore2/bitpusher/56.scotty,aclgag19:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/xh/borg/xh/bns/blobstore2/bitpusher/56:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBJ"
+ ],
+ "X-Google-Storage-Location": [
+ "US"
+ ],
+ "X-Guploader-Customer": [
+ "cloud-storage"
+ ],
+ "X-Guploader-Request-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Upload-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UoID9l6tyltcSHgLV69E97wXKAD-WE81yY0iXvNFvdpm015fzIqnhV2V7ZMBUN7MDdQrniSPTv19biVJsQbMFKmQuXGeA"
+ ]
+ },
+ "Body": "PD94bWwgdmVyc2lvbj0nMS4wJyBlbmNvZGluZz0nVVRGLTgnPz48RXJyb3I+PENvZGU+SW52YWxpZFJhbmdlPC9Db2RlPjxNZXNzYWdlPlRoZSByZXF1ZXN0ZWQgcmFuZ2UgY2Fubm90IGJlIHNhdGlzZmllZC48L01lc3NhZ2U+PERldGFpbHM+Ynl0ZXM9MzItNDE8L0RldGFpbHM+PC9FcnJvcj4="
+ }
+ },
+ {
+ "ID": "5f4b31aaff5df0cc",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/obj1?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "21c5e6e73109926f023bb79cdaafcc44/12225089055022145811;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/obj1?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3243"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:12 GMT"
+ ],
+ "Etag": [
+ "CI7Bn9GW290CEAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051345000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrbq123:4158,/bns/yr/borg/yr/bns/blobstore2/bitpusher/55.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=7MusW6y8Ncir4QTO6IXwDg"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/55.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/55:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRYnFLZDRCTjBkdm9mZm9PZVZZS0p1VDRROFVJT3NhUTljbFFvbW42UElpcDBpenczVUc1ZHZUMVZlZE1OWGp3cHJDNUUyam9FUUZwbldFellKMWd5Tlp1T3o4dy16UUMxaXAtb3VNMjdkM0JqNGR4SmNfUDVYRXRjeHNYWVN3LXNuNXEtcXpLZ1NvM3BKMGx4Ym9YaGNlZHBiR2t6VGVSdlc5QnVxZDFESV9pbE84ZEFXSDVOLVJnNDQwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UrAONkHQISdEo7cEP4cm1vetvXWVS9a80QVkqu9SZg59_a9lpik1K4gnAkyp_eO4UAV121zCztwRsueq59YHW-EBBWI4w"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmoxLzE1MzgwNTEwNDQ1MzIzNjYiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9vYmoxIiwibmFtZSI6Im9iajEiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NDUzMjM2NiIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbiIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDowNC41MzJaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MDQuNTMyWiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjA0LjUzMloiLCJzaXplIjoiMTYiLCJtZDVIYXNoIjoiN3dVRkg4bUREd0hGWXFvN29seGRQZz09IiwibWVkaWFMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vZG93bmxvYWQvc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iajE/Z2VuZXJhdGlvbj0xNTM4MDUxMDQ0NTMyMzY2JmFsdD1tZWRpYSIsImNhY2hlQ29udHJvbCI6InB1YmxpYywgbWF4LWFnZT02MCIsImFjbCI6W3sia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL29iajEvMTUzODA1MTA0NDUzMjM2Ni9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iajEvYWNsL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0Ijoib2JqMSIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDQ0NTMyMzY2IiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDSTdCbjlHVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqMS8xNTM4MDUxMDQ0NTMyMzY2L3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iajEvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Im9iajEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NDUzMjM2NiIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDSTdCbjlHVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqMS8xNTM4MDUxMDQ0NTMyMzY2L3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iajEvYWNsL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Im9iajEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NDUzMjM2NiIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0k3Qm45R1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL29iajEvMTUzODA1MTA0NDUzMjM2Ni91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vb2JqMS9hY2wvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Im9iajEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NDUzMjM2NiIsImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJyb2xlIjoiT1dORVIiLCJlbWFpbCI6IjM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiZXRhZyI6IkNJN0JuOUdXMjkwQ0VBRT0ifV0sIm93bmVyIjp7ImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20ifSwiY3JjMzJjIjoiKzdSMTFnPT0iLCJldGFnIjoiQ0k3Qm45R1cyOTBDRUFFPSJ9"
+ }
+ },
+ {
+ "ID": "e47f597968365398",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "3076aa16329e4789b551e820d99ef754/13815500959089297074;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0, must-revalidate, no-transform"
+ ],
+ "Content-Length": [
+ "2492"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:13 GMT"
+ ],
+ "Etag": [
+ "CAU="
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:24:13 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051345000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrbo6:4135,/bns/yv/borg/yv/bns/blobstore2/bitpusher/181.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=7MusW6jMOcfugwS5tIzoDQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/181.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/181:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRYnFLZDRCTjBkdm9mZm9PZVZZS0p1VDRROFVJT3NhUTljbFFvbW42UElpcDBpenczVUc1ZHZUMVZlZE1OWGp3cHJDNUUyam9FUUZwbldFellKMWd5Tlp1T3o4dy16UUMxaXAtb3VNMjdkM0JqNGR4SmNfUDVYRXRjeHNYWVN3LXNuNXEtcXpLZ1NvM3BKMGx4Ym9YaGNlZHBiR2t6VGVSdlc5QnVxZDFESV9pbE84ZEFXSDVOLVJnNDQwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Up1-8QHizF8BXIhjqFiS8CwZD-iwIM6O8OdKS_SE-Vh6DpGI70tPsNdURqd04DRDsV-RUrtM6T-zuesc7-KgKVw6mMOhw"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjM6NTIuMzU1WiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjAyLjEyOVoiLCJtZXRhZ2VuZXJhdGlvbiI6IjUiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBVT0ifSx7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDQVU9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNBVT0ifV0sImRlZmF1bHRPYmplY3RBY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBVT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0FVPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0FVPSJ9XSwib3duZXIiOnsiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUifSwibG9jYXRpb24iOiJVUyIsInZlcnNpb25pbmciOnsiZW5hYmxlZCI6ZmFsc2V9LCJsaWZlY3ljbGUiOnsicnVsZSI6W3siYWN0aW9uIjp7InR5cGUiOiJEZWxldGUifSwiY29uZGl0aW9uIjp7ImFnZSI6MzB9fV19LCJsYWJlbHMiOnsibDEiOiJ2MiIsIm5ldyI6Im5ldyJ9LCJzdG9yYWdlQ2xhc3MiOiJTVEFOREFSRCIsImV0YWciOiJDQVU9In0="
+ }
+ },
+ {
+ "ID": "40317a730e582890",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/obj1/rewriteTo/b/go-integration-test-20180927-44630911863640-0001/o/copy-obj1?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "3"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "808117ec5164e049873a57f9d75f176c/15405911759349984336;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/obj1/rewriteTo/b/go-integration-test-20180927-44630911863640-0001/o/copy-obj1?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "e30K"
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3426"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:13 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051353000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrwe17:4005,/bns/yr/borg/yr/bns/blobstore2/bitpusher/112.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=7cusW7_8DoiVkASQyLSgCw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/112.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/112:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp0ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4StK4wESxgF5YTI5LmMuRW93QkpRYnFLZDRCTjBkdm9mZm9PZVZZS0p1VDRROFVJT3NhUTljbFFvbW42UElpcDBpenczVUc1ZHZUMVZlZE1OWGp3cHJDNUUyam9FUUZwbldFellKMWd5Tlp1T3o4dy16UUMxaXAtb3VNMjdkM0JqNGR4SmNfUDVYRXRjeHNYWVN3LXNuNXEtcXpLZ1NvM3BKMGx4Ym9YaGNlZHBiR2t6VGVSdlc5QnVxZDFESV9pbE84ZEFXSDVOLVJnNDQwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UoUNvhhQ0zd70YwDbOepu-hwK9grkIt_2RiEejT3Rj3AMn9HDTHdDZ-5r6mOw20lJBouR5jU8fLFoy7vo9bNAnCUOQGTQ"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNyZXdyaXRlUmVzcG9uc2UiLCJ0b3RhbEJ5dGVzUmV3cml0dGVuIjoiMTYiLCJvYmplY3RTaXplIjoiMTYiLCJkb25lIjp0cnVlLCJyZXNvdXJjZSI6eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jb3B5LW9iajEvMTUzODA1MTA1MzcyNjgyOCIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2NvcHktb2JqMSIsIm5hbWUiOiJjb3B5LW9iajEiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA1MzcyNjgyOCIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbiIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDoxMy43MjZaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MTMuNzI2WiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjEzLjcyNloiLCJzaXplIjoiMTYiLCJtZDVIYXNoIjoiN3dVRkg4bUREd0hGWXFvN29seGRQZz09IiwibWVkaWFMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vZG93bmxvYWQvc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2NvcHktb2JqMT9nZW5lcmF0aW9uPTE1MzgwNTEwNTM3MjY4MjgmYWx0PW1lZGlhIiwiY2FjaGVDb250cm9sIjoicHVibGljLCBtYXgtYWdlPTYwIiwiYWNsIjpbeyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvY29weS1vYmoxLzE1MzgwNTEwNTM3MjY4MjgvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9jb3B5LW9iajEvYWNsL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiY29weS1vYmoxIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNTM3MjY4MjgiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNPelkwTldXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jb3B5LW9iajEvMTUzODA1MTA1MzcyNjgyOC9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9jb3B5LW9iajEvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6ImNvcHktb2JqMSIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDUzNzI2ODI4IiwiZW50aXR5IjoicHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6ImVkaXRvcnMifSwiZXRhZyI6IkNPelkwTldXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jb3B5LW9iajEvMTUzODA1MTA1MzcyNjgyOC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9jb3B5LW9iajEvYWNsL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6ImNvcHktb2JqMSIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDUzNzI2ODI4IiwiZW50aXR5IjoicHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6IlJFQURFUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJ2aWV3ZXJzIn0sImV0YWciOiJDT3pZME5XVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvY29weS1vYmoxLzE1MzgwNTEwNTM3MjY4MjgvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2NvcHktb2JqMS9hY2wvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6ImNvcHktb2JqMSIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDUzNzI2ODI4IiwiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInJvbGUiOiJPV05FUiIsImVtYWlsIjoiMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJldGFnIjoiQ096WTBOV1cyOTBDRUFFPSJ9XSwib3duZXIiOnsiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSJ9LCJjcmMzMmMiOiIrN1IxMWc9PSIsImV0YWciOiJDT3pZME5XVzI5MENFQUU9In19"
+ }
+ },
+ {
+ "ID": "7c3fbfa4c28e7623",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/obj1/rewriteTo/b/go-integration-test-20180927-44630911863640-0001/o/copy-obj1?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "31"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "1efea7e671407b24046cb68f9467a222/16996042192735392239;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/obj1/rewriteTo/b/go-integration-test-20180927-44630911863640-0001/o/copy-obj1?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJjb250ZW50RW5jb2RpbmciOiJpZGVudGl0eSJ9Cg=="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3392"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:14 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051353000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vnv70:4268,/bns/yw/borg/yw/bns/blobstore2/bitpusher/172.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=7cusW9PCO4GQhwSdyY-ADQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yw/borg/yw/bns/blobstore2/bitpusher/172.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yw/borg/yw/bns/blobstore2/bitpusher/172:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp0ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4StK4wESxgF5YTI5LmMuRW93QkpRYnFLZDRCTjBkdm9mZm9PZVZZS0p1VDRROFVJT3NhUTljbFFvbW42UElpcDBpenczVUc1ZHZUMVZlZE1OWGp3cHJDNUUyam9FUUZwbldFellKMWd5Tlp1T3o4dy16UUMxaXAtb3VNMjdkM0JqNGR4SmNfUDVYRXRjeHNYWVN3LXNuNXEtcXpLZ1NvM3BKMGx4Ym9YaGNlZHBiR2t6VGVSdlc5QnVxZDFESV9pbE84ZEFXSDVOLVJnNDQwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Up33epgf_s87PSifY-y8vQLl43RsrHASyr8ALFMlZw8YfpoG2NAwQES9MZmUZyba-yAq30TyHZ99rRIenUr9Dc1ui9rsw"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNyZXdyaXRlUmVzcG9uc2UiLCJ0b3RhbEJ5dGVzUmV3cml0dGVuIjoiMTYiLCJvYmplY3RTaXplIjoiMTYiLCJkb25lIjp0cnVlLCJyZXNvdXJjZSI6eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jb3B5LW9iajEvMTUzODA1MTA1NDQyODYzOCIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2NvcHktb2JqMSIsIm5hbWUiOiJjb3B5LW9iajEiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA1NDQyODYzOCIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDoxNC40MjhaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MTQuNDI4WiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjE0LjQyOFoiLCJzaXplIjoiMTYiLCJtZDVIYXNoIjoiN3dVRkg4bUREd0hGWXFvN29seGRQZz09IiwibWVkaWFMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vZG93bmxvYWQvc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2NvcHktb2JqMT9nZW5lcmF0aW9uPTE1MzgwNTEwNTQ0Mjg2MzgmYWx0PW1lZGlhIiwiY29udGVudEVuY29kaW5nIjoiaWRlbnRpdHkiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jb3B5LW9iajEvMTUzODA1MTA1NDQyODYzOC9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2NvcHktb2JqMS9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJjb3B5LW9iajEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA1NDQyODYzOCIsImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6Im93bmVycyJ9LCJldGFnIjoiQ043RCs5V1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2NvcHktb2JqMS8xNTM4MDUxMDU0NDI4NjM4L3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2NvcHktb2JqMS9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiY29weS1vYmoxIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNTQ0Mjg2MzgiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ043RCs5V1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2NvcHktb2JqMS8xNTM4MDUxMDU0NDI4NjM4L3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2NvcHktb2JqMS9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiY29weS1vYmoxIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNTQ0Mjg2MzgiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNON0QrOVdXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jb3B5LW9iajEvMTUzODA1MTA1NDQyODYzOC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vY29weS1vYmoxL2FjbC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiY29weS1vYmoxIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNTQ0Mjg2MzgiLCJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwicm9sZSI6Ik9XTkVSIiwiZW1haWwiOiIzNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImV0YWciOiJDTjdEKzlXVzI5MENFQUU9In1dLCJvd25lciI6eyJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIn0sImNyYzMyYyI6Iis3UjExZz09IiwiZXRhZyI6IkNON0QrOVdXMjkwQ0VBRT0ifX0="
+ }
+ },
+ {
+ "ID": "1784d4812eaeaade",
+ "Request": {
+ "Method": "PATCH",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/obj1?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "193"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "818f5c53c45ebea5a3d0031cb5bfdc65/139991498052990861;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/obj1?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJhY2wiOlt7ImVudGl0eSI6ImRvbWFpbi1nb29nbGUuY29tIiwicm9sZSI6IlJFQURFUiJ9XSwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwiY29udGVudExhbmd1YWdlIjoiZW4iLCJjb250ZW50VHlwZSI6InRleHQvaHRtbCIsIm1ldGFkYXRhIjp7ImtleSI6InZhbHVlIn19Cg=="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "2151"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:14 GMT"
+ ],
+ "Etag": [
+ "CI7Bn9GW290CEAI="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051354000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrs186:4456,/bns/yw/borg/yw/bns/blobstore2/bitpusher/88.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=7susW4HKIYHThATpoLP4DQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yw/borg/yw/bns/blobstore2/bitpusher/88.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yw/borg/yw/bns/blobstore2/bitpusher/88:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATpxChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4CtK4wESxgF5YTI5LmMuRW93QkpRYnFLZDRCTjBkdm9mZm9PZVZZS0p1VDRROFVJT3NhUTljbFFvbW42UElpcDBpenczVUc1ZHZUMVZlZE1OWGp3cHJDNUUyam9FUUZwbldFellKMWd5Tlp1T3o4dy16UUMxaXAtb3VNMjdkM0JqNGR4SmNfUDVYRXRjeHNYWVN3LXNuNXEtcXpLZ1NvM3BKMGx4Ym9YaGNlZHBiR2t6VGVSdlc5QnVxZDFESV9pbE84ZEFXSDVOLVJnNDQwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UoYxKDkKtLtPDhSLnUQOcGlMYcLsZCmb_BMAWiEx4kPh-aSCKvKxmxQ2Pyx3GmtzGPQfEH1BDK7SXJINgP-EsUMPejF4g"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmoxLzE1MzgwNTEwNDQ1MzIzNjYiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9vYmoxIiwibmFtZSI6Im9iajEiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NDUzMjM2NiIsIm1ldGFnZW5lcmF0aW9uIjoiMiIsImNvbnRlbnRUeXBlIjoidGV4dC9odG1sIiwidGltZUNyZWF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjA0LjUzMloiLCJ1cGRhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDoxNC42NzBaIiwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJ0aW1lU3RvcmFnZUNsYXNzVXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MDQuNTMyWiIsInNpemUiOiIxNiIsIm1kNUhhc2giOiI3d1VGSDhtRER3SEZZcW83b2x4ZFBnPT0iLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vb2JqMT9nZW5lcmF0aW9uPTE1MzgwNTEwNDQ1MzIzNjYmYWx0PW1lZGlhIiwiY29udGVudExhbmd1YWdlIjoiZW4iLCJjYWNoZUNvbnRyb2wiOiJwdWJsaWMsIG1heC1hZ2U9NjAiLCJtZXRhZGF0YSI6eyJrZXkiOiJ2YWx1ZSJ9LCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmoxLzE1MzgwNTEwNDQ1MzIzNjYvZG9tYWluLWdvb2dsZS5jb20iLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9vYmoxL2FjbC9kb21haW4tZ29vZ2xlLmNvbSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Im9iajEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NDUzMjM2NiIsImVudGl0eSI6ImRvbWFpbi1nb29nbGUuY29tIiwicm9sZSI6IlJFQURFUiIsImRvbWFpbiI6Imdvb2dsZS5jb20iLCJldGFnIjoiQ0k3Qm45R1cyOTBDRUFJPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL29iajEvMTUzODA1MTA0NDUzMjM2Ni91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vb2JqMS9hY2wvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Im9iajEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NDUzMjM2NiIsImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJyb2xlIjoiT1dORVIiLCJlbWFpbCI6IjM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiZXRhZyI6IkNJN0JuOUdXMjkwQ0VBST0ifV0sIm93bmVyIjp7ImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20ifSwiY3JjMzJjIjoiKzdSMTFnPT0iLCJldGFnIjoiQ0k3Qm45R1cyOTBDRUFJPSJ9"
+ }
+ },
+ {
+ "ID": "ed8837066cd682d4",
+ "Request": {
+ "Method": "PATCH",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/obj1?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "120"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "e31962cb701aec17955519bbc8994ef5/1658346907593841708;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/obj1?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJjb250ZW50TGFuZ3VhZ2UiOm51bGwsImNvbnRlbnRUeXBlIjpudWxsLCJtZXRhZGF0YSI6bnVsbH0K"
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "2075"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:14 GMT"
+ ],
+ "Etag": [
+ "CI7Bn9GW290CEAM="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051354000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vnen196:4410,/bns/yx/borg/yx/bns/blobstore2/bitpusher/115.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=7susW7KPMIigzALuzLGYBQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yx/borg/yx/bns/blobstore2/bitpusher/115.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yx/borg/yx/bns/blobstore2/bitpusher/115:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATpxChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4CtK4wESxgF5YTI5LmMuRW93QkpRYnFLZDRCTjBkdm9mZm9PZVZZS0p1VDRROFVJT3NhUTljbFFvbW42UElpcDBpenczVUc1ZHZUMVZlZE1OWGp3cHJDNUUyam9FUUZwbldFellKMWd5Tlp1T3o4dy16UUMxaXAtb3VNMjdkM0JqNGR4SmNfUDVYRXRjeHNYWVN3LXNuNXEtcXpLZ1NvM3BKMGx4Ym9YaGNlZHBiR2t6VGVSdlc5QnVxZDFESV9pbE84ZEFXSDVOLVJnNDQwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Uqbu1PynGWlbjSeyTQwegY8fK2Ywxed0wJDknj_zqpsVed8gDtlvoWg8oM4ZKcNajzVapPj-mNAsDPj42T-Uc4lmxcHFg"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmoxLzE1MzgwNTEwNDQ1MzIzNjYiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9vYmoxIiwibmFtZSI6Im9iajEiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NDUzMjM2NiIsIm1ldGFnZW5lcmF0aW9uIjoiMyIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDowNC41MzJaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MTQuODg4WiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjA0LjUzMloiLCJzaXplIjoiMTYiLCJtZDVIYXNoIjoiN3dVRkg4bUREd0hGWXFvN29seGRQZz09IiwibWVkaWFMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vZG93bmxvYWQvc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iajE/Z2VuZXJhdGlvbj0xNTM4MDUxMDQ0NTMyMzY2JmFsdD1tZWRpYSIsImNhY2hlQ29udHJvbCI6InB1YmxpYywgbWF4LWFnZT02MCIsImFjbCI6W3sia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL29iajEvMTUzODA1MTA0NDUzMjM2Ni9kb21haW4tZ29vZ2xlLmNvbSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iajEvYWNsL2RvbWFpbi1nb29nbGUuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0Ijoib2JqMSIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDQ0NTMyMzY2IiwiZW50aXR5IjoiZG9tYWluLWdvb2dsZS5jb20iLCJyb2xlIjoiUkVBREVSIiwiZG9tYWluIjoiZ29vZ2xlLmNvbSIsImV0YWciOiJDSTdCbjlHVzI5MENFQU09In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqMS8xNTM4MDUxMDQ0NTMyMzY2L3VzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9vYmoxL2FjbC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0Ijoib2JqMSIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDQ0NTMyMzY2IiwiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInJvbGUiOiJPV05FUiIsImVtYWlsIjoiMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJldGFnIjoiQ0k3Qm45R1cyOTBDRUFNPSJ9XSwib3duZXIiOnsiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSJ9LCJjcmMzMmMiOiIrN1IxMWc9PSIsImV0YWciOiJDSTdCbjlHVzI5MENFQU09In0="
+ }
+ },
+ {
+ "ID": "2da4d03d65e44aff",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Type": [
+ "multipart/related; boundary=29bfc48d421eb985742aa3c01fa02a8f4f07eb13a9df1f3a6d2ffbabd8c2"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "4b38b821542f76a1d762740d02b631d9/2489440367246438267;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "LS0yOWJmYzQ4ZDQyMWViOTg1NzQyYWEzYzAxZmEwMmE4ZjRmMDdlYjEzYTlkZjFmM2E2ZDJmZmJhYmQ4YzINCkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vanNvbg0KDQp7ImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm5hbWUiOiJjaGVja3N1bS1vYmplY3QifQoNCi0tMjliZmM0OGQ0MjFlYjk4NTc0MmFhM2MwMWZhMDJhOGY0ZjA3ZWIxM2E5ZGYxZjNhNmQyZmZiYWJkOGMyDQpDb250ZW50LVR5cGU6IHRleHQvcGxhaW47IGNoYXJzZXQ9dXRmLTgNCg0KaGVsbG93b3JsZA0KLS0yOWJmYzQ4ZDQyMWViOTg1NzQyYWEzYzAxZmEwMmE4ZjRmMDdlYjEzYTlkZjFmM2E2ZDJmZmJhYmQ4YzItLQ0K"
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3398"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:15 GMT"
+ ],
+ "Etag": [
+ "CK+As9aW290CEAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051344000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrp62:4379,/bns/yv/borg/yv/bns/blobstore2/bitpusher/111.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=78usW-1oz5yBBLWtmIgB"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/111.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/111:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRYnFLZDRCTjBkdm9mZm9PZVZZS0p1VDRROFVJT3NhUTljbFFvbW42UElpcDBpenczVUc1ZHZUMVZlZE1OWGp3cHJDNUUyam9FUUZwbldFellKMWd5Tlp1T3o4dy16UUMxaXAtb3VNMjdkM0JqNGR4SmNfUDVYRXRjeHNYWVN3LXNuNXEtcXpLZ1NvM3BKMGx4Ym9YaGNlZHBiR2t6VGVSdlc5QnVxZDFESV9pbE84ZEFXSDVOLVJnNDQwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_single_post_uploads"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UowJsm6E91bsGVBm6CM-mz8rDfoul1oIecNfHPOUKCznqaR9zK2zwL7-0GmZY0j80eiUDC7pO726ekxFHOv4yM7p6uzug"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jaGVja3N1bS1vYmplY3QvMTUzODA1MTA1NTMzNzUxOSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2NoZWNrc3VtLW9iamVjdCIsIm5hbWUiOiJjaGVja3N1bS1vYmplY3QiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA1NTMzNzUxOSIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOCIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDoxNS4zMzdaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MTUuMzM3WiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjE1LjMzN1oiLCJzaXplIjoiMTAiLCJtZDVIYXNoIjoiL0Y0RGpUaWxjRElJVkVIbi9uQVFzQT09IiwibWVkaWFMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vZG93bmxvYWQvc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2NoZWNrc3VtLW9iamVjdD9nZW5lcmF0aW9uPTE1MzgwNTEwNTUzMzc1MTkmYWx0PW1lZGlhIiwiYWNsIjpbeyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvY2hlY2tzdW0tb2JqZWN0LzE1MzgwNTEwNTUzMzc1MTkvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9jaGVja3N1bS1vYmplY3QvYWNsL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiY2hlY2tzdW0tb2JqZWN0IiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNTUzMzc1MTkiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNLK0FzOWFXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jaGVja3N1bS1vYmplY3QvMTUzODA1MTA1NTMzNzUxOS9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9jaGVja3N1bS1vYmplY3QvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6ImNoZWNrc3VtLW9iamVjdCIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDU1MzM3NTE5IiwiZW50aXR5IjoicHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6ImVkaXRvcnMifSwiZXRhZyI6IkNLK0FzOWFXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jaGVja3N1bS1vYmplY3QvMTUzODA1MTA1NTMzNzUxOS9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9jaGVja3N1bS1vYmplY3QvYWNsL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6ImNoZWNrc3VtLW9iamVjdCIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDU1MzM3NTE5IiwiZW50aXR5IjoicHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6IlJFQURFUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJ2aWV3ZXJzIn0sImV0YWciOiJDSytBczlhVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvY2hlY2tzdW0tb2JqZWN0LzE1MzgwNTEwNTUzMzc1MTkvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2NoZWNrc3VtLW9iamVjdC9hY2wvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6ImNoZWNrc3VtLW9iamVjdCIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDU1MzM3NTE5IiwiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInJvbGUiOiJPV05FUiIsImVtYWlsIjoiMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJldGFnIjoiQ0srQXM5YVcyOTBDRUFFPSJ9XSwib3duZXIiOnsiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSJ9LCJjcmMzMmMiOiJWc3UwZ0E9PSIsImV0YWciOiJDSytBczlhVzI5MENFQUU9In0="
+ }
+ },
+ {
+ "ID": "7493d7564de97c32",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Type": [
+ "multipart/related; boundary=83686c59a67e3a3090aacc06f8cc35bc689e1130c5abb2208114560bd462"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "ade53e256843f2179ea331cc5e743445/3248758807366091211;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "LS04MzY4NmM1OWE2N2UzYTMwOTBhYWNjMDZmOGNjMzViYzY4OWUxMTMwYzVhYmIyMjA4MTE0NTYwYmQ0NjINCkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vanNvbg0KDQp7ImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm5hbWUiOiJ6ZXJvLW9iamVjdCJ9Cg0KLS04MzY4NmM1OWE2N2UzYTMwOTBhYWNjMDZmOGNjMzViYzY4OWUxMTMwYzVhYmIyMjA4MTE0NTYwYmQ0NjINCkNvbnRlbnQtVHlwZTogdGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOA0KDQoNCi0tODM2ODZjNTlhNjdlM2EzMDkwYWFjYzA2ZjhjYzM1YmM2ODllMTEzMGM1YWJiMjIwODExNDU2MGJkNDYyLS0NCg=="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3333"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:16 GMT"
+ ],
+ "Etag": [
+ "CPbJ19aW290CEAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051344000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrks2:4058,/bns/yv/borg/yv/bns/blobstore2/bitpusher/323.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=78usW4eCI5XYgQTfuLnICg"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/323.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/323:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRYnFLZDRCTjBkdm9mZm9PZVZZS0p1VDRROFVJT3NhUTljbFFvbW42UElpcDBpenczVUc1ZHZUMVZlZE1OWGp3cHJDNUUyam9FUUZwbldFellKMWd5Tlp1T3o4dy16UUMxaXAtb3VNMjdkM0JqNGR4SmNfUDVYRXRjeHNYWVN3LXNuNXEtcXpLZ1NvM3BKMGx4Ym9YaGNlZHBiR2t6VGVSdlc5QnVxZDFESV9pbE84ZEFXSDVOLVJnNDQwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_single_post_uploads"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UqhWY1Ab_R5DZveNFpWX2c-1hrdM8jXZdJRqFjpgtkI00Ya1DA0RgxrWCZI9zbGnWSoD1CFZn3oBDKQMDdbLLqOW3zihw"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS96ZXJvLW9iamVjdC8xNTM4MDUxMDU1OTM2NzU4Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vemVyby1vYmplY3QiLCJuYW1lIjoiemVyby1vYmplY3QiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA1NTkzNjc1OCIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOCIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDoxNS45MzZaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MTUuOTM2WiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjE1LjkzNloiLCJzaXplIjoiMCIsIm1kNUhhc2giOiIxQjJNMlk4QXNnVHBnQW1ZN1BoQ2ZnPT0iLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vemVyby1vYmplY3Q/Z2VuZXJhdGlvbj0xNTM4MDUxMDU1OTM2NzU4JmFsdD1tZWRpYSIsImFjbCI6W3sia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL3plcm8tb2JqZWN0LzE1MzgwNTEwNTU5MzY3NTgvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby96ZXJvLW9iamVjdC9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJ6ZXJvLW9iamVjdCIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDU1OTM2NzU4IiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDUGJKMTlhVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvemVyby1vYmplY3QvMTUzODA1MTA1NTkzNjc1OC9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby96ZXJvLW9iamVjdC9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiemVyby1vYmplY3QiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA1NTkzNjc1OCIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDUGJKMTlhVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvemVyby1vYmplY3QvMTUzODA1MTA1NTkzNjc1OC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby96ZXJvLW9iamVjdC9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiemVyby1vYmplY3QiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA1NTkzNjc1OCIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ1BiSjE5YVcyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL3plcm8tb2JqZWN0LzE1MzgwNTEwNTU5MzY3NTgvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL3plcm8tb2JqZWN0L2FjbC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiemVyby1vYmplY3QiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA1NTkzNjc1OCIsImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJyb2xlIjoiT1dORVIiLCJlbWFpbCI6IjM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiZXRhZyI6IkNQYkoxOWFXMjkwQ0VBRT0ifV0sIm93bmVyIjp7ImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20ifSwiY3JjMzJjIjoiQUFBQUFBPT0iLCJldGFnIjoiQ1BiSjE5YVcyOTBDRUFFPSJ9"
+ }
+ },
+ {
+ "ID": "cc0322fc546d79b7",
+ "Request": {
+ "Method": "PUT",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/obj1/acl/allUsers?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "98"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "33f9664c55b05032698ecc2d6673d6bf/4838888141239936873;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/obj1/acl/allUsers?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJlbnRpdHkiOiJhbGxVc2VycyIsInJvbGUiOiJSRUFERVIifQo="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "417"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:16 GMT"
+ ],
+ "Etag": [
+ "CI7Bn9GW290CEAQ="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051354000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vnbf187:4310,/bns/yx/borg/yx/bns/blobstore2/bitpusher/100.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=8MusW4rgA8rpzgLno6zgCQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yx/borg/yx/bns/blobstore2/bitpusher/100.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yx/borg/yx/bns/blobstore2/bitpusher/100:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATpxChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4CtK4wESxgF5YTI5LmMuRW93QkpRYnFLZDRCTjBkdm9mZm9PZVZZS0p1VDRROFVJT3NhUTljbFFvbW42UElpcDBpenczVUc1ZHZUMVZlZE1OWGp3cHJDNUUyam9FUUZwbldFellKMWd5Tlp1T3o4dy16UUMxaXAtb3VNMjdkM0JqNGR4SmNfUDVYRXRjeHNYWVN3LXNuNXEtcXpLZ1NvM3BKMGx4Ym9YaGNlZHBiR2t6VGVSdlc5QnVxZDFESV9pbE84ZEFXSDVOLVJnNDQwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UrpvmIybpBCVebTDqqsidgrv6r5XJxfkgIb_b4OdZyS6TDxQJumscogNbWOP14ydRFDoIao0YBIztO_mFhZHqa_FtHANw"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqMS8xNTM4MDUxMDQ0NTMyMzY2L2FsbFVzZXJzIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vb2JqMS9hY2wvYWxsVXNlcnMiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJvYmoxIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNDQ1MzIzNjYiLCJlbnRpdHkiOiJhbGxVc2VycyIsInJvbGUiOiJSRUFERVIiLCJldGFnIjoiQ0k3Qm45R1cyOTBDRUFRPSJ9"
+ }
+ },
+ {
+ "ID": "3d0b287f3cb38a1a",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://storage.googleapis.com/go-integration-test-20180927-44630911863640-0001/obj1",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "User-Agent": [
+ "Go-http-client/1.1"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "690d0db937791a93fb309e862ad54704/6429300045307087880;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "storage.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://storage.googleapis.com/go-integration-test-20180927-44630911863640-0001/obj1"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Accept-Ranges": [
+ "bytes"
+ ],
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "public, max-age=60"
+ ],
+ "Content-Length": [
+ "16"
+ ],
+ "Content-Type": [
+ "application/octet-stream"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:16 GMT"
+ ],
+ "Etag": [
+ "\"ef05051fc9830f01c562aa3ba25c5d3e\""
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:25:16 GMT"
+ ],
+ "Last-Modified": [
+ "Thu, 27 Sep 2018 12:24:04 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "X-Goog-Expiration": [
+ "Sat, 27 Oct 2018 12:24:04 GMT"
+ ],
+ "X-Goog-Generation": [
+ "1538051044532366"
+ ],
+ "X-Goog-Hash": [
+ "crc32c=+7R11g==",
+ "md5=7wUFH8mDDwHFYqo7olxdPg=="
+ ],
+ "X-Goog-Metageneration": [
+ "4"
+ ],
+ "X-Goog-Storage-Class": [
+ "STANDARD"
+ ],
+ "X-Goog-Stored-Content-Encoding": [
+ "identity"
+ ],
+ "X-Goog-Stored-Content-Length": [
+ "16"
+ ],
+ "X-Google-Backends": [
+ "/bns/xh/borg/xh/bns/cloud-storage/prod-cloud-storage-frontend.frontend/36,/bns/xh/borg/xh/bns/blobstore2/bitpusher/14.scotty,aclgag19:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=8MusW9aLFMKgswasv66gCg"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "aclgag19:443,/bns/xh/borg/xh/bns/blobstore2/bitpusher/14.scotty,aclgag19:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/xh/borg/xh/bns/blobstore2/bitpusher/14:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBJ"
+ ],
+ "X-Google-Storage-Location": [
+ "US"
+ ],
+ "X-Guploader-Customer": [
+ "cloud-storage"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UodxwoKYGU9MxqABteUDaXQqlKGdhkVHcajT7guddfpYQr1LRepGJXYbFR9Qs2gdcsSHWrgNx6HyMYR6YLY5M456Mko7w"
+ ]
+ },
+ "Body": "G7YE7d4n0dy1PXohFJpUnw=="
+ }
+ },
+ {
+ "ID": "cae829cdb9b34f3e",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Content-Type": [
+ "multipart/related; boundary=29bb3acea632c820a568e150cb4a4bf04415fd1bdf63309db1e96c525d7a"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "8a62594ad456c247ec2bd76dc9e52f57/7260393509254586199;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "LS0yOWJiM2FjZWE2MzJjODIwYTU2OGUxNTBjYjRhNGJmMDQ0MTVmZDFiZGY2MzMwOWRiMWU5NmM1MjVkN2ENCkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vanNvbg0KDQp7ImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm5hbWUiOiJvYmoxIn0KDQotLTI5YmIzYWNlYTYzMmM4MjBhNTY4ZTE1MGNiNGE0YmYwNDQxNWZkMWJkZjYzMzA5ZGIxZTk2YzUyNWQ3YQ0KQ29udGVudC1UeXBlOiB0ZXh0L3BsYWluOyBjaGFyc2V0PXV0Zi04DQoNCmhlbGxvDQotLTI5YmIzYWNlYTYzMmM4MjBhNTY4ZTE1MGNiNGE0YmYwNDQxNWZkMWJkZjYzMzA5ZGIxZTk2YzUyNWQ3YS0tDQo="
+ },
+ "Response": {
+ "StatusCode": 401,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Content-Length": [
+ "30139"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:16 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "Www-Authenticate": [
+ "Bearer realm=\"https://accounts.google.com/\""
+ ],
+ "X-Google-Backends": [
+ "vrqp19:4117,/bns/yv/borg/yv/bns/blobstore2/bitpusher/203.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=8MusW5PmF5C0ggSujK6wDw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/203.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/203:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "GgIYBiAB"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_single_post_uploads"
+ ],
+ "X-Guploader-Request-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Upload-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UqWr2rfS-bwg-Gq7do_pbFNKm2Y8I25oad-2ZZG3L56Sy5jUKoxRp1icBi27T5FiJu6D5V0nkc7qgcMqJALSN9rMHPscQ"
+ ]
+ },
+ "Body": "eyJlcnJvciI6eyJlcnJvcnMiOlt7ImRvbWFpbiI6Imdsb2JhbCIsInJlYXNvbiI6InJlcXVpcmVkIiwibWVzc2FnZSI6IkFub255bW91cyBjYWxsZXIgZG9lcyBub3QgaGF2ZSBzdG9yYWdlLm9iamVjdHMuY3JlYXRlIGFjY2VzcyB0byBnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqMS4iLCJsb2NhdGlvblR5cGUiOiJoZWFkZXIiLCJsb2NhdGlvbiI6IkF1dGhvcml6YXRpb24iLCJkZWJ1Z0luZm8iOiJjb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6QUNDRVNTX0RFTklFRDogQW5vbnltb3VzIGNhbGxlciBkb2VzIG5vdCBoYXZlIHN0b3JhZ2Uub2JqZWN0cy5jcmVhdGUgYWNjZXNzIHRvIGdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmoxLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5JbnNlcnRPYmplY3QuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKEluc2VydE9iamVjdC5qYXZhOjIxNylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5vYmplY3RzLkluc2VydE9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoSW5zZXJ0T2JqZWN0LmphdmE6NTEpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5PYmplY3RzRGVsZWdhdG9yLmluc2VydChPYmplY3RzRGVsZWdhdG9yLmphdmE6OTUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBBbm9ueW1vdXMgY2FsbGVyIGRvZXMgbm90IGhhdmUgc3RvcmFnZS5vYmplY3RzLmNyZWF0ZSBhY2Nlc3MgdG8gZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL29iajEuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93T25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjI5MClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMSlcblx0Li4uIDE3IG1vcmVcblxuY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUuRmF1bHQ6IEltbXV0YWJsZUVycm9yRGVmaW5pdGlvbntiYXNlPUxPR0lOX1JFUVVJUkVELCBjYXRlZ29yeT1VU0VSX0VSUk9SLCBjYXVzZT1jb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS5GYXVsdDogSW1tdXRhYmxlRXJyb3JEZWZpbml0aW9ue2Jhc2U9TE9HSU5fUkVRVUlSRUQsIGNhdGVnb3J5PVVTRVJfRVJST1IsIGNhdXNlPW51bGwsIGRlYnVnSW5mbz1jb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6QUNDRVNTX0RFTklFRDogQW5vbnltb3VzIGNhbGxlciBkb2VzIG5vdCBoYXZlIHN0b3JhZ2Uub2JqZWN0cy5jcmVhdGUgYWNjZXNzIHRvIGdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmoxLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5JbnNlcnRPYmplY3QuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKEluc2VydE9iamVjdC5qYXZhOjIxNylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5vYmplY3RzLkluc2VydE9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoSW5zZXJ0T2JqZWN0LmphdmE6NTEpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5PYmplY3RzRGVsZWdhdG9yLmluc2VydChPYmplY3RzRGVsZWdhdG9yLmphdmE6OTUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBBbm9ueW1vdXMgY2FsbGVyIGRvZXMgbm90IGhhdmUgc3RvcmFnZS5vYmplY3RzLmNyZWF0ZSBhY2Nlc3MgdG8gZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL29iajEuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93T25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjI5MClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMSlcblx0Li4uIDE3IG1vcmVcbiwgZG9tYWluPWdsb2JhbCwgZXh0ZW5kZWRIZWxwPW51bGwsIGh0dHBIZWFkZXJzPXt9LCBodHRwU3RhdHVzPXVuYXV0aG9yaXplZCwgaW50ZXJuYWxSZWFzb249UmVhc29ue2FyZ3VtZW50cz17fSwgY2F1c2U9bnVsbCwgY29kZT1nZGF0YS5Db3JlRXJyb3JEb21haW4uUkVRVUlSRUQsIGNyZWF0ZWRCeUJhY2tlbmQ9dHJ1ZSwgZGVidWdNZXNzYWdlPWNvbS5nb29nbGUubmV0LnJwYzMuUnBjRXhjZXB0aW9uOiBjbG91ZC5iaWdzdG9yZS5SZXNwb25zZUNvZGUuRXJyb3JDb2RlOjpBQ0NFU1NfREVOSUVEOiBBbm9ueW1vdXMgY2FsbGVyIGRvZXMgbm90IGhhdmUgc3RvcmFnZS5vYmplY3RzLmNyZWF0ZSBhY2Nlc3MgdG8gZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL29iajEuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRvUnBjM0V4Y2VwdGlvbihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjEzNSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5vYmplY3RzLkluc2VydE9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoSW5zZXJ0T2JqZWN0LmphdmE6MjE3KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuSW5zZXJ0T2JqZWN0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChJbnNlcnRPYmplY3QuamF2YTo1MSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLk9iamVjdHNEZWxlZ2F0b3IuaW5zZXJ0KE9iamVjdHNEZWxlZ2F0b3IuamF2YTo5NSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uUnBjUmVjZWl2ZXIubGFtYmRhJHByb2Nlc3NSZXF1ZXN0QXN5bmMkNChScGNSZWNlaXZlci5qYXZhOjIwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uQXN5bmNFeGVjdXRvci5sYW1iZGEkc3VibWl0JDAoQXN5bmNFeGVjdXRvci5qYXZhOjI3Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KENvbnRleHRSdW5uYWJsZS5qYXZhOjUwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZSQxLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozOSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NzIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozNilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRXhlY3V0b3JzJFJ1bm5hYmxlQWRhcHRlci5jYWxsKEV4ZWN1dG9ycy5qYXZhOjUxMSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRnV0dXJlVGFzay5ydW4oRnV0dXJlVGFzay5qYXZhOjI2Nilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yLnJ1bldvcmtlcihUaHJlYWRQb29sRXhlY3V0b3IuamF2YToxMTQ5KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IkV29ya2VyLnJ1bihUaHJlYWRQb29sRXhlY3V0b3IuamF2YTo2MjQpXG5cdGF0IGphdmEubGFuZy5UaHJlYWQucnVuKFRocmVhZC5qYXZhOjc0OClcbkNhdXNlZCBieTogY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb246IEFub255bW91cyBjYWxsZXIgZG9lcyBub3QgaGF2ZSBzdG9yYWdlLm9iamVjdHMuY3JlYXRlIGFjY2VzcyB0byBnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqMS5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MjkwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAxKVxuXHQuLi4gMTcgbW9yZVxuLCBlcnJvclByb3RvQ29kZT1SRVFVSVJFRCwgZXJyb3JQcm90b0RvbWFpbj1nZGF0YS5Db3JlRXJyb3JEb21haW4sIGZpbHRlcmVkTWVzc2FnZT1udWxsLCBsb2NhdGlvbj1lbnRpdHkuYXV0aGVudGljYXRlZF91c2VyLCBtZXNzYWdlPUFub255bW91cyBjYWxsZXIgZG9lcyBub3QgaGF2ZSBzdG9yYWdlLm9iamVjdHMuY3JlYXRlIGFjY2VzcyB0byBnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqMS4sIHVubmFtZWRBcmd1bWVudHM9W119LCBsb2NhdGlvbj1oZWFkZXJzLkF1dGhvcml6YXRpb24sIG1lc3NhZ2U9QW5vbnltb3VzIGNhbGxlciBkb2VzIG5vdCBoYXZlIHN0b3JhZ2Uub2JqZWN0cy5jcmVhdGUgYWNjZXNzIHRvIGdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmoxLiwgcmVhc29uPXJlcXVpcmVkLCBycGNDb2RlPTQwMX0gQW5vbnltb3VzIGNhbGxlciBkb2VzIG5vdCBoYXZlIHN0b3JhZ2Uub2JqZWN0cy5jcmVhdGUgYWNjZXNzIHRvIGdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmoxLjogY29tLmdvb2dsZS5uZXQucnBjMy5ScGNFeGNlcHRpb246IGNsb3VkLmJpZ3N0b3JlLlJlc3BvbnNlQ29kZS5FcnJvckNvZGU6OkFDQ0VTU19ERU5JRUQ6IEFub255bW91cyBjYWxsZXIgZG9lcyBub3QgaGF2ZSBzdG9yYWdlLm9iamVjdHMuY3JlYXRlIGFjY2VzcyB0byBnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqMS5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udG9ScGMzRXhjZXB0aW9uKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MTM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuSW5zZXJ0T2JqZWN0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChJbnNlcnRPYmplY3QuamF2YToyMTcpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5JbnNlcnRPYmplY3QuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKEluc2VydE9iamVjdC5qYXZhOjUxKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmZyYW1ld29yay5SZXF1ZXN0SGFuZGxlci5oYW5kbGUoUmVxdWVzdEhhbmRsZXIuamF2YToyOTQpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uT2JqZWN0c0RlbGVnYXRvci5pbnNlcnQoT2JqZWN0c0RlbGVnYXRvci5qYXZhOjk1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5ScGNSZWNlaXZlci5sYW1iZGEkcHJvY2Vzc1JlcXVlc3RBc3luYyQ0KFJwY1JlY2VpdmVyLmphdmE6MjAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5Bc3luY0V4ZWN1dG9yLmxhbWJkYSRzdWJtaXQkMChBc3luY0V4ZWN1dG9yLmphdmE6MjcyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoQ29udGV4dFJ1bm5hYmxlLmphdmE6NTApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlJDEucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM5KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo3Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5FeGVjdXRvcnMkUnVubmFibGVBZGFwdGVyLmNhbGwoRXhlY3V0b3JzLmphdmE6NTExKVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5GdXR1cmVUYXNrLnJ1bihGdXR1cmVUYXNrLmphdmE6MjY2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IucnVuV29ya2VyKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjExNDkpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvciRXb3JrZXIucnVuKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjYyNClcblx0YXQgamF2YS5sYW5nLlRocmVhZC5ydW4oVGhyZWFkLmphdmE6NzQ4KVxuQ2F1c2VkIGJ5OiBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbjogQW5vbnltb3VzIGNhbGxlciBkb2VzIG5vdCBoYXZlIHN0b3JhZ2Uub2JqZWN0cy5jcmVhdGUgYWNjZXNzIHRvIGdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmoxLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxNyBtb3JlXG4sIGRlYnVnSW5mbz1jb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6QUNDRVNTX0RFTklFRDogQW5vbnltb3VzIGNhbGxlciBkb2VzIG5vdCBoYXZlIHN0b3JhZ2Uub2JqZWN0cy5jcmVhdGUgYWNjZXNzIHRvIGdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmoxLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5JbnNlcnRPYmplY3QuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKEluc2VydE9iamVjdC5qYXZhOjIxNylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5vYmplY3RzLkluc2VydE9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoSW5zZXJ0T2JqZWN0LmphdmE6NTEpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5PYmplY3RzRGVsZWdhdG9yLmluc2VydChPYmplY3RzRGVsZWdhdG9yLmphdmE6OTUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBBbm9ueW1vdXMgY2FsbGVyIGRvZXMgbm90IGhhdmUgc3RvcmFnZS5vYmplY3RzLmNyZWF0ZSBhY2Nlc3MgdG8gZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL29iajEuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93T25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjI5MClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMSlcblx0Li4uIDE3IG1vcmVcbiwgZG9tYWluPWdsb2JhbCwgZXh0ZW5kZWRIZWxwPW51bGwsIGh0dHBIZWFkZXJzPXtXV1ctQXV0aGVudGljYXRlPVtCZWFyZXIgcmVhbG09XCJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20vXCJdfSwgaHR0cFN0YXR1cz11bmF1dGhvcml6ZWQsIGludGVybmFsUmVhc29uPVJlYXNvbnthcmd1bWVudHM9e30sIGNhdXNlPW51bGwsIGNvZGU9Z2RhdGEuQ29yZUVycm9yRG9tYWluLlJFUVVJUkVELCBjcmVhdGVkQnlCYWNrZW5kPXRydWUsIGRlYnVnTWVzc2FnZT1jb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6QUNDRVNTX0RFTklFRDogQW5vbnltb3VzIGNhbGxlciBkb2VzIG5vdCBoYXZlIHN0b3JhZ2Uub2JqZWN0cy5jcmVhdGUgYWNjZXNzIHRvIGdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmoxLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5JbnNlcnRPYmplY3QuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKEluc2VydE9iamVjdC5qYXZhOjIxNylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5vYmplY3RzLkluc2VydE9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoSW5zZXJ0T2JqZWN0LmphdmE6NTEpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5PYmplY3RzRGVsZWdhdG9yLmluc2VydChPYmplY3RzRGVsZWdhdG9yLmphdmE6OTUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBBbm9ueW1vdXMgY2FsbGVyIGRvZXMgbm90IGhhdmUgc3RvcmFnZS5vYmplY3RzLmNyZWF0ZSBhY2Nlc3MgdG8gZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL29iajEuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93T25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjI5MClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMSlcblx0Li4uIDE3IG1vcmVcbiwgZXJyb3JQcm90b0NvZGU9UkVRVUlSRUQsIGVycm9yUHJvdG9Eb21haW49Z2RhdGEuQ29yZUVycm9yRG9tYWluLCBmaWx0ZXJlZE1lc3NhZ2U9bnVsbCwgbG9jYXRpb249ZW50aXR5LmF1dGhlbnRpY2F0ZWRfdXNlciwgbWVzc2FnZT1Bbm9ueW1vdXMgY2FsbGVyIGRvZXMgbm90IGhhdmUgc3RvcmFnZS5vYmplY3RzLmNyZWF0ZSBhY2Nlc3MgdG8gZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL29iajEuLCB1bm5hbWVkQXJndW1lbnRzPVtdfSwgbG9jYXRpb249aGVhZGVycy5BdXRob3JpemF0aW9uLCBtZXNzYWdlPUFub255bW91cyBjYWxsZXIgZG9lcyBub3QgaGF2ZSBzdG9yYWdlLm9iamVjdHMuY3JlYXRlIGFjY2VzcyB0byBnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqMS4sIHJlYXNvbj1yZXF1aXJlZCwgcnBjQ29kZT00MDF9IEFub255bW91cyBjYWxsZXIgZG9lcyBub3QgaGF2ZSBzdG9yYWdlLm9iamVjdHMuY3JlYXRlIGFjY2VzcyB0byBnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqMS46IGNvbS5nb29nbGUubmV0LnJwYzMuUnBjRXhjZXB0aW9uOiBjbG91ZC5iaWdzdG9yZS5SZXNwb25zZUNvZGUuRXJyb3JDb2RlOjpBQ0NFU1NfREVOSUVEOiBBbm9ueW1vdXMgY2FsbGVyIGRvZXMgbm90IGhhdmUgc3RvcmFnZS5vYmplY3RzLmNyZWF0ZSBhY2Nlc3MgdG8gZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL29iajEuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRvUnBjM0V4Y2VwdGlvbihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjEzNSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5vYmplY3RzLkluc2VydE9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoSW5zZXJ0T2JqZWN0LmphdmE6MjE3KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuSW5zZXJ0T2JqZWN0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChJbnNlcnRPYmplY3QuamF2YTo1MSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLk9iamVjdHNEZWxlZ2F0b3IuaW5zZXJ0KE9iamVjdHNEZWxlZ2F0b3IuamF2YTo5NSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uUnBjUmVjZWl2ZXIubGFtYmRhJHByb2Nlc3NSZXF1ZXN0QXN5bmMkNChScGNSZWNlaXZlci5qYXZhOjIwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uQXN5bmNFeGVjdXRvci5sYW1iZGEkc3VibWl0JDAoQXN5bmNFeGVjdXRvci5qYXZhOjI3Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KENvbnRleHRSdW5uYWJsZS5qYXZhOjUwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZSQxLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozOSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NzIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozNilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRXhlY3V0b3JzJFJ1bm5hYmxlQWRhcHRlci5jYWxsKEV4ZWN1dG9ycy5qYXZhOjUxMSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRnV0dXJlVGFzay5ydW4oRnV0dXJlVGFzay5qYXZhOjI2Nilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yLnJ1bldvcmtlcihUaHJlYWRQb29sRXhlY3V0b3IuamF2YToxMTQ5KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IkV29ya2VyLnJ1bihUaHJlYWRQb29sRXhlY3V0b3IuamF2YTo2MjQpXG5cdGF0IGphdmEubGFuZy5UaHJlYWQucnVuKFRocmVhZC5qYXZhOjc0OClcbkNhdXNlZCBieTogY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb246IEFub255bW91cyBjYWxsZXIgZG9lcyBub3QgaGF2ZSBzdG9yYWdlLm9iamVjdHMuY3JlYXRlIGFjY2VzcyB0byBnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqMS5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MjkwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAxKVxuXHQuLi4gMTcgbW9yZVxuXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5hdXRoLkF1dGhlbnRpY2F0b3JJbnRlcmNlcHRvci5hZGRDaGFsbGVuZ2VIZWFkZXIoQXV0aGVudGljYXRvckludGVyY2VwdG9yLmphdmE6MjY0KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuYXV0aC5BdXRoZW50aWNhdG9ySW50ZXJjZXB0b3IucHJvY2Vzc0Vycm9yUmVzcG9uc2UoQXV0aGVudGljYXRvckludGVyY2VwdG9yLmphdmE6MjMxKVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuYXV0aC5HYWlhTWludEludGVyY2VwdG9yLnByb2Nlc3NFcnJvclJlc3BvbnNlKEdhaWFNaW50SW50ZXJjZXB0b3IuamF2YTo3NjQpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLmludGVyY2VwdC5Bcm91bmRJbnRlcmNlcHRvcldyYXBwZXIucHJvY2Vzc0Vycm9yUmVzcG9uc2UoQXJvdW5kSW50ZXJjZXB0b3JXcmFwcGVyLmphdmE6MjgpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5zdGF0cy5TdGF0c0Jvb3RzdHJhcCRJbnRlcmNlcHRvclN0YXRzUmVjb3JkZXIucHJvY2Vzc0Vycm9yUmVzcG9uc2UoU3RhdHNCb290c3RyYXAuamF2YTozMTIpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLmludGVyY2VwdC5JbnRlcmNlcHRpb25zJEFyb3VuZEludGVyY2VwdGlvbi5oYW5kbGVFcnJvclJlc3BvbnNlKEludGVyY2VwdGlvbnMuamF2YToyMDIpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLmludGVyY2VwdC5JbnRlcmNlcHRpb25zJEFyb3VuZEludGVyY2VwdGlvbi5hY2Nlc3MkMjAwKEludGVyY2VwdGlvbnMuamF2YToxMDMpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLmludGVyY2VwdC5JbnRlcmNlcHRpb25zJEFyb3VuZEludGVyY2VwdGlvbiQxLmNhbGwoSW50ZXJjZXB0aW9ucy5qYXZhOjE0NClcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUuaW50ZXJjZXB0LkludGVyY2VwdGlvbnMkQXJvdW5kSW50ZXJjZXB0aW9uJDEuY2FsbChJbnRlcmNlcHRpb25zLmphdmE6MTM3KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS51dGlsLkNhbGxhYmxlRnV0dXJlLnJ1bihDYWxsYWJsZUZ1dHVyZS5qYXZhOjYyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuRGlyZWN0RXhlY3V0b3IuZXhlY3V0ZShEaXJlY3RFeGVjdXRvci5qYXZhOjMwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuZXhlY3V0ZUxpc3RlbmVyKEFic3RyYWN0RnV0dXJlLmphdmE6MTE0Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmNvbXBsZXRlKEFic3RyYWN0RnV0dXJlLmphdmE6OTYzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuc2V0RXhjZXB0aW9uKEFic3RyYWN0RnV0dXJlLmphdmE6NzUzKVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS51dGlsLkNhbGxhYmxlRnV0dXJlLnJ1bihDYWxsYWJsZUZ1dHVyZS5qYXZhOjY4KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuRGlyZWN0RXhlY3V0b3IuZXhlY3V0ZShEaXJlY3RFeGVjdXRvci5qYXZhOjMwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuZXhlY3V0ZUxpc3RlbmVyKEFic3RyYWN0RnV0dXJlLmphdmE6MTE0Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmNvbXBsZXRlKEFic3RyYWN0RnV0dXJlLmphdmE6OTYzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuc2V0KEFic3RyYWN0RnV0dXJlLmphdmE6NzMxKVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS51dGlsLkNhbGxhYmxlRnV0dXJlLnJ1bihDYWxsYWJsZUZ1dHVyZS5qYXZhOjYyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuRGlyZWN0RXhlY3V0b3IuZXhlY3V0ZShEaXJlY3RFeGVjdXRvci5qYXZhOjMwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuZXhlY3V0ZUxpc3RlbmVyKEFic3RyYWN0RnV0dXJlLmphdmE6MTE0Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmNvbXBsZXRlKEFic3RyYWN0RnV0dXJlLmphdmE6OTYzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuc2V0KEFic3RyYWN0RnV0dXJlLmphdmE6NzMxKVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS51dGlsLkNhbGxhYmxlRnV0dXJlLnJ1bihDYWxsYWJsZUZ1dHVyZS5qYXZhOjYyKVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIudGhyZWFkLlRocmVhZFRyYWNrZXJzJFRocmVhZFRyYWNraW5nUnVubmFibGUucnVuKFRocmVhZFRyYWNrZXJzLmphdmE6MTI2KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JFRyYWNlQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChUcmFjZUNvbnRleHQuamF2YTo0NTUpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5zZXJ2ZXIuQ29tbW9uTW9kdWxlJENvbnRleHRDYXJyeWluZ0V4ZWN1dG9yU2VydmljZSQxLnJ1bkluQ29udGV4dChDb21tb25Nb2R1bGUuamF2YTo4NDYpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkVHJhY2VDb250ZXh0UnVubmFibGUkMS5ydW4oVHJhY2VDb250ZXh0LmphdmE6NDYyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JEFic3RyYWN0VHJhY2VDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihUcmFjZUNvbnRleHQuamF2YTozMjEpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkQWJzdHJhY3RUcmFjZUNvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoVHJhY2VDb250ZXh0LmphdmE6MzEzKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JFRyYWNlQ29udGV4dFJ1bm5hYmxlLnJ1bihUcmFjZUNvbnRleHQuamF2YTo0NTkpXG5cdGF0IGNvbS5nb29nbGUuZ3NlLmludGVybmFsLkRpc3BhdGNoUXVldWVJbXBsJFdvcmtlclRocmVhZC5ydW4oRGlzcGF0Y2hRdWV1ZUltcGwuamF2YTo0MDMpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLkZhdWx0OiBJbW11dGFibGVFcnJvckRlZmluaXRpb257YmFzZT1MT0dJTl9SRVFVSVJFRCwgY2F0ZWdvcnk9VVNFUl9FUlJPUiwgY2F1c2U9bnVsbCwgZGVidWdJbmZvPWNvbS5nb29nbGUubmV0LnJwYzMuUnBjRXhjZXB0aW9uOiBjbG91ZC5iaWdzdG9yZS5SZXNwb25zZUNvZGUuRXJyb3JDb2RlOjpBQ0NFU1NfREVOSUVEOiBBbm9ueW1vdXMgY2FsbGVyIGRvZXMgbm90IGhhdmUgc3RvcmFnZS5vYmplY3RzLmNyZWF0ZSBhY2Nlc3MgdG8gZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL29iajEuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRvUnBjM0V4Y2VwdGlvbihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjEzNSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5vYmplY3RzLkluc2VydE9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoSW5zZXJ0T2JqZWN0LmphdmE6MjE3KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuSW5zZXJ0T2JqZWN0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChJbnNlcnRPYmplY3QuamF2YTo1MSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLk9iamVjdHNEZWxlZ2F0b3IuaW5zZXJ0KE9iamVjdHNEZWxlZ2F0b3IuamF2YTo5NSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uUnBjUmVjZWl2ZXIubGFtYmRhJHByb2Nlc3NSZXF1ZXN0QXN5bmMkNChScGNSZWNlaXZlci5qYXZhOjIwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uQXN5bmNFeGVjdXRvci5sYW1iZGEkc3VibWl0JDAoQXN5bmNFeGVjdXRvci5qYXZhOjI3Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KENvbnRleHRSdW5uYWJsZS5qYXZhOjUwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZSQxLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozOSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NzIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozNilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRXhlY3V0b3JzJFJ1bm5hYmxlQWRhcHRlci5jYWxsKEV4ZWN1dG9ycy5qYXZhOjUxMSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRnV0dXJlVGFzay5ydW4oRnV0dXJlVGFzay5qYXZhOjI2Nilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yLnJ1bldvcmtlcihUaHJlYWRQb29sRXhlY3V0b3IuamF2YToxMTQ5KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IkV29ya2VyLnJ1bihUaHJlYWRQb29sRXhlY3V0b3IuamF2YTo2MjQpXG5cdGF0IGphdmEubGFuZy5UaHJlYWQucnVuKFRocmVhZC5qYXZhOjc0OClcbkNhdXNlZCBieTogY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb246IEFub255bW91cyBjYWxsZXIgZG9lcyBub3QgaGF2ZSBzdG9yYWdlLm9iamVjdHMuY3JlYXRlIGFjY2VzcyB0byBnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqMS5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MjkwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAxKVxuXHQuLi4gMTcgbW9yZVxuLCBkb21haW49Z2xvYmFsLCBleHRlbmRlZEhlbHA9bnVsbCwgaHR0cEhlYWRlcnM9e30sIGh0dHBTdGF0dXM9dW5hdXRob3JpemVkLCBpbnRlcm5hbFJlYXNvbj1SZWFzb257YXJndW1lbnRzPXt9LCBjYXVzZT1udWxsLCBjb2RlPWdkYXRhLkNvcmVFcnJvckRvbWFpbi5SRVFVSVJFRCwgY3JlYXRlZEJ5QmFja2VuZD10cnVlLCBkZWJ1Z01lc3NhZ2U9Y29tLmdvb2dsZS5uZXQucnBjMy5ScGNFeGNlcHRpb246IGNsb3VkLmJpZ3N0b3JlLlJlc3BvbnNlQ29kZS5FcnJvckNvZGU6OkFDQ0VTU19ERU5JRUQ6IEFub255bW91cyBjYWxsZXIgZG9lcyBub3QgaGF2ZSBzdG9yYWdlLm9iamVjdHMuY3JlYXRlIGFjY2VzcyB0byBnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqMS5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udG9ScGMzRXhjZXB0aW9uKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MTM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuSW5zZXJ0T2JqZWN0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChJbnNlcnRPYmplY3QuamF2YToyMTcpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5JbnNlcnRPYmplY3QuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKEluc2VydE9iamVjdC5qYXZhOjUxKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmZyYW1ld29yay5SZXF1ZXN0SGFuZGxlci5oYW5kbGUoUmVxdWVzdEhhbmRsZXIuamF2YToyOTQpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uT2JqZWN0c0RlbGVnYXRvci5pbnNlcnQoT2JqZWN0c0RlbGVnYXRvci5qYXZhOjk1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5ScGNSZWNlaXZlci5sYW1iZGEkcHJvY2Vzc1JlcXVlc3RBc3luYyQ0KFJwY1JlY2VpdmVyLmphdmE6MjAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5Bc3luY0V4ZWN1dG9yLmxhbWJkYSRzdWJtaXQkMChBc3luY0V4ZWN1dG9yLmphdmE6MjcyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoQ29udGV4dFJ1bm5hYmxlLmphdmE6NTApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlJDEucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM5KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo3Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5FeGVjdXRvcnMkUnVubmFibGVBZGFwdGVyLmNhbGwoRXhlY3V0b3JzLmphdmE6NTExKVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5GdXR1cmVUYXNrLnJ1bihGdXR1cmVUYXNrLmphdmE6MjY2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IucnVuV29ya2VyKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjExNDkpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvciRXb3JrZXIucnVuKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjYyNClcblx0YXQgamF2YS5sYW5nLlRocmVhZC5ydW4oVGhyZWFkLmphdmE6NzQ4KVxuQ2F1c2VkIGJ5OiBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbjogQW5vbnltb3VzIGNhbGxlciBkb2VzIG5vdCBoYXZlIHN0b3JhZ2Uub2JqZWN0cy5jcmVhdGUgYWNjZXNzIHRvIGdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmoxLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxNyBtb3JlXG4sIGVycm9yUHJvdG9Db2RlPVJFUVVJUkVELCBlcnJvclByb3RvRG9tYWluPWdkYXRhLkNvcmVFcnJvckRvbWFpbiwgZmlsdGVyZWRNZXNzYWdlPW51bGwsIGxvY2F0aW9uPWVudGl0eS5hdXRoZW50aWNhdGVkX3VzZXIsIG1lc3NhZ2U9QW5vbnltb3VzIGNhbGxlciBkb2VzIG5vdCBoYXZlIHN0b3JhZ2Uub2JqZWN0cy5jcmVhdGUgYWNjZXNzIHRvIGdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmoxLiwgdW5uYW1lZEFyZ3VtZW50cz1bXX0sIGxvY2F0aW9uPWhlYWRlcnMuQXV0aG9yaXphdGlvbiwgbWVzc2FnZT1Bbm9ueW1vdXMgY2FsbGVyIGRvZXMgbm90IGhhdmUgc3RvcmFnZS5vYmplY3RzLmNyZWF0ZSBhY2Nlc3MgdG8gZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL29iajEuLCByZWFzb249cmVxdWlyZWQsIHJwY0NvZGU9NDAxfSBBbm9ueW1vdXMgY2FsbGVyIGRvZXMgbm90IGhhdmUgc3RvcmFnZS5vYmplY3RzLmNyZWF0ZSBhY2Nlc3MgdG8gZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL29iajEuOiBjb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6QUNDRVNTX0RFTklFRDogQW5vbnltb3VzIGNhbGxlciBkb2VzIG5vdCBoYXZlIHN0b3JhZ2Uub2JqZWN0cy5jcmVhdGUgYWNjZXNzIHRvIGdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmoxLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5JbnNlcnRPYmplY3QuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKEluc2VydE9iamVjdC5qYXZhOjIxNylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5vYmplY3RzLkluc2VydE9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoSW5zZXJ0T2JqZWN0LmphdmE6NTEpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5PYmplY3RzRGVsZWdhdG9yLmluc2VydChPYmplY3RzRGVsZWdhdG9yLmphdmE6OTUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBBbm9ueW1vdXMgY2FsbGVyIGRvZXMgbm90IGhhdmUgc3RvcmFnZS5vYmplY3RzLmNyZWF0ZSBhY2Nlc3MgdG8gZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL29iajEuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93T25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjI5MClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMSlcblx0Li4uIDE3IG1vcmVcblxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS5FcnJvckNvbGxlY3Rvci50b0ZhdWx0KEVycm9yQ29sbGVjdG9yLmphdmE6NTQpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5yZXN0LmFkYXB0ZXIucm9zeS5Sb3N5RXJyb3JDb252ZXJ0ZXIudG9GYXVsdChSb3N5RXJyb3JDb252ZXJ0ZXIuamF2YTo2Nylcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnJlc3QuYWRhcHRlci5yb3N5LlJvc3lIYW5kbGVyJDIuY2FsbChSb3N5SGFuZGxlci5qYXZhOjI1OClcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnJlc3QuYWRhcHRlci5yb3N5LlJvc3lIYW5kbGVyJDIuY2FsbChSb3N5SGFuZGxlci5qYXZhOjIzOClcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0Li4uIDE5IG1vcmVcbiJ9XSwiY29kZSI6NDAxLCJtZXNzYWdlIjoiQW5vbnltb3VzIGNhbGxlciBkb2VzIG5vdCBoYXZlIHN0b3JhZ2Uub2JqZWN0cy5jcmVhdGUgYWNjZXNzIHRvIGdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmoxLiJ9fQ=="
+ }
+ },
+ {
+ "ID": "8758aed3ba16e613",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/copy-obj1?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "6afbb969fe0885a2b78dd5858f886be6/8019711945062560423;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/copy-obj1?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 204,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "0"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:16 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051344000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrdg20:4229,/bns/yw/borg/yw/bns/blobstore2/bitpusher/70.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=8MusW6TyLMP_N8WAs9AK"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yw/borg/yw/bns/blobstore2/bitpusher/70.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yw/borg/yw/bns/blobstore2/bitpusher/70:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRYnFLZDRCTjBkdm9mZm9PZVZZS0p1VDRROFVJT3NhUTljbFFvbW42UElpcDBpenczVUc1ZHZUMVZlZE1OWGp3cHJDNUUyam9FUUZwbldFellKMWd5Tlp1T3o4dy16UUMxaXAtb3VNMjdkM0JqNGR4SmNfUDVYRXRjeHNYWVN3LXNuNXEtcXpLZ1NvM3BKMGx4Ym9YaGNlZHBiR2t6VGVSdlc5QnVxZDFESV9pbE84ZEFXSDVOLVJnNDQwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Uo_WB_TIzYXheVC2PJxwKX79DTZxYv5LtBQXsHamFWDNH7tEHd8DHlpDI9Jo2cqRV5n41EYgQ8qbNPMD5IQCnn-ClF1g5EMIraE8-GyrOhLPzDudG0"
+ ]
+ },
+ "Body": ""
+ }
+ },
+ {
+ "ID": "9b9733451f86c731",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/copy-obj1?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "4ed613e1f2dd59d68cc9f92a23ace1da/8850805409010058742;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/copy-obj1?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 404,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0"
+ ],
+ "Content-Length": [
+ "12167"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:17 GMT"
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:24:17 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051344000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vnes8:4151,/bns/yx/borg/yx/bns/blobstore2/bitpusher/113.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=8MusW96TO8P9zALA9KDoCQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yx/borg/yx/bns/blobstore2/bitpusher/113.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yx/borg/yx/bns/blobstore2/bitpusher/113:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRYnFLZDRCTjBkdm9mZm9PZVZZS0p1VDRROFVJT3NhUTljbFFvbW42UElpcDBpenczVUc1ZHZUMVZlZE1OWGp3cHJDNUUyam9FUUZwbldFellKMWd5Tlp1T3o4dy16UUMxaXAtb3VNMjdkM0JqNGR4SmNfUDVYRXRjeHNYWVN3LXNuNXEtcXpLZ1NvM3BKMGx4Ym9YaGNlZHBiR2t6VGVSdlc5QnVxZDFESV9pbE84ZEFXSDVOLVJnNDQwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Upload-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UpQL7qcvVzjYBgZfUSe7_5liX8MrrghnugMlAYRFFtlEiR6qULOiIf42xoZ5ufqXErot0V89XuVLD6JnhdYSiKdu0Q3IQ"
+ ]
+ },
+ "Body": "eyJlcnJvciI6eyJlcnJvcnMiOlt7ImRvbWFpbiI6Imdsb2JhbCIsInJlYXNvbiI6Im5vdEZvdW5kIiwibWVzc2FnZSI6Ik5vIHN1Y2ggb2JqZWN0OiBnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvY29weS1vYmoxIiwiZGVidWdJbmZvIjoiY29tLmdvb2dsZS5uZXQucnBjMy5ScGNFeGNlcHRpb246IGNsb3VkLmJpZ3N0b3JlLlJlc3BvbnNlQ29kZS5FcnJvckNvZGU6Ok9CSkVDVF9OT1RfRk9VTkQ6IE5vIHN1Y2ggb2JqZWN0OiBnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvY29weS1vYmoxXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRvUnBjM0V4Y2VwdGlvbihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjEzNSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5vYmplY3RzLkRlbGV0ZU9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoRGVsZXRlT2JqZWN0LmphdmE6NzcpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5EZWxldGVPYmplY3QuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKERlbGV0ZU9iamVjdC5qYXZhOjIzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmZyYW1ld29yay5SZXF1ZXN0SGFuZGxlci5oYW5kbGUoUmVxdWVzdEhhbmRsZXIuamF2YToyOTQpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uT2JqZWN0c0RlbGVnYXRvci5kZWxldGUoT2JqZWN0c0RlbGVnYXRvci5qYXZhOjExMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uUnBjUmVjZWl2ZXIubGFtYmRhJHByb2Nlc3NSZXF1ZXN0QXN5bmMkNChScGNSZWNlaXZlci5qYXZhOjIwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uQXN5bmNFeGVjdXRvci5sYW1iZGEkc3VibWl0JDAoQXN5bmNFeGVjdXRvci5qYXZhOjI3Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KENvbnRleHRSdW5uYWJsZS5qYXZhOjUwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZSQxLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozOSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NzIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozNilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRXhlY3V0b3JzJFJ1bm5hYmxlQWRhcHRlci5jYWxsKEV4ZWN1dG9ycy5qYXZhOjUxMSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRnV0dXJlVGFzay5ydW4oRnV0dXJlVGFzay5qYXZhOjI2Nilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yLnJ1bldvcmtlcihUaHJlYWRQb29sRXhlY3V0b3IuamF2YToxMTQ5KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IkV29ya2VyLnJ1bihUaHJlYWRQb29sRXhlY3V0b3IuamF2YTo2MjQpXG5cdGF0IGphdmEubGFuZy5UaHJlYWQucnVuKFRocmVhZC5qYXZhOjc0OClcbkNhdXNlZCBieTogY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb246IE5vIHN1Y2ggb2JqZWN0OiBnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvY29weS1vYmoxXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93T25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjI5MClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMSlcblx0Li4uIDE3IG1vcmVcblxuY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUuRmF1bHQ6IEltbXV0YWJsZUVycm9yRGVmaW5pdGlvbntiYXNlPU5PVF9GT1VORCwgY2F0ZWdvcnk9VVNFUl9FUlJPUiwgY2F1c2U9bnVsbCwgZGVidWdJbmZvPWNvbS5nb29nbGUubmV0LnJwYzMuUnBjRXhjZXB0aW9uOiBjbG91ZC5iaWdzdG9yZS5SZXNwb25zZUNvZGUuRXJyb3JDb2RlOjpPQkpFQ1RfTk9UX0ZPVU5EOiBObyBzdWNoIG9iamVjdDogZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2NvcHktb2JqMVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5EZWxldGVPYmplY3QuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKERlbGV0ZU9iamVjdC5qYXZhOjc3KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuRGVsZXRlT2JqZWN0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChEZWxldGVPYmplY3QuamF2YToyMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLk9iamVjdHNEZWxlZ2F0b3IuZGVsZXRlKE9iamVjdHNEZWxlZ2F0b3IuamF2YToxMTMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBObyBzdWNoIG9iamVjdDogZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2NvcHktb2JqMVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxNyBtb3JlXG4sIGRvbWFpbj1nbG9iYWwsIGV4dGVuZGVkSGVscD1udWxsLCBodHRwSGVhZGVycz17fSwgaHR0cFN0YXR1cz1ub3RGb3VuZCwgaW50ZXJuYWxSZWFzb249UmVhc29ue2FyZ3VtZW50cz17fSwgY2F1c2U9bnVsbCwgY29kZT1nZGF0YS5Db3JlRXJyb3JEb21haW4uTk9UX0ZPVU5ELCBjcmVhdGVkQnlCYWNrZW5kPXRydWUsIGRlYnVnTWVzc2FnZT1jb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6T0JKRUNUX05PVF9GT1VORDogTm8gc3VjaCBvYmplY3Q6IGdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jb3B5LW9iajFcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udG9ScGMzRXhjZXB0aW9uKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MTM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuRGVsZXRlT2JqZWN0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChEZWxldGVPYmplY3QuamF2YTo3Nylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5vYmplY3RzLkRlbGV0ZU9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoRGVsZXRlT2JqZWN0LmphdmE6MjMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5PYmplY3RzRGVsZWdhdG9yLmRlbGV0ZShPYmplY3RzRGVsZWdhdG9yLmphdmE6MTEzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5ScGNSZWNlaXZlci5sYW1iZGEkcHJvY2Vzc1JlcXVlc3RBc3luYyQ0KFJwY1JlY2VpdmVyLmphdmE6MjAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5Bc3luY0V4ZWN1dG9yLmxhbWJkYSRzdWJtaXQkMChBc3luY0V4ZWN1dG9yLmphdmE6MjcyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoQ29udGV4dFJ1bm5hYmxlLmphdmE6NTApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlJDEucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM5KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo3Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5FeGVjdXRvcnMkUnVubmFibGVBZGFwdGVyLmNhbGwoRXhlY3V0b3JzLmphdmE6NTExKVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5GdXR1cmVUYXNrLnJ1bihGdXR1cmVUYXNrLmphdmE6MjY2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IucnVuV29ya2VyKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjExNDkpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvciRXb3JrZXIucnVuKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjYyNClcblx0YXQgamF2YS5sYW5nLlRocmVhZC5ydW4oVGhyZWFkLmphdmE6NzQ4KVxuQ2F1c2VkIGJ5OiBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbjogTm8gc3VjaCBvYmplY3Q6IGdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jb3B5LW9iajFcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MjkwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAxKVxuXHQuLi4gMTcgbW9yZVxuLCBlcnJvclByb3RvQ29kZT1OT1RfRk9VTkQsIGVycm9yUHJvdG9Eb21haW49Z2RhdGEuQ29yZUVycm9yRG9tYWluLCBmaWx0ZXJlZE1lc3NhZ2U9bnVsbCwgbG9jYXRpb249ZW50aXR5LnJlc291cmNlX2lkLm5hbWUsIG1lc3NhZ2U9Tm8gc3VjaCBvYmplY3Q6IGdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jb3B5LW9iajEsIHVubmFtZWRBcmd1bWVudHM9W119LCBsb2NhdGlvbj1lbnRpdHkucmVzb3VyY2VfaWQubmFtZSwgbWVzc2FnZT1ObyBzdWNoIG9iamVjdDogZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2NvcHktb2JqMSwgcmVhc29uPW5vdEZvdW5kLCBycGNDb2RlPTQwNH0gTm8gc3VjaCBvYmplY3Q6IGdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jb3B5LW9iajE6IGNvbS5nb29nbGUubmV0LnJwYzMuUnBjRXhjZXB0aW9uOiBjbG91ZC5iaWdzdG9yZS5SZXNwb25zZUNvZGUuRXJyb3JDb2RlOjpPQkpFQ1RfTk9UX0ZPVU5EOiBObyBzdWNoIG9iamVjdDogZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2NvcHktb2JqMVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5EZWxldGVPYmplY3QuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKERlbGV0ZU9iamVjdC5qYXZhOjc3KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuRGVsZXRlT2JqZWN0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChEZWxldGVPYmplY3QuamF2YToyMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLk9iamVjdHNEZWxlZ2F0b3IuZGVsZXRlKE9iamVjdHNEZWxlZ2F0b3IuamF2YToxMTMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBObyBzdWNoIG9iamVjdDogZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2NvcHktb2JqMVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxNyBtb3JlXG5cblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUuRXJyb3JDb2xsZWN0b3IudG9GYXVsdChFcnJvckNvbGxlY3Rvci5qYXZhOjU0KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIucmVzdC5hZGFwdGVyLnJvc3kuUm9zeUVycm9yQ29udmVydGVyLnRvRmF1bHQoUm9zeUVycm9yQ29udmVydGVyLmphdmE6NjcpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5yZXN0LmFkYXB0ZXIucm9zeS5Sb3N5SGFuZGxlciQyLmNhbGwoUm9zeUhhbmRsZXIuamF2YToyNTgpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5yZXN0LmFkYXB0ZXIucm9zeS5Sb3N5SGFuZGxlciQyLmNhbGwoUm9zeUhhbmRsZXIuamF2YToyMzgpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLnV0aWwuQ2FsbGFibGVGdXR1cmUucnVuKENhbGxhYmxlRnV0dXJlLmphdmE6NjIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5EaXJlY3RFeGVjdXRvci5leGVjdXRlKERpcmVjdEV4ZWN1dG9yLmphdmE6MzApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5leGVjdXRlTGlzdGVuZXIoQWJzdHJhY3RGdXR1cmUuamF2YToxMTQzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuY29tcGxldGUoQWJzdHJhY3RGdXR1cmUuamF2YTo5NjMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5zZXQoQWJzdHJhY3RGdXR1cmUuamF2YTo3MzEpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLnV0aWwuQ2FsbGFibGVGdXR1cmUucnVuKENhbGxhYmxlRnV0dXJlLmphdmE6NjIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5EaXJlY3RFeGVjdXRvci5leGVjdXRlKERpcmVjdEV4ZWN1dG9yLmphdmE6MzApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5leGVjdXRlTGlzdGVuZXIoQWJzdHJhY3RGdXR1cmUuamF2YToxMTQzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuY29tcGxldGUoQWJzdHJhY3RGdXR1cmUuamF2YTo5NjMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5zZXQoQWJzdHJhY3RGdXR1cmUuamF2YTo3MzEpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLnV0aWwuQ2FsbGFibGVGdXR1cmUucnVuKENhbGxhYmxlRnV0dXJlLmphdmE6NjIpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci50aHJlYWQuVGhyZWFkVHJhY2tlcnMkVGhyZWFkVHJhY2tpbmdSdW5uYWJsZS5ydW4oVGhyZWFkVHJhY2tlcnMuamF2YToxMjYpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkVHJhY2VDb250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KFRyYWNlQ29udGV4dC5qYXZhOjQ1NSlcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnNlcnZlci5Db21tb25Nb2R1bGUkQ29udGV4dENhcnJ5aW5nRXhlY3V0b3JTZXJ2aWNlJDEucnVuSW5Db250ZXh0KENvbW1vbk1vZHVsZS5qYXZhOjg0Nilcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRUcmFjZUNvbnRleHRSdW5uYWJsZSQxLnJ1bihUcmFjZUNvbnRleHQuamF2YTo0NjIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkQWJzdHJhY3RUcmFjZUNvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKFRyYWNlQ29udGV4dC5qYXZhOjMyMSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRBYnN0cmFjdFRyYWNlQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChUcmFjZUNvbnRleHQuamF2YTozMTMpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkVHJhY2VDb250ZXh0UnVubmFibGUucnVuKFRyYWNlQ29udGV4dC5qYXZhOjQ1OSlcblx0YXQgY29tLmdvb2dsZS5nc2UuaW50ZXJuYWwuRGlzcGF0Y2hRdWV1ZUltcGwkV29ya2VyVGhyZWFkLnJ1bihEaXNwYXRjaFF1ZXVlSW1wbC5qYXZhOjQwMylcbiJ9XSwiY29kZSI6NDA0LCJtZXNzYWdlIjoiTm8gc3VjaCBvYmplY3Q6IGdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jb3B5LW9iajEifX0="
+ }
+ },
+ {
+ "ID": "d6873ffc79300971",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/copy-obj1?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "08e7bf5864621c4b488ed652bb33efa8/10441217313077209749;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/copy-obj1?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 404,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0"
+ ],
+ "Content-Length": [
+ "12107"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:17 GMT"
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:24:17 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051345000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vnnl20:4294,/bns/yx/borg/yx/bns/blobstore2/bitpusher/86.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=8cusW9T2AsK0zALEw4ygDw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yx/borg/yx/bns/blobstore2/bitpusher/86.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yx/borg/yx/bns/blobstore2/bitpusher/86:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRYnFLZDRCTjBkdm9mZm9PZVZZS0p1VDRROFVJT3NhUTljbFFvbW42UElpcDBpenczVUc1ZHZUMVZlZE1OWGp3cHJDNUUyam9FUUZwbldFellKMWd5Tlp1T3o4dy16UUMxaXAtb3VNMjdkM0JqNGR4SmNfUDVYRXRjeHNYWVN3LXNuNXEtcXpLZ1NvM3BKMGx4Ym9YaGNlZHBiR2t6VGVSdlc5QnVxZDFESV9pbE84ZEFXSDVOLVJnNDQwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Upload-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UokNGRr71RRY51b_oxACRzHO0T0SKYySfLa0FwXM-OtehDW-Ck9X2Q17U8IVWtiH3JL37eb5NYUCBv065INRRt6SnW2ZA"
+ ]
+ },
+ "Body": "eyJlcnJvciI6eyJlcnJvcnMiOlt7ImRvbWFpbiI6Imdsb2JhbCIsInJlYXNvbiI6Im5vdEZvdW5kIiwibWVzc2FnZSI6Ik5vIHN1Y2ggb2JqZWN0OiBnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvY29weS1vYmoxIiwiZGVidWdJbmZvIjoiY29tLmdvb2dsZS5uZXQucnBjMy5ScGNFeGNlcHRpb246IGNsb3VkLmJpZ3N0b3JlLlJlc3BvbnNlQ29kZS5FcnJvckNvZGU6Ok9CSkVDVF9OT1RfRk9VTkQ6IE5vIHN1Y2ggb2JqZWN0OiBnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvY29weS1vYmoxXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRvUnBjM0V4Y2VwdGlvbihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjEzNSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5vYmplY3RzLkdldE9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoR2V0T2JqZWN0LmphdmE6Mjk4KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuR2V0T2JqZWN0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChHZXRPYmplY3QuamF2YTo3MSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLk9iamVjdHNEZWxlZ2F0b3IuZ2V0KE9iamVjdHNEZWxlZ2F0b3IuamF2YTo4MSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uUnBjUmVjZWl2ZXIubGFtYmRhJHByb2Nlc3NSZXF1ZXN0QXN5bmMkNChScGNSZWNlaXZlci5qYXZhOjIwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uQXN5bmNFeGVjdXRvci5sYW1iZGEkc3VibWl0JDAoQXN5bmNFeGVjdXRvci5qYXZhOjI3Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KENvbnRleHRSdW5uYWJsZS5qYXZhOjUwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZSQxLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozOSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NzIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozNilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRXhlY3V0b3JzJFJ1bm5hYmxlQWRhcHRlci5jYWxsKEV4ZWN1dG9ycy5qYXZhOjUxMSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRnV0dXJlVGFzay5ydW4oRnV0dXJlVGFzay5qYXZhOjI2Nilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yLnJ1bldvcmtlcihUaHJlYWRQb29sRXhlY3V0b3IuamF2YToxMTQ5KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IkV29ya2VyLnJ1bihUaHJlYWRQb29sRXhlY3V0b3IuamF2YTo2MjQpXG5cdGF0IGphdmEubGFuZy5UaHJlYWQucnVuKFRocmVhZC5qYXZhOjc0OClcbkNhdXNlZCBieTogY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb246IE5vIHN1Y2ggb2JqZWN0OiBnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvY29weS1vYmoxXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93T25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjI5MClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMSlcblx0Li4uIDE3IG1vcmVcblxuY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUuRmF1bHQ6IEltbXV0YWJsZUVycm9yRGVmaW5pdGlvbntiYXNlPU5PVF9GT1VORCwgY2F0ZWdvcnk9VVNFUl9FUlJPUiwgY2F1c2U9bnVsbCwgZGVidWdJbmZvPWNvbS5nb29nbGUubmV0LnJwYzMuUnBjRXhjZXB0aW9uOiBjbG91ZC5iaWdzdG9yZS5SZXNwb25zZUNvZGUuRXJyb3JDb2RlOjpPQkpFQ1RfTk9UX0ZPVU5EOiBObyBzdWNoIG9iamVjdDogZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2NvcHktb2JqMVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5HZXRPYmplY3QuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKEdldE9iamVjdC5qYXZhOjI5OClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5vYmplY3RzLkdldE9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoR2V0T2JqZWN0LmphdmE6NzEpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5PYmplY3RzRGVsZWdhdG9yLmdldChPYmplY3RzRGVsZWdhdG9yLmphdmE6ODEpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBObyBzdWNoIG9iamVjdDogZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2NvcHktb2JqMVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxNyBtb3JlXG4sIGRvbWFpbj1nbG9iYWwsIGV4dGVuZGVkSGVscD1udWxsLCBodHRwSGVhZGVycz17fSwgaHR0cFN0YXR1cz1ub3RGb3VuZCwgaW50ZXJuYWxSZWFzb249UmVhc29ue2FyZ3VtZW50cz17fSwgY2F1c2U9bnVsbCwgY29kZT1nZGF0YS5Db3JlRXJyb3JEb21haW4uTk9UX0ZPVU5ELCBjcmVhdGVkQnlCYWNrZW5kPXRydWUsIGRlYnVnTWVzc2FnZT1jb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6T0JKRUNUX05PVF9GT1VORDogTm8gc3VjaCBvYmplY3Q6IGdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jb3B5LW9iajFcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udG9ScGMzRXhjZXB0aW9uKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MTM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuR2V0T2JqZWN0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChHZXRPYmplY3QuamF2YToyOTgpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5HZXRPYmplY3QuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKEdldE9iamVjdC5qYXZhOjcxKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmZyYW1ld29yay5SZXF1ZXN0SGFuZGxlci5oYW5kbGUoUmVxdWVzdEhhbmRsZXIuamF2YToyOTQpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uT2JqZWN0c0RlbGVnYXRvci5nZXQoT2JqZWN0c0RlbGVnYXRvci5qYXZhOjgxKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5ScGNSZWNlaXZlci5sYW1iZGEkcHJvY2Vzc1JlcXVlc3RBc3luYyQ0KFJwY1JlY2VpdmVyLmphdmE6MjAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5Bc3luY0V4ZWN1dG9yLmxhbWJkYSRzdWJtaXQkMChBc3luY0V4ZWN1dG9yLmphdmE6MjcyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoQ29udGV4dFJ1bm5hYmxlLmphdmE6NTApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlJDEucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM5KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo3Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5FeGVjdXRvcnMkUnVubmFibGVBZGFwdGVyLmNhbGwoRXhlY3V0b3JzLmphdmE6NTExKVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5GdXR1cmVUYXNrLnJ1bihGdXR1cmVUYXNrLmphdmE6MjY2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IucnVuV29ya2VyKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjExNDkpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvciRXb3JrZXIucnVuKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjYyNClcblx0YXQgamF2YS5sYW5nLlRocmVhZC5ydW4oVGhyZWFkLmphdmE6NzQ4KVxuQ2F1c2VkIGJ5OiBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbjogTm8gc3VjaCBvYmplY3Q6IGdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jb3B5LW9iajFcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MjkwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAxKVxuXHQuLi4gMTcgbW9yZVxuLCBlcnJvclByb3RvQ29kZT1OT1RfRk9VTkQsIGVycm9yUHJvdG9Eb21haW49Z2RhdGEuQ29yZUVycm9yRG9tYWluLCBmaWx0ZXJlZE1lc3NhZ2U9bnVsbCwgbG9jYXRpb249ZW50aXR5LnJlc291cmNlX2lkLm5hbWUsIG1lc3NhZ2U9Tm8gc3VjaCBvYmplY3Q6IGdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jb3B5LW9iajEsIHVubmFtZWRBcmd1bWVudHM9W119LCBsb2NhdGlvbj1lbnRpdHkucmVzb3VyY2VfaWQubmFtZSwgbWVzc2FnZT1ObyBzdWNoIG9iamVjdDogZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2NvcHktb2JqMSwgcmVhc29uPW5vdEZvdW5kLCBycGNDb2RlPTQwNH0gTm8gc3VjaCBvYmplY3Q6IGdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jb3B5LW9iajE6IGNvbS5nb29nbGUubmV0LnJwYzMuUnBjRXhjZXB0aW9uOiBjbG91ZC5iaWdzdG9yZS5SZXNwb25zZUNvZGUuRXJyb3JDb2RlOjpPQkpFQ1RfTk9UX0ZPVU5EOiBObyBzdWNoIG9iamVjdDogZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2NvcHktb2JqMVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5HZXRPYmplY3QuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKEdldE9iamVjdC5qYXZhOjI5OClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5vYmplY3RzLkdldE9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoR2V0T2JqZWN0LmphdmE6NzEpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5PYmplY3RzRGVsZWdhdG9yLmdldChPYmplY3RzRGVsZWdhdG9yLmphdmE6ODEpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBObyBzdWNoIG9iamVjdDogZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2NvcHktb2JqMVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxNyBtb3JlXG5cblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUuRXJyb3JDb2xsZWN0b3IudG9GYXVsdChFcnJvckNvbGxlY3Rvci5qYXZhOjU0KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIucmVzdC5hZGFwdGVyLnJvc3kuUm9zeUVycm9yQ29udmVydGVyLnRvRmF1bHQoUm9zeUVycm9yQ29udmVydGVyLmphdmE6NjcpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5yZXN0LmFkYXB0ZXIucm9zeS5Sb3N5SGFuZGxlciQyLmNhbGwoUm9zeUhhbmRsZXIuamF2YToyNTgpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5yZXN0LmFkYXB0ZXIucm9zeS5Sb3N5SGFuZGxlciQyLmNhbGwoUm9zeUhhbmRsZXIuamF2YToyMzgpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLnV0aWwuQ2FsbGFibGVGdXR1cmUucnVuKENhbGxhYmxlRnV0dXJlLmphdmE6NjIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5EaXJlY3RFeGVjdXRvci5leGVjdXRlKERpcmVjdEV4ZWN1dG9yLmphdmE6MzApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5leGVjdXRlTGlzdGVuZXIoQWJzdHJhY3RGdXR1cmUuamF2YToxMTQzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuY29tcGxldGUoQWJzdHJhY3RGdXR1cmUuamF2YTo5NjMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5zZXQoQWJzdHJhY3RGdXR1cmUuamF2YTo3MzEpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLnV0aWwuQ2FsbGFibGVGdXR1cmUucnVuKENhbGxhYmxlRnV0dXJlLmphdmE6NjIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5EaXJlY3RFeGVjdXRvci5leGVjdXRlKERpcmVjdEV4ZWN1dG9yLmphdmE6MzApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5leGVjdXRlTGlzdGVuZXIoQWJzdHJhY3RGdXR1cmUuamF2YToxMTQzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuY29tcGxldGUoQWJzdHJhY3RGdXR1cmUuamF2YTo5NjMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5zZXQoQWJzdHJhY3RGdXR1cmUuamF2YTo3MzEpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLnV0aWwuQ2FsbGFibGVGdXR1cmUucnVuKENhbGxhYmxlRnV0dXJlLmphdmE6NjIpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci50aHJlYWQuVGhyZWFkVHJhY2tlcnMkVGhyZWFkVHJhY2tpbmdSdW5uYWJsZS5ydW4oVGhyZWFkVHJhY2tlcnMuamF2YToxMjYpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkVHJhY2VDb250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KFRyYWNlQ29udGV4dC5qYXZhOjQ1NSlcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnNlcnZlci5Db21tb25Nb2R1bGUkQ29udGV4dENhcnJ5aW5nRXhlY3V0b3JTZXJ2aWNlJDEucnVuSW5Db250ZXh0KENvbW1vbk1vZHVsZS5qYXZhOjg0Nilcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRUcmFjZUNvbnRleHRSdW5uYWJsZSQxLnJ1bihUcmFjZUNvbnRleHQuamF2YTo0NjIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkQWJzdHJhY3RUcmFjZUNvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKFRyYWNlQ29udGV4dC5qYXZhOjMyMSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRBYnN0cmFjdFRyYWNlQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChUcmFjZUNvbnRleHQuamF2YTozMTMpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkVHJhY2VDb250ZXh0UnVubmFibGUucnVuKFRyYWNlQ29udGV4dC5qYXZhOjQ1OSlcblx0YXQgY29tLmdvb2dsZS5nc2UuaW50ZXJuYWwuRGlzcGF0Y2hRdWV1ZUltcGwkV29ya2VyVGhyZWFkLnJ1bihEaXNwYXRjaFF1ZXVlSW1wbC5qYXZhOjQwMylcbiJ9XSwiY29kZSI6NDA0LCJtZXNzYWdlIjoiTm8gc3VjaCBvYmplY3Q6IGdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jb3B5LW9iajEifX0="
+ }
+ },
+ {
+ "ID": "6cc70dcba7bada17",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/composed1/compose?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "156"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "9863e2969d42a229b723aedca5070485/12031628117632798771;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/composed1/compose?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJkZXN0aW5hdGlvbiI6eyJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEifSwic291cmNlT2JqZWN0cyI6W3sibmFtZSI6Im9iajEifSx7Im5hbWUiOiJvYmoyIn0seyJuYW1lIjoib2JqL3dpdGgvc2xhc2hlcyJ9XX0K"
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "750"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:17 GMT"
+ ],
+ "Etag": [
+ "CPK8wteW290CEAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051353000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrmu6:4354,/bns/yr/borg/yr/bns/blobstore2/bitpusher/80.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=8cusW4fEE9L6kAP667DgBA"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/80.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/80:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp0ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4StK4wESxgF5YTI5LmMuRW93QkpRYnFLZDRCTjBkdm9mZm9PZVZZS0p1VDRROFVJT3NhUTljbFFvbW42UElpcDBpenczVUc1ZHZUMVZlZE1OWGp3cHJDNUUyam9FUUZwbldFellKMWd5Tlp1T3o4dy16UUMxaXAtb3VNMjdkM0JqNGR4SmNfUDVYRXRjeHNYWVN3LXNuNXEtcXpLZ1NvM3BKMGx4Ym9YaGNlZHBiR2t6VGVSdlc5QnVxZDFESV9pbE84ZEFXSDVOLVJnNDQwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UqVIeiy4Si_0YNKLwY3IG9GOLU0P0n1CkorBkpJAR_BfS1jk_56Sw6HKwDphzFjNssouMyenjo7arMSaMAmsUdvFlYB9w"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jb21wb3NlZDEvMTUzODA1MTA1NzY4ODE3OCIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2NvbXBvc2VkMSIsIm5hbWUiOiJjb21wb3NlZDEiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA1NzY4ODE3OCIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDoxNy42ODhaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MTcuNjg4WiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjE3LjY4OFoiLCJzaXplIjoiNDgiLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vY29tcG9zZWQxP2dlbmVyYXRpb249MTUzODA1MTA1NzY4ODE3OCZhbHQ9bWVkaWEiLCJjcmMzMmMiOiJib0I4bXc9PSIsImNvbXBvbmVudENvdW50IjozLCJldGFnIjoiQ1BLOHd0ZVcyOTBDRUFFPSJ9"
+ }
+ },
+ {
+ "ID": "50f8730f385d030c",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://storage.googleapis.com/go-integration-test-20180927-44630911863640-0001/composed1",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "Go-http-client/1.1"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "760c277df2c97acc454ce434914ee9e8/13549702052197004754;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "storage.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://storage.googleapis.com/go-integration-test-20180927-44630911863640-0001/composed1"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Accept-Ranges": [
+ "bytes"
+ ],
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0"
+ ],
+ "Content-Length": [
+ "48"
+ ],
+ "Content-Type": [
+ "application/octet-stream"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:17 GMT"
+ ],
+ "Etag": [
+ "\"-CPK8wteW290CEAE=\""
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:24:17 GMT"
+ ],
+ "Last-Modified": [
+ "Thu, 27 Sep 2018 12:24:17 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "X-Goog-Component-Count": [
+ "3"
+ ],
+ "X-Goog-Expiration": [
+ "Sat, 27 Oct 2018 12:24:17 GMT"
+ ],
+ "X-Goog-Generation": [
+ "1538051057688178"
+ ],
+ "X-Goog-Hash": [
+ "crc32c=boB8mw=="
+ ],
+ "X-Goog-Metageneration": [
+ "1"
+ ],
+ "X-Goog-Storage-Class": [
+ "STANDARD"
+ ],
+ "X-Goog-Stored-Content-Encoding": [
+ "identity"
+ ],
+ "X-Goog-Stored-Content-Length": [
+ "48"
+ ],
+ "X-Google-Backends": [
+ "/bns/xh/borg/xh/bns/cloud-storage/prod-cloud-storage-frontend.frontend/18,/bns/xh/borg/xh/bns/blobstore2/bitpusher/34.scotty,aclgag19:443"
+ ],
+ "X-Google-Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=8cusW9ebMdCoswa6y4HoAw"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "aclgag19:443,/bns/xh/borg/xh/bns/blobstore2/bitpusher/34.scotty,aclgag19:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/xh/borg/xh/bns/blobstore2/bitpusher/34:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBJ"
+ ],
+ "X-Google-Storage-Location": [
+ "US"
+ ],
+ "X-Guploader-Customer": [
+ "cloud-storage"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UoX-eaOWQ9wa_8D4JqhxXvp57Z8lKcw7mTxFIfWfaKu1KAUgjL9WuATvzG1v-OCqywESusNWkTDMqjoDaCDrd7JK3sf0A"
+ ]
+ },
+ "Body": "G7YE7d4n0dy1PXohFJpUn8PZcNJccaSrouZ5qGqfKcNY+xSKoJ2Yh9xMlR8v8x6R"
+ }
+ },
+ {
+ "ID": "4f10cc8a4c605e16",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/composed2/compose?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "182"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "2a7e45e04c9b2ba8510787a4626e0409/15140113956247378801;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/composed2/compose?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJkZXN0aW5hdGlvbiI6eyJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJjb250ZW50VHlwZSI6InRleHQvanNvbiJ9LCJzb3VyY2VPYmplY3RzIjpbeyJuYW1lIjoib2JqMSJ9LHsibmFtZSI6Im9iajIifSx7Im5hbWUiOiJvYmovd2l0aC9zbGFzaGVzIn1dfQo="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "776"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:18 GMT"
+ ],
+ "Etag": [
+ "CNnn7NeW290CEAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051353000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrfx72:4146,/bns/yv/borg/yv/bns/blobstore2/bitpusher/63.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=8cusW5aPOMeCNruzofgP"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/63.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/63:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp0ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4StK4wESxgF5YTI5LmMuRW93QkpRYnFLZDRCTjBkdm9mZm9PZVZZS0p1VDRROFVJT3NhUTljbFFvbW42UElpcDBpenczVUc1ZHZUMVZlZE1OWGp3cHJDNUUyam9FUUZwbldFellKMWd5Tlp1T3o4dy16UUMxaXAtb3VNMjdkM0JqNGR4SmNfUDVYRXRjeHNYWVN3LXNuNXEtcXpLZ1NvM3BKMGx4Ym9YaGNlZHBiR2t6VGVSdlc5QnVxZDFESV9pbE84ZEFXSDVOLVJnNDQwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UrggIUXoQRGOBqCG_DLynaYwpyl_4lENPEOVra5582u9rZmF-icWSkCFTlLj14A0wP6_ZaqI_ZgXHPSrgXC2GkiLC3MWw"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jb21wb3NlZDIvMTUzODA1MTA1ODM4MTc4NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2NvbXBvc2VkMiIsIm5hbWUiOiJjb21wb3NlZDIiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA1ODM4MTc4NSIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoidGV4dC9qc29uIiwidGltZUNyZWF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjE4LjM3OVoiLCJ1cGRhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDoxOC4zNzlaIiwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJ0aW1lU3RvcmFnZUNsYXNzVXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MTguMzc5WiIsInNpemUiOiI0OCIsIm1lZGlhTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2Rvd25sb2FkL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9jb21wb3NlZDI/Z2VuZXJhdGlvbj0xNTM4MDUxMDU4MzgxNzg1JmFsdD1tZWRpYSIsImNyYzMyYyI6ImJvQjhtdz09IiwiY29tcG9uZW50Q291bnQiOjMsImV0YWciOiJDTm5uN05lVzI5MENFQUU9In0="
+ }
+ },
+ {
+ "ID": "0139c847dd24ca22",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://storage.googleapis.com/go-integration-test-20180927-44630911863640-0001/composed2",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "Go-http-client/1.1"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "43c359bcc9599df1fa41050f8c44953f/16730525860314595343;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "storage.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://storage.googleapis.com/go-integration-test-20180927-44630911863640-0001/composed2"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Accept-Ranges": [
+ "bytes"
+ ],
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0"
+ ],
+ "Content-Length": [
+ "48"
+ ],
+ "Content-Type": [
+ "text/json"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:18 GMT"
+ ],
+ "Etag": [
+ "\"-CNnn7NeW290CEAE=\""
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:24:18 GMT"
+ ],
+ "Last-Modified": [
+ "Thu, 27 Sep 2018 12:24:18 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "X-Goog-Component-Count": [
+ "3"
+ ],
+ "X-Goog-Expiration": [
+ "Sat, 27 Oct 2018 12:24:18 GMT"
+ ],
+ "X-Goog-Generation": [
+ "1538051058381785"
+ ],
+ "X-Goog-Hash": [
+ "crc32c=boB8mw=="
+ ],
+ "X-Goog-Metageneration": [
+ "1"
+ ],
+ "X-Goog-Storage-Class": [
+ "STANDARD"
+ ],
+ "X-Goog-Stored-Content-Encoding": [
+ "identity"
+ ],
+ "X-Goog-Stored-Content-Length": [
+ "48"
+ ],
+ "X-Google-Backends": [
+ "/bns/xh/borg/xh/bns/cloud-storage/prod-cloud-storage-frontend.frontend/27,/bns/xh/borg/xh/bns/blobstore2/bitpusher/1.scotty,aclgag19:443"
+ ],
+ "X-Google-Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=8susW7SaJfCoswa-l4W4Dw"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "aclgag19:443,/bns/xh/borg/xh/bns/blobstore2/bitpusher/1.scotty,aclgag19:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/xh/borg/xh/bns/blobstore2/bitpusher/1:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBJ"
+ ],
+ "X-Google-Storage-Location": [
+ "US"
+ ],
+ "X-Guploader-Customer": [
+ "cloud-storage"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UpIx0vuK5NPFu7_CxRMZ61vPnJlQWjZ6ejYGdikaD8AawSgJJPLhcBGALUiFI3jv-gCL18r8Mig_JKoDCCxy0-LmuQ85A"
+ ]
+ },
+ "Body": "G7YE7d4n0dy1PXohFJpUn8PZcNJccaSrouZ5qGqfKcNY+xSKoJ2Yh9xMlR8v8x6R"
+ }
+ },
+ {
+ "ID": "8da163d5370e63a2",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Type": [
+ "multipart/related; boundary=44415e54fcdbc755b78a8ae8f64c45c109d270e3315c08e5b5ab2a272972"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "bfc01e37d4ef5d0f121b282467264d29/17561619324262028127;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "LS00NDQxNWU1NGZjZGJjNzU1Yjc4YThhZThmNjRjNDVjMTA5ZDI3MGUzMzE1YzA4ZTViNWFiMmEyNzI5NzINCkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vanNvbg0KDQp7ImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsImNvbnRlbnRFbmNvZGluZyI6Imd6aXAiLCJuYW1lIjoiZ3ppcC10ZXN0In0KDQotLTQ0NDE1ZTU0ZmNkYmM3NTViNzhhOGFlOGY2NGM0NWMxMDlkMjcwZTMzMTVjMDhlNWI1YWIyYTI3Mjk3Mg0KQ29udGVudC1UeXBlOiBhcHBsaWNhdGlvbi94LWd6aXANCg0KH4sIAAAAAAAA/2IgEgACAAD//7E97OkoAAAADQotLTQ0NDE1ZTU0ZmNkYmM3NTViNzhhOGFlOGY2NGM0NWMxMDlkMjcwZTMzMTVjMDhlNWI1YWIyYTI3Mjk3Mi0tDQo="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3320"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:19 GMT"
+ ],
+ "Etag": [
+ "CND/mtiW290CEAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051358000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrnb2:4089,/bns/yw/borg/yw/bns/blobstore2/bitpusher/224.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=8susW7LLL4-chASN_IugDw"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yw/borg/yw/bns/blobstore2/bitpusher/224.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yw/borg/yw/bns/blobstore2/bitpusher/224:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRYmxNeVZwMGdUN0o0YlgxVmMtQTlEaHc0eV9GbmdDSHlYYUt0U0VxRHJZV1RVWUxpYnBGRzJxTTlKYTdLNURwTk1hV0ZIaVFoc2tDN1pTaGhHSW53eHJWMHN2bnpGdGZnNmpMc2pjVFdLZU16eUs0c2RRNEo4S3pTMk9kSGxJYmZVVmZTd0pQQjVuRTRrYWxxVjRhbkF4eC1nRUxIU19pTU5nVFVGam5ZOFJTNlFwT2hGdHB6bHBGUG8wBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_single_post_uploads"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UoUbsWpAqL_JeVZbn_zAy2jD-kFzPJRAaxYSNgmnXwpw3SguayQhxx1ULy41CNY5eZP0vxXwt5U5vHHasuOQZLDq18GpA"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9nemlwLXRlc3QvMTUzODA1MTA1OTEzODUxMiIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2d6aXAtdGVzdCIsIm5hbWUiOiJnemlwLXRlc3QiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA1OTEzODUxMiIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoiYXBwbGljYXRpb24veC1nemlwIiwidGltZUNyZWF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjE5LjEzOFoiLCJ1cGRhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDoxOS4xMzhaIiwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJ0aW1lU3RvcmFnZUNsYXNzVXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MTkuMTM4WiIsInNpemUiOiIyNyIsIm1kNUhhc2giOiJPdEN3K2FSUklScUtHRkFFT2F4K3F3PT0iLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vZ3ppcC10ZXN0P2dlbmVyYXRpb249MTUzODA1MTA1OTEzODUxMiZhbHQ9bWVkaWEiLCJjb250ZW50RW5jb2RpbmciOiJnemlwIiwiYWNsIjpbeyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvZ3ppcC10ZXN0LzE1MzgwNTEwNTkxMzg1MTIvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9nemlwLXRlc3QvYWNsL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiZ3ppcC10ZXN0IiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNTkxMzg1MTIiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNORC9tdGlXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9nemlwLXRlc3QvMTUzODA1MTA1OTEzODUxMi9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9nemlwLXRlc3QvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Imd6aXAtdGVzdCIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDU5MTM4NTEyIiwiZW50aXR5IjoicHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6ImVkaXRvcnMifSwiZXRhZyI6IkNORC9tdGlXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9nemlwLXRlc3QvMTUzODA1MTA1OTEzODUxMi9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9nemlwLXRlc3QvYWNsL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Imd6aXAtdGVzdCIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDU5MTM4NTEyIiwiZW50aXR5IjoicHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6IlJFQURFUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJ2aWV3ZXJzIn0sImV0YWciOiJDTkQvbXRpVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvZ3ppcC10ZXN0LzE1MzgwNTEwNTkxMzg1MTIvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2d6aXAtdGVzdC9hY2wvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Imd6aXAtdGVzdCIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDU5MTM4NTEyIiwiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInJvbGUiOiJPV05FUiIsImVtYWlsIjoiMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJldGFnIjoiQ05EL210aVcyOTBDRUFFPSJ9XSwib3duZXIiOnsiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSJ9LCJjcmMzMmMiOiI5RGh3QkE9PSIsImV0YWciOiJDTkQvbXRpVzI5MENFQUU9In0="
+ }
+ },
+ {
+ "ID": "3b90c911e5184c72",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://storage.googleapis.com/go-integration-test-20180927-44630911863640-0001/gzip-test",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "Go-http-client/1.1"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "8dcb355604083d45976f1b6230e58bae/705568625301502205;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "storage.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://storage.googleapis.com/go-integration-test-20180927-44630911863640-0001/gzip-test"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Accept-Ranges": [
+ "none"
+ ],
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0"
+ ],
+ "Content-Type": [
+ "application/x-gzip"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:19 GMT"
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:24:19 GMT"
+ ],
+ "Last-Modified": [
+ "Thu, 27 Sep 2018 12:24:19 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Accept-Encoding"
+ ],
+ "X-Goog-Expiration": [
+ "Sat, 27 Oct 2018 12:24:19 GMT"
+ ],
+ "X-Goog-Generation": [
+ "1538051059138512"
+ ],
+ "X-Goog-Hash": [
+ "crc32c=9DhwBA==",
+ "md5=OtCw+aRRIRqKGFAEOax+qw=="
+ ],
+ "X-Goog-Metageneration": [
+ "1"
+ ],
+ "X-Goog-Storage-Class": [
+ "STANDARD"
+ ],
+ "X-Goog-Stored-Content-Encoding": [
+ "gzip"
+ ],
+ "X-Goog-Stored-Content-Length": [
+ "27"
+ ],
+ "X-Google-Backends": [
+ "/bns/xh/borg/xh/bns/cloud-storage/prod-cloud-storage-frontend.frontend/33,/bns/xh/borg/xh/bns/blobstore2/bitpusher/32.scotty,aclgag19:443"
+ ],
+ "X-Google-Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=88usW9nbFseoswbavqfIAQ"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "aclgag19:443,/bns/xh/borg/xh/bns/blobstore2/bitpusher/32.scotty,aclgag19:443"
+ ],
+ "X-Google-Gfe-Response-Body-Transformations": [
+ "gunzipped,chunked"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/xh/borg/xh/bns/blobstore2/bitpusher/32:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBJ"
+ ],
+ "X-Google-Storage-Location": [
+ "US"
+ ],
+ "X-Guploader-Customer": [
+ "cloud-storage"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UrqJq-PaCwRos5X_sDmM2fxtLX2i9NL56DXNhSP4KJAtDQpYHyiYPTEtmGOC2Qwvj0qlphWquvmwpMQiznCoS7DuYCYKA"
+ ]
+ },
+ "Body": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="
+ }
+ },
+ {
+ "ID": "68d9c7cc86eac452",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://storage.googleapis.com/go-integration-test-20180927-44630911863640-0001/obj-not-exists",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "Go-http-client/1.1"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "452523ae4fe3e75b632b9c7aca76ddab/2295979429857025692;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "storage.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://storage.googleapis.com/go-integration-test-20180927-44630911863640-0001/obj-not-exists"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 404,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0"
+ ],
+ "Content-Length": [
+ "225"
+ ],
+ "Content-Type": [
+ "application/xml; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:19 GMT"
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:24:19 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "X-Google-Backends": [
+ "/bns/xh/borg/xh/bns/cloud-storage/prod-cloud-storage-frontend.frontend/43,/bns/xh/borg/xh/bns/blobstore2/bitpusher/20.scotty,aclgag19:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=88usW5S8HMesswbQ_qAo"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "aclgag19:443,/bns/xh/borg/xh/bns/blobstore2/bitpusher/20.scotty,aclgag19:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/xh/borg/xh/bns/blobstore2/bitpusher/20:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBJ"
+ ],
+ "X-Guploader-Customer": [
+ "cloud-storage"
+ ],
+ "X-Guploader-Request-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Upload-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Ur0o8XTl6cwQYgCGmxXT4871JIv-OvohYl-kWfphF7WUjyN0lnJFPDbq3EcGXMmlMZAkD3NsbPQ5enswas8sWhAD_pw8Q"
+ ]
+ },
+ "Body": "PD94bWwgdmVyc2lvbj0nMS4wJyBlbmNvZGluZz0nVVRGLTgnPz48RXJyb3I+PENvZGU+Tm9TdWNoS2V5PC9Db2RlPjxNZXNzYWdlPlRoZSBzcGVjaWZpZWQga2V5IGRvZXMgbm90IGV4aXN0LjwvTWVzc2FnZT48RGV0YWlscz5ObyBzdWNoIG9iamVjdDogZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL29iai1ub3QtZXhpc3RzPC9EZXRhaWxzPjwvRXJyb3I+"
+ }
+ },
+ {
+ "ID": "3b10b1db50d2db0b",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Type": [
+ "multipart/related; boundary=1442371c68bf0f93dba7b4d3265c434f493a6e71f9331861397c4d652891"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "148ee3c75f4f071e711419694ce354a8/3055016399295000811;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "LS0xNDQyMzcxYzY4YmYwZjkzZGJhN2I0ZDMyNjVjNDM0ZjQ5M2E2ZTcxZjkzMzE4NjEzOTdjNGQ2NTI4OTENCkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vanNvbg0KDQp7ImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsImNhY2hlQ29udHJvbCI6InB1YmxpYywgbWF4LWFnZT02MCIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbiIsIm5hbWUiOiJzaWduZWRVUkwifQoNCi0tMTQ0MjM3MWM2OGJmMGY5M2RiYTdiNGQzMjY1YzQzNGY0OTNhNmU3MWY5MzMxODYxMzk3YzRkNjUyODkxDQpDb250ZW50LVR5cGU6IHRleHQvcGxhaW4NCg0KVGhpcyBpcyBhIHRlc3Qgb2YgU2lnbmVkVVJMLgoNCi0tMTQ0MjM3MWM2OGJmMGY5M2RiYTdiNGQzMjY1YzQzNGY0OTNhNmU3MWY5MzMxODYxMzk3YzRkNjUyODkxLS0NCg=="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3323"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:20 GMT"
+ ],
+ "Etag": [
+ "CMS019iW290CEAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051359000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrlh9:4090,/bns/yw/borg/yw/bns/blobstore2/bitpusher/202.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=88usW5ejMdjmhATG4KKIBA"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yw/borg/yw/bns/blobstore2/bitpusher/202.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yw/borg/yw/bns/blobstore2/bitpusher/202:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRYlVHbHo5aEdpZEl3eXlKS0N0RXMyRVBVdWRfaVJncG1hTkFvQmlGVmNzQ3B2dnNuRFZfTlc0aWF2YmtHTURVWW9QZHE5UThXRlNQbWZ5YzFlZUtmTnNmV3d2Q2J4R3RoS2FaWm5NUzdBMmdJM0FydU5tbHhTLXAwY2lOdzdwdTFXRkg3TnhSYmowUThZQ3FrcERoU0RIUkMyYllobWhoZXlKaEhEUk5GNkJyT2hHOFRaTm81QUlvbFUwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_single_post_uploads"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Uqjnuu0O7kv5rFkyxOHMrOB8DkSNtM4n6d1jpNnSmIIVL7XXmSRa78auaiUOyo4-qafkT3xdqmKEFjGLwSp8TgycKb0dw"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9zaWduZWRVUkwvMTUzODA1MTA2MDEyODMyNCIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL3NpZ25lZFVSTCIsIm5hbWUiOiJzaWduZWRVUkwiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA2MDEyODMyNCIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbiIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDoyMC4xMjhaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MjAuMTI4WiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjIwLjEyOFoiLCJzaXplIjoiMjkiLCJtZDVIYXNoIjoiSnl4dmd3bTluMk1zckdUTVBiTWVZQT09IiwibWVkaWFMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vZG93bmxvYWQvc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL3NpZ25lZFVSTD9nZW5lcmF0aW9uPTE1MzgwNTEwNjAxMjgzMjQmYWx0PW1lZGlhIiwiY2FjaGVDb250cm9sIjoicHVibGljLCBtYXgtYWdlPTYwIiwiYWNsIjpbeyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvc2lnbmVkVVJMLzE1MzgwNTEwNjAxMjgzMjQvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9zaWduZWRVUkwvYWNsL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0Ijoic2lnbmVkVVJMIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNjAxMjgzMjQiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNNUzAxOWlXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9zaWduZWRVUkwvMTUzODA1MTA2MDEyODMyNC9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9zaWduZWRVUkwvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6InNpZ25lZFVSTCIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDYwMTI4MzI0IiwiZW50aXR5IjoicHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6ImVkaXRvcnMifSwiZXRhZyI6IkNNUzAxOWlXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9zaWduZWRVUkwvMTUzODA1MTA2MDEyODMyNC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9zaWduZWRVUkwvYWNsL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6InNpZ25lZFVSTCIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDYwMTI4MzI0IiwiZW50aXR5IjoicHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6IlJFQURFUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJ2aWV3ZXJzIn0sImV0YWciOiJDTVMwMTlpVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvc2lnbmVkVVJMLzE1MzgwNTEwNjAxMjgzMjQvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL3NpZ25lZFVSTC9hY2wvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6InNpZ25lZFVSTCIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDYwMTI4MzI0IiwiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInJvbGUiOiJPV05FUiIsImVtYWlsIjoiMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJldGFnIjoiQ01TMDE5aVcyOTBDRUFFPSJ9XSwib3duZXIiOnsiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSJ9LCJjcmMzMmMiOiJaVHFBTHc9PSIsImV0YWciOiJDTVMwMTlpVzI5MENFQUU9In0="
+ }
+ },
+ {
+ "ID": "23beecdc4886db0d",
+ "Request": {
+ "Method": "PUT",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/defaultObjectAcl/domain-google.com?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "107"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "e45c86a08dfdca44f43e256839e02da6/4645428303345374858;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/defaultObjectAcl/domain-google.com?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJlbnRpdHkiOiJkb21haW4tZ29vZ2xlLmNvbSIsInJvbGUiOiJSRUFERVIifQo="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "119"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:22 GMT"
+ ],
+ "Etag": [
+ "CAY="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051361000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrjk75:4456,/bns/yv/borg/yv/bns/blobstore2/bitpusher/268.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=9cusW8i_BtKeggS9oqBY"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/268.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/268:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATpxChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4CtK4wESxgF5YTI5LmMuRW93QkpRWW5wTmtlLU9kVkRTVDlqMDhzYkVvZ2hLYjlqRzhpWDJuQm5JM01lY1Z4VHg3Nnl6Z3lXb3hkeTZQNk43bDc3WlFuNmVUUm5mcnpKX1VUNEpvV05pcmpXTGxCT2gteHBPQVFpMTQ3NnU5ak9IZEVNVElfSTVrQzJQV2tBcUxmWXpDVjIwN041aXgweGItdW1NQkJKN1ExUFdFSEtyNE1pS3JZTjhteWdELUVxRjVDS2w2eTl5NjFTZ0EwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Uq3lv20s_T1WTNLRb4NTrmOZgRAwMwC72Ie5cc_1yk34PGxL_K-AylFLpjvdcIKkq9QNwiDcsKH9lrb8KnFfeYict3K5w"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiZW50aXR5IjoiZG9tYWluLWdvb2dsZS5jb20iLCJyb2xlIjoiUkVBREVSIiwiZG9tYWluIjoiZ29vZ2xlLmNvbSIsImV0YWciOiJDQVk9In0="
+ }
+ },
+ {
+ "ID": "8087b8417cc402c5",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/defaultObjectAcl?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "3e3d9d350b89e4de9e2dc4a451e4be0b/6235558732435946280;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/defaultObjectAcl?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0, must-revalidate, no-transform"
+ ],
+ "Content-Length": [
+ "678"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:22 GMT"
+ ],
+ "Etag": [
+ "CAY="
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:24:22 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051361000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vryy5:4338,/bns/yv/borg/yv/bns/blobstore2/bitpusher/360.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=9susW6HtI5fJgASEx7egAQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/360.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/360:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATpxChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4CtK4wESxgF5YTI5LmMuRW93QkpRWW5wTmtlLU9kVkRTVDlqMDhzYkVvZ2hLYjlqRzhpWDJuQm5JM01lY1Z4VHg3Nnl6Z3lXb3hkeTZQNk43bDc3WlFuNmVUUm5mcnpKX1VUNEpvV05pcmpXTGxCT2gteHBPQVFpMTQ3NnU5ak9IZEVNVElfSTVrQzJQV2tBcUxmWXpDVjIwN041aXgweGItdW1NQkJKN1ExUFdFSEtyNE1pS3JZTjhteWdELUVxRjVDS2w2eTl5NjFTZ0EwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UozGaSoDn-YihIPaUMVTDXgWpSz9PKEcpp3TLb1cFU6g8v8A1cOtx7L8qLF1aB2Z15qRD89do749K8f9Sx22l_Pydij6Q"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9scyIsIml0ZW1zIjpbeyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDQVk9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiZW50aXR5IjoicHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6ImVkaXRvcnMifSwiZXRhZyI6IkNBWT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNBWT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJkb21haW4tZ29vZ2xlLmNvbSIsInJvbGUiOiJSRUFERVIiLCJkb21haW4iOiJnb29nbGUuY29tIiwiZXRhZyI6IkNBWT0ifV19"
+ }
+ },
+ {
+ "ID": "634c2d25d926440d",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Type": [
+ "multipart/related; boundary=3ddfe24a6384ff14089cd949180c2222a1402c31668eda555039fa69e9bf"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "e2548d029256a26c6b18f6073fe21adf/6994877172538822264;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "LS0zZGRmZTI0YTYzODRmZjE0MDg5Y2Q5NDkxODBjMjIyMmExNDAyYzMxNjY4ZWRhNTU1MDM5ZmE2OWU5YmYNCkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vanNvbg0KDQp7ImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsImNhY2hlQ29udHJvbCI6InB1YmxpYywgbWF4LWFnZT02MCIsIm5hbWUiOiJhY2wxIn0KDQotLTNkZGZlMjRhNjM4NGZmMTQwODljZDk0OTE4MGMyMjIyYTE0MDJjMzE2NjhlZGE1NTUwMzlmYTY5ZTliZg0KQ29udGVudC1UeXBlOiBhcHBsaWNhdGlvbi9vY3RldC1zdHJlYW0NCg0KR8dXiQCBOn5esIR367SwUA0KLS0zZGRmZTI0YTYzODRmZjE0MDg5Y2Q5NDkxODBjMjIyMmExNDAyYzMxNjY4ZWRhNTU1MDM5ZmE2OWU5YmYtLQ0K"
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3724"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:23 GMT"
+ ],
+ "Etag": [
+ "CNXmlNqW290CEAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051362000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrbv14:4486,/bns/yv/borg/yv/bns/blobstore2/bitpusher/176.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=9susW6n9N4GjgATktYzACw"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/176.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/176:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWW5wTmtlLU9kVkRTVDlqMDhzYkVvZ2hLYjlqRzhpWDJuQm5JM01lY1Z4VHg3Nnl6Z3lXb3hkeTZQNk43bDc3WlFuNmVUUm5mcnpKX1VUNEpvV05pcmpXTGxCT2gteHBPQVFpMTQ3NnU5ak9IZEVNVElfSTVrQzJQV2tBcUxmWXpDVjIwN041aXgweGItdW1NQkJKN1ExUFdFSEtyNE1pS3JZTjhteWdELUVxRjVDS2w2eTl5NjFTZ0EwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_single_post_uploads"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UpxBKcmuCe-OuHfbZcZvw2Kdf8HCiIhoicR-fibw-U04VOSzFXZgl_rIFsqwTwrsBvt5t-Zlr7P67XF7mgTXboogFCwAw"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9hY2wxLzE1MzgwNTEwNjMyMzEzMTciLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9hY2wxIiwibmFtZSI6ImFjbDEiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA2MzIzMTMxNyIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoiYXBwbGljYXRpb24vb2N0ZXQtc3RyZWFtIiwidGltZUNyZWF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjIzLjIzMFoiLCJ1cGRhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDoyMy4yMzBaIiwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJ0aW1lU3RvcmFnZUNsYXNzVXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MjMuMjMwWiIsInNpemUiOiIxNiIsIm1kNUhhc2giOiJ6cENKM29yUTk1eXh2ZnorUXE3dlFBPT0iLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vYWNsMT9nZW5lcmF0aW9uPTE1MzgwNTEwNjMyMzEzMTcmYWx0PW1lZGlhIiwiY2FjaGVDb250cm9sIjoicHVibGljLCBtYXgtYWdlPTYwIiwiYWNsIjpbeyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvYWNsMS8xNTM4MDUxMDYzMjMxMzE3L3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vYWNsMS9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJhY2wxIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNjMyMzEzMTciLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNOWG1sTnFXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9hY2wxLzE1MzgwNTEwNjMyMzEzMTcvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vYWNsMS9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiYWNsMSIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDYzMjMxMzE3IiwiZW50aXR5IjoicHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6ImVkaXRvcnMifSwiZXRhZyI6IkNOWG1sTnFXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9hY2wxLzE1MzgwNTEwNjMyMzEzMTcvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vYWNsMS9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiYWNsMSIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDYzMjMxMzE3IiwiZW50aXR5IjoicHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6IlJFQURFUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJ2aWV3ZXJzIn0sImV0YWciOiJDTlhtbE5xVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvYWNsMS8xNTM4MDUxMDYzMjMxMzE3L2RvbWFpbi1nb29nbGUuY29tIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vYWNsMS9hY2wvZG9tYWluLWdvb2dsZS5jb20iLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJhY2wxIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNjMyMzEzMTciLCJlbnRpdHkiOiJkb21haW4tZ29vZ2xlLmNvbSIsInJvbGUiOiJSRUFERVIiLCJkb21haW4iOiJnb29nbGUuY29tIiwiZXRhZyI6IkNOWG1sTnFXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9hY2wxLzE1MzgwNTEwNjMyMzEzMTcvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2FjbDEvYWNsL3VzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJhY2wxIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNjMyMzEzMTciLCJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwicm9sZSI6Ik9XTkVSIiwiZW1haWwiOiIzNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImV0YWciOiJDTlhtbE5xVzI5MENFQUU9In1dLCJvd25lciI6eyJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIn0sImNyYzMyYyI6IjViL2ltZz09IiwiZXRhZyI6IkNOWG1sTnFXMjkwQ0VBRT0ifQ=="
+ }
+ },
+ {
+ "ID": "7d274cd0b9fb4e9e",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Type": [
+ "multipart/related; boundary=c110552d9287f2e64b941bf461feade0f6f61300ba49538ce5357cfffdb7"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "cf1e26c269814cea3ac75b3510540c63/7825970636486320583;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "LS1jMTEwNTUyZDkyODdmMmU2NGI5NDFiZjQ2MWZlYWRlMGY2ZjYxMzAwYmE0OTUzOGNlNTM1N2NmZmZkYjcNCkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vanNvbg0KDQp7ImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsImNhY2hlQ29udHJvbCI6InB1YmxpYywgbWF4LWFnZT02MCIsIm5hbWUiOiJhY2wyIn0KDQotLWMxMTA1NTJkOTI4N2YyZTY0Yjk0MWJmNDYxZmVhZGUwZjZmNjEzMDBiYTQ5NTM4Y2U1MzU3Y2ZmZmRiNw0KQ29udGVudC1UeXBlOiBhcHBsaWNhdGlvbi9vY3RldC1zdHJlYW0NCg0KYU6zehRNzcF55tSq9gS0EA0KLS1jMTEwNTUyZDkyODdmMmU2NGI5NDFiZjQ2MWZlYWRlMGY2ZjYxMzAwYmE0OTUzOGNlNTM1N2NmZmZkYjctLQ0K"
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3724"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:24 GMT"
+ ],
+ "Etag": [
+ "CIvhwNqW290CEAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051363000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrjo80:4463,/bns/yv/borg/yv/bns/blobstore2/bitpusher/227.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=98usW4bHHMTDswat-Z-oBg"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/227.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/227:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWW5wTmtlLU9kVkRTVDlqMDhzYkVvZ2hLYjlqRzhpWDJuQm5JM01lY1Z4VHg3Nnl6Z3lXb3hkeTZQNk43bDc3WlFuNmVUUm5mcnpKX1VUNEpvV05pcmpXTGxCT2gteHBPQVFpMTQ3NnU5ak9IZEVNVElfSTVrQzJQV2tBcUxmWXpDVjIwN041aXgweGItdW1NQkJKN1ExUFdFSEtyNE1pS3JZTjhteWdELUVxRjVDS2w2eTl5NjFTZ0EwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_single_post_uploads"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Up8vhQLTWrrLCJUmodPR52LzVY3pyY11BUbmWjHUWFWwG_PE_9vZUSZpSouGDBDWbFRxivAE0aMqb9hA38xDT0xE_6sSg"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9hY2wyLzE1MzgwNTEwNjM5NTE0OTkiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9hY2wyIiwibmFtZSI6ImFjbDIiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA2Mzk1MTQ5OSIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoiYXBwbGljYXRpb24vb2N0ZXQtc3RyZWFtIiwidGltZUNyZWF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjIzLjk1MVoiLCJ1cGRhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDoyMy45NTFaIiwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJ0aW1lU3RvcmFnZUNsYXNzVXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MjMuOTUxWiIsInNpemUiOiIxNiIsIm1kNUhhc2giOiJhbXRjMGpVZloyQ0VGMEdWZjVUemV3PT0iLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vYWNsMj9nZW5lcmF0aW9uPTE1MzgwNTEwNjM5NTE0OTkmYWx0PW1lZGlhIiwiY2FjaGVDb250cm9sIjoicHVibGljLCBtYXgtYWdlPTYwIiwiYWNsIjpbeyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvYWNsMi8xNTM4MDUxMDYzOTUxNDk5L3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vYWNsMi9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJhY2wyIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNjM5NTE0OTkiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNJdmh3TnFXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9hY2wyLzE1MzgwNTEwNjM5NTE0OTkvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vYWNsMi9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiYWNsMiIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDYzOTUxNDk5IiwiZW50aXR5IjoicHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6ImVkaXRvcnMifSwiZXRhZyI6IkNJdmh3TnFXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9hY2wyLzE1MzgwNTEwNjM5NTE0OTkvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vYWNsMi9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiYWNsMiIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDYzOTUxNDk5IiwiZW50aXR5IjoicHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6IlJFQURFUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJ2aWV3ZXJzIn0sImV0YWciOiJDSXZod05xVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvYWNsMi8xNTM4MDUxMDYzOTUxNDk5L2RvbWFpbi1nb29nbGUuY29tIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vYWNsMi9hY2wvZG9tYWluLWdvb2dsZS5jb20iLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJhY2wyIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNjM5NTE0OTkiLCJlbnRpdHkiOiJkb21haW4tZ29vZ2xlLmNvbSIsInJvbGUiOiJSRUFERVIiLCJkb21haW4iOiJnb29nbGUuY29tIiwiZXRhZyI6IkNJdmh3TnFXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9hY2wyLzE1MzgwNTEwNjM5NTE0OTkvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2FjbDIvYWNsL3VzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJhY2wyIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNjM5NTE0OTkiLCJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwicm9sZSI6Ik9XTkVSIiwiZW1haWwiOiIzNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImV0YWciOiJDSXZod05xVzI5MENFQUU9In1dLCJvd25lciI6eyJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIn0sImNyYzMyYyI6Illkcmp4Zz09IiwiZXRhZyI6IkNJdmh3TnFXMjkwQ0VBRT0ifQ=="
+ }
+ },
+ {
+ "ID": "a7899fab4dae114e",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/acl1/acl?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "c8c8a1cb5d5b081bd731d3092162697c/9416381441058621030;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/acl1/acl?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0, must-revalidate, no-transform"
+ ],
+ "Content-Length": [
+ "2839"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:24 GMT"
+ ],
+ "Etag": [
+ "CNXmlNqW290CEAE="
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:24:24 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051364000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vnlk21:4416,/bns/yx/borg/yx/bns/blobstore2/bitpusher/170.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=-MusW-KiC4TEzALh36GYDg"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yx/borg/yx/bns/blobstore2/bitpusher/170.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yx/borg/yx/bns/blobstore2/bitpusher/170:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATpxChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4CtK4wESxgF5YTI5LmMuRW93QkpRWW5wTmtlLU9kVkRTVDlqMDhzYkVvZ2hLYjlqRzhpWDJuQm5JM01lY1Z4VHg3Nnl6Z3lXb3hkeTZQNk43bDc3WlFuNmVUUm5mcnpKX1VUNEpvV05pcmpXTGxCT2gteHBPQVFpMTQ3NnU5ak9IZEVNVElfSTVrQzJQV2tBcUxmWXpDVjIwN041aXgweGItdW1NQkJKN1ExUFdFSEtyNE1pS3JZTjhteWdELUVxRjVDS2w2eTl5NjFTZ0EwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UpFRiGkVMXwsRyEVHcvreKGdfu1e4GRGxDKzqQzqicudPyGfU1oNimPJublOVcvpSMPGbFW3PG3R_cChKGjcMDAka_o6-u5l8M_0QCRcCL5jrK7YPE"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9scyIsIml0ZW1zIjpbeyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvYWNsMS8xNTM4MDUxMDYzMjMxMzE3L3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vYWNsMS9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJhY2wxIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNjMyMzEzMTciLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNOWG1sTnFXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9hY2wxLzE1MzgwNTEwNjMyMzEzMTcvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vYWNsMS9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiYWNsMSIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDYzMjMxMzE3IiwiZW50aXR5IjoicHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6ImVkaXRvcnMifSwiZXRhZyI6IkNOWG1sTnFXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9hY2wxLzE1MzgwNTEwNjMyMzEzMTcvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vYWNsMS9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiYWNsMSIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDYzMjMxMzE3IiwiZW50aXR5IjoicHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6IlJFQURFUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJ2aWV3ZXJzIn0sImV0YWciOiJDTlhtbE5xVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvYWNsMS8xNTM4MDUxMDYzMjMxMzE3L2RvbWFpbi1nb29nbGUuY29tIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vYWNsMS9hY2wvZG9tYWluLWdvb2dsZS5jb20iLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJhY2wxIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNjMyMzEzMTciLCJlbnRpdHkiOiJkb21haW4tZ29vZ2xlLmNvbSIsInJvbGUiOiJSRUFERVIiLCJkb21haW4iOiJnb29nbGUuY29tIiwiZXRhZyI6IkNOWG1sTnFXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9hY2wxLzE1MzgwNTEwNjMyMzEzMTcvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2FjbDEvYWNsL3VzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJhY2wxIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNjMyMzEzMTciLCJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwicm9sZSI6Ik9XTkVSIiwiZW1haWwiOiIzNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImV0YWciOiJDTlhtbE5xVzI5MENFQUU9In1dfQ=="
+ }
+ },
+ {
+ "ID": "71bd060a33809794",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/acl1/acl/domain-google.com?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "40eb07e858b191346b807395316f863c/11006793340814158852;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/acl1/acl/domain-google.com?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 204,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "0"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:24 GMT"
+ ],
+ "Etag": [
+ "CNXmlNqW290CEAI="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051361000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrkq2:4275,/bns/yv/borg/yv/bns/blobstore2/bitpusher/66.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=-MusW9feEYutgATw86vwBw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/66.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/66:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATpxChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4CtK4wESxgF5YTI5LmMuRW93QkpRWW5wTmtlLU9kVkRTVDlqMDhzYkVvZ2hLYjlqRzhpWDJuQm5JM01lY1Z4VHg3Nnl6Z3lXb3hkeTZQNk43bDc3WlFuNmVUUm5mcnpKX1VUNEpvV05pcmpXTGxCT2gteHBPQVFpMTQ3NnU5ak9IZEVNVElfSTVrQzJQV2tBcUxmWXpDVjIwN041aXgweGItdW1NQkJKN1ExUFdFSEtyNE1pS3JZTjhteWdELUVxRjVDS2w2eTl5NjFTZ0EwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UpWcAHikAmqOg613kF4GLJiEtCXxxIqN3tffPAx8FWSaOAq_FpvPloU22Ug_XvB_KhhecqbFCXQB6pcuta5ItyeOmLNeg"
+ ]
+ },
+ "Body": ""
+ }
+ },
+ {
+ "ID": "c8ad252a6aa45862",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/defaultObjectAcl/domain-google.com?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "be850e2dc6a30f10d7d84d57edf55b35/12596923774199566755;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/defaultObjectAcl/domain-google.com?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 204,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "0"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:26 GMT"
+ ],
+ "Etag": [
+ "CAc="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051361000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrub8:4298,/bns/yr/borg/yr/bns/blobstore2/bitpusher/74.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=-MusW-uRKtC64QSEt534Cw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/74.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/74:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATpxChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4CtK4wESxgF5YTI5LmMuRW93QkpRWW5wTmtlLU9kVkRTVDlqMDhzYkVvZ2hLYjlqRzhpWDJuQm5JM01lY1Z4VHg3Nnl6Z3lXb3hkeTZQNk43bDc3WlFuNmVUUm5mcnpKX1VUNEpvV05pcmpXTGxCT2gteHBPQVFpMTQ3NnU5ak9IZEVNVElfSTVrQzJQV2tBcUxmWXpDVjIwN041aXgweGItdW1NQkJKN1ExUFdFSEtyNE1pS3JZTjhteWdELUVxRjVDS2w2eTl5NjFTZ0EwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UpSjnNG8skCQpRLGO9ra7v9LGpcH7MJ7zZvV2z1z7mtvPZnVOI_c_4hoHzqBZK4BKOYIXZv29JlLxle7OIksM783IQ7xQ"
+ ]
+ },
+ "Body": ""
+ }
+ },
+ {
+ "ID": "ae6f08a80bb80c90",
+ "Request": {
+ "Method": "PUT",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/acl/user-jbd%40google.com?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "109"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "2c258adc583f7fd54fabdbd920701d4d/14187335678249940802;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/acl/user-jbd%40google.com?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJlbnRpdHkiOiJ1c2VyLWpiZEBnb29nbGUuY29tIiwicm9sZSI6IlJFQURFUiJ9Cg=="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "386"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:27 GMT"
+ ],
+ "Etag": [
+ "CAg="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051364000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vneu135:4203,/bns/yx/borg/yx/bns/blobstore2/bitpusher/117.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=-susW9jWCsW4zALG9Lq4BQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yx/borg/yx/bns/blobstore2/bitpusher/117.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yx/borg/yx/bns/blobstore2/bitpusher/117:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATpxChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4CtK4wESxgF5YTI5LmMuRW93QkpRWW5wTmtlLU9kVkRTVDlqMDhzYkVvZ2hLYjlqRzhpWDJuQm5JM01lY1Z4VHg3Nnl6Z3lXb3hkeTZQNk43bDc3WlFuNmVUUm5mcnpKX1VUNEpvV05pcmpXTGxCT2gteHBPQVFpMTQ3NnU5ak9IZEVNVElfSTVrQzJQV2tBcUxmWXpDVjIwN041aXgweGItdW1NQkJKN1ExUFdFSEtyNE1pS3JZTjhteWdELUVxRjVDS2w2eTl5NjFTZ0EwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UqTGiHMpN75V5boQOPvlbb2tLzUDUklf0wZc3HxAlGV7OG9Ugvl6ubQcDvmN80QOLwaKd4b_iV8jP3oLXAQRaTr13Q-hA"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvdXNlci1qYmRAZ29vZ2xlLmNvbSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9hY2wvdXNlci1qYmRAZ29vZ2xlLmNvbSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsImVudGl0eSI6InVzZXItamJkQGdvb2dsZS5jb20iLCJyb2xlIjoiUkVBREVSIiwiZW1haWwiOiJqYmRAZ29vZ2xlLmNvbSIsImV0YWciOiJDQWc9In0="
+ }
+ },
+ {
+ "ID": "dc66ea5c887df293",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/acl?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "7e111448e87fe73618a269734d491d61/15777747582317157600;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/acl?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0, must-revalidate, no-transform"
+ ],
+ "Content-Length": [
+ "1777"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:27 GMT"
+ ],
+ "Etag": [
+ "CAg="
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:24:27 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051364000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vnhp2:4092,/bns/yx/borg/yx/bns/blobstore2/bitpusher/50.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=-8usW62lKI-IzgKe0Y_gAg"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yx/borg/yx/bns/blobstore2/bitpusher/50.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yx/borg/yx/bns/blobstore2/bitpusher/50:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATpxChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4CtK4wESxgF5YTI5LmMuRW93QkpRWW5wTmtlLU9kVkRTVDlqMDhzYkVvZ2hLYjlqRzhpWDJuQm5JM01lY1Z4VHg3Nnl6Z3lXb3hkeTZQNk43bDc3WlFuNmVUUm5mcnpKX1VUNEpvV05pcmpXTGxCT2gteHBPQVFpMTQ3NnU5ak9IZEVNVElfSTVrQzJQV2tBcUxmWXpDVjIwN041aXgweGItdW1NQkJKN1ExUFdFSEtyNE1pS3JZTjhteWdELUVxRjVDS2w2eTl5NjFTZ0EwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UrflKaiPlva3DQV4NWxxnOa2hfduPuphSMtQD2OmKfWIDBhU1BPZpFeTcuNqMIOVwsC-M9G3R5XRryG0CapLuunYg3wng"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9scyIsIml0ZW1zIjpbeyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvYWNsL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDQWc9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2FjbC9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0FnPSJ9LHsia2luZCI6InN0b3JhZ2UjYnVja2V0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwiZW50aXR5IjoicHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6IlJFQURFUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJ2aWV3ZXJzIn0sImV0YWciOiJDQWc9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvdXNlci1qYmRAZ29vZ2xlLmNvbSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9hY2wvdXNlci1qYmRAZ29vZ2xlLmNvbSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsImVudGl0eSI6InVzZXItamJkQGdvb2dsZS5jb20iLCJyb2xlIjoiUkVBREVSIiwiZW1haWwiOiJqYmRAZ29vZ2xlLmNvbSIsImV0YWciOiJDQWc9In1dfQ=="
+ }
+ },
+ {
+ "ID": "6988c44cbcd63252",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/acl/user-jbd%40google.com?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "7824d8a22901b6dc78f094369cee52a4/17295820417369735807;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/acl/user-jbd%40google.com?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 204,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "0"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:29 GMT"
+ ],
+ "Etag": [
+ "CAk="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051361000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrlh82:4312,/bns/yv/borg/yv/bns/blobstore2/bitpusher/293.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=_MusW-ubAYrHggTf2qigAw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/293.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/293:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATpxChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4CtK4wESxgF5YTI5LmMuRW93QkpRWW5wTmtlLU9kVkRTVDlqMDhzYkVvZ2hLYjlqRzhpWDJuQm5JM01lY1Z4VHg3Nnl6Z3lXb3hkeTZQNk43bDc3WlFuNmVUUm5mcnpKX1VUNEpvV05pcmpXTGxCT2gteHBPQVFpMTQ3NnU5ak9IZEVNVElfSTVrQzJQV2tBcUxmWXpDVjIwN041aXgweGItdW1NQkJKN1ExUFdFSEtyNE1pS3JZTjhteWdELUVxRjVDS2w2eTl5NjFTZ0EwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Uq_n1FZwk3gYg6nAGXjBoIOUouelYbfFQqmodyBNo_ulBDapPpDibBCuyMxYoXTJP2tEN-TdzDpGLiZwNbDloq2veRMyg"
+ ]
+ },
+ "Body": ""
+ }
+ },
+ {
+ "ID": "eac7250806cf8014",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Type": [
+ "multipart/related; boundary=c6748b629d4eae76c06554d06fdeedfb8a51d443f380a3b048fd306bb5f0"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "fed836e58a3445cb457b56c538559402/18127195351998977486;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "LS1jNjc0OGI2MjlkNGVhZTc2YzA2NTU0ZDA2ZmRlZWRmYjhhNTFkNDQzZjM4MGEzYjA0OGZkMzA2YmI1ZjANCkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vanNvbg0KDQp7ImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsImNhY2hlQ29udHJvbCI6InB1YmxpYywgbWF4LWFnZT02MCIsIm5hbWUiOiJnb3BoZXIifQoNCi0tYzY3NDhiNjI5ZDRlYWU3NmMwNjU1NGQwNmZkZWVkZmI4YTUxZDQ0M2YzODBhM2IwNDhmZDMwNmJiNWYwDQpDb250ZW50LVR5cGU6IHRleHQvcGxhaW47IGNoYXJzZXQ9dXRmLTgNCg0KZGF0YQ0KLS1jNjc0OGI2MjlkNGVhZTc2YzA2NTU0ZDA2ZmRlZWRmYjhhNTFkNDQzZjM4MGEzYjA0OGZkMzA2YmI1ZjAtLQ0K"
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3289"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:29 GMT"
+ ],
+ "Etag": [
+ "CMDsot2W290CEAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051369000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrlh82:4312,/bns/yw/borg/yw/bns/blobstore2/bitpusher/85.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=_cusW8DTG8j0hQSdnoHgBg"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yw/borg/yw/bns/blobstore2/bitpusher/85.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yw/borg/yw/bns/blobstore2/bitpusher/85:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRYWpXSE1RZzgtWC1YcW42akZrMFVnT1pjQ2Rvc2J1RUtOdTFmNUpqa2xzSm0xUHllZVo1SEJlMG90M2RIanQ4V3RuaVVQNVNWR1JZOHd3eHhrUG5xV0ZOZkVnYl9YOWNNWUZuZ1R6bGhMQ05wZlZjM2ozYWZqQTgxM0VFSDVVeDlOdnRTalZyb1F4aFF0dW1SMTF5bVB0N0lLYjE3Q01LLVhtcVFtVVRlWWVkYTVsdkptOVR0R29RdjQwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_single_post_uploads"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Uodf8xTcx7etvqc3f4RRRu3WMp7IuuKJts9MRsx9NWjdzStcROpLMOWPCAEtzxu7s5M0DASp3Ci_Oo8NlRpnqCFkPOtIQ"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9nb3BoZXIvMTUzODA1MTA2OTc1Mjg5NiIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2dvcGhlciIsIm5hbWUiOiJnb3BoZXIiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA2OTc1Mjg5NiIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOCIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDoyOS43NTJaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MjkuNzUyWiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjI5Ljc1MloiLCJzaXplIjoiNCIsIm1kNUhhc2giOiJqWGQvT0YwOS9zaUJYU0QzU1dBbTNBPT0iLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vZ29waGVyP2dlbmVyYXRpb249MTUzODA1MTA2OTc1Mjg5NiZhbHQ9bWVkaWEiLCJjYWNoZUNvbnRyb2wiOiJwdWJsaWMsIG1heC1hZ2U9NjAiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9nb3BoZXIvMTUzODA1MTA2OTc1Mjg5Ni9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2dvcGhlci9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJnb3BoZXIiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA2OTc1Mjg5NiIsImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6Im93bmVycyJ9LCJldGFnIjoiQ01Ec290MlcyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2dvcGhlci8xNTM4MDUxMDY5NzUyODk2L3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2dvcGhlci9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiZ29waGVyIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNjk3NTI4OTYiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ01Ec290MlcyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2dvcGhlci8xNTM4MDUxMDY5NzUyODk2L3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2dvcGhlci9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiZ29waGVyIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNjk3NTI4OTYiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNNRHNvdDJXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9nb3BoZXIvMTUzODA1MTA2OTc1Mjg5Ni91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vZ29waGVyL2FjbC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiZ29waGVyIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNjk3NTI4OTYiLCJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwicm9sZSI6Ik9XTkVSIiwiZW1haWwiOiIzNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImV0YWciOiJDTURzb3QyVzI5MENFQUU9In1dLCJvd25lciI6eyJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIn0sImNyYzMyYyI6InJ0aDkwUT09IiwiZXRhZyI6IkNNRHNvdDJXMjkwQ0VBRT0ifQ=="
+ }
+ },
+ {
+ "ID": "4ef441b851b9a7a5",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Type": [
+ "multipart/related; boundary=f04625b0d2c2814594fbfad64c8c764f2a0494d870f89d82505f7f18263e"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "7196054bc52c5e48e243ecf0a0692ab4/439769722704045854;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "LS1mMDQ2MjViMGQyYzI4MTQ1OTRmYmZhZDY0YzhjNzY0ZjJhMDQ5NGQ4NzBmODlkODI1MDVmN2YxODI2M2UNCkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vanNvbg0KDQp7ImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsImNhY2hlQ29udHJvbCI6InB1YmxpYywgbWF4LWFnZT02MCIsIm5hbWUiOiLQk9C+0YTQtdGA0L7QstC4In0KDQotLWYwNDYyNWIwZDJjMjgxNDU5NGZiZmFkNjRjOGM3NjRmMmEwNDk0ZDg3MGY4OWQ4MjUwNWY3ZjE4MjYzZQ0KQ29udGVudC1UeXBlOiB0ZXh0L3BsYWluOyBjaGFyc2V0PXV0Zi04DQoNCmRhdGENCi0tZjA0NjI1YjBkMmMyODE0NTk0ZmJmYWQ2NGM4Yzc2NGYyYTA0OTRkODcwZjg5ZDgyNTA1ZjdmMTgyNjNlLS0NCg=="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3641"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:30 GMT"
+ ],
+ "Etag": [
+ "CJWewd2W290CEAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051369000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrbj128:4260,/bns/yv/borg/yv/bns/blobstore2/bitpusher/243.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=_cusW6G9OoGngASMt5uwAw"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/243.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/243:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRYWpXSE1RZzgtWC1YcW42akZrMFVnT1pjQ2Rvc2J1RUtOdTFmNUpqa2xzSm0xUHllZVo1SEJlMG90M2RIanQ4V3RuaVVQNVNWR1JZOHd3eHhrUG5xV0ZOZkVnYl9YOWNNWUZuZ1R6bGhMQ05wZlZjM2ozYWZqQTgxM0VFSDVVeDlOdnRTalZyb1F4aFF0dW1SMTF5bVB0N0lLYjE3Q01LLVhtcVFtVVRlWWVkYTVsdkptOVR0R29RdjQwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_single_post_uploads"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UoymSoCfGxXc7APKQXbmtsRQ5lzh2kvwdBa2Vk-i19BsKrjJdAKre3OMjddfdx92y6qJM6ifd_otz5K-1VT5fbVgGVktA"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS/Qk9C+0YTQtdGA0L7QstC4LzE1MzgwNTEwNzAyNTA3NzMiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby8lRDAlOTMlRDAlQkUlRDElODQlRDAlQjUlRDElODAlRDAlQkUlRDAlQjIlRDAlQjgiLCJuYW1lIjoi0JPQvtGE0LXRgNC+0LLQuCIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDcwMjUwNzczIiwibWV0YWdlbmVyYXRpb24iOiIxIiwiY29udGVudFR5cGUiOiJ0ZXh0L3BsYWluOyBjaGFyc2V0PXV0Zi04IiwidGltZUNyZWF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjMwLjI1MFoiLCJ1cGRhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDozMC4yNTBaIiwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJ0aW1lU3RvcmFnZUNsYXNzVXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MzAuMjUwWiIsInNpemUiOiI0IiwibWQ1SGFzaCI6ImpYZC9PRjA5L3NpQlhTRDNTV0FtM0E9PSIsIm1lZGlhTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2Rvd25sb2FkL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby8lRDAlOTMlRDAlQkUlRDElODQlRDAlQjUlRDElODAlRDAlQkUlRDAlQjIlRDAlQjg/Z2VuZXJhdGlvbj0xNTM4MDUxMDcwMjUwNzczJmFsdD1tZWRpYSIsImNhY2hlQ29udHJvbCI6InB1YmxpYywgbWF4LWFnZT02MCIsImFjbCI6W3sia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL9CT0L7RhNC10YDQvtCy0LgvMTUzODA1MTA3MDI1MDc3My9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vLyVEMCU5MyVEMCVCRSVEMSU4NCVEMCVCNSVEMSU4MCVEMCVCRSVEMCVCMiVEMCVCOC9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiLQk9C+0YTQtdGA0L7QstC4IiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNzAyNTA3NzMiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNKV2V3ZDJXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS/Qk9C+0YTQtdGA0L7QstC4LzE1MzgwNTEwNzAyNTA3NzMvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vJUQwJTkzJUQwJUJFJUQxJTg0JUQwJUI1JUQxJTgwJUQwJUJFJUQwJUIyJUQwJUI4L2FjbC9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiLQk9C+0YTQtdGA0L7QstC4IiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNzAyNTA3NzMiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0pXZXdkMlcyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL9CT0L7RhNC10YDQvtCy0LgvMTUzODA1MTA3MDI1MDc3My9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby8lRDAlOTMlRDAlQkUlRDElODQlRDAlQjUlRDElODAlRDAlQkUlRDAlQjIlRDAlQjgvYWNsL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6ItCT0L7RhNC10YDQvtCy0LgiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA3MDI1MDc3MyIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0pXZXdkMlcyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL9CT0L7RhNC10YDQvtCy0LgvMTUzODA1MTA3MDI1MDc3My91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vJUQwJTkzJUQwJUJFJUQxJTg0JUQwJUI1JUQxJTgwJUQwJUJFJUQwJUIyJUQwJUI4L2FjbC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0Ijoi0JPQvtGE0LXRgNC+0LLQuCIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDcwMjUwNzczIiwiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInJvbGUiOiJPV05FUiIsImVtYWlsIjoiMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJldGFnIjoiQ0pXZXdkMlcyOTBDRUFFPSJ9XSwib3duZXIiOnsiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSJ9LCJjcmMzMmMiOiJydGg5MFE9PSIsImV0YWciOiJDSldld2QyVzI5MENFQUU9In0="
+ }
+ },
+ {
+ "ID": "9b6f1ab259dce928",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Type": [
+ "multipart/related; boundary=5b1027ba28d1f511cf08fc457ba061ff4b2b59813cc7f9ec4cee9e9f594f"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "9ab324a2eab6d04c2e87770ac63723b7/1270863186651544173;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "LS01YjEwMjdiYTI4ZDFmNTExY2YwOGZjNDU3YmEwNjFmZjRiMmI1OTgxM2NjN2Y5ZWM0Y2VlOWU5ZjU5NGYNCkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vanNvbg0KDQp7ImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsImNhY2hlQ29udHJvbCI6InB1YmxpYywgbWF4LWFnZT02MCIsIm5hbWUiOiJhIn0KDQotLTViMTAyN2JhMjhkMWY1MTFjZjA4ZmM0NTdiYTA2MWZmNGIyYjU5ODEzY2M3ZjllYzRjZWU5ZTlmNTk0Zg0KQ29udGVudC1UeXBlOiB0ZXh0L3BsYWluOyBjaGFyc2V0PXV0Zi04DQoNCmRhdGENCi0tNWIxMDI3YmEyOGQxZjUxMWNmMDhmYzQ1N2JhMDYxZmY0YjJiNTk4MTNjYzdmOWVjNGNlZTllOWY1OTRmLS0NCg=="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3209"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:31 GMT"
+ ],
+ "Etag": [
+ "CIDy6t2W290CEAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051370000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vncw67:4172,/bns/yx/borg/yx/bns/blobstore2/bitpusher/105.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=_susW5zyHYbjzAKq95zACQ"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yx/borg/yx/bns/blobstore2/bitpusher/105.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yx/borg/yx/bns/blobstore2/bitpusher/105:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRYWpXSE1RZzgtWC1YcW42akZrMFVnT1pjQ2Rvc2J1RUtOdTFmNUpqa2xzSm0xUHllZVo1SEJlMG90M2RIanQ4V3RuaVVQNVNWR1JZOHd3eHhrUG5xV0ZOZkVnYl9YOWNNWUZuZ1R6bGhMQ05wZlZjM2ozYWZqQTgxM0VFSDVVeDlOdnRTalZyb1F4aFF0dW1SMTF5bVB0N0lLYjE3Q01LLVhtcVFtVVRlWWVkYTVsdkptOVR0R29RdjQwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_single_post_uploads"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Uo0atLVtSxYUq5rmgP5HeIiR7gyuLMhuEPkA-fQusOaxV0362YXm0oSsaVYF_Smh_-XKQJb8Yaf04_lO7ndJ2-Pv-9uew"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9hLzE1MzgwNTEwNzA5MzMyNDgiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9hIiwibmFtZSI6ImEiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA3MDkzMzI0OCIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOCIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDozMC45MzJaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MzAuOTMyWiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjMwLjkzMloiLCJzaXplIjoiNCIsIm1kNUhhc2giOiJqWGQvT0YwOS9zaUJYU0QzU1dBbTNBPT0iLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vYT9nZW5lcmF0aW9uPTE1MzgwNTEwNzA5MzMyNDgmYWx0PW1lZGlhIiwiY2FjaGVDb250cm9sIjoicHVibGljLCBtYXgtYWdlPTYwIiwiYWNsIjpbeyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvYS8xNTM4MDUxMDcwOTMzMjQ4L3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vYS9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJhIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNzA5MzMyNDgiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNJRHk2dDJXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9hLzE1MzgwNTEwNzA5MzMyNDgvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vYS9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiYSIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDcwOTMzMjQ4IiwiZW50aXR5IjoicHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6ImVkaXRvcnMifSwiZXRhZyI6IkNJRHk2dDJXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9hLzE1MzgwNTEwNzA5MzMyNDgvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vYS9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiYSIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDcwOTMzMjQ4IiwiZW50aXR5IjoicHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6IlJFQURFUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJ2aWV3ZXJzIn0sImV0YWciOiJDSUR5NnQyVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvYS8xNTM4MDUxMDcwOTMzMjQ4L3VzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9hL2FjbC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiYSIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDcwOTMzMjQ4IiwiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInJvbGUiOiJPV05FUiIsImVtYWlsIjoiMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJldGFnIjoiQ0lEeTZ0MlcyOTBDRUFFPSJ9XSwib3duZXIiOnsiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSJ9LCJjcmMzMmMiOiJydGg5MFE9PSIsImV0YWciOiJDSUR5NnQyVzI5MENFQUU9In0="
+ }
+ },
+ {
+ "ID": "56e95f3da4f5347b",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Type": [
+ "multipart/related; boundary=0798d81003f7bb4b09cf4ac08a194cf5f0d0f6a9a00f2deda8bd5d67fbe5"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "f590d185300c39d7a14ebc4e9eb2d352/2030181626754485692;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "LS0wNzk4ZDgxMDAzZjdiYjRiMDljZjRhYzA4YTE5NGNmNWYwZDBmNmE5YTAwZjJkZWRhOGJkNWQ2N2ZiZTUNCkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vanNvbg0KDQp7ImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsImNhY2hlQ29udHJvbCI6InB1YmxpYywgbWF4LWFnZT02MCIsIm5hbWUiOiJhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhIn0KDQotLTA3OThkODEwMDNmN2JiNGIwOWNmNGFjMDhhMTk0Y2Y1ZjBkMGY2YTlhMDBmMmRlZGE4YmQ1ZDY3ZmJlNQ0KQ29udGVudC1UeXBlOiB0ZXh0L3BsYWluOyBjaGFyc2V0PXV0Zi04DQoNCmRhdGENCi0tMDc5OGQ4MTAwM2Y3YmI0YjA5Y2Y0YWMwOGExOTRjZjVmMGQwZjZhOWEwMGYyZGVkYThiZDVkNjdmYmU1LS0NCg=="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "19577"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:31 GMT"
+ ],
+ "Etag": [
+ "CKaqkN6W290CEAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051369000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrda18:4093,/bns/yv/borg/yv/bns/blobstore2/bitpusher/135.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=_8usW-OlBoiRNq7qqOgL"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/135.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/135:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRYWpXSE1RZzgtWC1YcW42akZrMFVnT1pjQ2Rvc2J1RUtOdTFmNUpqa2xzSm0xUHllZVo1SEJlMG90M2RIanQ4V3RuaVVQNVNWR1JZOHd3eHhrUG5xV0ZOZkVnYl9YOWNNWUZuZ1R6bGhMQ05wZlZjM2ozYWZqQTgxM0VFSDVVeDlOdnRTalZyb1F4aFF0dW1SMTF5bVB0N0lLYjE3Q01LLVhtcVFtVVRlWWVkYTVsdkptOVR0R29RdjQwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_single_post_uploads"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UqitVkCUeUSJ0G4bi61MMByLVbIbbL-Xbw8R9bTZw4DcXcbckZu_ElUFTC7Up_z7JML2BBtH7edDzXjDj6yKygUj3t_3w"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9hYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhLzE1MzgwNTEwNzE1NDY2NjIiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9hYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhIiwibmFtZSI6ImFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWEiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA3MTU0NjY2MiIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOCIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDozMS41NDVaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MzEuNTQ1WiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjMxLjU0NVoiLCJzaXplIjoiNCIsIm1kNUhhc2giOiJqWGQvT0YwOS9zaUJYU0QzU1dBbTNBPT0iLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYT9nZW5lcmF0aW9uPTE1MzgwNTEwNzE1NDY2NjImYWx0PW1lZGlhIiwiY2FjaGVDb250cm9sIjoicHVibGljLCBtYXgtYWdlPTYwIiwiYWNsIjpbeyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYS8xNTM4MDUxMDcxNTQ2NjYyL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYS9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNzE1NDY2NjIiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNLYXFrTjZXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9hYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhLzE1MzgwNTEwNzE1NDY2NjIvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYS9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYSIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDcxNTQ2NjYyIiwiZW50aXR5IjoicHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6ImVkaXRvcnMifSwiZXRhZyI6IkNLYXFrTjZXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9hYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhLzE1MzgwNTEwNzE1NDY2NjIvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYS9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYSIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDcxNTQ2NjYyIiwiZW50aXR5IjoicHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6IlJFQURFUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJ2aWV3ZXJzIn0sImV0YWciOiJDS2Fxa042VzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYS8xNTM4MDUxMDcxNTQ2NjYyL3VzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9hYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhL2FjbC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYSIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDcxNTQ2NjYyIiwiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInJvbGUiOiJPV05FUiIsImVtYWlsIjoiMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJldGFnIjoiQ0thcWtONlcyOTBDRUFFPSJ9XSwib3duZXIiOnsiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSJ9LCJjcmMzMmMiOiJydGg5MFE9PSIsImV0YWciOiJDS2Fxa042VzI5MENFQUU9In0="
+ }
+ },
+ {
+ "ID": "50a6fa719716e926",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Type": [
+ "multipart/related; boundary=0f0345a33370001633096093c9ee25e720b209d560d3c5ec8e17c6144f51"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "d767ee61a2940cecbb7f6b2d1bc29950/2861275086423793420;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "LS0wZjAzNDVhMzMzNzAwMDE2MzMwOTYwOTNjOWVlMjVlNzIwYjIwOWQ1NjBkM2M1ZWM4ZTE3YzYxNDRmNTENCkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vanNvbg0KDQp7ImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsImNhY2hlQ29udHJvbCI6InB1YmxpYywgbWF4LWFnZT02MCJ9Cg0KLS0wZjAzNDVhMzMzNzAwMDE2MzMwOTYwOTNjOWVlMjVlNzIwYjIwOWQ1NjBkM2M1ZWM4ZTE3YzYxNDRmNTENCkNvbnRlbnQtVHlwZTogdGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOA0KDQpkYXRhDQotLTBmMDM0NWEzMzM3MDAwMTYzMzA5NjA5M2M5ZWUyNWU3MjBiMjA5ZDU2MGQzYzVlYzhlMTdjNjE0NGY1MS0tDQo="
+ },
+ "Response": {
+ "StatusCode": 400,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Content-Length": [
+ "2904"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:31 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051369000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrt3:4124,/bns/yr/borg/yr/bns/blobstore2/bitpusher/83.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=_8usW5bEKszg4QTBwYGIAw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/83.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/83:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRYWpXSE1RZzgtWC1YcW42akZrMFVnT1pjQ2Rvc2J1RUtOdTFmNUpqa2xzSm0xUHllZVo1SEJlMG90M2RIanQ4V3RuaVVQNVNWR1JZOHd3eHhrUG5xV0ZOZkVnYl9YOWNNWUZuZ1R6bGhMQ05wZlZjM2ozYWZqQTgxM0VFSDVVeDlOdnRTalZyb1F4aFF0dW1SMTF5bVB0N0lLYjE3Q01LLVhtcVFtVVRlWWVkYTVsdkptOVR0R29RdjQwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_single_post_uploads"
+ ],
+ "X-Guploader-Request-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Upload-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UqJW-7_6r7bI9eCj-JXqdY3BwbF-5mq1pbODJxD5tB34ilLdpKSYdEv7K0rLVA3hZMwyxbrlwJLEvD07ShK4YL90xl-WQ"
+ ]
+ },
+ "Body": "eyJlcnJvciI6eyJlcnJvcnMiOlt7ImRvbWFpbiI6Imdsb2JhbCIsInJlYXNvbiI6InJlcXVpcmVkIiwibWVzc2FnZSI6IlJlcXVpcmVkIiwiZGVidWdJbmZvIjoiY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUuRmF1bHQ6IEltbXV0YWJsZUVycm9yRGVmaW5pdGlvbntiYXNlPVJFUVVJUkVELCBjYXRlZ29yeT1VU0VSX0VSUk9SLCBjYXVzZT1udWxsLCBkZWJ1Z0luZm89bnVsbCwgZG9tYWluPWdsb2JhbCwgZXh0ZW5kZWRIZWxwPW51bGwsIGh0dHBIZWFkZXJzPXt9LCBodHRwU3RhdHVzPWJhZFJlcXVlc3QsIGludGVybmFsUmVhc29uPVJlYXNvbnthcmd1bWVudHM9e30sIGNhdXNlPW51bGwsIGNvZGU9Z2RhdGEuQ29yZUVycm9yRG9tYWluLlJFUVVJUkVELCBjcmVhdGVkQnlCYWNrZW5kPXRydWUsIGRlYnVnTWVzc2FnZT1udWxsLCBlcnJvclByb3RvQ29kZT1SRVFVSVJFRCwgZXJyb3JQcm90b0RvbWFpbj1nZGF0YS5Db3JlRXJyb3JEb21haW4sIGZpbHRlcmVkTWVzc2FnZT1udWxsLCBsb2NhdGlvbj1lbnRpdHkucmVzb3VyY2UuaWQubmFtZSwgbWVzc2FnZT1udWxsLCB1bm5hbWVkQXJndW1lbnRzPVtdfSwgbG9jYXRpb249ZW50aXR5LnJlc291cmNlLmlkLm5hbWUsIG1lc3NhZ2U9UmVxdWlyZWQsIHJlYXNvbj1yZXF1aXJlZCwgcnBjQ29kZT00MDB9IFJlcXVpcmVkXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLkVycm9yQ29sbGVjdG9yLnRvRmF1bHQoRXJyb3JDb2xsZWN0b3IuamF2YTo1NClcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnJlc3QuYWRhcHRlci5yb3N5LlJvc3lFcnJvckNvbnZlcnRlci50b0ZhdWx0KFJvc3lFcnJvckNvbnZlcnRlci5qYXZhOjY3KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIucmVzdC5hZGFwdGVyLnJvc3kuUm9zeUhhbmRsZXIkMi5jYWxsKFJvc3lIYW5kbGVyLmphdmE6MjU4KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIucmVzdC5hZGFwdGVyLnJvc3kuUm9zeUhhbmRsZXIkMi5jYWxsKFJvc3lIYW5kbGVyLmphdmE6MjM4KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS51dGlsLkNhbGxhYmxlRnV0dXJlLnJ1bihDYWxsYWJsZUZ1dHVyZS5qYXZhOjYyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuRGlyZWN0RXhlY3V0b3IuZXhlY3V0ZShEaXJlY3RFeGVjdXRvci5qYXZhOjMwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuZXhlY3V0ZUxpc3RlbmVyKEFic3RyYWN0RnV0dXJlLmphdmE6MTE0Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmNvbXBsZXRlKEFic3RyYWN0RnV0dXJlLmphdmE6OTYzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuc2V0KEFic3RyYWN0RnV0dXJlLmphdmE6NzMxKVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS51dGlsLkNhbGxhYmxlRnV0dXJlLnJ1bihDYWxsYWJsZUZ1dHVyZS5qYXZhOjYyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuRGlyZWN0RXhlY3V0b3IuZXhlY3V0ZShEaXJlY3RFeGVjdXRvci5qYXZhOjMwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuZXhlY3V0ZUxpc3RlbmVyKEFic3RyYWN0RnV0dXJlLmphdmE6MTE0Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmNvbXBsZXRlKEFic3RyYWN0RnV0dXJlLmphdmE6OTYzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuc2V0KEFic3RyYWN0RnV0dXJlLmphdmE6NzMxKVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS51dGlsLkNhbGxhYmxlRnV0dXJlLnJ1bihDYWxsYWJsZUZ1dHVyZS5qYXZhOjYyKVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIudGhyZWFkLlRocmVhZFRyYWNrZXJzJFRocmVhZFRyYWNraW5nUnVubmFibGUucnVuKFRocmVhZFRyYWNrZXJzLmphdmE6MTI2KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JFRyYWNlQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChUcmFjZUNvbnRleHQuamF2YTo0NTUpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5zZXJ2ZXIuQ29tbW9uTW9kdWxlJENvbnRleHRDYXJyeWluZ0V4ZWN1dG9yU2VydmljZSQxLnJ1bkluQ29udGV4dChDb21tb25Nb2R1bGUuamF2YTo4NDYpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkVHJhY2VDb250ZXh0UnVubmFibGUkMS5ydW4oVHJhY2VDb250ZXh0LmphdmE6NDYyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JEFic3RyYWN0VHJhY2VDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihUcmFjZUNvbnRleHQuamF2YTozMjEpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkQWJzdHJhY3RUcmFjZUNvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoVHJhY2VDb250ZXh0LmphdmE6MzEzKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JFRyYWNlQ29udGV4dFJ1bm5hYmxlLnJ1bihUcmFjZUNvbnRleHQuamF2YTo0NTkpXG5cdGF0IGNvbS5nb29nbGUuZ3NlLmludGVybmFsLkRpc3BhdGNoUXVldWVJbXBsJFdvcmtlclRocmVhZC5ydW4oRGlzcGF0Y2hRdWV1ZUltcGwuamF2YTo0MDMpXG4ifV0sImNvZGUiOjQwMCwibWVzc2FnZSI6IlJlcXVpcmVkIn19"
+ }
+ },
+ {
+ "ID": "0ae9542b9ce49562",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Type": [
+ "multipart/related; boundary=bcdca74de9a098617ef24a96ac27659fd795f59257d9d3c5216fc1ead110"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "9cb312c9ed3dcb4d3eb2dfd968e32e2e/3620593526526734939;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "LS1iY2RjYTc0ZGU5YTA5ODYxN2VmMjRhOTZhYzI3NjU5ZmQ3OTVmNTkyNTdkOWQzYzUyMTZmYzFlYWQxMTANCkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vanNvbg0KDQp7ImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsImNhY2hlQ29udHJvbCI6InB1YmxpYywgbWF4LWFnZT02MCIsIm5hbWUiOiJhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYSJ9Cg0KLS1iY2RjYTc0ZGU5YTA5ODYxN2VmMjRhOTZhYzI3NjU5ZmQ3OTVmNTkyNTdkOWQzYzUyMTZmYzFlYWQxMTANCkNvbnRlbnQtVHlwZTogdGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOA0KDQpkYXRhDQotLWJjZGNhNzRkZTlhMDk4NjE3ZWYyNGE5NmFjMjc2NTlmZDc5NWY1OTI1N2Q5ZDNjNTIxNmZjMWVhZDExMC0tDQo="
+ },
+ "Response": {
+ "StatusCode": 400,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Content-Length": [
+ "4741"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:31 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051369000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrhl7:4484,/bns/yr/borg/yr/bns/blobstore2/bitpusher/103.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=_8usW6jXLcbo4QTkprCgCA"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/103.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/103:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRYWpXSE1RZzgtWC1YcW42akZrMFVnT1pjQ2Rvc2J1RUtOdTFmNUpqa2xzSm0xUHllZVo1SEJlMG90M2RIanQ4V3RuaVVQNVNWR1JZOHd3eHhrUG5xV0ZOZkVnYl9YOWNNWUZuZ1R6bGhMQ05wZlZjM2ozYWZqQTgxM0VFSDVVeDlOdnRTalZyb1F4aFF0dW1SMTF5bVB0N0lLYjE3Q01LLVhtcVFtVVRlWWVkYTVsdkptOVR0R29RdjQwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_single_post_uploads"
+ ],
+ "X-Guploader-Request-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Upload-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UrwiJOmyTbYn2nlEF1jPhSu_VazrdoOwJr2lCIC0mrJbSxlG2HMan9jQZe_-TpkuFPxrsS_ZN7W54ZgE9cQNrDjgeESBw"
+ ]
+ },
+ "Body": "eyJlcnJvciI6eyJlcnJvcnMiOlt7ImRvbWFpbiI6Imdsb2JhbCIsInJlYXNvbiI6ImludmFsaWQiLCJtZXNzYWdlIjoiVGhlIG1heGltdW0gb2JqZWN0IGxlbmd0aCBpcyAxMDI0IGNoYXJhY3RlcnMsIGJ1dCBnb3QgYSBuYW1lIHdpdGggMTAyNSBjaGFyYWN0ZXJzOiAnJ2FhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhLi4uJyciLCJkZWJ1Z0luZm8iOiJjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS5GYXVsdDogSW1tdXRhYmxlRXJyb3JEZWZpbml0aW9ue2Jhc2U9SU5WQUxJRF9WQUxVRSwgY2F0ZWdvcnk9VVNFUl9FUlJPUiwgY2F1c2U9bnVsbCwgZGVidWdJbmZvPW51bGwsIGRvbWFpbj1nbG9iYWwsIGV4dGVuZGVkSGVscD1udWxsLCBodHRwSGVhZGVycz17fSwgaHR0cFN0YXR1cz1iYWRSZXF1ZXN0LCBpbnRlcm5hbFJlYXNvbj1SZWFzb257YXJndW1lbnRzPXt9LCBjYXVzZT1udWxsLCBjb2RlPWdkYXRhLkNvcmVFcnJvckRvbWFpbi5JTlZBTElEX1ZBTFVFLCBjcmVhdGVkQnlCYWNrZW5kPXRydWUsIGRlYnVnTWVzc2FnZT1udWxsLCBlcnJvclByb3RvQ29kZT1JTlZBTElEX1ZBTFVFLCBlcnJvclByb3RvRG9tYWluPWdkYXRhLkNvcmVFcnJvckRvbWFpbiwgZmlsdGVyZWRNZXNzYWdlPW51bGwsIGxvY2F0aW9uPWVudGl0eS5yZXNvdXJjZS5pZC5uYW1lLCBtZXNzYWdlPVRoZSBtYXhpbXVtIG9iamVjdCBsZW5ndGggaXMgMTAyNCBjaGFyYWN0ZXJzLCBidXQgZ290IGEgbmFtZSB3aXRoIDEwMjUgY2hhcmFjdGVyczogJydhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYS4uLicnLCB1bm5hbWVkQXJndW1lbnRzPVthYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYV19LCBsb2NhdGlvbj1lbnRpdHkucmVzb3VyY2UuaWQubmFtZSwgbWVzc2FnZT1UaGUgbWF4aW11bSBvYmplY3QgbGVuZ3RoIGlzIDEwMjQgY2hhcmFjdGVycywgYnV0IGdvdCBhIG5hbWUgd2l0aCAxMDI1IGNoYXJhY3RlcnM6ICcnYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWEuLi4nJywgcmVhc29uPWludmFsaWQsIHJwY0NvZGU9NDAwfSBUaGUgbWF4aW11bSBvYmplY3QgbGVuZ3RoIGlzIDEwMjQgY2hhcmFjdGVycywgYnV0IGdvdCBhIG5hbWUgd2l0aCAxMDI1IGNoYXJhY3RlcnM6ICcnYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWEuLi4nJ1xuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS5FcnJvckNvbGxlY3Rvci50b0ZhdWx0KEVycm9yQ29sbGVjdG9yLmphdmE6NTQpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5yZXN0LmFkYXB0ZXIucm9zeS5Sb3N5RXJyb3JDb252ZXJ0ZXIudG9GYXVsdChSb3N5RXJyb3JDb252ZXJ0ZXIuamF2YTo2Nylcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnJlc3QuYWRhcHRlci5yb3N5LlJvc3lIYW5kbGVyJDIuY2FsbChSb3N5SGFuZGxlci5qYXZhOjI1OClcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnJlc3QuYWRhcHRlci5yb3N5LlJvc3lIYW5kbGVyJDIuY2FsbChSb3N5SGFuZGxlci5qYXZhOjIzOClcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkRpcmVjdEV4ZWN1dG9yLmV4ZWN1dGUoRGlyZWN0RXhlY3V0b3IuamF2YTozMClcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmV4ZWN1dGVMaXN0ZW5lcihBYnN0cmFjdEZ1dHVyZS5qYXZhOjExNDMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5jb21wbGV0ZShBYnN0cmFjdEZ1dHVyZS5qYXZhOjk2Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLnNldChBYnN0cmFjdEZ1dHVyZS5qYXZhOjczMSlcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkRpcmVjdEV4ZWN1dG9yLmV4ZWN1dGUoRGlyZWN0RXhlY3V0b3IuamF2YTozMClcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmV4ZWN1dGVMaXN0ZW5lcihBYnN0cmFjdEZ1dHVyZS5qYXZhOjExNDMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5jb21wbGV0ZShBYnN0cmFjdEZ1dHVyZS5qYXZhOjk2Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLnNldChBYnN0cmFjdEZ1dHVyZS5qYXZhOjczMSlcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnRocmVhZC5UaHJlYWRUcmFja2VycyRUaHJlYWRUcmFja2luZ1J1bm5hYmxlLnJ1bihUaHJlYWRUcmFja2Vycy5qYXZhOjEyNilcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRUcmFjZUNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoVHJhY2VDb250ZXh0LmphdmE6NDU1KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuc2VydmVyLkNvbW1vbk1vZHVsZSRDb250ZXh0Q2FycnlpbmdFeGVjdXRvclNlcnZpY2UkMS5ydW5JbkNvbnRleHQoQ29tbW9uTW9kdWxlLmphdmE6ODQ2KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JFRyYWNlQ29udGV4dFJ1bm5hYmxlJDEucnVuKFRyYWNlQ29udGV4dC5qYXZhOjQ2Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRBYnN0cmFjdFRyYWNlQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoVHJhY2VDb250ZXh0LmphdmE6MzIxKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JEFic3RyYWN0VHJhY2VDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KFRyYWNlQ29udGV4dC5qYXZhOjMxMylcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRUcmFjZUNvbnRleHRSdW5uYWJsZS5ydW4oVHJhY2VDb250ZXh0LmphdmE6NDU5KVxuXHRhdCBjb20uZ29vZ2xlLmdzZS5pbnRlcm5hbC5EaXNwYXRjaFF1ZXVlSW1wbCRXb3JrZXJUaHJlYWQucnVuKERpc3BhdGNoUXVldWVJbXBsLmphdmE6NDAzKVxuIn1dLCJjb2RlIjo0MDAsIm1lc3NhZ2UiOiJUaGUgbWF4aW11bSBvYmplY3QgbGVuZ3RoIGlzIDEwMjQgY2hhcmFjdGVycywgYnV0IGdvdCBhIG5hbWUgd2l0aCAxMDI1IGNoYXJhY3RlcnM6ICcnYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWEuLi4nJyJ9fQ=="
+ }
+ },
+ {
+ "ID": "1f03f6aec789f628",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Type": [
+ "multipart/related; boundary=190e7ca1112dfae89a1cc94346bd93ebccf5adb1d3ed48a35941130b41ef"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "1c95398a95c726e69ab68d3262faba63/4451686990474233258;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "LS0xOTBlN2NhMTExMmRmYWU4OWExY2M5NDM0NmJkOTNlYmNjZjVhZGIxZDNlZDQ4YTM1OTQxMTMwYjQxZWYNCkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vanNvbg0KDQp7ImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsImNhY2hlQ29udHJvbCI6InB1YmxpYywgbWF4LWFnZT02MCIsIm5hbWUiOiJuZXdcbmxpbmVzIn0KDQotLTE5MGU3Y2ExMTEyZGZhZTg5YTFjYzk0MzQ2YmQ5M2ViY2NmNWFkYjFkM2VkNDhhMzU5NDExMzBiNDFlZg0KQ29udGVudC1UeXBlOiB0ZXh0L3BsYWluOyBjaGFyc2V0PXV0Zi04DQoNCmRhdGENCi0tMTkwZTdjYTExMTJkZmFlODlhMWNjOTQzNDZiZDkzZWJjY2Y1YWRiMWQzZWQ0OGEzNTk0MTEzMGI0MWVmLS0NCg=="
+ },
+ "Response": {
+ "StatusCode": 400,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Content-Length": [
+ "3226"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:31 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051369000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrwe17:4005,/bns/yw/borg/yw/bns/blobstore2/bitpusher/148.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=_8usW5H7MIfzhASA9r_IDA"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yw/borg/yw/bns/blobstore2/bitpusher/148.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yw/borg/yw/bns/blobstore2/bitpusher/148:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRYWpXSE1RZzgtWC1YcW42akZrMFVnT1pjQ2Rvc2J1RUtOdTFmNUpqa2xzSm0xUHllZVo1SEJlMG90M2RIanQ4V3RuaVVQNVNWR1JZOHd3eHhrUG5xV0ZOZkVnYl9YOWNNWUZuZ1R6bGhMQ05wZlZjM2ozYWZqQTgxM0VFSDVVeDlOdnRTalZyb1F4aFF0dW1SMTF5bVB0N0lLYjE3Q01LLVhtcVFtVVRlWWVkYTVsdkptOVR0R29RdjQwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_single_post_uploads"
+ ],
+ "X-Guploader-Request-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Upload-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UoAw4fjAOMtenHDXGbbkruczcQ5b8dIlEWdgiUXDyk4sWlmuMwgGtMVolvIBmrtajzJFtIYHNLBbIUWsXruMmnk2Hlwpw"
+ ]
+ },
+ "Body": "eyJlcnJvciI6eyJlcnJvcnMiOlt7ImRvbWFpbiI6Imdsb2JhbCIsInJlYXNvbiI6ImludmFsaWQiLCJtZXNzYWdlIjoiRGlzYWxsb3dlZCB1bmljb2RlIGNoYXJhY3RlcnMgcHJlc2VudCBpbiBvYmplY3QgbmFtZSAnJ25ld1xubGluZXMnJyIsImRlYnVnSW5mbyI6ImNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLkZhdWx0OiBJbW11dGFibGVFcnJvckRlZmluaXRpb257YmFzZT1JTlZBTElEX1ZBTFVFLCBjYXRlZ29yeT1VU0VSX0VSUk9SLCBjYXVzZT1udWxsLCBkZWJ1Z0luZm89bnVsbCwgZG9tYWluPWdsb2JhbCwgZXh0ZW5kZWRIZWxwPW51bGwsIGh0dHBIZWFkZXJzPXt9LCBodHRwU3RhdHVzPWJhZFJlcXVlc3QsIGludGVybmFsUmVhc29uPVJlYXNvbnthcmd1bWVudHM9e30sIGNhdXNlPW51bGwsIGNvZGU9Z2RhdGEuQ29yZUVycm9yRG9tYWluLklOVkFMSURfVkFMVUUsIGNyZWF0ZWRCeUJhY2tlbmQ9dHJ1ZSwgZGVidWdNZXNzYWdlPW51bGwsIGVycm9yUHJvdG9Db2RlPUlOVkFMSURfVkFMVUUsIGVycm9yUHJvdG9Eb21haW49Z2RhdGEuQ29yZUVycm9yRG9tYWluLCBmaWx0ZXJlZE1lc3NhZ2U9bnVsbCwgbG9jYXRpb249ZW50aXR5LnJlc291cmNlLmlkLm5hbWUsIG1lc3NhZ2U9RGlzYWxsb3dlZCB1bmljb2RlIGNoYXJhY3RlcnMgcHJlc2VudCBpbiBvYmplY3QgbmFtZSAnJ25ld1xubGluZXMnJywgdW5uYW1lZEFyZ3VtZW50cz1bbmV3XG5saW5lc119LCBsb2NhdGlvbj1lbnRpdHkucmVzb3VyY2UuaWQubmFtZSwgbWVzc2FnZT1EaXNhbGxvd2VkIHVuaWNvZGUgY2hhcmFjdGVycyBwcmVzZW50IGluIG9iamVjdCBuYW1lICcnbmV3XG5saW5lcycnLCByZWFzb249aW52YWxpZCwgcnBjQ29kZT00MDB9IERpc2FsbG93ZWQgdW5pY29kZSBjaGFyYWN0ZXJzIHByZXNlbnQgaW4gb2JqZWN0IG5hbWUgJyduZXdcbmxpbmVzJydcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUuRXJyb3JDb2xsZWN0b3IudG9GYXVsdChFcnJvckNvbGxlY3Rvci5qYXZhOjU0KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIucmVzdC5hZGFwdGVyLnJvc3kuUm9zeUVycm9yQ29udmVydGVyLnRvRmF1bHQoUm9zeUVycm9yQ29udmVydGVyLmphdmE6NjcpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5yZXN0LmFkYXB0ZXIucm9zeS5Sb3N5SGFuZGxlciQyLmNhbGwoUm9zeUhhbmRsZXIuamF2YToyNTgpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5yZXN0LmFkYXB0ZXIucm9zeS5Sb3N5SGFuZGxlciQyLmNhbGwoUm9zeUhhbmRsZXIuamF2YToyMzgpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLnV0aWwuQ2FsbGFibGVGdXR1cmUucnVuKENhbGxhYmxlRnV0dXJlLmphdmE6NjIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5EaXJlY3RFeGVjdXRvci5leGVjdXRlKERpcmVjdEV4ZWN1dG9yLmphdmE6MzApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5leGVjdXRlTGlzdGVuZXIoQWJzdHJhY3RGdXR1cmUuamF2YToxMTQzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuY29tcGxldGUoQWJzdHJhY3RGdXR1cmUuamF2YTo5NjMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5zZXQoQWJzdHJhY3RGdXR1cmUuamF2YTo3MzEpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLnV0aWwuQ2FsbGFibGVGdXR1cmUucnVuKENhbGxhYmxlRnV0dXJlLmphdmE6NjIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5EaXJlY3RFeGVjdXRvci5leGVjdXRlKERpcmVjdEV4ZWN1dG9yLmphdmE6MzApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5leGVjdXRlTGlzdGVuZXIoQWJzdHJhY3RGdXR1cmUuamF2YToxMTQzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuY29tcGxldGUoQWJzdHJhY3RGdXR1cmUuamF2YTo5NjMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5zZXQoQWJzdHJhY3RGdXR1cmUuamF2YTo3MzEpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLnV0aWwuQ2FsbGFibGVGdXR1cmUucnVuKENhbGxhYmxlRnV0dXJlLmphdmE6NjIpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci50aHJlYWQuVGhyZWFkVHJhY2tlcnMkVGhyZWFkVHJhY2tpbmdSdW5uYWJsZS5ydW4oVGhyZWFkVHJhY2tlcnMuamF2YToxMjYpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkVHJhY2VDb250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KFRyYWNlQ29udGV4dC5qYXZhOjQ1NSlcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnNlcnZlci5Db21tb25Nb2R1bGUkQ29udGV4dENhcnJ5aW5nRXhlY3V0b3JTZXJ2aWNlJDEucnVuSW5Db250ZXh0KENvbW1vbk1vZHVsZS5qYXZhOjg0Nilcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRUcmFjZUNvbnRleHRSdW5uYWJsZSQxLnJ1bihUcmFjZUNvbnRleHQuamF2YTo0NjIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkQWJzdHJhY3RUcmFjZUNvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKFRyYWNlQ29udGV4dC5qYXZhOjMyMSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRBYnN0cmFjdFRyYWNlQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChUcmFjZUNvbnRleHQuamF2YTozMTMpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkVHJhY2VDb250ZXh0UnVubmFibGUucnVuKFRyYWNlQ29udGV4dC5qYXZhOjQ1OSlcblx0YXQgY29tLmdvb2dsZS5nc2UuaW50ZXJuYWwuRGlzcGF0Y2hRdWV1ZUltcGwkV29ya2VyVGhyZWFkLnJ1bihEaXNwYXRjaFF1ZXVlSW1wbC5qYXZhOjQwMylcbiJ9XSwiY29kZSI6NDAwLCJtZXNzYWdlIjoiRGlzYWxsb3dlZCB1bmljb2RlIGNoYXJhY3RlcnMgcHJlc2VudCBpbiBvYmplY3QgbmFtZSAnJ25ld1xubGluZXMnJyJ9fQ=="
+ }
+ },
+ {
+ "ID": "77888c98dd46c50f",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "6a67c18da7762883b55d939f73d65794/5210723959895365882;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 204,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "0"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:32 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051369000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrnx7:4114,/bns/yw/borg/yw/bns/blobstore2/bitpusher/219.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=_8usW97SM5LfhASR57fgCA"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yw/borg/yw/bns/blobstore2/bitpusher/219.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yw/borg/yw/bns/blobstore2/bitpusher/219:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRYWpXSE1RZzgtWC1YcW42akZrMFVnT1pjQ2Rvc2J1RUtOdTFmNUpqa2xzSm0xUHllZVo1SEJlMG90M2RIanQ4V3RuaVVQNVNWR1JZOHd3eHhrUG5xV0ZOZkVnYl9YOWNNWUZuZ1R6bGhMQ05wZlZjM2ozYWZqQTgxM0VFSDVVeDlOdnRTalZyb1F4aFF0dW1SMTF5bVB0N0lLYjE3Q01LLVhtcVFtVVRlWWVkYTVsdkptOVR0R29RdjQwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UoMc9F9yE2HeDdmEyOjq_-pQVZkOPldnsVVz6TZ3F8Mzo0k_Pw5pjoQds9zzYbTnyrARRx-JKmlMCz2Ct6Zxuk-XTwiog"
+ ]
+ },
+ "Body": ""
+ }
+ },
+ {
+ "ID": "1e9c96c18d261238",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/a?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "2ffd36f41fda2e22f7b334d1571d73db/6042098894541384265;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/a?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 204,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "0"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:32 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051369000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrgm187:4292,/bns/yr/borg/yr/bns/blobstore2/bitpusher/53.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=AMysW97oE8X4kAOu3LKIDg"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/53.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/53:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRYWpXSE1RZzgtWC1YcW42akZrMFVnT1pjQ2Rvc2J1RUtOdTFmNUpqa2xzSm0xUHllZVo1SEJlMG90M2RIanQ4V3RuaVVQNVNWR1JZOHd3eHhrUG5xV0ZOZkVnYl9YOWNNWUZuZ1R6bGhMQ05wZlZjM2ozYWZqQTgxM0VFSDVVeDlOdnRTalZyb1F4aFF0dW1SMTF5bVB0N0lLYjE3Q01LLVhtcVFtVVRlWWVkYTVsdkptOVR0R29RdjQwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Uq_TALy4oWt6x7_UhdJcTrDd-XeBpQCTuE_VL6gZAVdlJrsyEVmfzEimkElArzI936P6aIYOGxvtUg1KAvmtRwrd1DkFA"
+ ]
+ },
+ "Body": ""
+ }
+ },
+ {
+ "ID": "ee39c82f0126f7df",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/%D0%93%D0%BE%D1%84%D0%B5%D1%80%D0%BE%D0%B2%D0%B8?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "f17bd9206bec1c206ae08560a1123fc7/6801134764467731864;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/%D0%93%D0%BE%D1%84%D0%B5%D1%80%D0%BE%D0%B2%D0%B8?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 204,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "0"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:32 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051369000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrtj9:4196,/bns/yr/borg/yr/bns/blobstore2/bitpusher/71.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=AMysW8PRJ4_k4QTxpY3ICg"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/71.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/71:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRYWpXSE1RZzgtWC1YcW42akZrMFVnT1pjQ2Rvc2J1RUtOdTFmNUpqa2xzSm0xUHllZVo1SEJlMG90M2RIanQ4V3RuaVVQNVNWR1JZOHd3eHhrUG5xV0ZOZkVnYl9YOWNNWUZuZ1R6bGhMQ05wZlZjM2ozYWZqQTgxM0VFSDVVeDlOdnRTalZyb1F4aFF0dW1SMTF5bVB0N0lLYjE3Q01LLVhtcVFtVVRlWWVkYTVsdkptOVR0R29RdjQwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UpcuhQp3DVIylZVBiYUzlifqq6BCn60_Q9aODaQvOV57lTYDXmbWGOQWx6g7oXxCQSixgDxuXhWjEsD2NWOQrGVjiKbrA"
+ ]
+ },
+ "Body": ""
+ }
+ },
+ {
+ "ID": "7b050c6c970e744f",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/gopher?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "4e3ba0b43bf75c16b32d162fa5dc35ff/7632228228415164648;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/gopher?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 204,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "0"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:33 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051369000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrvr22:4007,/bns/yr/borg/yr/bns/blobstore2/bitpusher/100.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=AMysW43oOc3WkAPE_IHQBA"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/100.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/100:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRYWpXSE1RZzgtWC1YcW42akZrMFVnT1pjQ2Rvc2J1RUtOdTFmNUpqa2xzSm0xUHllZVo1SEJlMG90M2RIanQ4V3RuaVVQNVNWR1JZOHd3eHhrUG5xV0ZOZkVnYl9YOWNNWUZuZ1R6bGhMQ05wZlZjM2ozYWZqQTgxM0VFSDVVeDlOdnRTalZyb1F4aFF0dW1SMTF5bVB0N0lLYjE3Q01LLVhtcVFtVVRlWWVkYTVsdkptOVR0R29RdjQwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Uo8308ofp3thGvMbSzyEx7nd1KdasYsdKvP0E4v7TM_frJ4pKcQm6YU2wFVXsdXCn4X2Na4TrqZS-l9SB5jhAxZpl4c4A"
+ ]
+ },
+ "Body": ""
+ }
+ },
+ {
+ "ID": "f24404f9531c7e01",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Type": [
+ "multipart/related; boundary=79457bd469f23815a10c54bd62cf8a97d11ef0e4f79358930776cd29e128"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "c98f2d57e237dd67a4cceceb3b4423a9/8391546664223204151;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "LS03OTQ1N2JkNDY5ZjIzODE1YTEwYzU0YmQ2MmNmOGE5N2QxMWVmMGU0Zjc5MzU4OTMwNzc2Y2QyOWUxMjgNCkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vanNvbg0KDQp7ImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsImNhY2hlQ29udHJvbCI6InB1YmxpYywgbWF4LWFnZT02MCIsIm5hbWUiOiJjb250ZW50In0KDQotLTc5NDU3YmQ0NjlmMjM4MTVhMTBjNTRiZDYyY2Y4YTk3ZDExZWYwZTRmNzkzNTg5MzA3NzZjZDI5ZTEyOA0KQ29udGVudC1UeXBlOiB0ZXh0L3BsYWluOyBjaGFyc2V0PXV0Zi04DQoNCkl0IHdhcyB0aGUgYmVzdCBvZiB0aW1lcywgaXQgd2FzIHRoZSB3b3JzdCBvZiB0aW1lcy4NCi0tNzk0NTdiZDQ2OWYyMzgxNWExMGM1NGJkNjJjZjhhOTdkMTFlZjBlNGY3OTM1ODkzMDc3NmNkMjllMTI4LS0NCg=="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3306"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:33 GMT"
+ ],
+ "Etag": [
+ "COOykd+W290CEAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051373000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrl7:4233,/bns/yr/borg/yr/bns/blobstore2/bitpusher/69.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=AcysW7zkFMzx4QSiqbCQCw"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/69.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/69:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWTdKaTNpQUtFYXBEb2hLZmRaV2FzVEpZLWRqMW43X1dRLUlwOGVYZ0cxOE93NE5IYkEwUHZlX0paQnd6b0pUNE9JRUYwcjVzM01Fa1ZQbHpvSnpXT1VOOUtsQV9OSENJcDl4QlRucmgtYU4wcDhuYkxwOTI2SHdRY0ZWRGQtMVBIclZQUVhZck9pQ3o1WUI1bkw4UjZpNWFJb3NHTUl4Qk4xV1ZUOWlCZW5malJ1TTF5SkUyQ2VTMDAwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_single_post_uploads"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Ur4QwSCgclPX6trpMIhT0vdtpmHrRu46ea8c1Ic6bXrHSLHx81tT13NQ4Pp0hdYA8XatyZAwmgUb4WFY3qyapXMVLO_1w"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jb250ZW50LzE1MzgwNTEwNzM2NjEyODMiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9jb250ZW50IiwibmFtZSI6ImNvbnRlbnQiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA3MzY2MTI4MyIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOCIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDozMy42NjFaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MzMuNjYxWiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjMzLjY2MVoiLCJzaXplIjoiNTIiLCJtZDVIYXNoIjoiSzI4NUF3S1dXZlZSZEJjQ1VYaHpOZz09IiwibWVkaWFMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vZG93bmxvYWQvc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2NvbnRlbnQ/Z2VuZXJhdGlvbj0xNTM4MDUxMDczNjYxMjgzJmFsdD1tZWRpYSIsImNhY2hlQ29udHJvbCI6InB1YmxpYywgbWF4LWFnZT02MCIsImFjbCI6W3sia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2NvbnRlbnQvMTUzODA1MTA3MzY2MTI4My9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2NvbnRlbnQvYWNsL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiY29udGVudCIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDczNjYxMjgzIiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDT095a2QrVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvY29udGVudC8xNTM4MDUxMDczNjYxMjgzL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2NvbnRlbnQvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6ImNvbnRlbnQiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA3MzY2MTI4MyIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDT095a2QrVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvY29udGVudC8xNTM4MDUxMDczNjYxMjgzL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2NvbnRlbnQvYWNsL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6ImNvbnRlbnQiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA3MzY2MTI4MyIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ09PeWtkK1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2NvbnRlbnQvMTUzODA1MTA3MzY2MTI4My91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vY29udGVudC9hY2wvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6ImNvbnRlbnQiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA3MzY2MTI4MyIsImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJyb2xlIjoiT1dORVIiLCJlbWFpbCI6IjM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiZXRhZyI6IkNPT3lrZCtXMjkwQ0VBRT0ifV0sIm93bmVyIjp7ImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20ifSwiY3JjMzJjIjoiRmNYTThRPT0iLCJldGFnIjoiQ09PeWtkK1cyOTBDRUFFPSJ9"
+ }
+ },
+ {
+ "ID": "e9d49ef6cb2edd09",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/content?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "3bff2347d8fb90f52b03b63484c816c2/9981677097608612054;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/content?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3306"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:33 GMT"
+ ],
+ "Etag": [
+ "COOykd+W290CEAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051373000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrv5:4481,/bns/yv/borg/yv/bns/blobstore2/bitpusher/182.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=AcysW4SxL9WFgQSM1K-oDQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/182.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/182:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRWTdKaTNpQUtFYXBEb2hLZmRaV2FzVEpZLWRqMW43X1dRLUlwOGVYZ0cxOE93NE5IYkEwUHZlX0paQnd6b0pUNE9JRUYwcjVzM01Fa1ZQbHpvSnpXT1VOOUtsQV9OSENJcDl4QlRucmgtYU4wcDhuYkxwOTI2SHdRY0ZWRGQtMVBIclZQUVhZck9pQ3o1WUI1bkw4UjZpNWFJb3NHTUl4Qk4xV1ZUOWlCZW5malJ1TTF5SkUyQ2VTMDAwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UpKyKaISEWquueFV4lfr3BrKEbt91VU2X2w7V9LAq9yelzjZBmz-oC-cQzyVvn0C0eLYGwXBVxtpNEKR4av7BY4G2BRfZAfM10r9K-cVmNkKBG3gZo"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jb250ZW50LzE1MzgwNTEwNzM2NjEyODMiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9jb250ZW50IiwibmFtZSI6ImNvbnRlbnQiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA3MzY2MTI4MyIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOCIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDozMy42NjFaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MzMuNjYxWiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjMzLjY2MVoiLCJzaXplIjoiNTIiLCJtZDVIYXNoIjoiSzI4NUF3S1dXZlZSZEJjQ1VYaHpOZz09IiwibWVkaWFMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vZG93bmxvYWQvc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2NvbnRlbnQ/Z2VuZXJhdGlvbj0xNTM4MDUxMDczNjYxMjgzJmFsdD1tZWRpYSIsImNhY2hlQ29udHJvbCI6InB1YmxpYywgbWF4LWFnZT02MCIsImFjbCI6W3sia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2NvbnRlbnQvMTUzODA1MTA3MzY2MTI4My9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2NvbnRlbnQvYWNsL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiY29udGVudCIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDczNjYxMjgzIiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDT095a2QrVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvY29udGVudC8xNTM4MDUxMDczNjYxMjgzL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2NvbnRlbnQvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6ImNvbnRlbnQiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA3MzY2MTI4MyIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDT095a2QrVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvY29udGVudC8xNTM4MDUxMDczNjYxMjgzL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2NvbnRlbnQvYWNsL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6ImNvbnRlbnQiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA3MzY2MTI4MyIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ09PeWtkK1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2NvbnRlbnQvMTUzODA1MTA3MzY2MTI4My91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vY29udGVudC9hY2wvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6ImNvbnRlbnQiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA3MzY2MTI4MyIsImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJyb2xlIjoiT1dORVIiLCJlbWFpbCI6IjM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiZXRhZyI6IkNPT3lrZCtXMjkwQ0VBRT0ifV0sIm93bmVyIjp7ImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20ifSwiY3JjMzJjIjoiRmNYTThRPT0iLCJldGFnIjoiQ09PeWtkK1cyOTBDRUFFPSJ9"
+ }
+ },
+ {
+ "ID": "151fc10cc5fad9fd",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Type": [
+ "multipart/related; boundary=988437801ee1a9246232838eec36a9a90e52a9a42f54ffe7c8b6e41a5972"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "fcd3d5168b79bde9c2fce272a552a779/10740995537711553317;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "LS05ODg0Mzc4MDFlZTFhOTI0NjIzMjgzOGVlYzM2YTlhOTBlNTJhOWE0MmY1NGZmZTdjOGI2ZTQxYTU5NzINCkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vanNvbg0KDQp7ImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsImNhY2hlQ29udHJvbCI6InB1YmxpYywgbWF4LWFnZT02MCIsIm5hbWUiOiJjb250ZW50In0KDQotLTk4ODQzNzgwMWVlMWE5MjQ2MjMyODM4ZWVjMzZhOWE5MGU1MmE5YTQyZjU0ZmZlN2M4YjZlNDFhNTk3Mg0KQ29udGVudC1UeXBlOiB0ZXh0L2h0bWw7IGNoYXJzZXQ9dXRmLTgNCg0KPGh0bWw+PGhlYWQ+PHRpdGxlPk15IGZpcnN0IHBhZ2U8L3RpdGxlPjwvaGVhZD48L2h0bWw+DQotLTk4ODQzNzgwMWVlMWE5MjQ2MjMyODM4ZWVjMzZhOWE5MGU1MmE5YTQyZjU0ZmZlN2M4YjZlNDFhNTk3Mi0tDQo="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3305"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:34 GMT"
+ ],
+ "Etag": [
+ "CLLBtN+W290CEAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051373000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vraw6:4495,/bns/yr/borg/yr/bns/blobstore2/bitpusher/99.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=AcysW9foNYi44QT15L5A"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/99.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/99:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWTdKaTNpQUtFYXBEb2hLZmRaV2FzVEpZLWRqMW43X1dRLUlwOGVYZ0cxOE93NE5IYkEwUHZlX0paQnd6b0pUNE9JRUYwcjVzM01Fa1ZQbHpvSnpXT1VOOUtsQV9OSENJcDl4QlRucmgtYU4wcDhuYkxwOTI2SHdRY0ZWRGQtMVBIclZQUVhZck9pQ3o1WUI1bkw4UjZpNWFJb3NHTUl4Qk4xV1ZUOWlCZW5malJ1TTF5SkUyQ2VTMDAwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_single_post_uploads"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Uq0AeI4jGor5HSsfQM95EEyapL69zFATtcCRzvjOwNAcDuFOz94hOPLrpRQzUqLAGqS4q8DOEzE-xnP5WD64o-UkoR5bg"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jb250ZW50LzE1MzgwNTEwNzQyMzY1OTQiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9jb250ZW50IiwibmFtZSI6ImNvbnRlbnQiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA3NDIzNjU5NCIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoidGV4dC9odG1sOyBjaGFyc2V0PXV0Zi04IiwidGltZUNyZWF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjM0LjIzNloiLCJ1cGRhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDozNC4yMzZaIiwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJ0aW1lU3RvcmFnZUNsYXNzVXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MzQuMjM2WiIsInNpemUiOiI1NCIsIm1kNUhhc2giOiJOOHA4L3M5RndkQUFubHZyL2xFQWpRPT0iLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vY29udGVudD9nZW5lcmF0aW9uPTE1MzgwNTEwNzQyMzY1OTQmYWx0PW1lZGlhIiwiY2FjaGVDb250cm9sIjoicHVibGljLCBtYXgtYWdlPTYwIiwiYWNsIjpbeyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvY29udGVudC8xNTM4MDUxMDc0MjM2NTk0L3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vY29udGVudC9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJjb250ZW50IiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNzQyMzY1OTQiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNMTEJ0TitXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jb250ZW50LzE1MzgwNTEwNzQyMzY1OTQvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vY29udGVudC9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiY29udGVudCIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDc0MjM2NTk0IiwiZW50aXR5IjoicHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6ImVkaXRvcnMifSwiZXRhZyI6IkNMTEJ0TitXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jb250ZW50LzE1MzgwNTEwNzQyMzY1OTQvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vY29udGVudC9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiY29udGVudCIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDc0MjM2NTk0IiwiZW50aXR5IjoicHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6IlJFQURFUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJ2aWV3ZXJzIn0sImV0YWciOiJDTExCdE4rVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvY29udGVudC8xNTM4MDUxMDc0MjM2NTk0L3VzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9jb250ZW50L2FjbC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiY29udGVudCIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDc0MjM2NTk0IiwiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInJvbGUiOiJPV05FUiIsImVtYWlsIjoiMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJldGFnIjoiQ0xMQnROK1cyOTBDRUFFPSJ9XSwib3duZXIiOnsiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSJ9LCJjcmMzMmMiOiJHb1Vic1E9PSIsImV0YWciOiJDTExCdE4rVzI5MENFQUU9In0="
+ }
+ },
+ {
+ "ID": "7a91c5fbf00267a1",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/content?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "f27bc1c9491d357a63da36391e4159dd/12331407441778704580;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/content?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3305"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:34 GMT"
+ ],
+ "Etag": [
+ "CLLBtN+W290CEAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051373000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrat7:4174,/bns/yv/borg/yv/bns/blobstore2/bitpusher/129.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=AsysW5bFFdP-gASw_pngAw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/129.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/129:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRWTdKaTNpQUtFYXBEb2hLZmRaV2FzVEpZLWRqMW43X1dRLUlwOGVYZ0cxOE93NE5IYkEwUHZlX0paQnd6b0pUNE9JRUYwcjVzM01Fa1ZQbHpvSnpXT1VOOUtsQV9OSENJcDl4QlRucmgtYU4wcDhuYkxwOTI2SHdRY0ZWRGQtMVBIclZQUVhZck9pQ3o1WUI1bkw4UjZpNWFJb3NHTUl4Qk4xV1ZUOWlCZW5malJ1TTF5SkUyQ2VTMDAwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UqNYY40vODTXqZDpfJEqECTQgqog4KbGxuycuszoFuk-7fVUd6p446qgHeljXPOeNB44EDswGxKxpWPX-PX_FrzqFU41g"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jb250ZW50LzE1MzgwNTEwNzQyMzY1OTQiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9jb250ZW50IiwibmFtZSI6ImNvbnRlbnQiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA3NDIzNjU5NCIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoidGV4dC9odG1sOyBjaGFyc2V0PXV0Zi04IiwidGltZUNyZWF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjM0LjIzNloiLCJ1cGRhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDozNC4yMzZaIiwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJ0aW1lU3RvcmFnZUNsYXNzVXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MzQuMjM2WiIsInNpemUiOiI1NCIsIm1kNUhhc2giOiJOOHA4L3M5RndkQUFubHZyL2xFQWpRPT0iLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vY29udGVudD9nZW5lcmF0aW9uPTE1MzgwNTEwNzQyMzY1OTQmYWx0PW1lZGlhIiwiY2FjaGVDb250cm9sIjoicHVibGljLCBtYXgtYWdlPTYwIiwiYWNsIjpbeyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvY29udGVudC8xNTM4MDUxMDc0MjM2NTk0L3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vY29udGVudC9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJjb250ZW50IiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNzQyMzY1OTQiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNMTEJ0TitXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jb250ZW50LzE1MzgwNTEwNzQyMzY1OTQvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vY29udGVudC9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiY29udGVudCIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDc0MjM2NTk0IiwiZW50aXR5IjoicHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6ImVkaXRvcnMifSwiZXRhZyI6IkNMTEJ0TitXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jb250ZW50LzE1MzgwNTEwNzQyMzY1OTQvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vY29udGVudC9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiY29udGVudCIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDc0MjM2NTk0IiwiZW50aXR5IjoicHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6IlJFQURFUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJ2aWV3ZXJzIn0sImV0YWciOiJDTExCdE4rVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvY29udGVudC8xNTM4MDUxMDc0MjM2NTk0L3VzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9jb250ZW50L2FjbC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiY29udGVudCIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDc0MjM2NTk0IiwiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInJvbGUiOiJPV05FUiIsImVtYWlsIjoiMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJldGFnIjoiQ0xMQnROK1cyOTBDRUFFPSJ9XSwib3duZXIiOnsiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSJ9LCJjcmMzMmMiOiJHb1Vic1E9PSIsImV0YWciOiJDTExCdE4rVzI5MENFQUU9In0="
+ }
+ },
+ {
+ "ID": "4c7ff4fe8be88426",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Type": [
+ "multipart/related; boundary=2bc3dd5645f4717661991904c39270871075913fb3be34dd4fb00e9fb533"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "37b1664652a23037c645c3f3dfac05d5/13162500905726202643;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "LS0yYmMzZGQ1NjQ1ZjQ3MTc2NjE5OTE5MDRjMzkyNzA4NzEwNzU5MTNmYjNiZTM0ZGQ0ZmIwMGU5ZmI1MzMNCkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vanNvbg0KDQp7ImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsImNhY2hlQ29udHJvbCI6InB1YmxpYywgbWF4LWFnZT02MCIsImNvbnRlbnRUeXBlIjoidGV4dC9odG1sIiwibmFtZSI6ImNvbnRlbnQifQoNCi0tMmJjM2RkNTY0NWY0NzE3NjYxOTkxOTA0YzM5MjcwODcxMDc1OTEzZmIzYmUzNGRkNGZiMDBlOWZiNTMzDQpDb250ZW50LVR5cGU6IHRleHQvaHRtbA0KDQo8aHRtbD48aGVhZD48dGl0bGU+TXkgZmlyc3QgcGFnZTwvdGl0bGU+PC9oZWFkPjwvaHRtbD4NCi0tMmJjM2RkNTY0NWY0NzE3NjYxOTkxOTA0YzM5MjcwODcxMDc1OTEzZmIzYmUzNGRkNGZiMDBlOWZiNTMzLS0NCg=="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3290"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:34 GMT"
+ ],
+ "Etag": [
+ "CKia1N+W290CEAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051374000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vnau137:4408,/bns/yx/borg/yx/bns/blobstore2/bitpusher/84.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=AsysW-vzGcO1zALTr7lY"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yx/borg/yx/bns/blobstore2/bitpusher/84.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yx/borg/yx/bns/blobstore2/bitpusher/84:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWTdKaTNpQUtFYXBEb2hLZmRaV2FzVEpZLWRqMW43X1dRLUlwOGVYZ0cxOE93NE5IYkEwUHZlX0paQnd6b0pUNE9JRUYwcjVzM01Fa1ZQbHpvSnpXT1VOOUtsQV9OSENJcDl4QlRucmgtYU4wcDhuYkxwOTI2SHdRY0ZWRGQtMVBIclZQUVhZck9pQ3o1WUI1bkw4UjZpNWFJb3NHTUl4Qk4xV1ZUOWlCZW5malJ1TTF5SkUyQ2VTMDAwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_single_post_uploads"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UoNJgqctgeYS02cdv67cIAhN4zbfhd5Igx0oOKU3ZYQnBDRFSS_YnaxjWfyGJpyzUYK-492G_o2VbkSQZ9hKyGVQecFtQ"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jb250ZW50LzE1MzgwNTEwNzQ3NTU4ODAiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9jb250ZW50IiwibmFtZSI6ImNvbnRlbnQiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA3NDc1NTg4MCIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoidGV4dC9odG1sIiwidGltZUNyZWF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjM0Ljc1NVoiLCJ1cGRhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDozNC43NTVaIiwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJ0aW1lU3RvcmFnZUNsYXNzVXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MzQuNzU1WiIsInNpemUiOiI1NCIsIm1kNUhhc2giOiJOOHA4L3M5RndkQUFubHZyL2xFQWpRPT0iLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vY29udGVudD9nZW5lcmF0aW9uPTE1MzgwNTEwNzQ3NTU4ODAmYWx0PW1lZGlhIiwiY2FjaGVDb250cm9sIjoicHVibGljLCBtYXgtYWdlPTYwIiwiYWNsIjpbeyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvY29udGVudC8xNTM4MDUxMDc0NzU1ODgwL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vY29udGVudC9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJjb250ZW50IiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNzQ3NTU4ODAiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNLaWExTitXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jb250ZW50LzE1MzgwNTEwNzQ3NTU4ODAvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vY29udGVudC9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiY29udGVudCIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDc0NzU1ODgwIiwiZW50aXR5IjoicHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6ImVkaXRvcnMifSwiZXRhZyI6IkNLaWExTitXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jb250ZW50LzE1MzgwNTEwNzQ3NTU4ODAvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vY29udGVudC9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiY29udGVudCIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDc0NzU1ODgwIiwiZW50aXR5IjoicHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6IlJFQURFUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJ2aWV3ZXJzIn0sImV0YWciOiJDS2lhMU4rVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvY29udGVudC8xNTM4MDUxMDc0NzU1ODgwL3VzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9jb250ZW50L2FjbC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiY29udGVudCIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDc0NzU1ODgwIiwiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInJvbGUiOiJPV05FUiIsImVtYWlsIjoiMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJldGFnIjoiQ0tpYTFOK1cyOTBDRUFFPSJ9XSwib3duZXIiOnsiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSJ9LCJjcmMzMmMiOiJHb1Vic1E9PSIsImV0YWciOiJDS2lhMU4rVzI5MENFQUU9In0="
+ }
+ },
+ {
+ "ID": "b6e9d9ae9b9ab978",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/content?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "2a9df9fee84fe18940299e1e19b963f3/14752911705986890161;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/content?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3290"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:34 GMT"
+ ],
+ "Etag": [
+ "CKia1N+W290CEAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051373000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrnb2:4089,/bns/yv/borg/yv/bns/blobstore2/bitpusher/259.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=AsysW9TQNsmngASFkp7wAw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/259.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/259:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRWTdKaTNpQUtFYXBEb2hLZmRaV2FzVEpZLWRqMW43X1dRLUlwOGVYZ0cxOE93NE5IYkEwUHZlX0paQnd6b0pUNE9JRUYwcjVzM01Fa1ZQbHpvSnpXT1VOOUtsQV9OSENJcDl4QlRucmgtYU4wcDhuYkxwOTI2SHdRY0ZWRGQtMVBIclZQUVhZck9pQ3o1WUI1bkw4UjZpNWFJb3NHTUl4Qk4xV1ZUOWlCZW5malJ1TTF5SkUyQ2VTMDAwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Uo2QCAedXJWZRu0_FYQQyJ9LFvRMq2tC7QKpClrN37a6mnhCEudZtWqGhevEpEYba9YwKYwez8KFNv0vso_czdyYI0IRQ"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jb250ZW50LzE1MzgwNTEwNzQ3NTU4ODAiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9jb250ZW50IiwibmFtZSI6ImNvbnRlbnQiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA3NDc1NTg4MCIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoidGV4dC9odG1sIiwidGltZUNyZWF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjM0Ljc1NVoiLCJ1cGRhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDozNC43NTVaIiwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJ0aW1lU3RvcmFnZUNsYXNzVXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MzQuNzU1WiIsInNpemUiOiI1NCIsIm1kNUhhc2giOiJOOHA4L3M5RndkQUFubHZyL2xFQWpRPT0iLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vY29udGVudD9nZW5lcmF0aW9uPTE1MzgwNTEwNzQ3NTU4ODAmYWx0PW1lZGlhIiwiY2FjaGVDb250cm9sIjoicHVibGljLCBtYXgtYWdlPTYwIiwiYWNsIjpbeyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvY29udGVudC8xNTM4MDUxMDc0NzU1ODgwL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vY29udGVudC9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJjb250ZW50IiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNzQ3NTU4ODAiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNLaWExTitXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jb250ZW50LzE1MzgwNTEwNzQ3NTU4ODAvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vY29udGVudC9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiY29udGVudCIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDc0NzU1ODgwIiwiZW50aXR5IjoicHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6ImVkaXRvcnMifSwiZXRhZyI6IkNLaWExTitXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jb250ZW50LzE1MzgwNTEwNzQ3NTU4ODAvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vY29udGVudC9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiY29udGVudCIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDc0NzU1ODgwIiwiZW50aXR5IjoicHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6IlJFQURFUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJ2aWV3ZXJzIn0sImV0YWciOiJDS2lhMU4rVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvY29udGVudC8xNTM4MDUxMDc0NzU1ODgwL3VzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9jb250ZW50L2FjbC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiY29udGVudCIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDc0NzU1ODgwIiwiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInJvbGUiOiJPV05FUiIsImVtYWlsIjoiMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJldGFnIjoiQ0tpYTFOK1cyOTBDRUFFPSJ9XSwib3duZXIiOnsiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSJ9LCJjcmMzMmMiOiJHb1Vic1E9PSIsImV0YWciOiJDS2lhMU4rVzI5MENFQUU9In0="
+ }
+ },
+ {
+ "ID": "7d1ddfc4a79aed5c",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Type": [
+ "multipart/related; boundary=51b79aa9dfea162830fbd443aaeec47fe3d21d207f16c34b06ad6efaba79"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "994ad2d293093b6ed73587008f24a071/15511948675424799489;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "LS01MWI3OWFhOWRmZWExNjI4MzBmYmQ0NDNhYWVlYzQ3ZmUzZDIxZDIwN2YxNmMzNGIwNmFkNmVmYWJhNzkNCkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vanNvbg0KDQp7ImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsImNhY2hlQ29udHJvbCI6InB1YmxpYywgbWF4LWFnZT02MCIsImNvbnRlbnRUeXBlIjoiaW1hZ2UvanBlZyIsIm5hbWUiOiJjb250ZW50In0KDQotLTUxYjc5YWE5ZGZlYTE2MjgzMGZiZDQ0M2FhZWVjNDdmZTNkMjFkMjA3ZjE2YzM0YjA2YWQ2ZWZhYmE3OQ0KQ29udGVudC1UeXBlOiBpbWFnZS9qcGVnDQoNCjxodG1sPjxoZWFkPjx0aXRsZT5NeSBmaXJzdCBwYWdlPC90aXRsZT48L2hlYWQ+PC9odG1sPg0KLS01MWI3OWFhOWRmZWExNjI4MzBmYmQ0NDNhYWVlYzQ3ZmUzZDIxZDIwN2YxNmMzNGIwNmFkNmVmYWJhNzktLQ0K"
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3291"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:35 GMT"
+ ],
+ "Etag": [
+ "CIGg99+W290CEAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051373000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrmk5:4135,/bns/yr/borg/yr/bns/blobstore2/bitpusher/58.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=AsysW4yKPKyRkAS0ioHgCQ"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/58.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/58:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWTdKaTNpQUtFYXBEb2hLZmRaV2FzVEpZLWRqMW43X1dRLUlwOGVYZ0cxOE93NE5IYkEwUHZlX0paQnd6b0pUNE9JRUYwcjVzM01Fa1ZQbHpvSnpXT1VOOUtsQV9OSENJcDl4QlRucmgtYU4wcDhuYkxwOTI2SHdRY0ZWRGQtMVBIclZQUVhZck9pQ3o1WUI1bkw4UjZpNWFJb3NHTUl4Qk4xV1ZUOWlCZW5malJ1TTF5SkUyQ2VTMDAwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_single_post_uploads"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Up2B0gN0Tp-hZeNdZzqXr32fqBuXEdF_UfypqatMEY_Z8FElRH7MLrj1Q-6Li1qrYCd5lWBQDs0wz5FpqsHjBN_hytJyQ"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jb250ZW50LzE1MzgwNTEwNzUzMzAwNDkiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9jb250ZW50IiwibmFtZSI6ImNvbnRlbnQiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA3NTMzMDA0OSIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoiaW1hZ2UvanBlZyIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDozNS4zMjlaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MzUuMzI5WiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjM1LjMyOVoiLCJzaXplIjoiNTQiLCJtZDVIYXNoIjoiTjhwOC9zOUZ3ZEFBbmx2ci9sRUFqUT09IiwibWVkaWFMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vZG93bmxvYWQvc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2NvbnRlbnQ/Z2VuZXJhdGlvbj0xNTM4MDUxMDc1MzMwMDQ5JmFsdD1tZWRpYSIsImNhY2hlQ29udHJvbCI6InB1YmxpYywgbWF4LWFnZT02MCIsImFjbCI6W3sia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2NvbnRlbnQvMTUzODA1MTA3NTMzMDA0OS9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2NvbnRlbnQvYWNsL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiY29udGVudCIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDc1MzMwMDQ5IiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDSUdnOTkrVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvY29udGVudC8xNTM4MDUxMDc1MzMwMDQ5L3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2NvbnRlbnQvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6ImNvbnRlbnQiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA3NTMzMDA0OSIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDSUdnOTkrVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvY29udGVudC8xNTM4MDUxMDc1MzMwMDQ5L3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2NvbnRlbnQvYWNsL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6ImNvbnRlbnQiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA3NTMzMDA0OSIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0lHZzk5K1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2NvbnRlbnQvMTUzODA1MTA3NTMzMDA0OS91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vY29udGVudC9hY2wvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6ImNvbnRlbnQiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA3NTMzMDA0OSIsImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJyb2xlIjoiT1dORVIiLCJlbWFpbCI6IjM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiZXRhZyI6IkNJR2c5OStXMjkwQ0VBRT0ifV0sIm93bmVyIjp7ImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20ifSwiY3JjMzJjIjoiR29VYnNRPT0iLCJldGFnIjoiQ0lHZzk5K1cyOTBDRUFFPSJ9"
+ }
+ },
+ {
+ "ID": "9b9ff11a993b6af6",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/content?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "c0c6e81b82b832c7e7354ea55a133407/17102360579475239327;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/content?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3291"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:35 GMT"
+ ],
+ "Etag": [
+ "CIGg99+W290CEAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051373000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrb20:4129,/bns/yv/borg/yv/bns/blobstore2/bitpusher/82.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=A8ysW4nMHYOlgASf-Jco"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/82.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/82:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRWTdKaTNpQUtFYXBEb2hLZmRaV2FzVEpZLWRqMW43X1dRLUlwOGVYZ0cxOE93NE5IYkEwUHZlX0paQnd6b0pUNE9JRUYwcjVzM01Fa1ZQbHpvSnpXT1VOOUtsQV9OSENJcDl4QlRucmgtYU4wcDhuYkxwOTI2SHdRY0ZWRGQtMVBIclZQUVhZck9pQ3o1WUI1bkw4UjZpNWFJb3NHTUl4Qk4xV1ZUOWlCZW5malJ1TTF5SkUyQ2VTMDAwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Urvkgc7dWXoce48Vak9OxsOqstuo9yJWf7VkQKIC7EoQ9ElFapB3F4vwy8RWd6rYlRY_A0lHq2d09QlQyMfn83kYVuG3A"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jb250ZW50LzE1MzgwNTEwNzUzMzAwNDkiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9jb250ZW50IiwibmFtZSI6ImNvbnRlbnQiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA3NTMzMDA0OSIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoiaW1hZ2UvanBlZyIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDozNS4zMjlaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MzUuMzI5WiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjM1LjMyOVoiLCJzaXplIjoiNTQiLCJtZDVIYXNoIjoiTjhwOC9zOUZ3ZEFBbmx2ci9sRUFqUT09IiwibWVkaWFMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vZG93bmxvYWQvc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2NvbnRlbnQ/Z2VuZXJhdGlvbj0xNTM4MDUxMDc1MzMwMDQ5JmFsdD1tZWRpYSIsImNhY2hlQ29udHJvbCI6InB1YmxpYywgbWF4LWFnZT02MCIsImFjbCI6W3sia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2NvbnRlbnQvMTUzODA1MTA3NTMzMDA0OS9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2NvbnRlbnQvYWNsL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiY29udGVudCIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDc1MzMwMDQ5IiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDSUdnOTkrVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvY29udGVudC8xNTM4MDUxMDc1MzMwMDQ5L3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2NvbnRlbnQvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6ImNvbnRlbnQiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA3NTMzMDA0OSIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDSUdnOTkrVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvY29udGVudC8xNTM4MDUxMDc1MzMwMDQ5L3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2NvbnRlbnQvYWNsL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6ImNvbnRlbnQiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA3NTMzMDA0OSIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0lHZzk5K1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2NvbnRlbnQvMTUzODA1MTA3NTMzMDA0OS91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vY29udGVudC9hY2wvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6ImNvbnRlbnQiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA3NTMzMDA0OSIsImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJyb2xlIjoiT1dORVIiLCJlbWFpbCI6IjM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiZXRhZyI6IkNJR2c5OStXMjkwQ0VBRT0ifV0sIm93bmVyIjp7ImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20ifSwiY3JjMzJjIjoiR29VYnNRPT0iLCJldGFnIjoiQ0lHZzk5K1cyOTBDRUFFPSJ9"
+ }
+ },
+ {
+ "ID": "7915606f6c21576d",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Type": [
+ "multipart/related; boundary=48c8e7da3f6b7f4e8dcc258f6ef3c4c7de9547cf4235aa7c2ed097aeedd4"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "b29b46c9f037a69e7b0959bc8004045b/17933454043422672111;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ],
+ "X-Goog-Encryption-Algorithm": [
+ "AES256"
+ ],
+ "X-Goog-Encryption-Key": [
+ "REDACTED"
+ ],
+ "X-Goog-Encryption-Key-Sha256": [
+ "H+LmnXhRoeI6TMW5bsV6HyUk6pyGc2IMbqYbAXBcps0="
+ ]
+ },
+ "Body": "LS00OGM4ZTdkYTNmNmI3ZjRlOGRjYzI1OGY2ZWYzYzRjN2RlOTU0N2NmNDIzNWFhN2MyZWQwOTdhZWVkZDQNCkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vanNvbg0KDQp7ImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm5hbWUiOiJjdXN0b21lci1lbmNyeXB0aW9uIn0KDQotLTQ4YzhlN2RhM2Y2YjdmNGU4ZGNjMjU4ZjZlZjNjNGM3ZGU5NTQ3Y2Y0MjM1YWE3YzJlZDA5N2FlZWRkNA0KQ29udGVudC1UeXBlOiB0ZXh0L3BsYWluOyBjaGFyc2V0PXV0Zi04DQoNCnRvcCBzZWNyZXQuDQotLTQ4YzhlN2RhM2Y2YjdmNGU4ZGNjMjU4ZjZlZjNjNGM3ZGU5NTQ3Y2Y0MjM1YWE3YzJlZDA5N2FlZWRkNC0tDQo="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3575"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:36 GMT"
+ ],
+ "Etag": [
+ "CP+9neCW290CEAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051375000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrdv17:4351,/bns/yv/borg/yv/bns/blobstore2/bitpusher/17.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=A8ysW4qiJ8XJswaz7rjgBA"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/17.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/17:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWUs4TEVnZzc0SE1jc2k2MENjN2doVUNwYXhuZlplOGJXWW1xSDdtR3h4UFFoVFo0OHVKNE9hSzBMbmltRms1bTFKRGNYOS1VS2FNNzlNaDNKNnRzb0JmVGt2MkxxTEJtM1RXMVJ2RGFiQTV6VlV1VHJUR2xMMTZlVjRNWG5oZGxDbEZMQmZtcWNvZU9CVzlDNkUwemVWVDUtTXFsU29OTUtsaG5iOGdlanREQW55QkZNWUVTb3pIa1kwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_single_post_uploads"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UqzvI3XEU4LsqPtTfuuCmlZUYL5YtpZotdBHPMzeBjObeeIK9wicxApkA1uLnmxXHG3wXe79KGzi_z0-7UOlOA8R7dfcQ"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jdXN0b21lci1lbmNyeXB0aW9uLzE1MzgwNTEwNzU5NTY0NzkiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9jdXN0b21lci1lbmNyeXB0aW9uIiwibmFtZSI6ImN1c3RvbWVyLWVuY3J5cHRpb24iLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA3NTk1NjQ3OSIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOCIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDozNS45NTZaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MzUuOTU2WiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjM1Ljk1NloiLCJzaXplIjoiMTEiLCJtZDVIYXNoIjoieHdXTkZhMFZkWFBtbEF3cmxjQUpjZz09IiwibWVkaWFMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vZG93bmxvYWQvc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2N1c3RvbWVyLWVuY3J5cHRpb24/Z2VuZXJhdGlvbj0xNTM4MDUxMDc1OTU2NDc5JmFsdD1tZWRpYSIsImFjbCI6W3sia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2N1c3RvbWVyLWVuY3J5cHRpb24vMTUzODA1MTA3NTk1NjQ3OS9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2N1c3RvbWVyLWVuY3J5cHRpb24vYWNsL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiY3VzdG9tZXItZW5jcnlwdGlvbiIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDc1OTU2NDc5IiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDUCs5bmVDVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvY3VzdG9tZXItZW5jcnlwdGlvbi8xNTM4MDUxMDc1OTU2NDc5L3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2N1c3RvbWVyLWVuY3J5cHRpb24vYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6ImN1c3RvbWVyLWVuY3J5cHRpb24iLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA3NTk1NjQ3OSIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDUCs5bmVDVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvY3VzdG9tZXItZW5jcnlwdGlvbi8xNTM4MDUxMDc1OTU2NDc5L3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2N1c3RvbWVyLWVuY3J5cHRpb24vYWNsL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6ImN1c3RvbWVyLWVuY3J5cHRpb24iLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA3NTk1NjQ3OSIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ1ArOW5lQ1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2N1c3RvbWVyLWVuY3J5cHRpb24vMTUzODA1MTA3NTk1NjQ3OS91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vY3VzdG9tZXItZW5jcnlwdGlvbi9hY2wvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6ImN1c3RvbWVyLWVuY3J5cHRpb24iLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA3NTk1NjQ3OSIsImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJyb2xlIjoiT1dORVIiLCJlbWFpbCI6IjM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiZXRhZyI6IkNQKzluZUNXMjkwQ0VBRT0ifV0sIm93bmVyIjp7ImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20ifSwiY3JjMzJjIjoicjBOR3JnPT0iLCJldGFnIjoiQ1ArOW5lQ1cyOTBDRUFFPSIsImN1c3RvbWVyRW5jcnlwdGlvbiI6eyJlbmNyeXB0aW9uQWxnb3JpdGhtIjoiQUVTMjU2Iiwia2V5U2hhMjU2IjoiSCtMbW5YaFJvZUk2VE1XNWJzVjZIeVVrNnB5R2MySU1icVliQVhCY3BzMD0ifX0="
+ }
+ },
+ {
+ "ID": "27279c404174cd0f",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/customer-encryption?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "2541c367ad31712ca166ba1982148194/1077403344462145933;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/customer-encryption?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3518"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:36 GMT"
+ ],
+ "Etag": [
+ "CP+9neCW290CEAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051376000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrd2:4398,/bns/yv/borg/yv/bns/blobstore2/bitpusher/289.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=BMysW4rOC4b-gQTynLpY"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/289.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/289:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRWUs4TEVnZzc0SE1jc2k2MENjN2doVUNwYXhuZlplOGJXWW1xSDdtR3h4UFFoVFo0OHVKNE9hSzBMbmltRms1bTFKRGNYOS1VS2FNNzlNaDNKNnRzb0JmVGt2MkxxTEJtM1RXMVJ2RGFiQTV6VlV1VHJUR2xMMTZlVjRNWG5oZGxDbEZMQmZtcWNvZU9CVzlDNkUwemVWVDUtTXFsU29OTUtsaG5iOGdlanREQW55QkZNWUVTb3pIa1kwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UobHr4iNFO6-9r3IkOShNUf7Rv82BaZMVlrnByS60R0XqB5gy7QwJuuI674ibIkITsLByBS3t5I3kadR6J7CZ03HgwNTQ"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jdXN0b21lci1lbmNyeXB0aW9uLzE1MzgwNTEwNzU5NTY0NzkiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9jdXN0b21lci1lbmNyeXB0aW9uIiwibmFtZSI6ImN1c3RvbWVyLWVuY3J5cHRpb24iLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA3NTk1NjQ3OSIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOCIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDozNS45NTZaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MzUuOTU2WiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjM1Ljk1NloiLCJzaXplIjoiMTEiLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vY3VzdG9tZXItZW5jcnlwdGlvbj9nZW5lcmF0aW9uPTE1MzgwNTEwNzU5NTY0NzkmYWx0PW1lZGlhIiwiYWNsIjpbeyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvY3VzdG9tZXItZW5jcnlwdGlvbi8xNTM4MDUxMDc1OTU2NDc5L3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vY3VzdG9tZXItZW5jcnlwdGlvbi9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJjdXN0b21lci1lbmNyeXB0aW9uIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNzU5NTY0NzkiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNQKzluZUNXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jdXN0b21lci1lbmNyeXB0aW9uLzE1MzgwNTEwNzU5NTY0NzkvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vY3VzdG9tZXItZW5jcnlwdGlvbi9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiY3VzdG9tZXItZW5jcnlwdGlvbiIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDc1OTU2NDc5IiwiZW50aXR5IjoicHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6ImVkaXRvcnMifSwiZXRhZyI6IkNQKzluZUNXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jdXN0b21lci1lbmNyeXB0aW9uLzE1MzgwNTEwNzU5NTY0NzkvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vY3VzdG9tZXItZW5jcnlwdGlvbi9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiY3VzdG9tZXItZW5jcnlwdGlvbiIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDc1OTU2NDc5IiwiZW50aXR5IjoicHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6IlJFQURFUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJ2aWV3ZXJzIn0sImV0YWciOiJDUCs5bmVDVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvY3VzdG9tZXItZW5jcnlwdGlvbi8xNTM4MDUxMDc1OTU2NDc5L3VzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9jdXN0b21lci1lbmNyeXB0aW9uL2FjbC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiY3VzdG9tZXItZW5jcnlwdGlvbiIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDc1OTU2NDc5IiwiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInJvbGUiOiJPV05FUiIsImVtYWlsIjoiMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJldGFnIjoiQ1ArOW5lQ1cyOTBDRUFFPSJ9XSwib3duZXIiOnsiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSJ9LCJldGFnIjoiQ1ArOW5lQ1cyOTBDRUFFPSIsImN1c3RvbWVyRW5jcnlwdGlvbiI6eyJlbmNyeXB0aW9uQWxnb3JpdGhtIjoiQUVTMjU2Iiwia2V5U2hhMjU2IjoiSCtMbW5YaFJvZUk2VE1XNWJzVjZIeVVrNnB5R2MySU1icVliQVhCY3BzMD0ifX0="
+ }
+ },
+ {
+ "ID": "9682ead127083c80",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/customer-encryption?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "2a7f95940036c65e3640342fae7c93c4/2595758754002996780;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/customer-encryption?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ],
+ "X-Goog-Encryption-Algorithm": [
+ "AES256"
+ ],
+ "X-Goog-Encryption-Key": [
+ "REDACTED"
+ ],
+ "X-Goog-Encryption-Key-Sha256": [
+ "H+LmnXhRoeI6TMW5bsV6HyUk6pyGc2IMbqYbAXBcps0="
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3575"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:36 GMT"
+ ],
+ "Etag": [
+ "CP+9neCW290CEAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051376000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrlj28:4249,/bns/yv/borg/yv/bns/blobstore2/bitpusher/301.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=BMysW9z8D8aPgQTXw4nIBw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/301.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/301:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRWUs4TEVnZzc0SE1jc2k2MENjN2doVUNwYXhuZlplOGJXWW1xSDdtR3h4UFFoVFo0OHVKNE9hSzBMbmltRms1bTFKRGNYOS1VS2FNNzlNaDNKNnRzb0JmVGt2MkxxTEJtM1RXMVJ2RGFiQTV6VlV1VHJUR2xMMTZlVjRNWG5oZGxDbEZMQmZtcWNvZU9CVzlDNkUwemVWVDUtTXFsU29OTUtsaG5iOGdlanREQW55QkZNWUVTb3pIa1kwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Urk5p961WUKAYqlreEga30c6yCAbsJOf9uK54oZVhHgQWkBTEaU0MOuITSi7FEkYeMOcd1opYywE1gTpHfv04nDNAA7bQ"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jdXN0b21lci1lbmNyeXB0aW9uLzE1MzgwNTEwNzU5NTY0NzkiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9jdXN0b21lci1lbmNyeXB0aW9uIiwibmFtZSI6ImN1c3RvbWVyLWVuY3J5cHRpb24iLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA3NTk1NjQ3OSIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOCIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDozNS45NTZaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MzUuOTU2WiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjM1Ljk1NloiLCJzaXplIjoiMTEiLCJtZDVIYXNoIjoieHdXTkZhMFZkWFBtbEF3cmxjQUpjZz09IiwibWVkaWFMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vZG93bmxvYWQvc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2N1c3RvbWVyLWVuY3J5cHRpb24/Z2VuZXJhdGlvbj0xNTM4MDUxMDc1OTU2NDc5JmFsdD1tZWRpYSIsImFjbCI6W3sia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2N1c3RvbWVyLWVuY3J5cHRpb24vMTUzODA1MTA3NTk1NjQ3OS9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2N1c3RvbWVyLWVuY3J5cHRpb24vYWNsL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiY3VzdG9tZXItZW5jcnlwdGlvbiIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDc1OTU2NDc5IiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDUCs5bmVDVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvY3VzdG9tZXItZW5jcnlwdGlvbi8xNTM4MDUxMDc1OTU2NDc5L3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2N1c3RvbWVyLWVuY3J5cHRpb24vYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6ImN1c3RvbWVyLWVuY3J5cHRpb24iLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA3NTk1NjQ3OSIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDUCs5bmVDVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvY3VzdG9tZXItZW5jcnlwdGlvbi8xNTM4MDUxMDc1OTU2NDc5L3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2N1c3RvbWVyLWVuY3J5cHRpb24vYWNsL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6ImN1c3RvbWVyLWVuY3J5cHRpb24iLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA3NTk1NjQ3OSIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ1ArOW5lQ1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2N1c3RvbWVyLWVuY3J5cHRpb24vMTUzODA1MTA3NTk1NjQ3OS91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vY3VzdG9tZXItZW5jcnlwdGlvbi9hY2wvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6ImN1c3RvbWVyLWVuY3J5cHRpb24iLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA3NTk1NjQ3OSIsImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJyb2xlIjoiT1dORVIiLCJlbWFpbCI6IjM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiZXRhZyI6IkNQKzluZUNXMjkwQ0VBRT0ifV0sIm93bmVyIjp7ImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20ifSwiY3JjMzJjIjoicjBOR3JnPT0iLCJldGFnIjoiQ1ArOW5lQ1cyOTBDRUFFPSIsImN1c3RvbWVyRW5jcnlwdGlvbiI6eyJlbmNyeXB0aW9uQWxnb3JpdGhtIjoiQUVTMjU2Iiwia2V5U2hhMjU2IjoiSCtMbW5YaFJvZUk2VE1XNWJzVjZIeVVrNnB5R2MySU1icVliQVhCY3BzMD0ifX0="
+ }
+ },
+ {
+ "ID": "54252acc3c2342bf",
+ "Request": {
+ "Method": "PATCH",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/customer-encryption?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "85"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "4952355c1972efdbeeb6168001442c8d/4185888087876777163;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/customer-encryption?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJjb250ZW50TGFuZ3VhZ2UiOiJlbiJ9Cg=="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3541"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:36 GMT"
+ ],
+ "Etag": [
+ "CP+9neCW290CEAI="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051376000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrlm74:4305,/bns/yw/borg/yw/bns/blobstore2/bitpusher/206.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=BMysW7COFIzohASsnZDICw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yw/borg/yw/bns/blobstore2/bitpusher/206.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yw/borg/yw/bns/blobstore2/bitpusher/206:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATpxChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4CtK4wESxgF5YTI5LmMuRW93QkpRWUs4TEVnZzc0SE1jc2k2MENjN2doVUNwYXhuZlplOGJXWW1xSDdtR3h4UFFoVFo0OHVKNE9hSzBMbmltRms1bTFKRGNYOS1VS2FNNzlNaDNKNnRzb0JmVGt2MkxxTEJtM1RXMVJ2RGFiQTV6VlV1VHJUR2xMMTZlVjRNWG5oZGxDbEZMQmZtcWNvZU9CVzlDNkUwemVWVDUtTXFsU29OTUtsaG5iOGdlanREQW55QkZNWUVTb3pIa1kwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UquZDDN58SJOlHG4q0ngzir-KWmWbmxlvTSDL3P_jtECyMoB_2ZDlcTEUZ7lVHBrykjtsUvSPWGdnlUnXukeMLh4jKHjw"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jdXN0b21lci1lbmNyeXB0aW9uLzE1MzgwNTEwNzU5NTY0NzkiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9jdXN0b21lci1lbmNyeXB0aW9uIiwibmFtZSI6ImN1c3RvbWVyLWVuY3J5cHRpb24iLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA3NTk1NjQ3OSIsIm1ldGFnZW5lcmF0aW9uIjoiMiIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOCIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDozNS45NTZaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MzYuMzk5WiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjM1Ljk1NloiLCJzaXplIjoiMTEiLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vY3VzdG9tZXItZW5jcnlwdGlvbj9nZW5lcmF0aW9uPTE1MzgwNTEwNzU5NTY0NzkmYWx0PW1lZGlhIiwiY29udGVudExhbmd1YWdlIjoiZW4iLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jdXN0b21lci1lbmNyeXB0aW9uLzE1MzgwNTEwNzU5NTY0NzkvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9jdXN0b21lci1lbmNyeXB0aW9uL2FjbC9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6ImN1c3RvbWVyLWVuY3J5cHRpb24iLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA3NTk1NjQ3OSIsImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6Im93bmVycyJ9LCJldGFnIjoiQ1ArOW5lQ1cyOTBDRUFJPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2N1c3RvbWVyLWVuY3J5cHRpb24vMTUzODA1MTA3NTk1NjQ3OS9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9jdXN0b21lci1lbmNyeXB0aW9uL2FjbC9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJjdXN0b21lci1lbmNyeXB0aW9uIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNzU5NTY0NzkiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ1ArOW5lQ1cyOTBDRUFJPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2N1c3RvbWVyLWVuY3J5cHRpb24vMTUzODA1MTA3NTk1NjQ3OS9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9jdXN0b21lci1lbmNyeXB0aW9uL2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJjdXN0b21lci1lbmNyeXB0aW9uIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNzU5NTY0NzkiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNQKzluZUNXMjkwQ0VBST0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jdXN0b21lci1lbmNyeXB0aW9uLzE1MzgwNTEwNzU5NTY0NzkvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2N1c3RvbWVyLWVuY3J5cHRpb24vYWNsL3VzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJjdXN0b21lci1lbmNyeXB0aW9uIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNzU5NTY0NzkiLCJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwicm9sZSI6Ik9XTkVSIiwiZW1haWwiOiIzNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImV0YWciOiJDUCs5bmVDVzI5MENFQUk9In1dLCJvd25lciI6eyJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIn0sImV0YWciOiJDUCs5bmVDVzI5MENFQUk9IiwiY3VzdG9tZXJFbmNyeXB0aW9uIjp7ImVuY3J5cHRpb25BbGdvcml0aG0iOiJBRVMyNTYiLCJrZXlTaGEyNTYiOiJIK0xtblhoUm9lSTZUTVc1YnNWNkh5VWs2cHlHYzJJTWJxWWJBWEJjcHMwPSJ9fQ=="
+ }
+ },
+ {
+ "ID": "1e4409ff71b6579d",
+ "Request": {
+ "Method": "PATCH",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/customer-encryption?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "85"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "c5ac5a686caeb5faf7bf1484a2414f90/5776299987649091945;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/customer-encryption?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ],
+ "X-Goog-Encryption-Algorithm": [
+ "AES256"
+ ],
+ "X-Goog-Encryption-Key": [
+ "REDACTED"
+ ],
+ "X-Goog-Encryption-Key-Sha256": [
+ "H+LmnXhRoeI6TMW5bsV6HyUk6pyGc2IMbqYbAXBcps0="
+ ]
+ },
+ "Body": "eyJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJjb250ZW50TGFuZ3VhZ2UiOiJlbiJ9Cg=="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3598"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:36 GMT"
+ ],
+ "Etag": [
+ "CP+9neCW290CEAM="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051376000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vru68:4179,/bns/yv/borg/yv/bns/blobstore2/bitpusher/118.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=BMysW67PH9-wggTBqo3gCg"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/118.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/118:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATpxChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4CtK4wESxgF5YTI5LmMuRW93QkpRWUs4TEVnZzc0SE1jc2k2MENjN2doVUNwYXhuZlplOGJXWW1xSDdtR3h4UFFoVFo0OHVKNE9hSzBMbmltRms1bTFKRGNYOS1VS2FNNzlNaDNKNnRzb0JmVGt2MkxxTEJtM1RXMVJ2RGFiQTV6VlV1VHJUR2xMMTZlVjRNWG5oZGxDbEZMQmZtcWNvZU9CVzlDNkUwemVWVDUtTXFsU29OTUtsaG5iOGdlanREQW55QkZNWUVTb3pIa1kwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UrPSaT_6vjBr5ZzV4WDMHPA_SSvFO-ebrb6xmFNECjX9cUZ-ZoC56VvHY8gL7uwHfUHPqeOaXwM9qnMLA0MlGHobq1-gg"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jdXN0b21lci1lbmNyeXB0aW9uLzE1MzgwNTEwNzU5NTY0NzkiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9jdXN0b21lci1lbmNyeXB0aW9uIiwibmFtZSI6ImN1c3RvbWVyLWVuY3J5cHRpb24iLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA3NTk1NjQ3OSIsIm1ldGFnZW5lcmF0aW9uIjoiMyIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOCIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDozNS45NTZaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MzYuNzQ3WiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjM1Ljk1NloiLCJzaXplIjoiMTEiLCJtZDVIYXNoIjoieHdXTkZhMFZkWFBtbEF3cmxjQUpjZz09IiwibWVkaWFMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vZG93bmxvYWQvc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2N1c3RvbWVyLWVuY3J5cHRpb24/Z2VuZXJhdGlvbj0xNTM4MDUxMDc1OTU2NDc5JmFsdD1tZWRpYSIsImNvbnRlbnRMYW5ndWFnZSI6ImVuIiwiYWNsIjpbeyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvY3VzdG9tZXItZW5jcnlwdGlvbi8xNTM4MDUxMDc1OTU2NDc5L3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vY3VzdG9tZXItZW5jcnlwdGlvbi9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJjdXN0b21lci1lbmNyeXB0aW9uIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNzU5NTY0NzkiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNQKzluZUNXMjkwQ0VBTT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jdXN0b21lci1lbmNyeXB0aW9uLzE1MzgwNTEwNzU5NTY0NzkvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vY3VzdG9tZXItZW5jcnlwdGlvbi9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiY3VzdG9tZXItZW5jcnlwdGlvbiIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDc1OTU2NDc5IiwiZW50aXR5IjoicHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6ImVkaXRvcnMifSwiZXRhZyI6IkNQKzluZUNXMjkwQ0VBTT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jdXN0b21lci1lbmNyeXB0aW9uLzE1MzgwNTEwNzU5NTY0NzkvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vY3VzdG9tZXItZW5jcnlwdGlvbi9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiY3VzdG9tZXItZW5jcnlwdGlvbiIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDc1OTU2NDc5IiwiZW50aXR5IjoicHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6IlJFQURFUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJ2aWV3ZXJzIn0sImV0YWciOiJDUCs5bmVDVzI5MENFQU09In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvY3VzdG9tZXItZW5jcnlwdGlvbi8xNTM4MDUxMDc1OTU2NDc5L3VzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9jdXN0b21lci1lbmNyeXB0aW9uL2FjbC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiY3VzdG9tZXItZW5jcnlwdGlvbiIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDc1OTU2NDc5IiwiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInJvbGUiOiJPV05FUiIsImVtYWlsIjoiMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJldGFnIjoiQ1ArOW5lQ1cyOTBDRUFNPSJ9XSwib3duZXIiOnsiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSJ9LCJjcmMzMmMiOiJyME5Hcmc9PSIsImV0YWciOiJDUCs5bmVDVzI5MENFQU09IiwiY3VzdG9tZXJFbmNyeXB0aW9uIjp7ImVuY3J5cHRpb25BbGdvcml0aG0iOiJBRVMyNTYiLCJrZXlTaGEyNTYiOiJIK0xtblhoUm9lSTZUTVc1YnNWNkh5VWs2cHlHYzJJTWJxWWJBWEJjcHMwPSJ9fQ=="
+ }
+ },
+ {
+ "ID": "1b79858ccfded5e8",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://storage.googleapis.com/go-integration-test-20180927-44630911863640-0001/customer-encryption",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "Go-http-client/1.1"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "28f1c3700c8886948e9777b86c1da2a1/7366711891699465992;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "storage.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://storage.googleapis.com/go-integration-test-20180927-44630911863640-0001/customer-encryption"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 400,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0"
+ ],
+ "Content-Length": [
+ "277"
+ ],
+ "Content-Type": [
+ "application/xml; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:36 GMT"
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:24:36 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "X-Google-Backends": [
+ "/bns/xh/borg/xh/bns/cloud-storage/prod-cloud-storage-frontend.frontend/33,/bns/xh/borg/xh/bns/blobstore2/bitpusher/17.scotty,aclgag19:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=BMysW6asNe6mswbty7iIBg"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "aclgag19:443,/bns/xh/borg/xh/bns/blobstore2/bitpusher/17.scotty,aclgag19:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/xh/borg/xh/bns/blobstore2/bitpusher/17:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBJ"
+ ],
+ "X-Guploader-Customer": [
+ "cloud-storage"
+ ],
+ "X-Guploader-Request-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Upload-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UpnPufth4dWvXWf0zY7TjZqhN75O9EPTouUOvwS7Q06UHww3586YUbdsiY8VBWkFg3YoB1n7DK1n6Xf6hJ0zAnB_lajBA"
+ ]
+ },
+ "Body": "PD94bWwgdmVyc2lvbj0nMS4wJyBlbmNvZGluZz0nVVRGLTgnPz48RXJyb3I+PENvZGU+UmVzb3VyY2VJc0VuY3J5cHRlZFdpdGhDdXN0b21lckVuY3J5cHRpb25LZXk8L0NvZGU+PE1lc3NhZ2U+VGhlIHJlc291cmNlIGlzIGVuY3J5cHRlZCB3aXRoIGEgY3VzdG9tZXIgZW5jcnlwdGlvbiBrZXkuPC9NZXNzYWdlPjxEZXRhaWxzPlRoZSByZXF1ZXN0ZWQgb2JqZWN0IGlzIGVuY3J5cHRlZCBieSBhIGN1c3RvbWVyLXN1cHBsaWVkIGVuY3J5cHRpb24ga2V5LjwvRGV0YWlscz48L0Vycm9yPg=="
+ }
+ },
+ {
+ "ID": "93cabc57ce6ec56f",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://storage.googleapis.com/go-integration-test-20180927-44630911863640-0001/customer-encryption",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "Go-http-client/1.1"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "46b21c18c1b22de8bcb7c8e6cad0fed5/8956842325084873895;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "storage.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://storage.googleapis.com/go-integration-test-20180927-44630911863640-0001/customer-encryption"
+ ],
+ "X-Goog-Encryption-Algorithm": [
+ "AES256"
+ ],
+ "X-Goog-Encryption-Key": [
+ "REDACTED"
+ ],
+ "X-Goog-Encryption-Key-Sha256": [
+ "H+LmnXhRoeI6TMW5bsV6HyUk6pyGc2IMbqYbAXBcps0="
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Accept-Ranges": [
+ "bytes"
+ ],
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Language": [
+ "en"
+ ],
+ "Content-Length": [
+ "11"
+ ],
+ "Content-Type": [
+ "text/plain; charset=utf-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:36 GMT"
+ ],
+ "Etag": [
+ "\"-CP+9neCW290CEAM=\""
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Last-Modified": [
+ "Thu, 27 Sep 2018 12:24:35 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "X-Goog-Encryption-Algorithm": [
+ "AES256"
+ ],
+ "X-Goog-Encryption-Key-Sha256": [
+ "H+LmnXhRoeI6TMW5bsV6HyUk6pyGc2IMbqYbAXBcps0="
+ ],
+ "X-Goog-Expiration": [
+ "Sat, 27 Oct 2018 12:24:35 GMT"
+ ],
+ "X-Goog-Generation": [
+ "1538051075956479"
+ ],
+ "X-Goog-Hash": [
+ "crc32c=r0NGrg==",
+ "md5=xwWNFa0VdXPmlAwrlcAJcg=="
+ ],
+ "X-Goog-Metageneration": [
+ "3"
+ ],
+ "X-Goog-Storage-Class": [
+ "STANDARD"
+ ],
+ "X-Goog-Stored-Content-Encoding": [
+ "identity"
+ ],
+ "X-Goog-Stored-Content-Length": [
+ "11"
+ ],
+ "X-Google-Backends": [
+ "/bns/xh/borg/xh/bns/cloud-storage/prod-cloud-storage-frontend.frontend/45,/bns/xh/borg/xh/bns/blobstore2/bitpusher/15.scotty,aclgag19:443"
+ ],
+ "X-Google-Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=BMysW_qrOOShswbYw67IAw"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "aclgag19:443,/bns/xh/borg/xh/bns/blobstore2/bitpusher/15.scotty,aclgag19:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/xh/borg/xh/bns/blobstore2/bitpusher/15:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBJ"
+ ],
+ "X-Google-Storage-Location": [
+ "US"
+ ],
+ "X-Guploader-Customer": [
+ "cloud-storage"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Upxs5C49MvrZj6aa9oojSto4f-3W7bgZwh4NhcGuxb2573bjz2bjoHbVnCmMJFeX12t4lCearSUmPPgKbZ5YlE7wCjeOQ"
+ ]
+ },
+ "Body": "dG9wIHNlY3JldC4="
+ }
+ },
+ {
+ "ID": "61df6bb6e1b0ad73",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/customer-encryption/rewriteTo/b/go-integration-test-20180927-44630911863640-0001/o/customer-encryption-2?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "3"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "d4b09a52787ac8818e2cfd1ddf37a52d/10547254229135313477;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/customer-encryption/rewriteTo/b/go-integration-test-20180927-44630911863640-0001/o/customer-encryption-2?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "e30K"
+ },
+ "Response": {
+ "StatusCode": 400,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Content-Length": [
+ "14271"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:37 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051377000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vno63:4474,/bns/yx/borg/yx/bns/blobstore2/bitpusher/70.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=BcysW6euAYTbzAKpmb-YBw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yx/borg/yx/bns/blobstore2/bitpusher/70.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yx/borg/yx/bns/blobstore2/bitpusher/70:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp0ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4StK4wESxgF5YTI5LmMuRW93QkpRWUs4TEVnZzc0SE1jc2k2MENjN2doVUNwYXhuZlplOGJXWW1xSDdtR3h4UFFoVFo0OHVKNE9hSzBMbmltRms1bTFKRGNYOS1VS2FNNzlNaDNKNnRzb0JmVGt2MkxxTEJtM1RXMVJ2RGFiQTV6VlV1VHJUR2xMMTZlVjRNWG5oZGxDbEZMQmZtcWNvZU9CVzlDNkUwemVWVDUtTXFsU29OTUtsaG5iOGdlanREQW55QkZNWUVTb3pIa1kwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Upload-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Uqs1CpXLAmyRtjb9DQCQZQiZKmFmaJNTEtGuC4e4UDlMkZKcyFOc8R_Tee_amgXHR66SM_zYyIUaHvjAAdLWElZ3F7oyg"
+ ]
+ },
+ "Body": "eyJlcnJvciI6eyJlcnJvcnMiOlt7ImRvbWFpbiI6Imdsb2JhbCIsInJlYXNvbiI6InJlc291cmNlSXNFbmNyeXB0ZWRXaXRoQ3VzdG9tZXJFbmNyeXB0aW9uS2V5IiwibWVzc2FnZSI6IlRoZSB0YXJnZXQgb2JqZWN0IGlzIGVuY3J5cHRlZCBieSBhIGN1c3RvbWVyLXN1cHBsaWVkIGVuY3J5cHRpb24ga2V5LiIsImV4dGVuZGVkSGVscCI6Imh0dHBzOi8vY2xvdWQuZ29vZ2xlLmNvbS9zdG9yYWdlL2RvY3MvZW5jcnlwdGlvbiNjdXN0b21lci1zdXBwbGllZF9lbmNyeXB0aW9uX2tleXMiLCJkZWJ1Z0luZm8iOiJjb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6UkVTT1VSQ0VfSVNfRU5DUllQVEVEX1dJVEhfQ1VTVE9NRVJfRU5DUllQVElPTl9LRVk6IFRoZSByZXF1ZXN0ZWQgb2JqZWN0IGlzIGVuY3J5cHRlZCBieSBhIGN1c3RvbWVyLXN1cHBsaWVkIGVuY3J5cHRpb24ga2V5LlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjMwMilcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5PYmplY3RzRGVsZWdhdG9yLnJld3JpdGUoT2JqZWN0c0RlbGVnYXRvci5qYXZhOjEyNClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uUnBjUmVjZWl2ZXIubGFtYmRhJHByb2Nlc3NSZXF1ZXN0QXN5bmMkNChScGNSZWNlaXZlci5qYXZhOjIwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uQXN5bmNFeGVjdXRvci5sYW1iZGEkc3VibWl0JDAoQXN5bmNFeGVjdXRvci5qYXZhOjI3Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KENvbnRleHRSdW5uYWJsZS5qYXZhOjUwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZSQxLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozOSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NzIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozNilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRXhlY3V0b3JzJFJ1bm5hYmxlQWRhcHRlci5jYWxsKEV4ZWN1dG9ycy5qYXZhOjUxMSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRnV0dXJlVGFzay5ydW4oRnV0dXJlVGFzay5qYXZhOjI2Nilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yLnJ1bldvcmtlcihUaHJlYWRQb29sRXhlY3V0b3IuamF2YToxMTQ5KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IkV29ya2VyLnJ1bihUaHJlYWRQb29sRXhlY3V0b3IuamF2YTo2MjQpXG5cdGF0IGphdmEubGFuZy5UaHJlYWQucnVuKFRocmVhZC5qYXZhOjc0OClcbkNhdXNlZCBieTogY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb246IFRoZSByZXF1ZXN0ZWQgb2JqZWN0IGlzIGVuY3J5cHRlZCBieSBhIGN1c3RvbWVyLXN1cHBsaWVkIGVuY3J5cHRpb24ga2V5LlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5yZXdyaXRlci5QcmVwYXJlUmV3cml0ZU9wZXJhdGlvbi52YWxpZGF0ZVNvdXJjZUVuY3J5cHRpb24oUHJlcGFyZVJld3JpdGVPcGVyYXRpb24uamF2YTo2MTMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLnJld3JpdGVyLlByZXBhcmVSZXdyaXRlT3BlcmF0aW9uLnJ1bihQcmVwYXJlUmV3cml0ZU9wZXJhdGlvbi5qYXZhOjM0Milcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24ucmV3cml0ZXIuUmV3cml0ZXIucmV3cml0ZU9iamVjdEludGVybmFsKFJld3JpdGVyLmphdmE6NDA1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5yZXdyaXRlci5SZXdyaXRlci5yZXdyaXRlT2JqZWN0KFJld3JpdGVyLmphdmE6MzYzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5yZXdyaXRlci5SZXdyaXRlci5yZXdyaXRlT2JqZWN0KFJld3JpdGVyLmphdmE6MzMzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuUmV3cml0ZU9iamVjdC5yZXdyaXRlSW5Gcm9udGVuZChSZXdyaXRlT2JqZWN0LmphdmE6MzQ3KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuUmV3cml0ZU9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoUmV3cml0ZU9iamVjdC5qYXZhOjI0MClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5vYmplY3RzLlJld3JpdGVPYmplY3QuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKFJld3JpdGVPYmplY3QuamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHQuLi4gMTQgbW9yZVxuXG5jb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS5GYXVsdDogSW1tdXRhYmxlRXJyb3JEZWZpbml0aW9ue2Jhc2U9SU5WQUxJRF9WQUxVRSwgY2F0ZWdvcnk9VVNFUl9FUlJPUiwgY2F1c2U9bnVsbCwgZGVidWdJbmZvPWNvbS5nb29nbGUubmV0LnJwYzMuUnBjRXhjZXB0aW9uOiBjbG91ZC5iaWdzdG9yZS5SZXNwb25zZUNvZGUuRXJyb3JDb2RlOjpSRVNPVVJDRV9JU19FTkNSWVBURURfV0lUSF9DVVNUT01FUl9FTkNSWVBUSU9OX0tFWTogVGhlIHJlcXVlc3RlZCBvYmplY3QgaXMgZW5jcnlwdGVkIGJ5IGEgY3VzdG9tZXItc3VwcGxpZWQgZW5jcnlwdGlvbiBrZXkuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRvUnBjM0V4Y2VwdGlvbihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjEzNSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6MzAyKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLk9iamVjdHNEZWxlZ2F0b3IucmV3cml0ZShPYmplY3RzRGVsZWdhdG9yLmphdmE6MTI0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5ScGNSZWNlaXZlci5sYW1iZGEkcHJvY2Vzc1JlcXVlc3RBc3luYyQ0KFJwY1JlY2VpdmVyLmphdmE6MjAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5Bc3luY0V4ZWN1dG9yLmxhbWJkYSRzdWJtaXQkMChBc3luY0V4ZWN1dG9yLmphdmE6MjcyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoQ29udGV4dFJ1bm5hYmxlLmphdmE6NTApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlJDEucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM5KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo3Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5FeGVjdXRvcnMkUnVubmFibGVBZGFwdGVyLmNhbGwoRXhlY3V0b3JzLmphdmE6NTExKVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5GdXR1cmVUYXNrLnJ1bihGdXR1cmVUYXNrLmphdmE6MjY2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IucnVuV29ya2VyKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjExNDkpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvciRXb3JrZXIucnVuKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjYyNClcblx0YXQgamF2YS5sYW5nLlRocmVhZC5ydW4oVGhyZWFkLmphdmE6NzQ4KVxuQ2F1c2VkIGJ5OiBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbjogVGhlIHJlcXVlc3RlZCBvYmplY3QgaXMgZW5jcnlwdGVkIGJ5IGEgY3VzdG9tZXItc3VwcGxpZWQgZW5jcnlwdGlvbiBrZXkuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLnJld3JpdGVyLlByZXBhcmVSZXdyaXRlT3BlcmF0aW9uLnZhbGlkYXRlU291cmNlRW5jcnlwdGlvbihQcmVwYXJlUmV3cml0ZU9wZXJhdGlvbi5qYXZhOjYxMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24ucmV3cml0ZXIuUHJlcGFyZVJld3JpdGVPcGVyYXRpb24ucnVuKFByZXBhcmVSZXdyaXRlT3BlcmF0aW9uLmphdmE6MzQyKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5yZXdyaXRlci5SZXdyaXRlci5yZXdyaXRlT2JqZWN0SW50ZXJuYWwoUmV3cml0ZXIuamF2YTo0MDUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLnJld3JpdGVyLlJld3JpdGVyLnJld3JpdGVPYmplY3QoUmV3cml0ZXIuamF2YTozNjMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLnJld3JpdGVyLlJld3JpdGVyLnJld3JpdGVPYmplY3QoUmV3cml0ZXIuamF2YTozMzMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5SZXdyaXRlT2JqZWN0LnJld3JpdGVJbkZyb250ZW5kKFJld3JpdGVPYmplY3QuamF2YTozNDcpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5SZXdyaXRlT2JqZWN0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChSZXdyaXRlT2JqZWN0LmphdmE6MjQwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuUmV3cml0ZU9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoUmV3cml0ZU9iamVjdC5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmZyYW1ld29yay5SZXF1ZXN0SGFuZGxlci5oYW5kbGUoUmVxdWVzdEhhbmRsZXIuamF2YToyOTQpXG5cdC4uLiAxNCBtb3JlXG4sIGRvbWFpbj1nbG9iYWwsIGV4dGVuZGVkSGVscD1odHRwczovL2Nsb3VkLmdvb2dsZS5jb20vc3RvcmFnZS9kb2NzL2VuY3J5cHRpb24jY3VzdG9tZXItc3VwcGxpZWRfZW5jcnlwdGlvbl9rZXlzLCBodHRwSGVhZGVycz17fSwgaHR0cFN0YXR1cz1iYWRSZXF1ZXN0LCBpbnRlcm5hbFJlYXNvbj1SZWFzb257YXJndW1lbnRzPXt9LCBjYXVzZT1udWxsLCBjb2RlPWNsb3VkLmJpZ3N0b3JlLmFwaS5CaWdzdG9yZUVycm9yRG9tYWluLlJFU09VUkNFX0lTX0VOQ1JZUFRFRF9XSVRIX0NVU1RPTUVSX0VOQ1JZUFRJT05fS0VZLCBjcmVhdGVkQnlCYWNrZW5kPXRydWUsIGRlYnVnTWVzc2FnZT1jb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6UkVTT1VSQ0VfSVNfRU5DUllQVEVEX1dJVEhfQ1VTVE9NRVJfRU5DUllQVElPTl9LRVk6IFRoZSByZXF1ZXN0ZWQgb2JqZWN0IGlzIGVuY3J5cHRlZCBieSBhIGN1c3RvbWVyLXN1cHBsaWVkIGVuY3J5cHRpb24ga2V5LlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjMwMilcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5PYmplY3RzRGVsZWdhdG9yLnJld3JpdGUoT2JqZWN0c0RlbGVnYXRvci5qYXZhOjEyNClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uUnBjUmVjZWl2ZXIubGFtYmRhJHByb2Nlc3NSZXF1ZXN0QXN5bmMkNChScGNSZWNlaXZlci5qYXZhOjIwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uQXN5bmNFeGVjdXRvci5sYW1iZGEkc3VibWl0JDAoQXN5bmNFeGVjdXRvci5qYXZhOjI3Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KENvbnRleHRSdW5uYWJsZS5qYXZhOjUwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZSQxLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozOSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NzIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozNilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRXhlY3V0b3JzJFJ1bm5hYmxlQWRhcHRlci5jYWxsKEV4ZWN1dG9ycy5qYXZhOjUxMSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRnV0dXJlVGFzay5ydW4oRnV0dXJlVGFzay5qYXZhOjI2Nilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yLnJ1bldvcmtlcihUaHJlYWRQb29sRXhlY3V0b3IuamF2YToxMTQ5KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IkV29ya2VyLnJ1bihUaHJlYWRQb29sRXhlY3V0b3IuamF2YTo2MjQpXG5cdGF0IGphdmEubGFuZy5UaHJlYWQucnVuKFRocmVhZC5qYXZhOjc0OClcbkNhdXNlZCBieTogY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb246IFRoZSByZXF1ZXN0ZWQgb2JqZWN0IGlzIGVuY3J5cHRlZCBieSBhIGN1c3RvbWVyLXN1cHBsaWVkIGVuY3J5cHRpb24ga2V5LlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5yZXdyaXRlci5QcmVwYXJlUmV3cml0ZU9wZXJhdGlvbi52YWxpZGF0ZVNvdXJjZUVuY3J5cHRpb24oUHJlcGFyZVJld3JpdGVPcGVyYXRpb24uamF2YTo2MTMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLnJld3JpdGVyLlByZXBhcmVSZXdyaXRlT3BlcmF0aW9uLnJ1bihQcmVwYXJlUmV3cml0ZU9wZXJhdGlvbi5qYXZhOjM0Milcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24ucmV3cml0ZXIuUmV3cml0ZXIucmV3cml0ZU9iamVjdEludGVybmFsKFJld3JpdGVyLmphdmE6NDA1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5yZXdyaXRlci5SZXdyaXRlci5yZXdyaXRlT2JqZWN0KFJld3JpdGVyLmphdmE6MzYzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5yZXdyaXRlci5SZXdyaXRlci5yZXdyaXRlT2JqZWN0KFJld3JpdGVyLmphdmE6MzMzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuUmV3cml0ZU9iamVjdC5yZXdyaXRlSW5Gcm9udGVuZChSZXdyaXRlT2JqZWN0LmphdmE6MzQ3KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuUmV3cml0ZU9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoUmV3cml0ZU9iamVjdC5qYXZhOjI0MClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5vYmplY3RzLlJld3JpdGVPYmplY3QuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKFJld3JpdGVPYmplY3QuamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHQuLi4gMTQgbW9yZVxuLCBlcnJvclByb3RvQ29kZT1SRVNPVVJDRV9JU19FTkNSWVBURURfV0lUSF9DVVNUT01FUl9FTkNSWVBUSU9OX0tFWSwgZXJyb3JQcm90b0RvbWFpbj1jbG91ZC5iaWdzdG9yZS5hcGkuQmlnc3RvcmVFcnJvckRvbWFpbiwgZmlsdGVyZWRNZXNzYWdlPW51bGwsIGxvY2F0aW9uPW51bGwsIG1lc3NhZ2U9bnVsbCwgdW5uYW1lZEFyZ3VtZW50cz1bXX0sIGxvY2F0aW9uPW51bGwsIG1lc3NhZ2U9VGhlIHRhcmdldCBvYmplY3QgaXMgZW5jcnlwdGVkIGJ5IGEgY3VzdG9tZXItc3VwcGxpZWQgZW5jcnlwdGlvbiBrZXkuLCByZWFzb249cmVzb3VyY2VJc0VuY3J5cHRlZFdpdGhDdXN0b21lckVuY3J5cHRpb25LZXksIHJwY0NvZGU9NDAwfSBUaGUgdGFyZ2V0IG9iamVjdCBpcyBlbmNyeXB0ZWQgYnkgYSBjdXN0b21lci1zdXBwbGllZCBlbmNyeXB0aW9uIGtleS46IGNvbS5nb29nbGUubmV0LnJwYzMuUnBjRXhjZXB0aW9uOiBjbG91ZC5iaWdzdG9yZS5SZXNwb25zZUNvZGUuRXJyb3JDb2RlOjpSRVNPVVJDRV9JU19FTkNSWVBURURfV0lUSF9DVVNUT01FUl9FTkNSWVBUSU9OX0tFWTogVGhlIHJlcXVlc3RlZCBvYmplY3QgaXMgZW5jcnlwdGVkIGJ5IGEgY3VzdG9tZXItc3VwcGxpZWQgZW5jcnlwdGlvbiBrZXkuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRvUnBjM0V4Y2VwdGlvbihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjEzNSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6MzAyKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLk9iamVjdHNEZWxlZ2F0b3IucmV3cml0ZShPYmplY3RzRGVsZWdhdG9yLmphdmE6MTI0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5ScGNSZWNlaXZlci5sYW1iZGEkcHJvY2Vzc1JlcXVlc3RBc3luYyQ0KFJwY1JlY2VpdmVyLmphdmE6MjAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5Bc3luY0V4ZWN1dG9yLmxhbWJkYSRzdWJtaXQkMChBc3luY0V4ZWN1dG9yLmphdmE6MjcyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoQ29udGV4dFJ1bm5hYmxlLmphdmE6NTApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlJDEucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM5KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo3Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5FeGVjdXRvcnMkUnVubmFibGVBZGFwdGVyLmNhbGwoRXhlY3V0b3JzLmphdmE6NTExKVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5GdXR1cmVUYXNrLnJ1bihGdXR1cmVUYXNrLmphdmE6MjY2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IucnVuV29ya2VyKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjExNDkpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvciRXb3JrZXIucnVuKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjYyNClcblx0YXQgamF2YS5sYW5nLlRocmVhZC5ydW4oVGhyZWFkLmphdmE6NzQ4KVxuQ2F1c2VkIGJ5OiBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbjogVGhlIHJlcXVlc3RlZCBvYmplY3QgaXMgZW5jcnlwdGVkIGJ5IGEgY3VzdG9tZXItc3VwcGxpZWQgZW5jcnlwdGlvbiBrZXkuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLnJld3JpdGVyLlByZXBhcmVSZXdyaXRlT3BlcmF0aW9uLnZhbGlkYXRlU291cmNlRW5jcnlwdGlvbihQcmVwYXJlUmV3cml0ZU9wZXJhdGlvbi5qYXZhOjYxMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24ucmV3cml0ZXIuUHJlcGFyZVJld3JpdGVPcGVyYXRpb24ucnVuKFByZXBhcmVSZXdyaXRlT3BlcmF0aW9uLmphdmE6MzQyKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5yZXdyaXRlci5SZXdyaXRlci5yZXdyaXRlT2JqZWN0SW50ZXJuYWwoUmV3cml0ZXIuamF2YTo0MDUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLnJld3JpdGVyLlJld3JpdGVyLnJld3JpdGVPYmplY3QoUmV3cml0ZXIuamF2YTozNjMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLnJld3JpdGVyLlJld3JpdGVyLnJld3JpdGVPYmplY3QoUmV3cml0ZXIuamF2YTozMzMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5SZXdyaXRlT2JqZWN0LnJld3JpdGVJbkZyb250ZW5kKFJld3JpdGVPYmplY3QuamF2YTozNDcpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5SZXdyaXRlT2JqZWN0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChSZXdyaXRlT2JqZWN0LmphdmE6MjQwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuUmV3cml0ZU9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoUmV3cml0ZU9iamVjdC5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmZyYW1ld29yay5SZXF1ZXN0SGFuZGxlci5oYW5kbGUoUmVxdWVzdEhhbmRsZXIuamF2YToyOTQpXG5cdC4uLiAxNCBtb3JlXG5cblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUuRXJyb3JDb2xsZWN0b3IudG9GYXVsdChFcnJvckNvbGxlY3Rvci5qYXZhOjU0KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIucmVzdC5hZGFwdGVyLnJvc3kuUm9zeUVycm9yQ29udmVydGVyLnRvRmF1bHQoUm9zeUVycm9yQ29udmVydGVyLmphdmE6NjcpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5yZXN0LmFkYXB0ZXIucm9zeS5Sb3N5SGFuZGxlciQyLmNhbGwoUm9zeUhhbmRsZXIuamF2YToyNTgpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5yZXN0LmFkYXB0ZXIucm9zeS5Sb3N5SGFuZGxlciQyLmNhbGwoUm9zeUhhbmRsZXIuamF2YToyMzgpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLnV0aWwuQ2FsbGFibGVGdXR1cmUucnVuKENhbGxhYmxlRnV0dXJlLmphdmE6NjIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5EaXJlY3RFeGVjdXRvci5leGVjdXRlKERpcmVjdEV4ZWN1dG9yLmphdmE6MzApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5leGVjdXRlTGlzdGVuZXIoQWJzdHJhY3RGdXR1cmUuamF2YToxMTQzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuY29tcGxldGUoQWJzdHJhY3RGdXR1cmUuamF2YTo5NjMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5zZXQoQWJzdHJhY3RGdXR1cmUuamF2YTo3MzEpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLnV0aWwuQ2FsbGFibGVGdXR1cmUucnVuKENhbGxhYmxlRnV0dXJlLmphdmE6NjIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5EaXJlY3RFeGVjdXRvci5leGVjdXRlKERpcmVjdEV4ZWN1dG9yLmphdmE6MzApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5leGVjdXRlTGlzdGVuZXIoQWJzdHJhY3RGdXR1cmUuamF2YToxMTQzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuY29tcGxldGUoQWJzdHJhY3RGdXR1cmUuamF2YTo5NjMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5zZXQoQWJzdHJhY3RGdXR1cmUuamF2YTo3MzEpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLnV0aWwuQ2FsbGFibGVGdXR1cmUucnVuKENhbGxhYmxlRnV0dXJlLmphdmE6NjIpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci50aHJlYWQuVGhyZWFkVHJhY2tlcnMkVGhyZWFkVHJhY2tpbmdSdW5uYWJsZS5ydW4oVGhyZWFkVHJhY2tlcnMuamF2YToxMjYpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkVHJhY2VDb250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KFRyYWNlQ29udGV4dC5qYXZhOjQ1NSlcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnNlcnZlci5Db21tb25Nb2R1bGUkQ29udGV4dENhcnJ5aW5nRXhlY3V0b3JTZXJ2aWNlJDEucnVuSW5Db250ZXh0KENvbW1vbk1vZHVsZS5qYXZhOjg0Nilcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRUcmFjZUNvbnRleHRSdW5uYWJsZSQxLnJ1bihUcmFjZUNvbnRleHQuamF2YTo0NjIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkQWJzdHJhY3RUcmFjZUNvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKFRyYWNlQ29udGV4dC5qYXZhOjMyMSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRBYnN0cmFjdFRyYWNlQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChUcmFjZUNvbnRleHQuamF2YTozMTMpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkVHJhY2VDb250ZXh0UnVubmFibGUucnVuKFRyYWNlQ29udGV4dC5qYXZhOjQ1OSlcblx0YXQgY29tLmdvb2dsZS5nc2UuaW50ZXJuYWwuRGlzcGF0Y2hRdWV1ZUltcGwkV29ya2VyVGhyZWFkLnJ1bihEaXNwYXRjaFF1ZXVlSW1wbC5qYXZhOjQwMylcbiJ9XSwiY29kZSI6NDAwLCJtZXNzYWdlIjoiVGhlIHRhcmdldCBvYmplY3QgaXMgZW5jcnlwdGVkIGJ5IGEgY3VzdG9tZXItc3VwcGxpZWQgZW5jcnlwdGlvbiBrZXkuIn19"
+ }
+ },
+ {
+ "ID": "ce84af2c6aa2d36d",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/customer-encryption/rewriteTo/b/go-integration-test-20180927-44630911863640-0001/o/customer-encryption-2?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "3"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "bea423105d717ad175861ccbc2324689/12137665029412712420;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/customer-encryption/rewriteTo/b/go-integration-test-20180927-44630911863640-0001/o/customer-encryption-2?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ],
+ "X-Goog-Copy-Source-Encryption-Algorithm": [
+ "AES256"
+ ],
+ "X-Goog-Copy-Source-Encryption-Key": [
+ "REDACTED"
+ ],
+ "X-Goog-Copy-Source-Encryption-Key-Sha256": [
+ "H+LmnXhRoeI6TMW5bsV6HyUk6pyGc2IMbqYbAXBcps0="
+ ]
+ },
+ "Body": "e30K"
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3620"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:38 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051377000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrbc184:4336,/bns/yv/borg/yv/bns/blobstore2/bitpusher/20.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=BcysW4-eE8nMgASG3IeoCQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/20.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/20:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp0ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4StK4wESxgF5YTI5LmMuRW93QkpRWUs4TEVnZzc0SE1jc2k2MENjN2doVUNwYXhuZlplOGJXWW1xSDdtR3h4UFFoVFo0OHVKNE9hSzBMbmltRms1bTFKRGNYOS1VS2FNNzlNaDNKNnRzb0JmVGt2MkxxTEJtM1RXMVJ2RGFiQTV6VlV1VHJUR2xMMTZlVjRNWG5oZGxDbEZMQmZtcWNvZU9CVzlDNkUwemVWVDUtTXFsU29OTUtsaG5iOGdlanREQW55QkZNWUVTb3pIa1kwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Upxx3BvvnZJYIHgJTz9kSp10vjMWjJtn9_uAWAKe5an6Od-3BSGt6Q6RED4-Ibtc3RC0jJPGpi0Tw_Z-wkl16heHnuLAUEsBBV_adZ79hofU-Hx2Kc"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNyZXdyaXRlUmVzcG9uc2UiLCJ0b3RhbEJ5dGVzUmV3cml0dGVuIjoiMTEiLCJvYmplY3RTaXplIjoiMTEiLCJkb25lIjp0cnVlLCJyZXNvdXJjZSI6eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jdXN0b21lci1lbmNyeXB0aW9uLTIvMTUzODA1MTA3NzgyNzk4MSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2N1c3RvbWVyLWVuY3J5cHRpb24tMiIsIm5hbWUiOiJjdXN0b21lci1lbmNyeXB0aW9uLTIiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA3NzgyNzk4MSIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOCIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDozNy44MjdaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MzcuODI3WiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjM3LjgyN1oiLCJzaXplIjoiMTEiLCJtZDVIYXNoIjoieHdXTkZhMFZkWFBtbEF3cmxjQUpjZz09IiwibWVkaWFMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vZG93bmxvYWQvc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2N1c3RvbWVyLWVuY3J5cHRpb24tMj9nZW5lcmF0aW9uPTE1MzgwNTEwNzc4Mjc5ODEmYWx0PW1lZGlhIiwiY29udGVudExhbmd1YWdlIjoiZW4iLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jdXN0b21lci1lbmNyeXB0aW9uLTIvMTUzODA1MTA3NzgyNzk4MS9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2N1c3RvbWVyLWVuY3J5cHRpb24tMi9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJjdXN0b21lci1lbmNyeXB0aW9uLTIiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA3NzgyNzk4MSIsImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6Im93bmVycyJ9LCJldGFnIjoiQ0kzYmorR1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2N1c3RvbWVyLWVuY3J5cHRpb24tMi8xNTM4MDUxMDc3ODI3OTgxL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2N1c3RvbWVyLWVuY3J5cHRpb24tMi9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiY3VzdG9tZXItZW5jcnlwdGlvbi0yIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNzc4Mjc5ODEiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0kzYmorR1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2N1c3RvbWVyLWVuY3J5cHRpb24tMi8xNTM4MDUxMDc3ODI3OTgxL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2N1c3RvbWVyLWVuY3J5cHRpb24tMi9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiY3VzdG9tZXItZW5jcnlwdGlvbi0yIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNzc4Mjc5ODEiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNJM2JqK0dXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jdXN0b21lci1lbmNyeXB0aW9uLTIvMTUzODA1MTA3NzgyNzk4MS91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vY3VzdG9tZXItZW5jcnlwdGlvbi0yL2FjbC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiY3VzdG9tZXItZW5jcnlwdGlvbi0yIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNzc4Mjc5ODEiLCJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwicm9sZSI6Ik9XTkVSIiwiZW1haWwiOiIzNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImV0YWciOiJDSTNiaitHVzI5MENFQUU9In1dLCJvd25lciI6eyJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIn0sImNyYzMyYyI6InIwTkdyZz09IiwiZXRhZyI6IkNJM2JqK0dXMjkwQ0VBRT0ifX0="
+ }
+ },
+ {
+ "ID": "a999df3690b6e237",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://storage.googleapis.com/go-integration-test-20180927-44630911863640-0001/customer-encryption-2",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "Go-http-client/1.1"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "1705b1e6484692b737affea080b35228/13728076933463086467;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "storage.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://storage.googleapis.com/go-integration-test-20180927-44630911863640-0001/customer-encryption-2"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Accept-Ranges": [
+ "bytes"
+ ],
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0"
+ ],
+ "Content-Language": [
+ "en"
+ ],
+ "Content-Length": [
+ "11"
+ ],
+ "Content-Type": [
+ "text/plain; charset=utf-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:38 GMT"
+ ],
+ "Etag": [
+ "\"c7058d15ad157573e6940c2b95c00972\""
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:24:38 GMT"
+ ],
+ "Last-Modified": [
+ "Thu, 27 Sep 2018 12:24:37 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "X-Goog-Expiration": [
+ "Sat, 27 Oct 2018 12:24:37 GMT"
+ ],
+ "X-Goog-Generation": [
+ "1538051077827981"
+ ],
+ "X-Goog-Hash": [
+ "crc32c=r0NGrg==",
+ "md5=xwWNFa0VdXPmlAwrlcAJcg=="
+ ],
+ "X-Goog-Metageneration": [
+ "1"
+ ],
+ "X-Goog-Storage-Class": [
+ "STANDARD"
+ ],
+ "X-Goog-Stored-Content-Encoding": [
+ "identity"
+ ],
+ "X-Goog-Stored-Content-Length": [
+ "11"
+ ],
+ "X-Google-Backends": [
+ "/bns/xh/borg/xh/bns/cloud-storage/prod-cloud-storage-frontend.frontend/28,/bns/xh/borg/xh/bns/blobstore2/bitpusher/8.scotty,aclgag19:443"
+ ],
+ "X-Google-Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=BsysW8LLA--pswargaYo"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "aclgag19:443,/bns/xh/borg/xh/bns/blobstore2/bitpusher/8.scotty,aclgag19:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/xh/borg/xh/bns/blobstore2/bitpusher/8:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBJ"
+ ],
+ "X-Google-Storage-Location": [
+ "US"
+ ],
+ "X-Guploader-Customer": [
+ "cloud-storage"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Uq1CdxdvfAVgPz36drluRR3XOAVGxbcXHZLLuNRWrH_TRabeapqxPWBPlHbXA-EGVnBdA358uiErdYzW3U0Wz14YviqaA"
+ ]
+ },
+ "Body": "dG9wIHNlY3JldC4="
+ }
+ },
+ {
+ "ID": "61481b2562659560",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/customer-encryption/rewriteTo/b/go-integration-test-20180927-44630911863640-0001/o/customer-encryption-2?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "3"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "c8dad96b48876570d28a024bb8a5820f/15318207366848559649;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/customer-encryption/rewriteTo/b/go-integration-test-20180927-44630911863640-0001/o/customer-encryption-2?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ],
+ "X-Goog-Encryption-Algorithm": [
+ "AES256"
+ ],
+ "X-Goog-Encryption-Key": [
+ "REDACTED"
+ ],
+ "X-Goog-Encryption-Key-Sha256": [
+ "FnBvfQ1dDsyS8kHD+aB6HHIglDoQ5Im7WYDm3XYTGrQ="
+ ]
+ },
+ "Body": "e30K"
+ },
+ "Response": {
+ "StatusCode": 400,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Content-Length": [
+ "14271"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:38 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051377000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrng11:4017,/bns/yr/borg/yr/bns/blobstore2/bitpusher/28.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=BsysW-27CaiWkATJhbDgBQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/28.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/28:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp0ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4StK4wESxgF5YTI5LmMuRW93QkpRWUs4TEVnZzc0SE1jc2k2MENjN2doVUNwYXhuZlplOGJXWW1xSDdtR3h4UFFoVFo0OHVKNE9hSzBMbmltRms1bTFKRGNYOS1VS2FNNzlNaDNKNnRzb0JmVGt2MkxxTEJtM1RXMVJ2RGFiQTV6VlV1VHJUR2xMMTZlVjRNWG5oZGxDbEZMQmZtcWNvZU9CVzlDNkUwemVWVDUtTXFsU29OTUtsaG5iOGdlanREQW55QkZNWUVTb3pIa1kwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Upload-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UqLzeVXHyiNFMW3buLUpS_VSAbJU_2CwoEyGNKNBA8qGutAt-VmjsPfYO7yYHUxzQBVn4BYg5g-gG5rKWvp_qn1-N_rlQ"
+ ]
+ },
+ "Body": "eyJlcnJvciI6eyJlcnJvcnMiOlt7ImRvbWFpbiI6Imdsb2JhbCIsInJlYXNvbiI6InJlc291cmNlSXNFbmNyeXB0ZWRXaXRoQ3VzdG9tZXJFbmNyeXB0aW9uS2V5IiwibWVzc2FnZSI6IlRoZSB0YXJnZXQgb2JqZWN0IGlzIGVuY3J5cHRlZCBieSBhIGN1c3RvbWVyLXN1cHBsaWVkIGVuY3J5cHRpb24ga2V5LiIsImV4dGVuZGVkSGVscCI6Imh0dHBzOi8vY2xvdWQuZ29vZ2xlLmNvbS9zdG9yYWdlL2RvY3MvZW5jcnlwdGlvbiNjdXN0b21lci1zdXBwbGllZF9lbmNyeXB0aW9uX2tleXMiLCJkZWJ1Z0luZm8iOiJjb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6UkVTT1VSQ0VfSVNfRU5DUllQVEVEX1dJVEhfQ1VTVE9NRVJfRU5DUllQVElPTl9LRVk6IFRoZSByZXF1ZXN0ZWQgb2JqZWN0IGlzIGVuY3J5cHRlZCBieSBhIGN1c3RvbWVyLXN1cHBsaWVkIGVuY3J5cHRpb24ga2V5LlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjMwMilcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5PYmplY3RzRGVsZWdhdG9yLnJld3JpdGUoT2JqZWN0c0RlbGVnYXRvci5qYXZhOjEyNClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uUnBjUmVjZWl2ZXIubGFtYmRhJHByb2Nlc3NSZXF1ZXN0QXN5bmMkNChScGNSZWNlaXZlci5qYXZhOjIwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uQXN5bmNFeGVjdXRvci5sYW1iZGEkc3VibWl0JDAoQXN5bmNFeGVjdXRvci5qYXZhOjI3Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KENvbnRleHRSdW5uYWJsZS5qYXZhOjUwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZSQxLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozOSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NzIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozNilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRXhlY3V0b3JzJFJ1bm5hYmxlQWRhcHRlci5jYWxsKEV4ZWN1dG9ycy5qYXZhOjUxMSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRnV0dXJlVGFzay5ydW4oRnV0dXJlVGFzay5qYXZhOjI2Nilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yLnJ1bldvcmtlcihUaHJlYWRQb29sRXhlY3V0b3IuamF2YToxMTQ5KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IkV29ya2VyLnJ1bihUaHJlYWRQb29sRXhlY3V0b3IuamF2YTo2MjQpXG5cdGF0IGphdmEubGFuZy5UaHJlYWQucnVuKFRocmVhZC5qYXZhOjc0OClcbkNhdXNlZCBieTogY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb246IFRoZSByZXF1ZXN0ZWQgb2JqZWN0IGlzIGVuY3J5cHRlZCBieSBhIGN1c3RvbWVyLXN1cHBsaWVkIGVuY3J5cHRpb24ga2V5LlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5yZXdyaXRlci5QcmVwYXJlUmV3cml0ZU9wZXJhdGlvbi52YWxpZGF0ZVNvdXJjZUVuY3J5cHRpb24oUHJlcGFyZVJld3JpdGVPcGVyYXRpb24uamF2YTo2MTMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLnJld3JpdGVyLlByZXBhcmVSZXdyaXRlT3BlcmF0aW9uLnJ1bihQcmVwYXJlUmV3cml0ZU9wZXJhdGlvbi5qYXZhOjM0Milcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24ucmV3cml0ZXIuUmV3cml0ZXIucmV3cml0ZU9iamVjdEludGVybmFsKFJld3JpdGVyLmphdmE6NDA1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5yZXdyaXRlci5SZXdyaXRlci5yZXdyaXRlT2JqZWN0KFJld3JpdGVyLmphdmE6MzYzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5yZXdyaXRlci5SZXdyaXRlci5yZXdyaXRlT2JqZWN0KFJld3JpdGVyLmphdmE6MzMzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuUmV3cml0ZU9iamVjdC5yZXdyaXRlSW5Gcm9udGVuZChSZXdyaXRlT2JqZWN0LmphdmE6MzQ3KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuUmV3cml0ZU9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoUmV3cml0ZU9iamVjdC5qYXZhOjI0MClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5vYmplY3RzLlJld3JpdGVPYmplY3QuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKFJld3JpdGVPYmplY3QuamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHQuLi4gMTQgbW9yZVxuXG5jb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS5GYXVsdDogSW1tdXRhYmxlRXJyb3JEZWZpbml0aW9ue2Jhc2U9SU5WQUxJRF9WQUxVRSwgY2F0ZWdvcnk9VVNFUl9FUlJPUiwgY2F1c2U9bnVsbCwgZGVidWdJbmZvPWNvbS5nb29nbGUubmV0LnJwYzMuUnBjRXhjZXB0aW9uOiBjbG91ZC5iaWdzdG9yZS5SZXNwb25zZUNvZGUuRXJyb3JDb2RlOjpSRVNPVVJDRV9JU19FTkNSWVBURURfV0lUSF9DVVNUT01FUl9FTkNSWVBUSU9OX0tFWTogVGhlIHJlcXVlc3RlZCBvYmplY3QgaXMgZW5jcnlwdGVkIGJ5IGEgY3VzdG9tZXItc3VwcGxpZWQgZW5jcnlwdGlvbiBrZXkuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRvUnBjM0V4Y2VwdGlvbihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjEzNSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6MzAyKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLk9iamVjdHNEZWxlZ2F0b3IucmV3cml0ZShPYmplY3RzRGVsZWdhdG9yLmphdmE6MTI0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5ScGNSZWNlaXZlci5sYW1iZGEkcHJvY2Vzc1JlcXVlc3RBc3luYyQ0KFJwY1JlY2VpdmVyLmphdmE6MjAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5Bc3luY0V4ZWN1dG9yLmxhbWJkYSRzdWJtaXQkMChBc3luY0V4ZWN1dG9yLmphdmE6MjcyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoQ29udGV4dFJ1bm5hYmxlLmphdmE6NTApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlJDEucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM5KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo3Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5FeGVjdXRvcnMkUnVubmFibGVBZGFwdGVyLmNhbGwoRXhlY3V0b3JzLmphdmE6NTExKVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5GdXR1cmVUYXNrLnJ1bihGdXR1cmVUYXNrLmphdmE6MjY2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IucnVuV29ya2VyKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjExNDkpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvciRXb3JrZXIucnVuKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjYyNClcblx0YXQgamF2YS5sYW5nLlRocmVhZC5ydW4oVGhyZWFkLmphdmE6NzQ4KVxuQ2F1c2VkIGJ5OiBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbjogVGhlIHJlcXVlc3RlZCBvYmplY3QgaXMgZW5jcnlwdGVkIGJ5IGEgY3VzdG9tZXItc3VwcGxpZWQgZW5jcnlwdGlvbiBrZXkuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLnJld3JpdGVyLlByZXBhcmVSZXdyaXRlT3BlcmF0aW9uLnZhbGlkYXRlU291cmNlRW5jcnlwdGlvbihQcmVwYXJlUmV3cml0ZU9wZXJhdGlvbi5qYXZhOjYxMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24ucmV3cml0ZXIuUHJlcGFyZVJld3JpdGVPcGVyYXRpb24ucnVuKFByZXBhcmVSZXdyaXRlT3BlcmF0aW9uLmphdmE6MzQyKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5yZXdyaXRlci5SZXdyaXRlci5yZXdyaXRlT2JqZWN0SW50ZXJuYWwoUmV3cml0ZXIuamF2YTo0MDUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLnJld3JpdGVyLlJld3JpdGVyLnJld3JpdGVPYmplY3QoUmV3cml0ZXIuamF2YTozNjMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLnJld3JpdGVyLlJld3JpdGVyLnJld3JpdGVPYmplY3QoUmV3cml0ZXIuamF2YTozMzMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5SZXdyaXRlT2JqZWN0LnJld3JpdGVJbkZyb250ZW5kKFJld3JpdGVPYmplY3QuamF2YTozNDcpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5SZXdyaXRlT2JqZWN0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChSZXdyaXRlT2JqZWN0LmphdmE6MjQwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuUmV3cml0ZU9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoUmV3cml0ZU9iamVjdC5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmZyYW1ld29yay5SZXF1ZXN0SGFuZGxlci5oYW5kbGUoUmVxdWVzdEhhbmRsZXIuamF2YToyOTQpXG5cdC4uLiAxNCBtb3JlXG4sIGRvbWFpbj1nbG9iYWwsIGV4dGVuZGVkSGVscD1odHRwczovL2Nsb3VkLmdvb2dsZS5jb20vc3RvcmFnZS9kb2NzL2VuY3J5cHRpb24jY3VzdG9tZXItc3VwcGxpZWRfZW5jcnlwdGlvbl9rZXlzLCBodHRwSGVhZGVycz17fSwgaHR0cFN0YXR1cz1iYWRSZXF1ZXN0LCBpbnRlcm5hbFJlYXNvbj1SZWFzb257YXJndW1lbnRzPXt9LCBjYXVzZT1udWxsLCBjb2RlPWNsb3VkLmJpZ3N0b3JlLmFwaS5CaWdzdG9yZUVycm9yRG9tYWluLlJFU09VUkNFX0lTX0VOQ1JZUFRFRF9XSVRIX0NVU1RPTUVSX0VOQ1JZUFRJT05fS0VZLCBjcmVhdGVkQnlCYWNrZW5kPXRydWUsIGRlYnVnTWVzc2FnZT1jb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6UkVTT1VSQ0VfSVNfRU5DUllQVEVEX1dJVEhfQ1VTVE9NRVJfRU5DUllQVElPTl9LRVk6IFRoZSByZXF1ZXN0ZWQgb2JqZWN0IGlzIGVuY3J5cHRlZCBieSBhIGN1c3RvbWVyLXN1cHBsaWVkIGVuY3J5cHRpb24ga2V5LlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjMwMilcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5PYmplY3RzRGVsZWdhdG9yLnJld3JpdGUoT2JqZWN0c0RlbGVnYXRvci5qYXZhOjEyNClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uUnBjUmVjZWl2ZXIubGFtYmRhJHByb2Nlc3NSZXF1ZXN0QXN5bmMkNChScGNSZWNlaXZlci5qYXZhOjIwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uQXN5bmNFeGVjdXRvci5sYW1iZGEkc3VibWl0JDAoQXN5bmNFeGVjdXRvci5qYXZhOjI3Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KENvbnRleHRSdW5uYWJsZS5qYXZhOjUwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZSQxLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozOSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NzIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozNilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRXhlY3V0b3JzJFJ1bm5hYmxlQWRhcHRlci5jYWxsKEV4ZWN1dG9ycy5qYXZhOjUxMSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRnV0dXJlVGFzay5ydW4oRnV0dXJlVGFzay5qYXZhOjI2Nilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yLnJ1bldvcmtlcihUaHJlYWRQb29sRXhlY3V0b3IuamF2YToxMTQ5KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IkV29ya2VyLnJ1bihUaHJlYWRQb29sRXhlY3V0b3IuamF2YTo2MjQpXG5cdGF0IGphdmEubGFuZy5UaHJlYWQucnVuKFRocmVhZC5qYXZhOjc0OClcbkNhdXNlZCBieTogY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb246IFRoZSByZXF1ZXN0ZWQgb2JqZWN0IGlzIGVuY3J5cHRlZCBieSBhIGN1c3RvbWVyLXN1cHBsaWVkIGVuY3J5cHRpb24ga2V5LlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5yZXdyaXRlci5QcmVwYXJlUmV3cml0ZU9wZXJhdGlvbi52YWxpZGF0ZVNvdXJjZUVuY3J5cHRpb24oUHJlcGFyZVJld3JpdGVPcGVyYXRpb24uamF2YTo2MTMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLnJld3JpdGVyLlByZXBhcmVSZXdyaXRlT3BlcmF0aW9uLnJ1bihQcmVwYXJlUmV3cml0ZU9wZXJhdGlvbi5qYXZhOjM0Milcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24ucmV3cml0ZXIuUmV3cml0ZXIucmV3cml0ZU9iamVjdEludGVybmFsKFJld3JpdGVyLmphdmE6NDA1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5yZXdyaXRlci5SZXdyaXRlci5yZXdyaXRlT2JqZWN0KFJld3JpdGVyLmphdmE6MzYzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5yZXdyaXRlci5SZXdyaXRlci5yZXdyaXRlT2JqZWN0KFJld3JpdGVyLmphdmE6MzMzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuUmV3cml0ZU9iamVjdC5yZXdyaXRlSW5Gcm9udGVuZChSZXdyaXRlT2JqZWN0LmphdmE6MzQ3KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuUmV3cml0ZU9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoUmV3cml0ZU9iamVjdC5qYXZhOjI0MClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5vYmplY3RzLlJld3JpdGVPYmplY3QuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKFJld3JpdGVPYmplY3QuamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHQuLi4gMTQgbW9yZVxuLCBlcnJvclByb3RvQ29kZT1SRVNPVVJDRV9JU19FTkNSWVBURURfV0lUSF9DVVNUT01FUl9FTkNSWVBUSU9OX0tFWSwgZXJyb3JQcm90b0RvbWFpbj1jbG91ZC5iaWdzdG9yZS5hcGkuQmlnc3RvcmVFcnJvckRvbWFpbiwgZmlsdGVyZWRNZXNzYWdlPW51bGwsIGxvY2F0aW9uPW51bGwsIG1lc3NhZ2U9bnVsbCwgdW5uYW1lZEFyZ3VtZW50cz1bXX0sIGxvY2F0aW9uPW51bGwsIG1lc3NhZ2U9VGhlIHRhcmdldCBvYmplY3QgaXMgZW5jcnlwdGVkIGJ5IGEgY3VzdG9tZXItc3VwcGxpZWQgZW5jcnlwdGlvbiBrZXkuLCByZWFzb249cmVzb3VyY2VJc0VuY3J5cHRlZFdpdGhDdXN0b21lckVuY3J5cHRpb25LZXksIHJwY0NvZGU9NDAwfSBUaGUgdGFyZ2V0IG9iamVjdCBpcyBlbmNyeXB0ZWQgYnkgYSBjdXN0b21lci1zdXBwbGllZCBlbmNyeXB0aW9uIGtleS46IGNvbS5nb29nbGUubmV0LnJwYzMuUnBjRXhjZXB0aW9uOiBjbG91ZC5iaWdzdG9yZS5SZXNwb25zZUNvZGUuRXJyb3JDb2RlOjpSRVNPVVJDRV9JU19FTkNSWVBURURfV0lUSF9DVVNUT01FUl9FTkNSWVBUSU9OX0tFWTogVGhlIHJlcXVlc3RlZCBvYmplY3QgaXMgZW5jcnlwdGVkIGJ5IGEgY3VzdG9tZXItc3VwcGxpZWQgZW5jcnlwdGlvbiBrZXkuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRvUnBjM0V4Y2VwdGlvbihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjEzNSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6MzAyKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLk9iamVjdHNEZWxlZ2F0b3IucmV3cml0ZShPYmplY3RzRGVsZWdhdG9yLmphdmE6MTI0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5ScGNSZWNlaXZlci5sYW1iZGEkcHJvY2Vzc1JlcXVlc3RBc3luYyQ0KFJwY1JlY2VpdmVyLmphdmE6MjAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5Bc3luY0V4ZWN1dG9yLmxhbWJkYSRzdWJtaXQkMChBc3luY0V4ZWN1dG9yLmphdmE6MjcyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoQ29udGV4dFJ1bm5hYmxlLmphdmE6NTApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlJDEucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM5KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo3Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5FeGVjdXRvcnMkUnVubmFibGVBZGFwdGVyLmNhbGwoRXhlY3V0b3JzLmphdmE6NTExKVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5GdXR1cmVUYXNrLnJ1bihGdXR1cmVUYXNrLmphdmE6MjY2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IucnVuV29ya2VyKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjExNDkpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvciRXb3JrZXIucnVuKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjYyNClcblx0YXQgamF2YS5sYW5nLlRocmVhZC5ydW4oVGhyZWFkLmphdmE6NzQ4KVxuQ2F1c2VkIGJ5OiBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbjogVGhlIHJlcXVlc3RlZCBvYmplY3QgaXMgZW5jcnlwdGVkIGJ5IGEgY3VzdG9tZXItc3VwcGxpZWQgZW5jcnlwdGlvbiBrZXkuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLnJld3JpdGVyLlByZXBhcmVSZXdyaXRlT3BlcmF0aW9uLnZhbGlkYXRlU291cmNlRW5jcnlwdGlvbihQcmVwYXJlUmV3cml0ZU9wZXJhdGlvbi5qYXZhOjYxMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24ucmV3cml0ZXIuUHJlcGFyZVJld3JpdGVPcGVyYXRpb24ucnVuKFByZXBhcmVSZXdyaXRlT3BlcmF0aW9uLmphdmE6MzQyKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5yZXdyaXRlci5SZXdyaXRlci5yZXdyaXRlT2JqZWN0SW50ZXJuYWwoUmV3cml0ZXIuamF2YTo0MDUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLnJld3JpdGVyLlJld3JpdGVyLnJld3JpdGVPYmplY3QoUmV3cml0ZXIuamF2YTozNjMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLnJld3JpdGVyLlJld3JpdGVyLnJld3JpdGVPYmplY3QoUmV3cml0ZXIuamF2YTozMzMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5SZXdyaXRlT2JqZWN0LnJld3JpdGVJbkZyb250ZW5kKFJld3JpdGVPYmplY3QuamF2YTozNDcpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5SZXdyaXRlT2JqZWN0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChSZXdyaXRlT2JqZWN0LmphdmE6MjQwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuUmV3cml0ZU9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoUmV3cml0ZU9iamVjdC5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmZyYW1ld29yay5SZXF1ZXN0SGFuZGxlci5oYW5kbGUoUmVxdWVzdEhhbmRsZXIuamF2YToyOTQpXG5cdC4uLiAxNCBtb3JlXG5cblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUuRXJyb3JDb2xsZWN0b3IudG9GYXVsdChFcnJvckNvbGxlY3Rvci5qYXZhOjU0KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIucmVzdC5hZGFwdGVyLnJvc3kuUm9zeUVycm9yQ29udmVydGVyLnRvRmF1bHQoUm9zeUVycm9yQ29udmVydGVyLmphdmE6NjcpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5yZXN0LmFkYXB0ZXIucm9zeS5Sb3N5SGFuZGxlciQyLmNhbGwoUm9zeUhhbmRsZXIuamF2YToyNTgpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5yZXN0LmFkYXB0ZXIucm9zeS5Sb3N5SGFuZGxlciQyLmNhbGwoUm9zeUhhbmRsZXIuamF2YToyMzgpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLnV0aWwuQ2FsbGFibGVGdXR1cmUucnVuKENhbGxhYmxlRnV0dXJlLmphdmE6NjIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5EaXJlY3RFeGVjdXRvci5leGVjdXRlKERpcmVjdEV4ZWN1dG9yLmphdmE6MzApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5leGVjdXRlTGlzdGVuZXIoQWJzdHJhY3RGdXR1cmUuamF2YToxMTQzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuY29tcGxldGUoQWJzdHJhY3RGdXR1cmUuamF2YTo5NjMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5zZXQoQWJzdHJhY3RGdXR1cmUuamF2YTo3MzEpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLnV0aWwuQ2FsbGFibGVGdXR1cmUucnVuKENhbGxhYmxlRnV0dXJlLmphdmE6NjIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5EaXJlY3RFeGVjdXRvci5leGVjdXRlKERpcmVjdEV4ZWN1dG9yLmphdmE6MzApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5leGVjdXRlTGlzdGVuZXIoQWJzdHJhY3RGdXR1cmUuamF2YToxMTQzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuY29tcGxldGUoQWJzdHJhY3RGdXR1cmUuamF2YTo5NjMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5zZXQoQWJzdHJhY3RGdXR1cmUuamF2YTo3MzEpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLnV0aWwuQ2FsbGFibGVGdXR1cmUucnVuKENhbGxhYmxlRnV0dXJlLmphdmE6NjIpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci50aHJlYWQuVGhyZWFkVHJhY2tlcnMkVGhyZWFkVHJhY2tpbmdSdW5uYWJsZS5ydW4oVGhyZWFkVHJhY2tlcnMuamF2YToxMjYpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkVHJhY2VDb250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KFRyYWNlQ29udGV4dC5qYXZhOjQ1NSlcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnNlcnZlci5Db21tb25Nb2R1bGUkQ29udGV4dENhcnJ5aW5nRXhlY3V0b3JTZXJ2aWNlJDEucnVuSW5Db250ZXh0KENvbW1vbk1vZHVsZS5qYXZhOjg0Nilcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRUcmFjZUNvbnRleHRSdW5uYWJsZSQxLnJ1bihUcmFjZUNvbnRleHQuamF2YTo0NjIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkQWJzdHJhY3RUcmFjZUNvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKFRyYWNlQ29udGV4dC5qYXZhOjMyMSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRBYnN0cmFjdFRyYWNlQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChUcmFjZUNvbnRleHQuamF2YTozMTMpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkVHJhY2VDb250ZXh0UnVubmFibGUucnVuKFRyYWNlQ29udGV4dC5qYXZhOjQ1OSlcblx0YXQgY29tLmdvb2dsZS5nc2UuaW50ZXJuYWwuRGlzcGF0Y2hRdWV1ZUltcGwkV29ya2VyVGhyZWFkLnJ1bihEaXNwYXRjaFF1ZXVlSW1wbC5qYXZhOjQwMylcbiJ9XSwiY29kZSI6NDAwLCJtZXNzYWdlIjoiVGhlIHRhcmdldCBvYmplY3QgaXMgZW5jcnlwdGVkIGJ5IGEgY3VzdG9tZXItc3VwcGxpZWQgZW5jcnlwdGlvbiBrZXkuIn19"
+ }
+ },
+ {
+ "ID": "b6ec99f6d81fabb4",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/customer-encryption/rewriteTo/b/go-integration-test-20180927-44630911863640-0001/o/customer-encryption-2?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "3"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "902f8072774afaa43e582fad4756347f/16908619266604032192;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/customer-encryption/rewriteTo/b/go-integration-test-20180927-44630911863640-0001/o/customer-encryption-2?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ],
+ "X-Goog-Copy-Source-Encryption-Algorithm": [
+ "AES256"
+ ],
+ "X-Goog-Copy-Source-Encryption-Key": [
+ "REDACTED"
+ ],
+ "X-Goog-Copy-Source-Encryption-Key-Sha256": [
+ "H+LmnXhRoeI6TMW5bsV6HyUk6pyGc2IMbqYbAXBcps0="
+ ],
+ "X-Goog-Encryption-Algorithm": [
+ "AES256"
+ ],
+ "X-Goog-Encryption-Key": [
+ "REDACTED"
+ ],
+ "X-Goog-Encryption-Key-Sha256": [
+ "FnBvfQ1dDsyS8kHD+aB6HHIglDoQ5Im7WYDm3XYTGrQ="
+ ]
+ },
+ "Body": "e30K"
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3733"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:38 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051377000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vngu25:4297,/bns/yx/borg/yx/bns/blobstore2/bitpusher/103.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=BsysW9atE8-SzAKwt734Bg"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yx/borg/yx/bns/blobstore2/bitpusher/103.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yx/borg/yx/bns/blobstore2/bitpusher/103:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp0ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4StK4wESxgF5YTI5LmMuRW93QkpRWUs4TEVnZzc0SE1jc2k2MENjN2doVUNwYXhuZlplOGJXWW1xSDdtR3h4UFFoVFo0OHVKNE9hSzBMbmltRms1bTFKRGNYOS1VS2FNNzlNaDNKNnRzb0JmVGt2MkxxTEJtM1RXMVJ2RGFiQTV6VlV1VHJUR2xMMTZlVjRNWG5oZGxDbEZMQmZtcWNvZU9CVzlDNkUwemVWVDUtTXFsU29OTUtsaG5iOGdlanREQW55QkZNWUVTb3pIa1kwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UqAvNR3Fv4vliLe4057vGGJi3tYRwNVOtnOpX_n2kGwJVcvjq5HUkZ3ILlNbaiotOJX5pekim3kpy0YBBvTw1is7X9k1A"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNyZXdyaXRlUmVzcG9uc2UiLCJ0b3RhbEJ5dGVzUmV3cml0dGVuIjoiMTEiLCJvYmplY3RTaXplIjoiMTEiLCJkb25lIjp0cnVlLCJyZXNvdXJjZSI6eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jdXN0b21lci1lbmNyeXB0aW9uLTIvMTUzODA1MTA3ODgyODE1MyIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2N1c3RvbWVyLWVuY3J5cHRpb24tMiIsIm5hbWUiOiJjdXN0b21lci1lbmNyeXB0aW9uLTIiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA3ODgyODE1MyIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOCIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDozOC44MjdaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MzguODI3WiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjM4LjgyN1oiLCJzaXplIjoiMTEiLCJtZDVIYXNoIjoieHdXTkZhMFZkWFBtbEF3cmxjQUpjZz09IiwibWVkaWFMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vZG93bmxvYWQvc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2N1c3RvbWVyLWVuY3J5cHRpb24tMj9nZW5lcmF0aW9uPTE1MzgwNTEwNzg4MjgxNTMmYWx0PW1lZGlhIiwiY29udGVudExhbmd1YWdlIjoiZW4iLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jdXN0b21lci1lbmNyeXB0aW9uLTIvMTUzODA1MTA3ODgyODE1My9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2N1c3RvbWVyLWVuY3J5cHRpb24tMi9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJjdXN0b21lci1lbmNyeXB0aW9uLTIiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA3ODgyODE1MyIsImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6Im93bmVycyJ9LCJldGFnIjoiQ1BuZ3pPR1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2N1c3RvbWVyLWVuY3J5cHRpb24tMi8xNTM4MDUxMDc4ODI4MTUzL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2N1c3RvbWVyLWVuY3J5cHRpb24tMi9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiY3VzdG9tZXItZW5jcnlwdGlvbi0yIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNzg4MjgxNTMiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ1BuZ3pPR1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2N1c3RvbWVyLWVuY3J5cHRpb24tMi8xNTM4MDUxMDc4ODI4MTUzL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2N1c3RvbWVyLWVuY3J5cHRpb24tMi9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiY3VzdG9tZXItZW5jcnlwdGlvbi0yIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNzg4MjgxNTMiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNQbmd6T0dXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jdXN0b21lci1lbmNyeXB0aW9uLTIvMTUzODA1MTA3ODgyODE1My91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vY3VzdG9tZXItZW5jcnlwdGlvbi0yL2FjbC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiY3VzdG9tZXItZW5jcnlwdGlvbi0yIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNzg4MjgxNTMiLCJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwicm9sZSI6Ik9XTkVSIiwiZW1haWwiOiIzNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImV0YWciOiJDUG5nek9HVzI5MENFQUU9In1dLCJvd25lciI6eyJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIn0sImNyYzMyYyI6InIwTkdyZz09IiwiZXRhZyI6IkNQbmd6T0dXMjkwQ0VBRT0iLCJjdXN0b21lckVuY3J5cHRpb24iOnsiZW5jcnlwdGlvbkFsZ29yaXRobSI6IkFFUzI1NiIsImtleVNoYTI1NiI6IkZuQnZmUTFkRHN5UzhrSEQrYUI2SEhJZ2xEb1E1SW03V1lEbTNYWVRHclE9In19fQ=="
+ }
+ },
+ {
+ "ID": "af6300f23cc6c27c",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://storage.googleapis.com/go-integration-test-20180927-44630911863640-0001/customer-encryption-2",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "Go-http-client/1.1"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "34eb30af8a5d023668ef3bfebecd46df/52568571938342239;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "storage.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://storage.googleapis.com/go-integration-test-20180927-44630911863640-0001/customer-encryption-2"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 400,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0"
+ ],
+ "Content-Length": [
+ "277"
+ ],
+ "Content-Type": [
+ "application/xml; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:38 GMT"
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:24:38 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "X-Google-Backends": [
+ "/bns/xh/borg/xh/bns/cloud-storage/prod-cloud-storage-frontend.frontend/0,/bns/xh/borg/xh/bns/blobstore2/bitpusher/28.scotty,aclgag19:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=BsysW7-yOYuhswbl1qKYBg"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "aclgag19:443,/bns/xh/borg/xh/bns/blobstore2/bitpusher/28.scotty,aclgag19:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/xh/borg/xh/bns/blobstore2/bitpusher/28:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBJ"
+ ],
+ "X-Guploader-Customer": [
+ "cloud-storage"
+ ],
+ "X-Guploader-Request-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Upload-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UrjoQiF7Wn9tm0yro8yG5Q_IlGNtcRWwGXNmf76WCfoPNtEjykhr4I2C2Z7IMJu69JC7Ug7VKK_eCSeLk-GpliSCYK52Q"
+ ]
+ },
+ "Body": "PD94bWwgdmVyc2lvbj0nMS4wJyBlbmNvZGluZz0nVVRGLTgnPz48RXJyb3I+PENvZGU+UmVzb3VyY2VJc0VuY3J5cHRlZFdpdGhDdXN0b21lckVuY3J5cHRpb25LZXk8L0NvZGU+PE1lc3NhZ2U+VGhlIHJlc291cmNlIGlzIGVuY3J5cHRlZCB3aXRoIGEgY3VzdG9tZXIgZW5jcnlwdGlvbiBrZXkuPC9NZXNzYWdlPjxEZXRhaWxzPlRoZSByZXF1ZXN0ZWQgb2JqZWN0IGlzIGVuY3J5cHRlZCBieSBhIGN1c3RvbWVyLXN1cHBsaWVkIGVuY3J5cHRpb24ga2V5LjwvRGV0YWlscz48L0Vycm9yPg=="
+ }
+ },
+ {
+ "ID": "13b7d249a22c3226",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://storage.googleapis.com/go-integration-test-20180927-44630911863640-0001/customer-encryption-2",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "Go-http-client/1.1"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "6ec04258e9f0bf885bd0d408ba9d4a85/1642697905812188157;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "storage.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://storage.googleapis.com/go-integration-test-20180927-44630911863640-0001/customer-encryption-2"
+ ],
+ "X-Goog-Encryption-Algorithm": [
+ "AES256"
+ ],
+ "X-Goog-Encryption-Key": [
+ "REDACTED"
+ ],
+ "X-Goog-Encryption-Key-Sha256": [
+ "FnBvfQ1dDsyS8kHD+aB6HHIglDoQ5Im7WYDm3XYTGrQ="
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Accept-Ranges": [
+ "bytes"
+ ],
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Language": [
+ "en"
+ ],
+ "Content-Length": [
+ "11"
+ ],
+ "Content-Type": [
+ "text/plain; charset=utf-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:39 GMT"
+ ],
+ "Etag": [
+ "\"-CPngzOGW290CEAE=\""
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Last-Modified": [
+ "Thu, 27 Sep 2018 12:24:38 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "X-Goog-Encryption-Algorithm": [
+ "AES256"
+ ],
+ "X-Goog-Encryption-Key-Sha256": [
+ "FnBvfQ1dDsyS8kHD+aB6HHIglDoQ5Im7WYDm3XYTGrQ="
+ ],
+ "X-Goog-Expiration": [
+ "Sat, 27 Oct 2018 12:24:38 GMT"
+ ],
+ "X-Goog-Generation": [
+ "1538051078828153"
+ ],
+ "X-Goog-Hash": [
+ "crc32c=r0NGrg==",
+ "md5=xwWNFa0VdXPmlAwrlcAJcg=="
+ ],
+ "X-Goog-Metageneration": [
+ "1"
+ ],
+ "X-Goog-Storage-Class": [
+ "STANDARD"
+ ],
+ "X-Goog-Stored-Content-Encoding": [
+ "identity"
+ ],
+ "X-Goog-Stored-Content-Length": [
+ "11"
+ ],
+ "X-Google-Backends": [
+ "/bns/xh/borg/xh/bns/cloud-storage/prod-cloud-storage-frontend.frontend/12,/bns/xh/borg/xh/bns/blobstore2/bitpusher/52.scotty,aclgag19:443"
+ ],
+ "X-Google-Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=B8ysW6cIsKqzBr6kg8AP"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "aclgag19:443,/bns/xh/borg/xh/bns/blobstore2/bitpusher/52.scotty,aclgag19:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/xh/borg/xh/bns/blobstore2/bitpusher/52:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBJ"
+ ],
+ "X-Google-Storage-Location": [
+ "US"
+ ],
+ "X-Guploader-Customer": [
+ "cloud-storage"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Uogb9TrmaLESy0ok976HRo5Lcn2MEURdtotgODsMtPI9-W2lNDP6Xu951WGKM8lOEapQi_54VQ9XaY6faPuZz8_AUyXlw"
+ ]
+ },
+ "Body": "dG9wIHNlY3JldC4="
+ }
+ },
+ {
+ "ID": "3f85e3abeccd12ee",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/customer-encryption-2/rewriteTo/b/go-integration-test-20180927-44630911863640-0001/o/customer-encryption-2?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "3"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "790fd5e30e72862f5207a85bf97442a8/3233109805584437404;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/customer-encryption-2/rewriteTo/b/go-integration-test-20180927-44630911863640-0001/o/customer-encryption-2?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ],
+ "X-Goog-Copy-Source-Encryption-Algorithm": [
+ "AES256"
+ ],
+ "X-Goog-Copy-Source-Encryption-Key": [
+ "REDACTED"
+ ],
+ "X-Goog-Copy-Source-Encryption-Key-Sha256": [
+ "FnBvfQ1dDsyS8kHD+aB6HHIglDoQ5Im7WYDm3XYTGrQ="
+ ],
+ "X-Goog-Encryption-Algorithm": [
+ "AES256"
+ ],
+ "X-Goog-Encryption-Key": [
+ "REDACTED"
+ ],
+ "X-Goog-Encryption-Key-Sha256": [
+ "H+LmnXhRoeI6TMW5bsV6HyUk6pyGc2IMbqYbAXBcps0="
+ ]
+ },
+ "Body": "e30K"
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3733"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:39 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051377000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrno9:4295,/bns/yv/borg/yv/bns/blobstore2/bitpusher/88.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=B8ysW5XXB8KZgQTw9ZIQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/88.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/88:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp0ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4StK4wESxgF5YTI5LmMuRW93QkpRWUs4TEVnZzc0SE1jc2k2MENjN2doVUNwYXhuZlplOGJXWW1xSDdtR3h4UFFoVFo0OHVKNE9hSzBMbmltRms1bTFKRGNYOS1VS2FNNzlNaDNKNnRzb0JmVGt2MkxxTEJtM1RXMVJ2RGFiQTV6VlV1VHJUR2xMMTZlVjRNWG5oZGxDbEZMQmZtcWNvZU9CVzlDNkUwemVWVDUtTXFsU29OTUtsaG5iOGdlanREQW55QkZNWUVTb3pIa1kwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UrXkelifrzmM_ZibiAKC7mLpFqUeNomFI8UJ8PFAqN8RD84AJ-A1I8E6RE4RzsKdJC9Gi5dMDbBKV8rVm5YLLWXXo1Caw"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNyZXdyaXRlUmVzcG9uc2UiLCJ0b3RhbEJ5dGVzUmV3cml0dGVuIjoiMTEiLCJvYmplY3RTaXplIjoiMTEiLCJkb25lIjp0cnVlLCJyZXNvdXJjZSI6eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jdXN0b21lci1lbmNyeXB0aW9uLTIvMTUzODA1MTA3OTUxNTI1MyIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2N1c3RvbWVyLWVuY3J5cHRpb24tMiIsIm5hbWUiOiJjdXN0b21lci1lbmNyeXB0aW9uLTIiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA3OTUxNTI1MyIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOCIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDozOS41MTVaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MzkuNTE1WiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjM5LjUxNVoiLCJzaXplIjoiMTEiLCJtZDVIYXNoIjoieHdXTkZhMFZkWFBtbEF3cmxjQUpjZz09IiwibWVkaWFMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vZG93bmxvYWQvc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2N1c3RvbWVyLWVuY3J5cHRpb24tMj9nZW5lcmF0aW9uPTE1MzgwNTEwNzk1MTUyNTMmYWx0PW1lZGlhIiwiY29udGVudExhbmd1YWdlIjoiZW4iLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jdXN0b21lci1lbmNyeXB0aW9uLTIvMTUzODA1MTA3OTUxNTI1My9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2N1c3RvbWVyLWVuY3J5cHRpb24tMi9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJjdXN0b21lci1lbmNyeXB0aW9uLTIiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA3OTUxNTI1MyIsImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6Im93bmVycyJ9LCJldGFnIjoiQ1BYWTl1R1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2N1c3RvbWVyLWVuY3J5cHRpb24tMi8xNTM4MDUxMDc5NTE1MjUzL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2N1c3RvbWVyLWVuY3J5cHRpb24tMi9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiY3VzdG9tZXItZW5jcnlwdGlvbi0yIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNzk1MTUyNTMiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ1BYWTl1R1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2N1c3RvbWVyLWVuY3J5cHRpb24tMi8xNTM4MDUxMDc5NTE1MjUzL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2N1c3RvbWVyLWVuY3J5cHRpb24tMi9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiY3VzdG9tZXItZW5jcnlwdGlvbi0yIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNzk1MTUyNTMiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNQWFk5dUdXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jdXN0b21lci1lbmNyeXB0aW9uLTIvMTUzODA1MTA3OTUxNTI1My91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vY3VzdG9tZXItZW5jcnlwdGlvbi0yL2FjbC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiY3VzdG9tZXItZW5jcnlwdGlvbi0yIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNzk1MTUyNTMiLCJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwicm9sZSI6Ik9XTkVSIiwiZW1haWwiOiIzNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImV0YWciOiJDUFhZOXVHVzI5MENFQUU9In1dLCJvd25lciI6eyJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIn0sImNyYzMyYyI6InIwTkdyZz09IiwiZXRhZyI6IkNQWFk5dUdXMjkwQ0VBRT0iLCJjdXN0b21lckVuY3J5cHRpb24iOnsiZW5jcnlwdGlvbkFsZ29yaXRobSI6IkFFUzI1NiIsImtleVNoYTI1NiI6IkgrTG1uWGhSb2VJNlRNVzVic1Y2SHlVazZweUdjMklNYnFZYkFYQmNwczA9In19fQ=="
+ }
+ },
+ {
+ "ID": "082a7091d1ed2007",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/customer-encryption-3/compose?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "160"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "32ccef1e750b13cb8ebb9b1411568f72/4823521709634876986;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/customer-encryption-3/compose?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJkZXN0aW5hdGlvbiI6eyJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEifSwic291cmNlT2JqZWN0cyI6W3sibmFtZSI6ImN1c3RvbWVyLWVuY3J5cHRpb24ifSx7Im5hbWUiOiJjdXN0b21lci1lbmNyeXB0aW9uLTIifV19Cg=="
+ },
+ "Response": {
+ "StatusCode": 400,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Content-Length": [
+ "13226"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:39 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051377000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrmi1:4383,/bns/yw/borg/yw/bns/blobstore2/bitpusher/2.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=B8ysW9fRJpbRhASP5ryIBw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yw/borg/yw/bns/blobstore2/bitpusher/2.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yw/borg/yw/bns/blobstore2/bitpusher/2:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp0ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4StK4wESxgF5YTI5LmMuRW93QkpRWUs4TEVnZzc0SE1jc2k2MENjN2doVUNwYXhuZlplOGJXWW1xSDdtR3h4UFFoVFo0OHVKNE9hSzBMbmltRms1bTFKRGNYOS1VS2FNNzlNaDNKNnRzb0JmVGt2MkxxTEJtM1RXMVJ2RGFiQTV6VlV1VHJUR2xMMTZlVjRNWG5oZGxDbEZMQmZtcWNvZU9CVzlDNkUwemVWVDUtTXFsU29OTUtsaG5iOGdlanREQW55QkZNWUVTb3pIa1kwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Upload-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UqnSH1S0DzV-Tzbn9uZFehFnzCR3q7Tu5p04nCaneV0wfauN_YQTYLZCyLntmuHEkFeYFM1lLgwVSKjBYfRf7ED95Goug"
+ ]
+ },
+ "Body": "eyJlcnJvciI6eyJlcnJvcnMiOlt7ImRvbWFpbiI6Imdsb2JhbCIsInJlYXNvbiI6InJlc291cmNlSXNFbmNyeXB0ZWRXaXRoQ3VzdG9tZXJFbmNyeXB0aW9uS2V5IiwibWVzc2FnZSI6IlRoZSB0YXJnZXQgb2JqZWN0IGlzIGVuY3J5cHRlZCBieSBhIGN1c3RvbWVyLXN1cHBsaWVkIGVuY3J5cHRpb24ga2V5LiIsImV4dGVuZGVkSGVscCI6Imh0dHBzOi8vY2xvdWQuZ29vZ2xlLmNvbS9zdG9yYWdlL2RvY3MvZW5jcnlwdGlvbiNjdXN0b21lci1zdXBwbGllZF9lbmNyeXB0aW9uX2tleXMiLCJkZWJ1Z0luZm8iOiJjb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6UkVTT1VSQ0VfSVNfRU5DUllQVEVEX1dJVEhfQ1VTVE9NRVJfRU5DUllQVElPTl9LRVk6IENvbXBvbmVudCBvYmplY3QgKGdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jdXN0b21lci1lbmNyeXB0aW9uKSBpcyBlbmNyeXB0ZWQgYnkgYSBjdXN0b21lci1zdXBwbGllZCBlbmNyeXB0aW9uIGtleS5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udG9ScGMzRXhjZXB0aW9uKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MTM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuQ29tcG9zZU9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoQ29tcG9zZU9iamVjdC5qYXZhOjE5NSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5vYmplY3RzLkNvbXBvc2VPYmplY3QuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKENvbXBvc2VPYmplY3QuamF2YTo0NSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLk9iamVjdHNEZWxlZ2F0b3IuY29tcG9zZShPYmplY3RzRGVsZWdhdG9yLmphdmE6MTI5KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5ScGNSZWNlaXZlci5sYW1iZGEkcHJvY2Vzc1JlcXVlc3RBc3luYyQ0KFJwY1JlY2VpdmVyLmphdmE6MjAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5Bc3luY0V4ZWN1dG9yLmxhbWJkYSRzdWJtaXQkMChBc3luY0V4ZWN1dG9yLmphdmE6MjcyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoQ29udGV4dFJ1bm5hYmxlLmphdmE6NTApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlJDEucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM5KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo3Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5FeGVjdXRvcnMkUnVubmFibGVBZGFwdGVyLmNhbGwoRXhlY3V0b3JzLmphdmE6NTExKVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5GdXR1cmVUYXNrLnJ1bihGdXR1cmVUYXNrLmphdmE6MjY2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IucnVuV29ya2VyKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjExNDkpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvciRXb3JrZXIucnVuKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjYyNClcblx0YXQgamF2YS5sYW5nLlRocmVhZC5ydW4oVGhyZWFkLmphdmE6NzQ4KVxuQ2F1c2VkIGJ5OiBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbjogQ29tcG9uZW50IG9iamVjdCAoZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2N1c3RvbWVyLWVuY3J5cHRpb24pIGlzIGVuY3J5cHRlZCBieSBhIGN1c3RvbWVyLXN1cHBsaWVkIGVuY3J5cHRpb24ga2V5LlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxNyBtb3JlXG5cbmNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLkZhdWx0OiBJbW11dGFibGVFcnJvckRlZmluaXRpb257YmFzZT1JTlZBTElEX1ZBTFVFLCBjYXRlZ29yeT1VU0VSX0VSUk9SLCBjYXVzZT1udWxsLCBkZWJ1Z0luZm89Y29tLmdvb2dsZS5uZXQucnBjMy5ScGNFeGNlcHRpb246IGNsb3VkLmJpZ3N0b3JlLlJlc3BvbnNlQ29kZS5FcnJvckNvZGU6OlJFU09VUkNFX0lTX0VOQ1JZUFRFRF9XSVRIX0NVU1RPTUVSX0VOQ1JZUFRJT05fS0VZOiBDb21wb25lbnQgb2JqZWN0IChnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvY3VzdG9tZXItZW5jcnlwdGlvbikgaXMgZW5jcnlwdGVkIGJ5IGEgY3VzdG9tZXItc3VwcGxpZWQgZW5jcnlwdGlvbiBrZXkuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRvUnBjM0V4Y2VwdGlvbihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjEzNSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5vYmplY3RzLkNvbXBvc2VPYmplY3QuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKENvbXBvc2VPYmplY3QuamF2YToxOTUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5Db21wb3NlT2JqZWN0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChDb21wb3NlT2JqZWN0LmphdmE6NDUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5PYmplY3RzRGVsZWdhdG9yLmNvbXBvc2UoT2JqZWN0c0RlbGVnYXRvci5qYXZhOjEyOSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uUnBjUmVjZWl2ZXIubGFtYmRhJHByb2Nlc3NSZXF1ZXN0QXN5bmMkNChScGNSZWNlaXZlci5qYXZhOjIwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uQXN5bmNFeGVjdXRvci5sYW1iZGEkc3VibWl0JDAoQXN5bmNFeGVjdXRvci5qYXZhOjI3Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KENvbnRleHRSdW5uYWJsZS5qYXZhOjUwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZSQxLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozOSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NzIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozNilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRXhlY3V0b3JzJFJ1bm5hYmxlQWRhcHRlci5jYWxsKEV4ZWN1dG9ycy5qYXZhOjUxMSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRnV0dXJlVGFzay5ydW4oRnV0dXJlVGFzay5qYXZhOjI2Nilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yLnJ1bldvcmtlcihUaHJlYWRQb29sRXhlY3V0b3IuamF2YToxMTQ5KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IkV29ya2VyLnJ1bihUaHJlYWRQb29sRXhlY3V0b3IuamF2YTo2MjQpXG5cdGF0IGphdmEubGFuZy5UaHJlYWQucnVuKFRocmVhZC5qYXZhOjc0OClcbkNhdXNlZCBieTogY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb246IENvbXBvbmVudCBvYmplY3QgKGdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jdXN0b21lci1lbmNyeXB0aW9uKSBpcyBlbmNyeXB0ZWQgYnkgYSBjdXN0b21lci1zdXBwbGllZCBlbmNyeXB0aW9uIGtleS5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MjkwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAxKVxuXHQuLi4gMTcgbW9yZVxuLCBkb21haW49Z2xvYmFsLCBleHRlbmRlZEhlbHA9aHR0cHM6Ly9jbG91ZC5nb29nbGUuY29tL3N0b3JhZ2UvZG9jcy9lbmNyeXB0aW9uI2N1c3RvbWVyLXN1cHBsaWVkX2VuY3J5cHRpb25fa2V5cywgaHR0cEhlYWRlcnM9e30sIGh0dHBTdGF0dXM9YmFkUmVxdWVzdCwgaW50ZXJuYWxSZWFzb249UmVhc29ue2FyZ3VtZW50cz17fSwgY2F1c2U9bnVsbCwgY29kZT1jbG91ZC5iaWdzdG9yZS5hcGkuQmlnc3RvcmVFcnJvckRvbWFpbi5SRVNPVVJDRV9JU19FTkNSWVBURURfV0lUSF9DVVNUT01FUl9FTkNSWVBUSU9OX0tFWSwgY3JlYXRlZEJ5QmFja2VuZD10cnVlLCBkZWJ1Z01lc3NhZ2U9Y29tLmdvb2dsZS5uZXQucnBjMy5ScGNFeGNlcHRpb246IGNsb3VkLmJpZ3N0b3JlLlJlc3BvbnNlQ29kZS5FcnJvckNvZGU6OlJFU09VUkNFX0lTX0VOQ1JZUFRFRF9XSVRIX0NVU1RPTUVSX0VOQ1JZUFRJT05fS0VZOiBDb21wb25lbnQgb2JqZWN0IChnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvY3VzdG9tZXItZW5jcnlwdGlvbikgaXMgZW5jcnlwdGVkIGJ5IGEgY3VzdG9tZXItc3VwcGxpZWQgZW5jcnlwdGlvbiBrZXkuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRvUnBjM0V4Y2VwdGlvbihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjEzNSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5vYmplY3RzLkNvbXBvc2VPYmplY3QuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKENvbXBvc2VPYmplY3QuamF2YToxOTUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5Db21wb3NlT2JqZWN0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChDb21wb3NlT2JqZWN0LmphdmE6NDUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5PYmplY3RzRGVsZWdhdG9yLmNvbXBvc2UoT2JqZWN0c0RlbGVnYXRvci5qYXZhOjEyOSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uUnBjUmVjZWl2ZXIubGFtYmRhJHByb2Nlc3NSZXF1ZXN0QXN5bmMkNChScGNSZWNlaXZlci5qYXZhOjIwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uQXN5bmNFeGVjdXRvci5sYW1iZGEkc3VibWl0JDAoQXN5bmNFeGVjdXRvci5qYXZhOjI3Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KENvbnRleHRSdW5uYWJsZS5qYXZhOjUwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZSQxLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozOSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NzIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozNilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRXhlY3V0b3JzJFJ1bm5hYmxlQWRhcHRlci5jYWxsKEV4ZWN1dG9ycy5qYXZhOjUxMSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRnV0dXJlVGFzay5ydW4oRnV0dXJlVGFzay5qYXZhOjI2Nilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yLnJ1bldvcmtlcihUaHJlYWRQb29sRXhlY3V0b3IuamF2YToxMTQ5KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IkV29ya2VyLnJ1bihUaHJlYWRQb29sRXhlY3V0b3IuamF2YTo2MjQpXG5cdGF0IGphdmEubGFuZy5UaHJlYWQucnVuKFRocmVhZC5qYXZhOjc0OClcbkNhdXNlZCBieTogY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb246IENvbXBvbmVudCBvYmplY3QgKGdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jdXN0b21lci1lbmNyeXB0aW9uKSBpcyBlbmNyeXB0ZWQgYnkgYSBjdXN0b21lci1zdXBwbGllZCBlbmNyeXB0aW9uIGtleS5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MjkwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAxKVxuXHQuLi4gMTcgbW9yZVxuLCBlcnJvclByb3RvQ29kZT1SRVNPVVJDRV9JU19FTkNSWVBURURfV0lUSF9DVVNUT01FUl9FTkNSWVBUSU9OX0tFWSwgZXJyb3JQcm90b0RvbWFpbj1jbG91ZC5iaWdzdG9yZS5hcGkuQmlnc3RvcmVFcnJvckRvbWFpbiwgZmlsdGVyZWRNZXNzYWdlPW51bGwsIGxvY2F0aW9uPW51bGwsIG1lc3NhZ2U9Q29tcG9uZW50IG9iamVjdCAoZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2N1c3RvbWVyLWVuY3J5cHRpb24pIGlzIGVuY3J5cHRlZCBieSBhIGN1c3RvbWVyLXN1cHBsaWVkIGVuY3J5cHRpb24ga2V5LiwgdW5uYW1lZEFyZ3VtZW50cz1bXX0sIGxvY2F0aW9uPW51bGwsIG1lc3NhZ2U9VGhlIHRhcmdldCBvYmplY3QgaXMgZW5jcnlwdGVkIGJ5IGEgY3VzdG9tZXItc3VwcGxpZWQgZW5jcnlwdGlvbiBrZXkuLCByZWFzb249cmVzb3VyY2VJc0VuY3J5cHRlZFdpdGhDdXN0b21lckVuY3J5cHRpb25LZXksIHJwY0NvZGU9NDAwfSBUaGUgdGFyZ2V0IG9iamVjdCBpcyBlbmNyeXB0ZWQgYnkgYSBjdXN0b21lci1zdXBwbGllZCBlbmNyeXB0aW9uIGtleS46IGNvbS5nb29nbGUubmV0LnJwYzMuUnBjRXhjZXB0aW9uOiBjbG91ZC5iaWdzdG9yZS5SZXNwb25zZUNvZGUuRXJyb3JDb2RlOjpSRVNPVVJDRV9JU19FTkNSWVBURURfV0lUSF9DVVNUT01FUl9FTkNSWVBUSU9OX0tFWTogQ29tcG9uZW50IG9iamVjdCAoZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2N1c3RvbWVyLWVuY3J5cHRpb24pIGlzIGVuY3J5cHRlZCBieSBhIGN1c3RvbWVyLXN1cHBsaWVkIGVuY3J5cHRpb24ga2V5LlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5Db21wb3NlT2JqZWN0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChDb21wb3NlT2JqZWN0LmphdmE6MTk1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuQ29tcG9zZU9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoQ29tcG9zZU9iamVjdC5qYXZhOjQ1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmZyYW1ld29yay5SZXF1ZXN0SGFuZGxlci5oYW5kbGUoUmVxdWVzdEhhbmRsZXIuamF2YToyOTQpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uT2JqZWN0c0RlbGVnYXRvci5jb21wb3NlKE9iamVjdHNEZWxlZ2F0b3IuamF2YToxMjkpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBDb21wb25lbnQgb2JqZWN0IChnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvY3VzdG9tZXItZW5jcnlwdGlvbikgaXMgZW5jcnlwdGVkIGJ5IGEgY3VzdG9tZXItc3VwcGxpZWQgZW5jcnlwdGlvbiBrZXkuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93T25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjI5MClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMSlcblx0Li4uIDE3IG1vcmVcblxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS5FcnJvckNvbGxlY3Rvci50b0ZhdWx0KEVycm9yQ29sbGVjdG9yLmphdmE6NTQpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5yZXN0LmFkYXB0ZXIucm9zeS5Sb3N5RXJyb3JDb252ZXJ0ZXIudG9GYXVsdChSb3N5RXJyb3JDb252ZXJ0ZXIuamF2YTo2Nylcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnJlc3QuYWRhcHRlci5yb3N5LlJvc3lIYW5kbGVyJDIuY2FsbChSb3N5SGFuZGxlci5qYXZhOjI1OClcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnJlc3QuYWRhcHRlci5yb3N5LlJvc3lIYW5kbGVyJDIuY2FsbChSb3N5SGFuZGxlci5qYXZhOjIzOClcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkRpcmVjdEV4ZWN1dG9yLmV4ZWN1dGUoRGlyZWN0RXhlY3V0b3IuamF2YTozMClcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmV4ZWN1dGVMaXN0ZW5lcihBYnN0cmFjdEZ1dHVyZS5qYXZhOjExNDMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5jb21wbGV0ZShBYnN0cmFjdEZ1dHVyZS5qYXZhOjk2Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLnNldChBYnN0cmFjdEZ1dHVyZS5qYXZhOjczMSlcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkRpcmVjdEV4ZWN1dG9yLmV4ZWN1dGUoRGlyZWN0RXhlY3V0b3IuamF2YTozMClcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmV4ZWN1dGVMaXN0ZW5lcihBYnN0cmFjdEZ1dHVyZS5qYXZhOjExNDMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5jb21wbGV0ZShBYnN0cmFjdEZ1dHVyZS5qYXZhOjk2Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLnNldChBYnN0cmFjdEZ1dHVyZS5qYXZhOjczMSlcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnRocmVhZC5UaHJlYWRUcmFja2VycyRUaHJlYWRUcmFja2luZ1J1bm5hYmxlLnJ1bihUaHJlYWRUcmFja2Vycy5qYXZhOjEyNilcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRUcmFjZUNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoVHJhY2VDb250ZXh0LmphdmE6NDU1KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuc2VydmVyLkNvbW1vbk1vZHVsZSRDb250ZXh0Q2FycnlpbmdFeGVjdXRvclNlcnZpY2UkMS5ydW5JbkNvbnRleHQoQ29tbW9uTW9kdWxlLmphdmE6ODQ2KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JFRyYWNlQ29udGV4dFJ1bm5hYmxlJDEucnVuKFRyYWNlQ29udGV4dC5qYXZhOjQ2Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRBYnN0cmFjdFRyYWNlQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoVHJhY2VDb250ZXh0LmphdmE6MzIxKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JEFic3RyYWN0VHJhY2VDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KFRyYWNlQ29udGV4dC5qYXZhOjMxMylcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRUcmFjZUNvbnRleHRSdW5uYWJsZS5ydW4oVHJhY2VDb250ZXh0LmphdmE6NDU5KVxuXHRhdCBjb20uZ29vZ2xlLmdzZS5pbnRlcm5hbC5EaXNwYXRjaFF1ZXVlSW1wbCRXb3JrZXJUaHJlYWQucnVuKERpc3BhdGNoUXVldWVJbXBsLmphdmE6NDAzKVxuIn1dLCJjb2RlIjo0MDAsIm1lc3NhZ2UiOiJUaGUgdGFyZ2V0IG9iamVjdCBpcyBlbmNyeXB0ZWQgYnkgYSBjdXN0b21lci1zdXBwbGllZCBlbmNyeXB0aW9uIGtleS4ifX0="
+ }
+ },
+ {
+ "ID": "f38450f7b6994359",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/customer-encryption-3/compose?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "160"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "d80e51262f252122efbaf143063fec84/7172970583123226152;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/customer-encryption-3/compose?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ],
+ "X-Goog-Encryption-Algorithm": [
+ "AES256"
+ ],
+ "X-Goog-Encryption-Key": [
+ "REDACTED"
+ ],
+ "X-Goog-Encryption-Key-Sha256": [
+ "H+LmnXhRoeI6TMW5bsV6HyUk6pyGc2IMbqYbAXBcps0="
+ ]
+ },
+ "Body": "eyJkZXN0aW5hdGlvbiI6eyJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEifSwic291cmNlT2JqZWN0cyI6W3sibmFtZSI6ImN1c3RvbWVyLWVuY3J5cHRpb24ifSx7Im5hbWUiOiJjdXN0b21lci1lbmNyeXB0aW9uLTIifV19Cg=="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "911"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:40 GMT"
+ ],
+ "Etag": [
+ "CPPmruKW290CEAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051377000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrlb12:4251,/bns/yv/borg/yv/bns/blobstore2/bitpusher/43.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=B8ysW4izOIOegwTq3L2ADw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/43.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/43:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp0ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4StK4wESxgF5YTI5LmMuRW93QkpRWUs4TEVnZzc0SE1jc2k2MENjN2doVUNwYXhuZlplOGJXWW1xSDdtR3h4UFFoVFo0OHVKNE9hSzBMbmltRms1bTFKRGNYOS1VS2FNNzlNaDNKNnRzb0JmVGt2MkxxTEJtM1RXMVJ2RGFiQTV6VlV1VHJUR2xMMTZlVjRNWG5oZGxDbEZMQmZtcWNvZU9CVzlDNkUwemVWVDUtTXFsU29OTUtsaG5iOGdlanREQW55QkZNWUVTb3pIa1kwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UrylLVTdrDh4f0Vfz7f7uc-9JeMykJ4U6tLGFt1hxOEFQDcYOlrv4zBfNQWHFKEOybb0y9327li2CcTac2VQbWW2VVKsg"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jdXN0b21lci1lbmNyeXB0aW9uLTMvMTUzODA1MTA4MDQzNDU0NyIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2N1c3RvbWVyLWVuY3J5cHRpb24tMyIsIm5hbWUiOiJjdXN0b21lci1lbmNyeXB0aW9uLTMiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA4MDQzNDU0NyIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDo0MC40MzRaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6NDAuNDM0WiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjQwLjQzNFoiLCJzaXplIjoiMjIiLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vY3VzdG9tZXItZW5jcnlwdGlvbi0zP2dlbmVyYXRpb249MTUzODA1MTA4MDQzNDU0NyZhbHQ9bWVkaWEiLCJjcmMzMmMiOiI1ajF5cGc9PSIsImNvbXBvbmVudENvdW50IjoyLCJldGFnIjoiQ1BQbXJ1S1cyOTBDRUFFPSIsImN1c3RvbWVyRW5jcnlwdGlvbiI6eyJlbmNyeXB0aW9uQWxnb3JpdGhtIjoiQUVTMjU2Iiwia2V5U2hhMjU2IjoiSCtMbW5YaFJvZUk2VE1XNWJzVjZIeVVrNnB5R2MySU1icVliQVhCY3BzMD0ifX0="
+ }
+ },
+ {
+ "ID": "9e7050ed002cb668",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://storage.googleapis.com/go-integration-test-20180927-44630911863640-0001/customer-encryption-3",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "Go-http-client/1.1"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "73a2be99b8acfc1dee817e64a6745ea9/8763382482895475655;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "storage.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://storage.googleapis.com/go-integration-test-20180927-44630911863640-0001/customer-encryption-3"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 400,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0"
+ ],
+ "Content-Length": [
+ "277"
+ ],
+ "Content-Type": [
+ "application/xml; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:40 GMT"
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:24:40 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "X-Google-Backends": [
+ "/bns/xh/borg/xh/bns/cloud-storage/prod-cloud-storage-frontend.frontend/47,/bns/xh/borg/xh/bns/blobstore2/bitpusher/60.scotty,aclgag19:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=CMysW4i9IsWhswa5mIuQAg"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "aclgag19:443,/bns/xh/borg/xh/bns/blobstore2/bitpusher/60.scotty,aclgag19:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/xh/borg/xh/bns/blobstore2/bitpusher/60:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBJ"
+ ],
+ "X-Guploader-Customer": [
+ "cloud-storage"
+ ],
+ "X-Guploader-Request-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Upload-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UrCCK9bVrOWH7ud3eW9W3iMCeh8Qx_fEx62BWAY7Dz4jTrVQJP8pMyvE9WqwAMVLcsnZ4V2KTogN111cHGLj6rHRWoWLg"
+ ]
+ },
+ "Body": "PD94bWwgdmVyc2lvbj0nMS4wJyBlbmNvZGluZz0nVVRGLTgnPz48RXJyb3I+PENvZGU+UmVzb3VyY2VJc0VuY3J5cHRlZFdpdGhDdXN0b21lckVuY3J5cHRpb25LZXk8L0NvZGU+PE1lc3NhZ2U+VGhlIHJlc291cmNlIGlzIGVuY3J5cHRlZCB3aXRoIGEgY3VzdG9tZXIgZW5jcnlwdGlvbiBrZXkuPC9NZXNzYWdlPjxEZXRhaWxzPlRoZSByZXF1ZXN0ZWQgb2JqZWN0IGlzIGVuY3J5cHRlZCBieSBhIGN1c3RvbWVyLXN1cHBsaWVkIGVuY3J5cHRpb24ga2V5LjwvRGV0YWlscz48L0Vycm9yPg=="
+ }
+ },
+ {
+ "ID": "0fbb222f2534ff7a",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://storage.googleapis.com/go-integration-test-20180927-44630911863640-0001/customer-encryption-3",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "Go-http-client/1.1"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "6331c1e1f7b03eb25a98f3fc46f36369/10353511816769255782;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "storage.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://storage.googleapis.com/go-integration-test-20180927-44630911863640-0001/customer-encryption-3"
+ ],
+ "X-Goog-Encryption-Algorithm": [
+ "AES256"
+ ],
+ "X-Goog-Encryption-Key": [
+ "REDACTED"
+ ],
+ "X-Goog-Encryption-Key-Sha256": [
+ "H+LmnXhRoeI6TMW5bsV6HyUk6pyGc2IMbqYbAXBcps0="
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Accept-Ranges": [
+ "bytes"
+ ],
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "22"
+ ],
+ "Content-Type": [
+ "application/octet-stream"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:40 GMT"
+ ],
+ "Etag": [
+ "\"-CPPmruKW290CEAE=\""
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Last-Modified": [
+ "Thu, 27 Sep 2018 12:24:40 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "X-Goog-Component-Count": [
+ "2"
+ ],
+ "X-Goog-Encryption-Algorithm": [
+ "AES256"
+ ],
+ "X-Goog-Encryption-Key-Sha256": [
+ "H+LmnXhRoeI6TMW5bsV6HyUk6pyGc2IMbqYbAXBcps0="
+ ],
+ "X-Goog-Expiration": [
+ "Sat, 27 Oct 2018 12:24:40 GMT"
+ ],
+ "X-Goog-Generation": [
+ "1538051080434547"
+ ],
+ "X-Goog-Hash": [
+ "crc32c=5j1ypg=="
+ ],
+ "X-Goog-Metageneration": [
+ "1"
+ ],
+ "X-Goog-Storage-Class": [
+ "STANDARD"
+ ],
+ "X-Goog-Stored-Content-Encoding": [
+ "identity"
+ ],
+ "X-Goog-Stored-Content-Length": [
+ "22"
+ ],
+ "X-Google-Backends": [
+ "/bns/xh/borg/xh/bns/cloud-storage/prod-cloud-storage-frontend.frontend/34,/bns/xh/borg/xh/bns/blobstore2/bitpusher/86.scotty,aclgag19:443"
+ ],
+ "X-Google-Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=CMysW-ycJe6oswaP1oK4DA"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "aclgag19:443,/bns/xh/borg/xh/bns/blobstore2/bitpusher/86.scotty,aclgag19:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/xh/borg/xh/bns/blobstore2/bitpusher/86:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBJ"
+ ],
+ "X-Google-Storage-Location": [
+ "US"
+ ],
+ "X-Guploader-Customer": [
+ "cloud-storage"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UpuCcU3sd6d5b3_CAmlabI6q2Y6u8mNw58JWRfKayJ4R6dbktGbpQ-hZyXbWI9zCfwEr-ZA_-azw7Q8-WtMuO2xAI-8uA"
+ ]
+ },
+ "Body": "dG9wIHNlY3JldC50b3Agc2VjcmV0Lg=="
+ }
+ },
+ {
+ "ID": "2674faa2be795765",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/customer-encryption-2/rewriteTo/b/go-integration-test-20180927-44630911863640-0001/o/customer-encryption-2?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "3"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "96c928b3b824c63fe7484440c436c936/11943923720836472324;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/customer-encryption-2/rewriteTo/b/go-integration-test-20180927-44630911863640-0001/o/customer-encryption-2?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ],
+ "X-Goog-Copy-Source-Encryption-Algorithm": [
+ "AES256"
+ ],
+ "X-Goog-Copy-Source-Encryption-Key": [
+ "REDACTED"
+ ],
+ "X-Goog-Copy-Source-Encryption-Key-Sha256": [
+ "H+LmnXhRoeI6TMW5bsV6HyUk6pyGc2IMbqYbAXBcps0="
+ ]
+ },
+ "Body": "e30K"
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3620"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:41 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051377000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrae1:4130,/bns/yr/borg/yr/bns/blobstore2/bitpusher/72.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=CMysW4b8LM3ikAO8k6i4Cg"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/72.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/72:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp0ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4StK4wESxgF5YTI5LmMuRW93QkpRWUs4TEVnZzc0SE1jc2k2MENjN2doVUNwYXhuZlplOGJXWW1xSDdtR3h4UFFoVFo0OHVKNE9hSzBMbmltRms1bTFKRGNYOS1VS2FNNzlNaDNKNnRzb0JmVGt2MkxxTEJtM1RXMVJ2RGFiQTV6VlV1VHJUR2xMMTZlVjRNWG5oZGxDbEZMQmZtcWNvZU9CVzlDNkUwemVWVDUtTXFsU29OTUtsaG5iOGdlanREQW55QkZNWUVTb3pIa1kwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UqiHnplkYoA54YhU9ArFoa4wXcCr0oXVB1HTdzE_nCqLyPj3048fN0-OX3_eM3xHOmxELgRjw88jTxkXPQW6kTqXoaZBA"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNyZXdyaXRlUmVzcG9uc2UiLCJ0b3RhbEJ5dGVzUmV3cml0dGVuIjoiMTEiLCJvYmplY3RTaXplIjoiMTEiLCJkb25lIjp0cnVlLCJyZXNvdXJjZSI6eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jdXN0b21lci1lbmNyeXB0aW9uLTIvMTUzODA1MTA4MTIxNTYwNyIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2N1c3RvbWVyLWVuY3J5cHRpb24tMiIsIm5hbWUiOiJjdXN0b21lci1lbmNyeXB0aW9uLTIiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA4MTIxNTYwNyIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOCIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDo0MS4yMTRaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6NDEuMjE0WiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjQxLjIxNFoiLCJzaXplIjoiMTEiLCJtZDVIYXNoIjoieHdXTkZhMFZkWFBtbEF3cmxjQUpjZz09IiwibWVkaWFMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vZG93bmxvYWQvc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2N1c3RvbWVyLWVuY3J5cHRpb24tMj9nZW5lcmF0aW9uPTE1MzgwNTEwODEyMTU2MDcmYWx0PW1lZGlhIiwiY29udGVudExhbmd1YWdlIjoiZW4iLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jdXN0b21lci1lbmNyeXB0aW9uLTIvMTUzODA1MTA4MTIxNTYwNy9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2N1c3RvbWVyLWVuY3J5cHRpb24tMi9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJjdXN0b21lci1lbmNyeXB0aW9uLTIiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA4MTIxNTYwNyIsImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6Im93bmVycyJ9LCJldGFnIjoiQ1BlODN1S1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2N1c3RvbWVyLWVuY3J5cHRpb24tMi8xNTM4MDUxMDgxMjE1NjA3L3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2N1c3RvbWVyLWVuY3J5cHRpb24tMi9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiY3VzdG9tZXItZW5jcnlwdGlvbi0yIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwODEyMTU2MDciLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ1BlODN1S1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2N1c3RvbWVyLWVuY3J5cHRpb24tMi8xNTM4MDUxMDgxMjE1NjA3L3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2N1c3RvbWVyLWVuY3J5cHRpb24tMi9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiY3VzdG9tZXItZW5jcnlwdGlvbi0yIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwODEyMTU2MDciLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNQZTgzdUtXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jdXN0b21lci1lbmNyeXB0aW9uLTIvMTUzODA1MTA4MTIxNTYwNy91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vY3VzdG9tZXItZW5jcnlwdGlvbi0yL2FjbC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiY3VzdG9tZXItZW5jcnlwdGlvbi0yIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwODEyMTU2MDciLCJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwicm9sZSI6Ik9XTkVSIiwiZW1haWwiOiIzNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImV0YWciOiJDUGU4M3VLVzI5MENFQUU9In1dLCJvd25lciI6eyJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIn0sImNyYzMyYyI6InIwTkdyZz09IiwiZXRhZyI6IkNQZTgzdUtXMjkwQ0VBRT0ifX0="
+ }
+ },
+ {
+ "ID": "a69acbcb815e9a98",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/customer-encryption-3/compose?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "129"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "a7cd921f95aff6168c1cdf2558bbb8c2/13534335624886846627;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/customer-encryption-3/compose?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ],
+ "X-Goog-Encryption-Algorithm": [
+ "AES256"
+ ],
+ "X-Goog-Encryption-Key": [
+ "REDACTED"
+ ],
+ "X-Goog-Encryption-Key-Sha256": [
+ "H+LmnXhRoeI6TMW5bsV6HyUk6pyGc2IMbqYbAXBcps0="
+ ]
+ },
+ "Body": "eyJkZXN0aW5hdGlvbiI6eyJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEifSwic291cmNlT2JqZWN0cyI6W3sibmFtZSI6ImN1c3RvbWVyLWVuY3J5cHRpb24tMiJ9XX0K"
+ },
+ "Response": {
+ "StatusCode": 400,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Content-Length": [
+ "13336"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:41 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051377000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vns194:4293,/bns/yx/borg/yx/bns/blobstore2/bitpusher/80.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=CcysW6u5FYTBzAKH6JOIAg"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yx/borg/yx/bns/blobstore2/bitpusher/80.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yx/borg/yx/bns/blobstore2/bitpusher/80:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp0ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4StK4wESxgF5YTI5LmMuRW93QkpRWUs4TEVnZzc0SE1jc2k2MENjN2doVUNwYXhuZlplOGJXWW1xSDdtR3h4UFFoVFo0OHVKNE9hSzBMbmltRms1bTFKRGNYOS1VS2FNNzlNaDNKNnRzb0JmVGt2MkxxTEJtM1RXMVJ2RGFiQTV6VlV1VHJUR2xMMTZlVjRNWG5oZGxDbEZMQmZtcWNvZU9CVzlDNkUwemVWVDUtTXFsU29OTUtsaG5iOGdlanREQW55QkZNWUVTb3pIa1kwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Upload-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UrsewdwW9EJ0NcTaSD_uyyIskMhpsLlaImKZ_i0_-K6dCZQMXFB0P-8yHmIIOwuyNOq33P9ahzJ6_YlsOilZA0aRMlLDA"
+ ]
+ },
+ "Body": "eyJlcnJvciI6eyJlcnJvcnMiOlt7ImRvbWFpbiI6Imdsb2JhbCIsInJlYXNvbiI6InJlc291cmNlTm90RW5jcnlwdGVkV2l0aEN1c3RvbWVyRW5jcnlwdGlvbktleSIsIm1lc3NhZ2UiOiJUaGUgdGFyZ2V0IG9iamVjdCBpcyBub3QgZW5jcnlwdGVkIGJ5IGEgY3VzdG9tZXItc3VwcGxpZWQgZW5jcnlwdGlvbiBrZXkuIiwiZXh0ZW5kZWRIZWxwIjoiaHR0cHM6Ly9jbG91ZC5nb29nbGUuY29tL3N0b3JhZ2UvZG9jcy9lbmNyeXB0aW9uI2N1c3RvbWVyLXN1cHBsaWVkX2VuY3J5cHRpb25fa2V5cyIsImRlYnVnSW5mbyI6ImNvbS5nb29nbGUubmV0LnJwYzMuUnBjRXhjZXB0aW9uOiBjbG91ZC5iaWdzdG9yZS5SZXNwb25zZUNvZGUuRXJyb3JDb2RlOjpSRVNPVVJDRV9OT1RfRU5DUllQVEVEX1dJVEhfQ1VTVE9NRVJfRU5DUllQVElPTl9LRVk6IENvbXBvbmVudCBvYmplY3QgKGdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jdXN0b21lci1lbmNyeXB0aW9uLTIpIHVzIG5vdCBlbmNyeXB0ZWQgYnkgYSBjdXN0b21lci1zdXBwbGllZCBlbmNyeXB0aW9uIGtleS5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udG9ScGMzRXhjZXB0aW9uKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MTM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuQ29tcG9zZU9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoQ29tcG9zZU9iamVjdC5qYXZhOjE5NSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5vYmplY3RzLkNvbXBvc2VPYmplY3QuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKENvbXBvc2VPYmplY3QuamF2YTo0NSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLk9iamVjdHNEZWxlZ2F0b3IuY29tcG9zZShPYmplY3RzRGVsZWdhdG9yLmphdmE6MTI5KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5ScGNSZWNlaXZlci5sYW1iZGEkcHJvY2Vzc1JlcXVlc3RBc3luYyQ0KFJwY1JlY2VpdmVyLmphdmE6MjAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5Bc3luY0V4ZWN1dG9yLmxhbWJkYSRzdWJtaXQkMChBc3luY0V4ZWN1dG9yLmphdmE6MjcyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoQ29udGV4dFJ1bm5hYmxlLmphdmE6NTApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlJDEucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM5KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo3Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5FeGVjdXRvcnMkUnVubmFibGVBZGFwdGVyLmNhbGwoRXhlY3V0b3JzLmphdmE6NTExKVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5GdXR1cmVUYXNrLnJ1bihGdXR1cmVUYXNrLmphdmE6MjY2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IucnVuV29ya2VyKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjExNDkpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvciRXb3JrZXIucnVuKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjYyNClcblx0YXQgamF2YS5sYW5nLlRocmVhZC5ydW4oVGhyZWFkLmphdmE6NzQ4KVxuQ2F1c2VkIGJ5OiBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbjogQ29tcG9uZW50IG9iamVjdCAoZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2N1c3RvbWVyLWVuY3J5cHRpb24tMikgdXMgbm90IGVuY3J5cHRlZCBieSBhIGN1c3RvbWVyLXN1cHBsaWVkIGVuY3J5cHRpb24ga2V5LlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxNyBtb3JlXG5cbmNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLkZhdWx0OiBJbW11dGFibGVFcnJvckRlZmluaXRpb257YmFzZT1JTlZBTElEX1ZBTFVFLCBjYXRlZ29yeT1VU0VSX0VSUk9SLCBjYXVzZT1udWxsLCBkZWJ1Z0luZm89Y29tLmdvb2dsZS5uZXQucnBjMy5ScGNFeGNlcHRpb246IGNsb3VkLmJpZ3N0b3JlLlJlc3BvbnNlQ29kZS5FcnJvckNvZGU6OlJFU09VUkNFX05PVF9FTkNSWVBURURfV0lUSF9DVVNUT01FUl9FTkNSWVBUSU9OX0tFWTogQ29tcG9uZW50IG9iamVjdCAoZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2N1c3RvbWVyLWVuY3J5cHRpb24tMikgdXMgbm90IGVuY3J5cHRlZCBieSBhIGN1c3RvbWVyLXN1cHBsaWVkIGVuY3J5cHRpb24ga2V5LlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5Db21wb3NlT2JqZWN0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChDb21wb3NlT2JqZWN0LmphdmE6MTk1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuQ29tcG9zZU9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoQ29tcG9zZU9iamVjdC5qYXZhOjQ1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmZyYW1ld29yay5SZXF1ZXN0SGFuZGxlci5oYW5kbGUoUmVxdWVzdEhhbmRsZXIuamF2YToyOTQpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uT2JqZWN0c0RlbGVnYXRvci5jb21wb3NlKE9iamVjdHNEZWxlZ2F0b3IuamF2YToxMjkpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBDb21wb25lbnQgb2JqZWN0IChnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvY3VzdG9tZXItZW5jcnlwdGlvbi0yKSB1cyBub3QgZW5jcnlwdGVkIGJ5IGEgY3VzdG9tZXItc3VwcGxpZWQgZW5jcnlwdGlvbiBrZXkuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93T25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjI5MClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMSlcblx0Li4uIDE3IG1vcmVcbiwgZG9tYWluPWdsb2JhbCwgZXh0ZW5kZWRIZWxwPWh0dHBzOi8vY2xvdWQuZ29vZ2xlLmNvbS9zdG9yYWdlL2RvY3MvZW5jcnlwdGlvbiNjdXN0b21lci1zdXBwbGllZF9lbmNyeXB0aW9uX2tleXMsIGh0dHBIZWFkZXJzPXt9LCBodHRwU3RhdHVzPWJhZFJlcXVlc3QsIGludGVybmFsUmVhc29uPVJlYXNvbnthcmd1bWVudHM9e30sIGNhdXNlPW51bGwsIGNvZGU9Y2xvdWQuYmlnc3RvcmUuYXBpLkJpZ3N0b3JlRXJyb3JEb21haW4uUkVTT1VSQ0VfTk9UX0VOQ1JZUFRFRF9XSVRIX0NVU1RPTUVSX0VOQ1JZUFRJT05fS0VZLCBjcmVhdGVkQnlCYWNrZW5kPXRydWUsIGRlYnVnTWVzc2FnZT1jb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6UkVTT1VSQ0VfTk9UX0VOQ1JZUFRFRF9XSVRIX0NVU1RPTUVSX0VOQ1JZUFRJT05fS0VZOiBDb21wb25lbnQgb2JqZWN0IChnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvY3VzdG9tZXItZW5jcnlwdGlvbi0yKSB1cyBub3QgZW5jcnlwdGVkIGJ5IGEgY3VzdG9tZXItc3VwcGxpZWQgZW5jcnlwdGlvbiBrZXkuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRvUnBjM0V4Y2VwdGlvbihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjEzNSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5vYmplY3RzLkNvbXBvc2VPYmplY3QuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKENvbXBvc2VPYmplY3QuamF2YToxOTUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5Db21wb3NlT2JqZWN0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChDb21wb3NlT2JqZWN0LmphdmE6NDUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5PYmplY3RzRGVsZWdhdG9yLmNvbXBvc2UoT2JqZWN0c0RlbGVnYXRvci5qYXZhOjEyOSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uUnBjUmVjZWl2ZXIubGFtYmRhJHByb2Nlc3NSZXF1ZXN0QXN5bmMkNChScGNSZWNlaXZlci5qYXZhOjIwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uQXN5bmNFeGVjdXRvci5sYW1iZGEkc3VibWl0JDAoQXN5bmNFeGVjdXRvci5qYXZhOjI3Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KENvbnRleHRSdW5uYWJsZS5qYXZhOjUwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZSQxLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozOSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NzIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozNilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRXhlY3V0b3JzJFJ1bm5hYmxlQWRhcHRlci5jYWxsKEV4ZWN1dG9ycy5qYXZhOjUxMSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRnV0dXJlVGFzay5ydW4oRnV0dXJlVGFzay5qYXZhOjI2Nilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yLnJ1bldvcmtlcihUaHJlYWRQb29sRXhlY3V0b3IuamF2YToxMTQ5KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IkV29ya2VyLnJ1bihUaHJlYWRQb29sRXhlY3V0b3IuamF2YTo2MjQpXG5cdGF0IGphdmEubGFuZy5UaHJlYWQucnVuKFRocmVhZC5qYXZhOjc0OClcbkNhdXNlZCBieTogY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb246IENvbXBvbmVudCBvYmplY3QgKGdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jdXN0b21lci1lbmNyeXB0aW9uLTIpIHVzIG5vdCBlbmNyeXB0ZWQgYnkgYSBjdXN0b21lci1zdXBwbGllZCBlbmNyeXB0aW9uIGtleS5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MjkwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAxKVxuXHQuLi4gMTcgbW9yZVxuLCBlcnJvclByb3RvQ29kZT1SRVNPVVJDRV9OT1RfRU5DUllQVEVEX1dJVEhfQ1VTVE9NRVJfRU5DUllQVElPTl9LRVksIGVycm9yUHJvdG9Eb21haW49Y2xvdWQuYmlnc3RvcmUuYXBpLkJpZ3N0b3JlRXJyb3JEb21haW4sIGZpbHRlcmVkTWVzc2FnZT1udWxsLCBsb2NhdGlvbj1lbnRpdHkuZW5jcnlwdGlvbktleSwgbWVzc2FnZT1Db21wb25lbnQgb2JqZWN0IChnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvY3VzdG9tZXItZW5jcnlwdGlvbi0yKSB1cyBub3QgZW5jcnlwdGVkIGJ5IGEgY3VzdG9tZXItc3VwcGxpZWQgZW5jcnlwdGlvbiBrZXkuLCB1bm5hbWVkQXJndW1lbnRzPVtdfSwgbG9jYXRpb249ZW50aXR5LmVuY3J5cHRpb25LZXksIG1lc3NhZ2U9VGhlIHRhcmdldCBvYmplY3QgaXMgbm90IGVuY3J5cHRlZCBieSBhIGN1c3RvbWVyLXN1cHBsaWVkIGVuY3J5cHRpb24ga2V5LiwgcmVhc29uPXJlc291cmNlTm90RW5jcnlwdGVkV2l0aEN1c3RvbWVyRW5jcnlwdGlvbktleSwgcnBjQ29kZT00MDB9IFRoZSB0YXJnZXQgb2JqZWN0IGlzIG5vdCBlbmNyeXB0ZWQgYnkgYSBjdXN0b21lci1zdXBwbGllZCBlbmNyeXB0aW9uIGtleS46IGNvbS5nb29nbGUubmV0LnJwYzMuUnBjRXhjZXB0aW9uOiBjbG91ZC5iaWdzdG9yZS5SZXNwb25zZUNvZGUuRXJyb3JDb2RlOjpSRVNPVVJDRV9OT1RfRU5DUllQVEVEX1dJVEhfQ1VTVE9NRVJfRU5DUllQVElPTl9LRVk6IENvbXBvbmVudCBvYmplY3QgKGdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jdXN0b21lci1lbmNyeXB0aW9uLTIpIHVzIG5vdCBlbmNyeXB0ZWQgYnkgYSBjdXN0b21lci1zdXBwbGllZCBlbmNyeXB0aW9uIGtleS5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udG9ScGMzRXhjZXB0aW9uKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MTM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuQ29tcG9zZU9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoQ29tcG9zZU9iamVjdC5qYXZhOjE5NSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5vYmplY3RzLkNvbXBvc2VPYmplY3QuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKENvbXBvc2VPYmplY3QuamF2YTo0NSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLk9iamVjdHNEZWxlZ2F0b3IuY29tcG9zZShPYmplY3RzRGVsZWdhdG9yLmphdmE6MTI5KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5ScGNSZWNlaXZlci5sYW1iZGEkcHJvY2Vzc1JlcXVlc3RBc3luYyQ0KFJwY1JlY2VpdmVyLmphdmE6MjAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5Bc3luY0V4ZWN1dG9yLmxhbWJkYSRzdWJtaXQkMChBc3luY0V4ZWN1dG9yLmphdmE6MjcyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoQ29udGV4dFJ1bm5hYmxlLmphdmE6NTApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlJDEucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM5KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo3Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5FeGVjdXRvcnMkUnVubmFibGVBZGFwdGVyLmNhbGwoRXhlY3V0b3JzLmphdmE6NTExKVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5GdXR1cmVUYXNrLnJ1bihGdXR1cmVUYXNrLmphdmE6MjY2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IucnVuV29ya2VyKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjExNDkpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvciRXb3JrZXIucnVuKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjYyNClcblx0YXQgamF2YS5sYW5nLlRocmVhZC5ydW4oVGhyZWFkLmphdmE6NzQ4KVxuQ2F1c2VkIGJ5OiBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbjogQ29tcG9uZW50IG9iamVjdCAoZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2N1c3RvbWVyLWVuY3J5cHRpb24tMikgdXMgbm90IGVuY3J5cHRlZCBieSBhIGN1c3RvbWVyLXN1cHBsaWVkIGVuY3J5cHRpb24ga2V5LlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxNyBtb3JlXG5cblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUuRXJyb3JDb2xsZWN0b3IudG9GYXVsdChFcnJvckNvbGxlY3Rvci5qYXZhOjU0KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIucmVzdC5hZGFwdGVyLnJvc3kuUm9zeUVycm9yQ29udmVydGVyLnRvRmF1bHQoUm9zeUVycm9yQ29udmVydGVyLmphdmE6NjcpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5yZXN0LmFkYXB0ZXIucm9zeS5Sb3N5SGFuZGxlciQyLmNhbGwoUm9zeUhhbmRsZXIuamF2YToyNTgpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5yZXN0LmFkYXB0ZXIucm9zeS5Sb3N5SGFuZGxlciQyLmNhbGwoUm9zeUhhbmRsZXIuamF2YToyMzgpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLnV0aWwuQ2FsbGFibGVGdXR1cmUucnVuKENhbGxhYmxlRnV0dXJlLmphdmE6NjIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5EaXJlY3RFeGVjdXRvci5leGVjdXRlKERpcmVjdEV4ZWN1dG9yLmphdmE6MzApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5leGVjdXRlTGlzdGVuZXIoQWJzdHJhY3RGdXR1cmUuamF2YToxMTQzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuY29tcGxldGUoQWJzdHJhY3RGdXR1cmUuamF2YTo5NjMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5zZXQoQWJzdHJhY3RGdXR1cmUuamF2YTo3MzEpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLnV0aWwuQ2FsbGFibGVGdXR1cmUucnVuKENhbGxhYmxlRnV0dXJlLmphdmE6NjIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5EaXJlY3RFeGVjdXRvci5leGVjdXRlKERpcmVjdEV4ZWN1dG9yLmphdmE6MzApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5leGVjdXRlTGlzdGVuZXIoQWJzdHJhY3RGdXR1cmUuamF2YToxMTQzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuY29tcGxldGUoQWJzdHJhY3RGdXR1cmUuamF2YTo5NjMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5zZXQoQWJzdHJhY3RGdXR1cmUuamF2YTo3MzEpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLnV0aWwuQ2FsbGFibGVGdXR1cmUucnVuKENhbGxhYmxlRnV0dXJlLmphdmE6NjIpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci50aHJlYWQuVGhyZWFkVHJhY2tlcnMkVGhyZWFkVHJhY2tpbmdSdW5uYWJsZS5ydW4oVGhyZWFkVHJhY2tlcnMuamF2YToxMjYpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkVHJhY2VDb250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KFRyYWNlQ29udGV4dC5qYXZhOjQ1NSlcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnNlcnZlci5Db21tb25Nb2R1bGUkQ29udGV4dENhcnJ5aW5nRXhlY3V0b3JTZXJ2aWNlJDEucnVuSW5Db250ZXh0KENvbW1vbk1vZHVsZS5qYXZhOjg0Nilcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRUcmFjZUNvbnRleHRSdW5uYWJsZSQxLnJ1bihUcmFjZUNvbnRleHQuamF2YTo0NjIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkQWJzdHJhY3RUcmFjZUNvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKFRyYWNlQ29udGV4dC5qYXZhOjMyMSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRBYnN0cmFjdFRyYWNlQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChUcmFjZUNvbnRleHQuamF2YTozMTMpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkVHJhY2VDb250ZXh0UnVubmFibGUucnVuKFRyYWNlQ29udGV4dC5qYXZhOjQ1OSlcblx0YXQgY29tLmdvb2dsZS5nc2UuaW50ZXJuYWwuRGlzcGF0Y2hRdWV1ZUltcGwkV29ya2VyVGhyZWFkLnJ1bihEaXNwYXRjaFF1ZXVlSW1wbC5qYXZhOjQwMylcbiJ9XSwiY29kZSI6NDAwLCJtZXNzYWdlIjoiVGhlIHRhcmdldCBvYmplY3QgaXMgbm90IGVuY3J5cHRlZCBieSBhIGN1c3RvbWVyLXN1cHBsaWVkIGVuY3J5cHRpb24ga2V5LiJ9fQ=="
+ }
+ },
+ {
+ "ID": "6f9c244b2d250c5e",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "31eada18413479da75d3925cc7108f96/15124747524659095874;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0, must-revalidate, no-transform"
+ ],
+ "Content-Length": [
+ "2492"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:42 GMT"
+ ],
+ "Etag": [
+ "CAk="
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:24:42 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051381000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vngu25:4297,/bns/yx/borg/yx/bns/blobstore2/bitpusher/156.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=CcysW4nWKs6EzALbtZ-gDg"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yx/borg/yx/bns/blobstore2/bitpusher/156.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yx/borg/yx/bns/blobstore2/bitpusher/156:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRYnBxTXlCbWNNWUVoeVpDak45TUl5alRkV2U4Tkd3bWM0RktJRUk1NGNIWmhyVTNrbmhKU0pwc1FISTJCQkVVSUdaV29YZ3FhajlBV2hIMEF2TVlYN3V6YVdPRkxfR0hTNnJrcEFrRFZRMzBUdF9uUWFEb1QybXVGRkxYRXBNdnYxOExuX2R1aFZnVnRkdHJlWm9hN21jU3JnMXEtejlocnV2SGxiTzFYbzVvTDRoRUExd3BFOFZ6R1EwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UrZI72BrP6aXYwfG9Rnz_oveTk2w4RM4JsRUBErv5nhrD_CbfL-4BN_PU1l3IXj320SM9dp9j7Po-u9bTOr19l7NVQAQA"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjM6NTIuMzU1WiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjI5LjE0NVoiLCJtZXRhZ2VuZXJhdGlvbiI6IjkiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBaz0ifSx7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDQWs9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNBaz0ifV0sImRlZmF1bHRPYmplY3RBY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBaz0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0FrPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0FrPSJ9XSwib3duZXIiOnsiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUifSwibG9jYXRpb24iOiJVUyIsInZlcnNpb25pbmciOnsiZW5hYmxlZCI6ZmFsc2V9LCJsaWZlY3ljbGUiOnsicnVsZSI6W3siYWN0aW9uIjp7InR5cGUiOiJEZWxldGUifSwiY29uZGl0aW9uIjp7ImFnZSI6MzB9fV19LCJsYWJlbHMiOnsibmV3IjoibmV3IiwibDEiOiJ2MiJ9LCJzdG9yYWdlQ2xhc3MiOiJTVEFOREFSRCIsImV0YWciOiJDQWs9In0="
+ }
+ },
+ {
+ "ID": "9133d063a35c30e5",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Type": [
+ "multipart/related; boundary=a11b044a99f2443cf5038003dedb8e668d7fe177eab13c4a0b90234adb2e"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "1a85ca3ba39da04007da15869a2499c0/15883784494080294033;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "LS1hMTFiMDQ0YTk5ZjI0NDNjZjUwMzgwMDNkZWRiOGU2NjhkN2ZlMTc3ZWFiMTNjNGEwYjkwMjM0YWRiMmUNCkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vanNvbg0KDQp7ImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm5hbWUiOiJwb3NjIn0KDQotLWExMWIwNDRhOTlmMjQ0M2NmNTAzODAwM2RlZGI4ZTY2OGQ3ZmUxNzdlYWIxM2M0YTBiOTAyMzRhZGIyZQ0KQ29udGVudC1UeXBlOiB0ZXh0L3BsYWluOyBjaGFyc2V0PXV0Zi04DQoNCmZvbw0KLS1hMTFiMDQ0YTk5ZjI0NDNjZjUwMzgwMDNkZWRiOGU2NjhkN2ZlMTc3ZWFiMTNjNGEwYjkwMjM0YWRiMmUtLQ0K"
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3221"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:42 GMT"
+ ],
+ "Etag": [
+ "CPf3qOOW290CEAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051382000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrkm9:4009,/bns/yw/borg/yw/bns/blobstore2/bitpusher/139.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=CsysW5GnB9LfhAT69p74BQ"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yw/borg/yw/bns/blobstore2/bitpusher/139.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yw/borg/yw/bns/blobstore2/bitpusher/139:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRYnBxTXlCbWNNWUVoeVpDak45TUl5alRkV2U4Tkd3bWM0RktJRUk1NGNIWmhyVTNrbmhKU0pwc1FISTJCQkVVSUdaV29YZ3FhajlBV2hIMEF2TVlYN3V6YVdPRkxfR0hTNnJrcEFrRFZRMzBUdF9uUWFEb1QybXVGRkxYRXBNdnYxOExuX2R1aFZnVnRkdHJlWm9hN21jU3JnMXEtejlocnV2SGxiTzFYbzVvTDRoRUExd3BFOFZ6R1EwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_single_post_uploads"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UrjPZMs7lUyqu-BOU0UoEmJXSWt1nW1nznNnZyqbG7_XTwii-4DpkHyIRbgkfrZjwIom3uj1F31_r8i18UBQxWL7scHxg"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9wb3NjLzE1MzgwNTEwODI0MzU1NzUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9wb3NjIiwibmFtZSI6InBvc2MiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA4MjQzNTU3NSIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOCIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDo0Mi40MzVaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6NDIuNDM1WiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjQyLjQzNVoiLCJzaXplIjoiMyIsIm1kNUhhc2giOiJyTDBZMjB6QytGenQ3MlZQek1TazJBPT0iLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vcG9zYz9nZW5lcmF0aW9uPTE1MzgwNTEwODI0MzU1NzUmYWx0PW1lZGlhIiwiYWNsIjpbeyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvcG9zYy8xNTM4MDUxMDgyNDM1NTc1L3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vcG9zYy9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJwb3NjIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwODI0MzU1NzUiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNQZjNxT09XMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9wb3NjLzE1MzgwNTEwODI0MzU1NzUvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vcG9zYy9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoicG9zYyIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDgyNDM1NTc1IiwiZW50aXR5IjoicHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6ImVkaXRvcnMifSwiZXRhZyI6IkNQZjNxT09XMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9wb3NjLzE1MzgwNTEwODI0MzU1NzUvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vcG9zYy9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoicG9zYyIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDgyNDM1NTc1IiwiZW50aXR5IjoicHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6IlJFQURFUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJ2aWV3ZXJzIn0sImV0YWciOiJDUGYzcU9PVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvcG9zYy8xNTM4MDUxMDgyNDM1NTc1L3VzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9wb3NjL2FjbC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoicG9zYyIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDgyNDM1NTc1IiwiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInJvbGUiOiJPV05FUiIsImVtYWlsIjoiMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJldGFnIjoiQ1BmM3FPT1cyOTBDRUFFPSJ9XSwib3duZXIiOnsiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSJ9LCJjcmMzMmMiOiJ6OFN1SFE9PSIsImV0YWciOiJDUGYzcU9PVzI5MENFQUU9In0="
+ }
+ },
+ {
+ "ID": "793ce49241ead072",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/posc?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "737703d157645287eed0cf2d581c1afe/17474195298652594480;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/posc?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3221"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:42 GMT"
+ ],
+ "Etag": [
+ "CPf3qOOW290CEAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051382000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrmk10:4329,/bns/yr/borg/yr/bns/blobstore2/bitpusher/22.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=CsysW6T5KYfwkAOekpvQCA"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/22.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/22:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRYnBxTXlCbWNNWUVoeVpDak45TUl5alRkV2U4Tkd3bWM0RktJRUk1NGNIWmhyVTNrbmhKU0pwc1FISTJCQkVVSUdaV29YZ3FhajlBV2hIMEF2TVlYN3V6YVdPRkxfR0hTNnJrcEFrRFZRMzBUdF9uUWFEb1QybXVGRkxYRXBNdnYxOExuX2R1aFZnVnRkdHJlWm9hN21jU3JnMXEtejlocnV2SGxiTzFYbzVvTDRoRUExd3BFOFZ6R1EwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Upl0M0TYF99JpqqHFMfFDcvOI3Kyy2zWEV_5XuTlzdzzvhSphgs--na7KgwhJnlBmAbPwkJ-kQjZ_S2KSNY1WeGO3jt8w"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9wb3NjLzE1MzgwNTEwODI0MzU1NzUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9wb3NjIiwibmFtZSI6InBvc2MiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA4MjQzNTU3NSIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOCIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDo0Mi40MzVaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6NDIuNDM1WiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjQyLjQzNVoiLCJzaXplIjoiMyIsIm1kNUhhc2giOiJyTDBZMjB6QytGenQ3MlZQek1TazJBPT0iLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vcG9zYz9nZW5lcmF0aW9uPTE1MzgwNTEwODI0MzU1NzUmYWx0PW1lZGlhIiwiYWNsIjpbeyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvcG9zYy8xNTM4MDUxMDgyNDM1NTc1L3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vcG9zYy9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJwb3NjIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwODI0MzU1NzUiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNQZjNxT09XMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9wb3NjLzE1MzgwNTEwODI0MzU1NzUvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vcG9zYy9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoicG9zYyIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDgyNDM1NTc1IiwiZW50aXR5IjoicHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6ImVkaXRvcnMifSwiZXRhZyI6IkNQZjNxT09XMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9wb3NjLzE1MzgwNTEwODI0MzU1NzUvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vcG9zYy9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoicG9zYyIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDgyNDM1NTc1IiwiZW50aXR5IjoicHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6IlJFQURFUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJ2aWV3ZXJzIn0sImV0YWciOiJDUGYzcU9PVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvcG9zYy8xNTM4MDUxMDgyNDM1NTc1L3VzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9wb3NjL2FjbC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoicG9zYyIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDgyNDM1NTc1IiwiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInJvbGUiOiJPV05FUiIsImVtYWlsIjoiMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJldGFnIjoiQ1BmM3FPT1cyOTBDRUFFPSJ9XSwib3duZXIiOnsiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSJ9LCJjcmMzMmMiOiJ6OFN1SFE9PSIsImV0YWciOiJDUGYzcU9PVzI5MENFQUU9In0="
+ }
+ },
+ {
+ "ID": "7c3235e94e5f1d49",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/posc/rewriteTo/b/go-integration-test-20180927-44630911863640-0001/o/posc?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "34"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "045d3b6b50ecd5f20e668145d7067f65/617863128993548238;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/posc/rewriteTo/b/go-integration-test-20180927-44630911863640-0001/o/posc?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJzdG9yYWdlQ2xhc3MiOiJNVUxUSV9SRUdJT05BTCJ9Cg=="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3286"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:43 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051382000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrip90:4121,/bns/yr/borg/yr/bns/blobstore2/bitpusher/62.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=CsysW_zAL9Ge4QSorrjYCg"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/62.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/62:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp0ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4StK4wESxgF5YTI5LmMuRW93QkpRYnBxTXlCbWNNWUVoeVpDak45TUl5alRkV2U4Tkd3bWM0RktJRUk1NGNIWmhyVTNrbmhKU0pwc1FISTJCQkVVSUdaV29YZ3FhajlBV2hIMEF2TVlYN3V6YVdPRkxfR0hTNnJrcEFrRFZRMzBUdF9uUWFEb1QybXVGRkxYRXBNdnYxOExuX2R1aFZnVnRkdHJlWm9hN21jU3JnMXEtejlocnV2SGxiTzFYbzVvTDRoRUExd3BFOFZ6R1EwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UpBrEawAqmOFoyRSCwYrTqRiIMbZKnMzvTDTGGVXxV4EvhLJB06Pf06EFZdrIULrUqftTRnOu7rKWfe6FocLDponokX4A"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNyZXdyaXRlUmVzcG9uc2UiLCJ0b3RhbEJ5dGVzUmV3cml0dGVuIjoiMyIsIm9iamVjdFNpemUiOiIzIiwiZG9uZSI6dHJ1ZSwicmVzb3VyY2UiOnsia2luZCI6InN0b3JhZ2Ujb2JqZWN0IiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvcG9zYy8xNTM4MDUxMDgzMjI3NTQ3Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vcG9zYyIsIm5hbWUiOiJwb3NjIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwODMyMjc1NDciLCJtZXRhZ2VuZXJhdGlvbiI6IjEiLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6NDMuMjI1WiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjQzLjIyNVoiLCJzdG9yYWdlQ2xhc3MiOiJNVUxUSV9SRUdJT05BTCIsInRpbWVTdG9yYWdlQ2xhc3NVcGRhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDo0My4yMjVaIiwic2l6ZSI6IjMiLCJtZDVIYXNoIjoickwwWTIwekMrRnp0NzJWUHpNU2syQT09IiwibWVkaWFMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vZG93bmxvYWQvc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL3Bvc2M/Z2VuZXJhdGlvbj0xNTM4MDUxMDgzMjI3NTQ3JmFsdD1tZWRpYSIsImFjbCI6W3sia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL3Bvc2MvMTUzODA1MTA4MzIyNzU0Ny9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL3Bvc2MvYWNsL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoicG9zYyIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDgzMjI3NTQ3IiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDSnVqMmVPVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvcG9zYy8xNTM4MDUxMDgzMjI3NTQ3L3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL3Bvc2MvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6InBvc2MiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA4MzIyNzU0NyIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDSnVqMmVPVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvcG9zYy8xNTM4MDUxMDgzMjI3NTQ3L3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL3Bvc2MvYWNsL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6InBvc2MiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA4MzIyNzU0NyIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0p1ajJlT1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL3Bvc2MvMTUzODA1MTA4MzIyNzU0Ny91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vcG9zYy9hY2wvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6InBvc2MiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA4MzIyNzU0NyIsImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJyb2xlIjoiT1dORVIiLCJlbWFpbCI6IjM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiZXRhZyI6IkNKdWoyZU9XMjkwQ0VBRT0ifV0sIm93bmVyIjp7ImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20ifSwiY3JjMzJjIjoiejhTdUhRPT0iLCJldGFnIjoiQ0p1ajJlT1cyOTBDRUFFPSJ9fQ=="
+ }
+ },
+ {
+ "ID": "7f37efaaa4a10ba0",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Type": [
+ "multipart/related; boundary=f7d76450fb503dd31762a093ee2938e9271649529336ad7573571e65208b"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "5c75bb9317f75305458ad9b585bd658c/1377181569096423966;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "LS1mN2Q3NjQ1MGZiNTAzZGQzMTc2MmEwOTNlZTI5MzhlOTI3MTY0OTUyOTMzNmFkNzU3MzU3MWU2NTIwOGINCkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vanNvbg0KDQp7ImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm5hbWUiOiJwb3NjMiIsInN0b3JhZ2VDbGFzcyI6Ik1VTFRJX1JFR0lPTkFMIn0KDQotLWY3ZDc2NDUwZmI1MDNkZDMxNzYyYTA5M2VlMjkzOGU5MjcxNjQ5NTI5MzM2YWQ3NTczNTcxZTY1MjA4Yg0KQ29udGVudC1UeXBlOiB0ZXh0L3BsYWluOyBjaGFyc2V0PXV0Zi04DQoNCnh4eA0KLS1mN2Q3NjQ1MGZiNTAzZGQzMTc2MmEwOTNlZTI5MzhlOTI3MTY0OTUyOTMzNmFkNzU3MzU3MWU2NTIwOGItLQ0K"
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3243"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:43 GMT"
+ ],
+ "Etag": [
+ "CMvl9+OW290CEAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051382000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrl7:4233,/bns/yv/borg/yv/bns/blobstore2/bitpusher/286.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=C8ysW9TdFsnNgASH64bQDA"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/286.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/286:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRYnBxTXlCbWNNWUVoeVpDak45TUl5alRkV2U4Tkd3bWM0RktJRUk1NGNIWmhyVTNrbmhKU0pwc1FISTJCQkVVSUdaV29YZ3FhajlBV2hIMEF2TVlYN3V6YVdPRkxfR0hTNnJrcEFrRFZRMzBUdF9uUWFEb1QybXVGRkxYRXBNdnYxOExuX2R1aFZnVnRkdHJlWm9hN21jU3JnMXEtejlocnV2SGxiTzFYbzVvTDRoRUExd3BFOFZ6R1EwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_single_post_uploads"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UqQ8mwwlOeS-eMuzlQ-XHX2qnrG-A6DWwm5QKOhddYR2imhlwNxhnpDPJ6_5YhcFF03hm8mYxhq6GM87N4FasQmXuiPiA"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9wb3NjMi8xNTM4MDUxMDgzNzI3NTYzIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vcG9zYzIiLCJuYW1lIjoicG9zYzIiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA4MzcyNzU2MyIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOCIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDo0My43MjdaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6NDMuNzI3WiIsInN0b3JhZ2VDbGFzcyI6Ik1VTFRJX1JFR0lPTkFMIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjQzLjcyN1oiLCJzaXplIjoiMyIsIm1kNUhhc2giOiI5V0dxOXU4TDhVMUNDTHRHcE15enJRPT0iLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vcG9zYzI/Z2VuZXJhdGlvbj0xNTM4MDUxMDgzNzI3NTYzJmFsdD1tZWRpYSIsImFjbCI6W3sia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL3Bvc2MyLzE1MzgwNTEwODM3Mjc1NjMvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9wb3NjMi9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJwb3NjMiIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDgzNzI3NTYzIiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDTXZsOStPVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvcG9zYzIvMTUzODA1MTA4MzcyNzU2My9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9wb3NjMi9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoicG9zYzIiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA4MzcyNzU2MyIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDTXZsOStPVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvcG9zYzIvMTUzODA1MTA4MzcyNzU2My9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9wb3NjMi9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoicG9zYzIiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA4MzcyNzU2MyIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ012bDkrT1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL3Bvc2MyLzE1MzgwNTEwODM3Mjc1NjMvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL3Bvc2MyL2FjbC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoicG9zYzIiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA4MzcyNzU2MyIsImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJyb2xlIjoiT1dORVIiLCJlbWFpbCI6IjM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiZXRhZyI6IkNNdmw5K09XMjkwQ0VBRT0ifV0sIm93bmVyIjp7ImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20ifSwiY3JjMzJjIjoiMTdxQUJRPT0iLCJldGFnIjoiQ012bDkrT1cyOTBDRUFFPSJ9"
+ }
+ },
+ {
+ "ID": "b7982318c88f63e2",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Type": [
+ "multipart/related; boundary=aa69c137381c6410b1a82a7f891a07638054c96a3999bbab84aa50e35e5e"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "5aefb8960730d3277415ebd22c08f057/2208275033060699245;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "LS1hYTY5YzEzNzM4MWM2NDEwYjFhODJhN2Y4OTFhMDc2MzgwNTRjOTZhMzk5OWJiYWI4NGFhNTBlMzVlNWUNCkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vanNvbg0KDQp7ImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm5hbWUiOiJidWNrZXRJbkNvcHlBdHRycyJ9Cg0KLS1hYTY5YzEzNzM4MWM2NDEwYjFhODJhN2Y4OTFhMDc2MzgwNTRjOTZhMzk5OWJiYWI4NGFhNTBlMzVlNWUNCkNvbnRlbnQtVHlwZTogdGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOA0KDQpmb28NCi0tYWE2OWMxMzczODFjNjQxMGIxYTgyYTdmODkxYTA3NjM4MDU0Yzk2YTM5OTliYmFiODRhYTUwZTM1ZTVlLS0NCg=="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3429"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:44 GMT"
+ ],
+ "Etag": [
+ "CNiQluSW290CEAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051383000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrnm19:4486,/bns/yr/borg/yr/bns/blobstore2/bitpusher/32.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=C8ysW9uROMH5kAPknaPwAQ"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/32.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/32:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWTViWV96Nk5YcmI0c3JCbmd1Z0dCRHZSeldidE5ERFcwb201SUtrUENMdWdqUXRtR3dvd1JHbzlCcGtob2NnVEV3dXRLUUpRYXo2UXdNcVpNVGd6UFVzSmpJY3h0OThDVXhQQXpMcGJsUEE4Q1I5ZkNhSmU5bWc3X2pSQ3BJTzRpNWpNbHRfN2w5RnBsbUhqcGl6LVdKSXZ0TDBta1duRVFRR2dmQkJjLXBhbEhleFpWNElHcVQ0YTAwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_single_post_uploads"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UrYaPW-mVsy9yVtUYn-Xa4rHX25K84ldGpiSoDCXIKpmhvHpfE65GhDhdZtVnQnd91KAuaSxTJRfiUwx-4d0WkTWEuKDw"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9idWNrZXRJbkNvcHlBdHRycy8xNTM4MDUxMDg0MjI0NjAwIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vYnVja2V0SW5Db3B5QXR0cnMiLCJuYW1lIjoiYnVja2V0SW5Db3B5QXR0cnMiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA4NDIyNDYwMCIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOCIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDo0NC4yMjRaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6NDQuMjI0WiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjQ0LjIyNFoiLCJzaXplIjoiMyIsIm1kNUhhc2giOiJyTDBZMjB6QytGenQ3MlZQek1TazJBPT0iLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vYnVja2V0SW5Db3B5QXR0cnM/Z2VuZXJhdGlvbj0xNTM4MDUxMDg0MjI0NjAwJmFsdD1tZWRpYSIsImFjbCI6W3sia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2J1Y2tldEluQ29weUF0dHJzLzE1MzgwNTEwODQyMjQ2MDAvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9idWNrZXRJbkNvcHlBdHRycy9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJidWNrZXRJbkNvcHlBdHRycyIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDg0MjI0NjAwIiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDTmlRbHVTVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvYnVja2V0SW5Db3B5QXR0cnMvMTUzODA1MTA4NDIyNDYwMC9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9idWNrZXRJbkNvcHlBdHRycy9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiYnVja2V0SW5Db3B5QXR0cnMiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA4NDIyNDYwMCIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDTmlRbHVTVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvYnVja2V0SW5Db3B5QXR0cnMvMTUzODA1MTA4NDIyNDYwMC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9idWNrZXRJbkNvcHlBdHRycy9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiYnVja2V0SW5Db3B5QXR0cnMiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA4NDIyNDYwMCIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ05pUWx1U1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2J1Y2tldEluQ29weUF0dHJzLzE1MzgwNTEwODQyMjQ2MDAvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2J1Y2tldEluQ29weUF0dHJzL2FjbC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiYnVja2V0SW5Db3B5QXR0cnMiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA4NDIyNDYwMCIsImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJyb2xlIjoiT1dORVIiLCJlbWFpbCI6IjM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiZXRhZyI6IkNOaVFsdVNXMjkwQ0VBRT0ifV0sIm93bmVyIjp7ImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20ifSwiY3JjMzJjIjoiejhTdUhRPT0iLCJldGFnIjoiQ05pUWx1U1cyOTBDRUFFPSJ9"
+ }
+ },
+ {
+ "ID": "b63232023ceca5a0",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/bucketInCopyAttrs/rewriteTo/b/go-integration-test-20180927-44630911863640-0001/o/bucketInCopyAttrs?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "62"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "b359f31e9eda65b74dd2328cf1897da5/2967312002481897404;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/bucketInCopyAttrs/rewriteTo/b/go-integration-test-20180927-44630911863640-0001/o/bucketInCopyAttrs?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEifQo="
+ },
+ "Response": {
+ "StatusCode": 400,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Content-Length": [
+ "2928"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:44 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051384000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrhj8:4264,/bns/yv/borg/yv/bns/blobstore2/bitpusher/235.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=DMysW_maFYnuggSJ1Lr4CQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/235.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/235:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp0ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4StK4wESxgF5YTI5LmMuRW93QkpRWTViWV96Nk5YcmI0c3JCbmd1Z0dCRHZSeldidE5ERFcwb201SUtrUENMdWdqUXRtR3dvd1JHbzlCcGtob2NnVEV3dXRLUUpRYXo2UXdNcVpNVGd6UFVzSmpJY3h0OThDVXhQQXpMcGJsUEE4Q1I5ZkNhSmU5bWc3X2pSQ3BJTzRpNWpNbHRfN2w5RnBsbUhqcGl6LVdKSXZ0TDBta1duRVFRR2dmQkJjLXBhbEhleFpWNElHcVQ0YTAwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Upload-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UoDa0ITv4m8GBWZHkTRpUkhju59P-najn0K-qoegCn7bEUdjhc_c1kkm7BxbRXNMyCnqbLk4SjpJ8HgfxmBi4jHK9s8RQ"
+ ]
+ },
+ "Body": "eyJlcnJvciI6eyJlcnJvcnMiOlt7ImRvbWFpbiI6Imdsb2JhbCIsInJlYXNvbiI6InJlcXVpcmVkIiwibWVzc2FnZSI6IlJlcXVpcmVkIiwiZGVidWdJbmZvIjoiY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUuRmF1bHQ6IEltbXV0YWJsZUVycm9yRGVmaW5pdGlvbntiYXNlPVJFUVVJUkVELCBjYXRlZ29yeT1VU0VSX0VSUk9SLCBjYXVzZT1udWxsLCBkZWJ1Z0luZm89bnVsbCwgZG9tYWluPWdsb2JhbCwgZXh0ZW5kZWRIZWxwPW51bGwsIGh0dHBIZWFkZXJzPXt9LCBodHRwU3RhdHVzPWJhZFJlcXVlc3QsIGludGVybmFsUmVhc29uPVJlYXNvbnthcmd1bWVudHM9e30sIGNhdXNlPW51bGwsIGNvZGU9Z2RhdGEuQ29yZUVycm9yRG9tYWluLlJFUVVJUkVELCBjcmVhdGVkQnlCYWNrZW5kPXRydWUsIGRlYnVnTWVzc2FnZT1udWxsLCBlcnJvclByb3RvQ29kZT1SRVFVSVJFRCwgZXJyb3JQcm90b0RvbWFpbj1nZGF0YS5Db3JlRXJyb3JEb21haW4sIGZpbHRlcmVkTWVzc2FnZT1udWxsLCBsb2NhdGlvbj1lbnRpdHkuZGVzdGluYXRpb25fcmVzb3VyY2UuaWQubmFtZSwgbWVzc2FnZT1udWxsLCB1bm5hbWVkQXJndW1lbnRzPVtdfSwgbG9jYXRpb249ZW50aXR5LmRlc3RpbmF0aW9uX3Jlc291cmNlLmlkLm5hbWUsIG1lc3NhZ2U9UmVxdWlyZWQsIHJlYXNvbj1yZXF1aXJlZCwgcnBjQ29kZT00MDB9IFJlcXVpcmVkXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLkVycm9yQ29sbGVjdG9yLnRvRmF1bHQoRXJyb3JDb2xsZWN0b3IuamF2YTo1NClcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnJlc3QuYWRhcHRlci5yb3N5LlJvc3lFcnJvckNvbnZlcnRlci50b0ZhdWx0KFJvc3lFcnJvckNvbnZlcnRlci5qYXZhOjY3KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIucmVzdC5hZGFwdGVyLnJvc3kuUm9zeUhhbmRsZXIkMi5jYWxsKFJvc3lIYW5kbGVyLmphdmE6MjU4KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIucmVzdC5hZGFwdGVyLnJvc3kuUm9zeUhhbmRsZXIkMi5jYWxsKFJvc3lIYW5kbGVyLmphdmE6MjM4KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS51dGlsLkNhbGxhYmxlRnV0dXJlLnJ1bihDYWxsYWJsZUZ1dHVyZS5qYXZhOjYyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuRGlyZWN0RXhlY3V0b3IuZXhlY3V0ZShEaXJlY3RFeGVjdXRvci5qYXZhOjMwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuZXhlY3V0ZUxpc3RlbmVyKEFic3RyYWN0RnV0dXJlLmphdmE6MTE0Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmNvbXBsZXRlKEFic3RyYWN0RnV0dXJlLmphdmE6OTYzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuc2V0KEFic3RyYWN0RnV0dXJlLmphdmE6NzMxKVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS51dGlsLkNhbGxhYmxlRnV0dXJlLnJ1bihDYWxsYWJsZUZ1dHVyZS5qYXZhOjYyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuRGlyZWN0RXhlY3V0b3IuZXhlY3V0ZShEaXJlY3RFeGVjdXRvci5qYXZhOjMwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuZXhlY3V0ZUxpc3RlbmVyKEFic3RyYWN0RnV0dXJlLmphdmE6MTE0Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmNvbXBsZXRlKEFic3RyYWN0RnV0dXJlLmphdmE6OTYzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuc2V0KEFic3RyYWN0RnV0dXJlLmphdmE6NzMxKVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS51dGlsLkNhbGxhYmxlRnV0dXJlLnJ1bihDYWxsYWJsZUZ1dHVyZS5qYXZhOjYyKVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIudGhyZWFkLlRocmVhZFRyYWNrZXJzJFRocmVhZFRyYWNraW5nUnVubmFibGUucnVuKFRocmVhZFRyYWNrZXJzLmphdmE6MTI2KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JFRyYWNlQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChUcmFjZUNvbnRleHQuamF2YTo0NTUpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5zZXJ2ZXIuQ29tbW9uTW9kdWxlJENvbnRleHRDYXJyeWluZ0V4ZWN1dG9yU2VydmljZSQxLnJ1bkluQ29udGV4dChDb21tb25Nb2R1bGUuamF2YTo4NDYpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkVHJhY2VDb250ZXh0UnVubmFibGUkMS5ydW4oVHJhY2VDb250ZXh0LmphdmE6NDYyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JEFic3RyYWN0VHJhY2VDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihUcmFjZUNvbnRleHQuamF2YTozMjEpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkQWJzdHJhY3RUcmFjZUNvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoVHJhY2VDb250ZXh0LmphdmE6MzEzKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JFRyYWNlQ29udGV4dFJ1bm5hYmxlLnJ1bihUcmFjZUNvbnRleHQuamF2YTo0NTkpXG5cdGF0IGNvbS5nb29nbGUuZ3NlLmludGVybmFsLkRpc3BhdGNoUXVldWVJbXBsJFdvcmtlclRocmVhZC5ydW4oRGlzcGF0Y2hRdWV1ZUltcGwuamF2YTo0MDMpXG4ifV0sImNvZGUiOjQwMCwibWVzc2FnZSI6IlJlcXVpcmVkIn19"
+ }
+ },
+ {
+ "ID": "f39634171d163619",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Type": [
+ "multipart/related; boundary=9c11bb8c567eb4b2238e0f29baabdad7310c3407295239aab1f1ba158385"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "02e34d54248307bc8698501b08b37d8b/3798686937111073292;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "LS05YzExYmI4YzU2N2ViNGIyMjM4ZTBmMjliYWFiZGFkNzMxMGMzNDA3Mjk1MjM5YWFiMWYxYmExNTgzODUNCkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vanNvbg0KDQp7ImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsImNyYzMyYyI6ImNIK0Erdz09IiwibmFtZSI6Imhhc2hlc09uVXBsb2FkLTEifQoNCi0tOWMxMWJiOGM1NjdlYjRiMjIzOGUwZjI5YmFhYmRhZDczMTBjMzQwNzI5NTIzOWFhYjFmMWJhMTU4Mzg1DQpDb250ZW50LVR5cGU6IHRleHQvcGxhaW47IGNoYXJzZXQ9dXRmLTgNCg0KSSBjYW4ndCB3YWl0IHRvIGJlIHZlcmlmaWVkDQotLTljMTFiYjhjNTY3ZWI0YjIyMzhlMGYyOWJhYWJkYWQ3MzEwYzM0MDcyOTUyMzlhYWIxZjFiYTE1ODM4NS0tDQo="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3414"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:45 GMT"
+ ],
+ "Etag": [
+ "CLmKweSW290CEAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051384000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrat7:4174,/bns/yv/borg/yv/bns/blobstore2/bitpusher/208.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=DMysW7TbHcvWgwSzu6-IBw"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/208.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/208:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRYXdSQ1M2WXgtYjJEdmpBazA2dXVSS2FmSHRBSDFRYVk3ZmNZa3VsaXNyU19rbDJRRjJNMU1oUG5UX0wwelFUa1cwbkNkQ282RXlfckF5Y2J4aFdVQzh6SXIwMFZTaXJWaElfSWgzWlljc3VRQXR6eXk3ZXdYUTlYemJ0VjM0Tm9yZzBlUFNmaWFJTjlOVWtXY0NUbWY3cXczRkNWZWhHSFZUaW1OY1hFOXhyV3ZYY0FMZzR4N2JXV3MwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_single_post_uploads"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UrPbPHpxg2xi0jHMzfoGOksYnVbrNPFBA79OwbWop7GQk-hQCVhdQHH2oJuWzqkHO0nR-jdQzk7DI2SD2lwslSB7r16lg"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9oYXNoZXNPblVwbG9hZC0xLzE1MzgwNTEwODQ5MjgzMTMiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9oYXNoZXNPblVwbG9hZC0xIiwibmFtZSI6Imhhc2hlc09uVXBsb2FkLTEiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA4NDkyODMxMyIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOCIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDo0NC45MjhaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6NDQuOTI4WiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjQ0LjkyOFoiLCJzaXplIjoiMjciLCJtZDVIYXNoIjoib2ZaakdsY1hQSmlHT0FmS0ZiSmwxUT09IiwibWVkaWFMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vZG93bmxvYWQvc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2hhc2hlc09uVXBsb2FkLTE/Z2VuZXJhdGlvbj0xNTM4MDUxMDg0OTI4MzEzJmFsdD1tZWRpYSIsImFjbCI6W3sia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2hhc2hlc09uVXBsb2FkLTEvMTUzODA1MTA4NDkyODMxMy9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2hhc2hlc09uVXBsb2FkLTEvYWNsL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiaGFzaGVzT25VcGxvYWQtMSIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDg0OTI4MzEzIiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDTG1Ld2VTVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvaGFzaGVzT25VcGxvYWQtMS8xNTM4MDUxMDg0OTI4MzEzL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2hhc2hlc09uVXBsb2FkLTEvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Imhhc2hlc09uVXBsb2FkLTEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA4NDkyODMxMyIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDTG1Ld2VTVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvaGFzaGVzT25VcGxvYWQtMS8xNTM4MDUxMDg0OTI4MzEzL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2hhc2hlc09uVXBsb2FkLTEvYWNsL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Imhhc2hlc09uVXBsb2FkLTEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA4NDkyODMxMyIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0xtS3dlU1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2hhc2hlc09uVXBsb2FkLTEvMTUzODA1MTA4NDkyODMxMy91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vaGFzaGVzT25VcGxvYWQtMS9hY2wvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Imhhc2hlc09uVXBsb2FkLTEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA4NDkyODMxMyIsImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJyb2xlIjoiT1dORVIiLCJlbWFpbCI6IjM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiZXRhZyI6IkNMbUt3ZVNXMjkwQ0VBRT0ifV0sIm93bmVyIjp7ImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20ifSwiY3JjMzJjIjoiY0grQSt3PT0iLCJldGFnIjoiQ0xtS3dlU1cyOTBDRUFFPSJ9"
+ }
+ },
+ {
+ "ID": "a769205b3700f7a4",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Type": [
+ "multipart/related; boundary=24b4b20cd70ea2c753252870eee82bd68cf04ff437d12f5e2a35bf547a58"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "d8ef1d10c2ba55e62a6a721e3236b56c/4557723906532271451;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "LS0yNGI0YjIwY2Q3MGVhMmM3NTMyNTI4NzBlZWU4MmJkNjhjZjA0ZmY0MzdkMTJmNWUyYTM1YmY1NDdhNTgNCkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vanNvbg0KDQp7ImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsImNyYzMyYyI6ImNIK0EvQT09IiwibmFtZSI6Imhhc2hlc09uVXBsb2FkLTEifQoNCi0tMjRiNGIyMGNkNzBlYTJjNzUzMjUyODcwZWVlODJiZDY4Y2YwNGZmNDM3ZDEyZjVlMmEzNWJmNTQ3YTU4DQpDb250ZW50LVR5cGU6IHRleHQvcGxhaW47IGNoYXJzZXQ9dXRmLTgNCg0KSSBjYW4ndCB3YWl0IHRvIGJlIHZlcmlmaWVkDQotLTI0YjRiMjBjZDcwZWEyYzc1MzI1Mjg3MGVlZTgyYmQ2OGNmMDRmZjQzN2QxMmY1ZTJhMzViZjU0N2E1OC0tDQo="
+ },
+ "Response": {
+ "StatusCode": 400,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Content-Length": [
+ "3257"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:45 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051384000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrgb22:4240,/bns/yv/borg/yv/bns/blobstore2/bitpusher/396.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=DcysW66WCpGegQT-37-ACg"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/396.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/396:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRYXdSQ1M2WXgtYjJEdmpBazA2dXVSS2FmSHRBSDFRYVk3ZmNZa3VsaXNyU19rbDJRRjJNMU1oUG5UX0wwelFUa1cwbkNkQ282RXlfckF5Y2J4aFdVQzh6SXIwMFZTaXJWaElfSWgzWlljc3VRQXR6eXk3ZXdYUTlYemJ0VjM0Tm9yZzBlUFNmaWFJTjlOVWtXY0NUbWY3cXczRkNWZWhHSFZUaW1OY1hFOXhyV3ZYY0FMZzR4N2JXV3MwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_single_post_uploads"
+ ],
+ "X-Guploader-Request-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Upload-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Upo2Hgvl8XFud5oC3c-w4GBCnJ2pRoOuEIWiuJzNB7V_G-pdPLCzNdA4b9hBDqGf0zxjHaI7YyjF1fa5PoVg6u0GtAvkA"
+ ]
+ },
+ "Body": "eyJlcnJvciI6eyJlcnJvcnMiOlt7ImRvbWFpbiI6Imdsb2JhbCIsInJlYXNvbiI6ImludmFsaWQiLCJtZXNzYWdlIjoiUHJvdmlkZWQgQ1JDMzJDIFwiY0grQS9BPT1cIiBkb2Vzbid0IG1hdGNoIGNhbGN1bGF0ZWQgQ1JDMzJDIFwiY0grQSt3PT1cIi4iLCJkZWJ1Z0luZm8iOiJjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS5GYXVsdDogSW1tdXRhYmxlRXJyb3JEZWZpbml0aW9ue2Jhc2U9SU5WQUxJRF9WQUxVRSwgY2F0ZWdvcnk9VVNFUl9FUlJPUiwgY2F1c2U9bnVsbCwgZGVidWdJbmZvPW51bGwsIGRvbWFpbj1nbG9iYWwsIGV4dGVuZGVkSGVscD1udWxsLCBodHRwSGVhZGVycz17fSwgaHR0cFN0YXR1cz1iYWRSZXF1ZXN0LCBpbnRlcm5hbFJlYXNvbj1SZWFzb257YXJndW1lbnRzPXt9LCBjYXVzZT1udWxsLCBjb2RlPWdkYXRhLkNvcmVFcnJvckRvbWFpbi5JTlZBTElEX1ZBTFVFLCBjcmVhdGVkQnlCYWNrZW5kPXRydWUsIGRlYnVnTWVzc2FnZT1udWxsLCBlcnJvclByb3RvQ29kZT1JTlZBTElEX1ZBTFVFLCBlcnJvclByb3RvRG9tYWluPWdkYXRhLkNvcmVFcnJvckRvbWFpbiwgZmlsdGVyZWRNZXNzYWdlPW51bGwsIGxvY2F0aW9uPWVudGl0eS5yZXNvdXJjZS5jcmMzMmMsIG1lc3NhZ2U9UHJvdmlkZWQgQ1JDMzJDIFwiY0grQS9BPT1cIiBkb2Vzbid0IG1hdGNoIGNhbGN1bGF0ZWQgQ1JDMzJDIFwiY0grQSt3PT1cIi4sIHVubmFtZWRBcmd1bWVudHM9W2NIK0EvQT09XX0sIGxvY2F0aW9uPWVudGl0eS5yZXNvdXJjZS5jcmMzMmMsIG1lc3NhZ2U9UHJvdmlkZWQgQ1JDMzJDIFwiY0grQS9BPT1cIiBkb2Vzbid0IG1hdGNoIGNhbGN1bGF0ZWQgQ1JDMzJDIFwiY0grQSt3PT1cIi4sIHJlYXNvbj1pbnZhbGlkLCBycGNDb2RlPTQwMH0gUHJvdmlkZWQgQ1JDMzJDIFwiY0grQS9BPT1cIiBkb2Vzbid0IG1hdGNoIGNhbGN1bGF0ZWQgQ1JDMzJDIFwiY0grQSt3PT1cIi5cblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUuRXJyb3JDb2xsZWN0b3IudG9GYXVsdChFcnJvckNvbGxlY3Rvci5qYXZhOjU0KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIucmVzdC5hZGFwdGVyLnJvc3kuUm9zeUVycm9yQ29udmVydGVyLnRvRmF1bHQoUm9zeUVycm9yQ29udmVydGVyLmphdmE6NjcpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5yZXN0LmFkYXB0ZXIucm9zeS5Sb3N5SGFuZGxlciQyLmNhbGwoUm9zeUhhbmRsZXIuamF2YToyNTgpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5yZXN0LmFkYXB0ZXIucm9zeS5Sb3N5SGFuZGxlciQyLmNhbGwoUm9zeUhhbmRsZXIuamF2YToyMzgpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLnV0aWwuQ2FsbGFibGVGdXR1cmUucnVuKENhbGxhYmxlRnV0dXJlLmphdmE6NjIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5EaXJlY3RFeGVjdXRvci5leGVjdXRlKERpcmVjdEV4ZWN1dG9yLmphdmE6MzApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5leGVjdXRlTGlzdGVuZXIoQWJzdHJhY3RGdXR1cmUuamF2YToxMTQzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuY29tcGxldGUoQWJzdHJhY3RGdXR1cmUuamF2YTo5NjMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5zZXQoQWJzdHJhY3RGdXR1cmUuamF2YTo3MzEpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLnV0aWwuQ2FsbGFibGVGdXR1cmUucnVuKENhbGxhYmxlRnV0dXJlLmphdmE6NjIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5EaXJlY3RFeGVjdXRvci5leGVjdXRlKERpcmVjdEV4ZWN1dG9yLmphdmE6MzApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5leGVjdXRlTGlzdGVuZXIoQWJzdHJhY3RGdXR1cmUuamF2YToxMTQzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuY29tcGxldGUoQWJzdHJhY3RGdXR1cmUuamF2YTo5NjMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5zZXQoQWJzdHJhY3RGdXR1cmUuamF2YTo3MzEpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLnV0aWwuQ2FsbGFibGVGdXR1cmUucnVuKENhbGxhYmxlRnV0dXJlLmphdmE6NjIpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci50aHJlYWQuVGhyZWFkVHJhY2tlcnMkVGhyZWFkVHJhY2tpbmdSdW5uYWJsZS5ydW4oVGhyZWFkVHJhY2tlcnMuamF2YToxMjYpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkVHJhY2VDb250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KFRyYWNlQ29udGV4dC5qYXZhOjQ1NSlcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnNlcnZlci5Db21tb25Nb2R1bGUkQ29udGV4dENhcnJ5aW5nRXhlY3V0b3JTZXJ2aWNlJDEucnVuSW5Db250ZXh0KENvbW1vbk1vZHVsZS5qYXZhOjg0Nilcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRUcmFjZUNvbnRleHRSdW5uYWJsZSQxLnJ1bihUcmFjZUNvbnRleHQuamF2YTo0NjIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkQWJzdHJhY3RUcmFjZUNvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKFRyYWNlQ29udGV4dC5qYXZhOjMyMSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRBYnN0cmFjdFRyYWNlQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChUcmFjZUNvbnRleHQuamF2YTozMTMpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkVHJhY2VDb250ZXh0UnVubmFibGUucnVuKFRyYWNlQ29udGV4dC5qYXZhOjQ1OSlcblx0YXQgY29tLmdvb2dsZS5nc2UuaW50ZXJuYWwuRGlzcGF0Y2hRdWV1ZUltcGwkV29ya2VyVGhyZWFkLnJ1bihEaXNwYXRjaFF1ZXVlSW1wbC5qYXZhOjQwMylcbiJ9XSwiY29kZSI6NDAwLCJtZXNzYWdlIjoiUHJvdmlkZWQgQ1JDMzJDIFwiY0grQS9BPT1cIiBkb2Vzbid0IG1hdGNoIGNhbGN1bGF0ZWQgQ1JDMzJDIFwiY0grQSt3PT1cIi4ifX0="
+ }
+ },
+ {
+ "ID": "ef48f17d06d0157a",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Type": [
+ "multipart/related; boundary=810d5c6fdc019b24eacbdf8682c8627d6590a79b617cff6feb47a044a0b1"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "07d0fdae8f7007415ffc49d93dd59bb2/5389098841178290090;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "LS04MTBkNWM2ZmRjMDE5YjI0ZWFjYmRmODY4MmM4NjI3ZDY1OTBhNzliNjE3Y2ZmNmZlYjQ3YTA0NGEwYjENCkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vanNvbg0KDQp7ImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm5hbWUiOiJoYXNoZXNPblVwbG9hZC0xIn0KDQotLTgxMGQ1YzZmZGMwMTliMjRlYWNiZGY4NjgyYzg2MjdkNjU5MGE3OWI2MTdjZmY2ZmViNDdhMDQ0YTBiMQ0KQ29udGVudC1UeXBlOiB0ZXh0L3BsYWluOyBjaGFyc2V0PXV0Zi04DQoNCkkgY2FuJ3Qgd2FpdCB0byBiZSB2ZXJpZmllZA0KLS04MTBkNWM2ZmRjMDE5YjI0ZWFjYmRmODY4MmM4NjI3ZDY1OTBhNzliNjE3Y2ZmNmZlYjQ3YTA0NGEwYjEtLQ0K"
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3414"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:45 GMT"
+ ],
+ "Etag": [
+ "CN6r5uSW290CEAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051384000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrkb18:4313,/bns/yr/borg/yr/bns/blobstore2/bitpusher/108.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=DcysW86fDYSf4QTOgaLYAg"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/108.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/108:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRYXdSQ1M2WXgtYjJEdmpBazA2dXVSS2FmSHRBSDFRYVk3ZmNZa3VsaXNyU19rbDJRRjJNMU1oUG5UX0wwelFUa1cwbkNkQ282RXlfckF5Y2J4aFdVQzh6SXIwMFZTaXJWaElfSWgzWlljc3VRQXR6eXk3ZXdYUTlYemJ0VjM0Tm9yZzBlUFNmaWFJTjlOVWtXY0NUbWY3cXczRkNWZWhHSFZUaW1OY1hFOXhyV3ZYY0FMZzR4N2JXV3MwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_single_post_uploads"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UrS6-Vhz80rJNSjtGGXmdL55rkkvP0-kGTd4jruD1fpNr1WUVbnNm2DyoUOF72Xjr7cMMKCr4SLBMAy0rLCnjApMSNnOg"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9oYXNoZXNPblVwbG9hZC0xLzE1MzgwNTEwODU1Mzg3ODIiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9oYXNoZXNPblVwbG9hZC0xIiwibmFtZSI6Imhhc2hlc09uVXBsb2FkLTEiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA4NTUzODc4MiIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOCIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDo0NS41MzhaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6NDUuNTM4WiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjQ1LjUzOFoiLCJzaXplIjoiMjciLCJtZDVIYXNoIjoib2ZaakdsY1hQSmlHT0FmS0ZiSmwxUT09IiwibWVkaWFMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vZG93bmxvYWQvc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2hhc2hlc09uVXBsb2FkLTE/Z2VuZXJhdGlvbj0xNTM4MDUxMDg1NTM4NzgyJmFsdD1tZWRpYSIsImFjbCI6W3sia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2hhc2hlc09uVXBsb2FkLTEvMTUzODA1MTA4NTUzODc4Mi9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2hhc2hlc09uVXBsb2FkLTEvYWNsL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiaGFzaGVzT25VcGxvYWQtMSIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDg1NTM4NzgyIiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDTjZyNXVTVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvaGFzaGVzT25VcGxvYWQtMS8xNTM4MDUxMDg1NTM4NzgyL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2hhc2hlc09uVXBsb2FkLTEvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Imhhc2hlc09uVXBsb2FkLTEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA4NTUzODc4MiIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDTjZyNXVTVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvaGFzaGVzT25VcGxvYWQtMS8xNTM4MDUxMDg1NTM4NzgyL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2hhc2hlc09uVXBsb2FkLTEvYWNsL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Imhhc2hlc09uVXBsb2FkLTEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA4NTUzODc4MiIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ042cjV1U1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2hhc2hlc09uVXBsb2FkLTEvMTUzODA1MTA4NTUzODc4Mi91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vaGFzaGVzT25VcGxvYWQtMS9hY2wvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Imhhc2hlc09uVXBsb2FkLTEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA4NTUzODc4MiIsImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJyb2xlIjoiT1dORVIiLCJlbWFpbCI6IjM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiZXRhZyI6IkNONnI1dVNXMjkwQ0VBRT0ifV0sIm93bmVyIjp7ImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20ifSwiY3JjMzJjIjoiY0grQSt3PT0iLCJldGFnIjoiQ042cjV1U1cyOTBDRUFFPSJ9"
+ }
+ },
+ {
+ "ID": "aeb6be04bcc74ba0",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Type": [
+ "multipart/related; boundary=ae418d65701db297ce527d2c120467ecb1ee80f563d94aee4866cbc0fd1b"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "25460195dd401365eac6bbd3a60d65a6/6148135806304520954;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "LS1hZTQxOGQ2NTcwMWRiMjk3Y2U1MjdkMmMxMjA0NjdlY2IxZWU4MGY1NjNkOTRhZWU0ODY2Y2JjMGZkMWINCkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vanNvbg0KDQp7ImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm1kNUhhc2giOiJvZlpqR2xjWFBKaUdPQWZLRmJKbDFRPT0iLCJuYW1lIjoiaGFzaGVzT25VcGxvYWQtMSJ9Cg0KLS1hZTQxOGQ2NTcwMWRiMjk3Y2U1MjdkMmMxMjA0NjdlY2IxZWU4MGY1NjNkOTRhZWU0ODY2Y2JjMGZkMWINCkNvbnRlbnQtVHlwZTogdGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOA0KDQpJIGNhbid0IHdhaXQgdG8gYmUgdmVyaWZpZWQNCi0tYWU0MThkNjU3MDFkYjI5N2NlNTI3ZDJjMTIwNDY3ZWNiMWVlODBmNTYzZDk0YWVlNDg2NmNiYzBmZDFiLS0NCg=="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3414"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:46 GMT"
+ ],
+ "Etag": [
+ "CP+iiuWW290CEAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051384000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrv5:4481,/bns/yv/borg/yv/bns/blobstore2/bitpusher/192.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=DcysW4P-L8HMggTy3YG4Bw"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/192.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/192:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRYXdSQ1M2WXgtYjJEdmpBazA2dXVSS2FmSHRBSDFRYVk3ZmNZa3VsaXNyU19rbDJRRjJNMU1oUG5UX0wwelFUa1cwbkNkQ282RXlfckF5Y2J4aFdVQzh6SXIwMFZTaXJWaElfSWgzWlljc3VRQXR6eXk3ZXdYUTlYemJ0VjM0Tm9yZzBlUFNmaWFJTjlOVWtXY0NUbWY3cXczRkNWZWhHSFZUaW1OY1hFOXhyV3ZYY0FMZzR4N2JXV3MwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_single_post_uploads"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Uri8JdVC7RYskcBM7EGhdtoW5uklcAnOgF98hGO545bvZD8IZyoFJ244dd5cMUw1-BPBoJPZvrk2B9_Lpki5xeRUxX_tw"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9oYXNoZXNPblVwbG9hZC0xLzE1MzgwNTEwODYxMjc0ODciLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9oYXNoZXNPblVwbG9hZC0xIiwibmFtZSI6Imhhc2hlc09uVXBsb2FkLTEiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA4NjEyNzQ4NyIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOCIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDo0Ni4xMjdaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6NDYuMTI3WiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjQ2LjEyN1oiLCJzaXplIjoiMjciLCJtZDVIYXNoIjoib2ZaakdsY1hQSmlHT0FmS0ZiSmwxUT09IiwibWVkaWFMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vZG93bmxvYWQvc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2hhc2hlc09uVXBsb2FkLTE/Z2VuZXJhdGlvbj0xNTM4MDUxMDg2MTI3NDg3JmFsdD1tZWRpYSIsImFjbCI6W3sia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2hhc2hlc09uVXBsb2FkLTEvMTUzODA1MTA4NjEyNzQ4Ny9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2hhc2hlc09uVXBsb2FkLTEvYWNsL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiaGFzaGVzT25VcGxvYWQtMSIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDg2MTI3NDg3IiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDUCtpaXVXVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvaGFzaGVzT25VcGxvYWQtMS8xNTM4MDUxMDg2MTI3NDg3L3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2hhc2hlc09uVXBsb2FkLTEvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Imhhc2hlc09uVXBsb2FkLTEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA4NjEyNzQ4NyIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDUCtpaXVXVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvaGFzaGVzT25VcGxvYWQtMS8xNTM4MDUxMDg2MTI3NDg3L3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2hhc2hlc09uVXBsb2FkLTEvYWNsL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Imhhc2hlc09uVXBsb2FkLTEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA4NjEyNzQ4NyIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ1AraWl1V1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2hhc2hlc09uVXBsb2FkLTEvMTUzODA1MTA4NjEyNzQ4Ny91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vaGFzaGVzT25VcGxvYWQtMS9hY2wvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Imhhc2hlc09uVXBsb2FkLTEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA4NjEyNzQ4NyIsImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJyb2xlIjoiT1dORVIiLCJlbWFpbCI6IjM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiZXRhZyI6IkNQK2lpdVdXMjkwQ0VBRT0ifV0sIm93bmVyIjp7ImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20ifSwiY3JjMzJjIjoiY0grQSt3PT0iLCJldGFnIjoiQ1AraWl1V1cyOTBDRUFFPSJ9"
+ }
+ },
+ {
+ "ID": "25cfb3bb34ff59eb",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Type": [
+ "multipart/related; boundary=0624f19c3413a5672f41d77972dec9fc931b569bfd152be7463506856c40"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "7b7d2972cae2d70e4f634e9d1c57cd4b/6979228170757168457;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "LS0wNjI0ZjE5YzM0MTNhNTY3MmY0MWQ3Nzk3MmRlYzlmYzkzMWI1NjliZmQxNTJiZTc0NjM1MDY4NTZjNDANCkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vanNvbg0KDQp7ImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm1kNUhhc2giOiJvdlpqR2xjWFBKaUdPQWZLRmJKbDFRPT0iLCJuYW1lIjoiaGFzaGVzT25VcGxvYWQtMSJ9Cg0KLS0wNjI0ZjE5YzM0MTNhNTY3MmY0MWQ3Nzk3MmRlYzlmYzkzMWI1NjliZmQxNTJiZTc0NjM1MDY4NTZjNDANCkNvbnRlbnQtVHlwZTogdGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOA0KDQpJIGNhbid0IHdhaXQgdG8gYmUgdmVyaWZpZWQNCi0tMDYyNGYxOWMzNDEzYTU2NzJmNDFkNzc5NzJkZWM5ZmM5MzFiNTY5YmZkMTUyYmU3NDYzNTA2ODU2YzQwLS0NCg=="
+ },
+ "Response": {
+ "StatusCode": 400,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Content-Length": [
+ "3471"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:46 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051384000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrmj23:4408,/bns/yv/borg/yv/bns/blobstore2/bitpusher/357.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=DsysW_WBD5CDgQS0t7uoDw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/357.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/357:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRYXdSQ1M2WXgtYjJEdmpBazA2dXVSS2FmSHRBSDFRYVk3ZmNZa3VsaXNyU19rbDJRRjJNMU1oUG5UX0wwelFUa1cwbkNkQ282RXlfckF5Y2J4aFdVQzh6SXIwMFZTaXJWaElfSWgzWlljc3VRQXR6eXk3ZXdYUTlYemJ0VjM0Tm9yZzBlUFNmaWFJTjlOVWtXY0NUbWY3cXczRkNWZWhHSFZUaW1OY1hFOXhyV3ZYY0FMZzR4N2JXV3MwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_single_post_uploads"
+ ],
+ "X-Guploader-Request-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Upload-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Uq8erhdm1paZ3UEIZubqTKU1EnYYuNgJe_aTfqhN8EodeBZORHefCWBiS9HdJUW3k020eEt1eOLWzuCC5gofjTnHsco7A"
+ ]
+ },
+ "Body": "eyJlcnJvciI6eyJlcnJvcnMiOlt7ImRvbWFpbiI6Imdsb2JhbCIsInJlYXNvbiI6ImludmFsaWQiLCJtZXNzYWdlIjoiUHJvdmlkZWQgTUQ1IGhhc2ggXCJvdlpqR2xjWFBKaUdPQWZLRmJKbDFRPT1cIiBkb2Vzbid0IG1hdGNoIGNhbGN1bGF0ZWQgTUQ1IGhhc2ggXCJvZlpqR2xjWFBKaUdPQWZLRmJKbDFRPT1cIi4iLCJkZWJ1Z0luZm8iOiJjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS5GYXVsdDogSW1tdXRhYmxlRXJyb3JEZWZpbml0aW9ue2Jhc2U9SU5WQUxJRF9WQUxVRSwgY2F0ZWdvcnk9VVNFUl9FUlJPUiwgY2F1c2U9bnVsbCwgZGVidWdJbmZvPW51bGwsIGRvbWFpbj1nbG9iYWwsIGV4dGVuZGVkSGVscD1udWxsLCBodHRwSGVhZGVycz17fSwgaHR0cFN0YXR1cz1iYWRSZXF1ZXN0LCBpbnRlcm5hbFJlYXNvbj1SZWFzb257YXJndW1lbnRzPXt9LCBjYXVzZT1udWxsLCBjb2RlPWdkYXRhLkNvcmVFcnJvckRvbWFpbi5JTlZBTElEX1ZBTFVFLCBjcmVhdGVkQnlCYWNrZW5kPXRydWUsIGRlYnVnTWVzc2FnZT1udWxsLCBlcnJvclByb3RvQ29kZT1JTlZBTElEX1ZBTFVFLCBlcnJvclByb3RvRG9tYWluPWdkYXRhLkNvcmVFcnJvckRvbWFpbiwgZmlsdGVyZWRNZXNzYWdlPW51bGwsIGxvY2F0aW9uPWVudGl0eS5yZXNvdXJjZS5tZDVfaGFzaF9iYXNlNjQsIG1lc3NhZ2U9UHJvdmlkZWQgTUQ1IGhhc2ggXCJvdlpqR2xjWFBKaUdPQWZLRmJKbDFRPT1cIiBkb2Vzbid0IG1hdGNoIGNhbGN1bGF0ZWQgTUQ1IGhhc2ggXCJvZlpqR2xjWFBKaUdPQWZLRmJKbDFRPT1cIi4sIHVubmFtZWRBcmd1bWVudHM9W292WmpHbGNYUEppR09BZktGYkpsMVE9PV19LCBsb2NhdGlvbj1lbnRpdHkucmVzb3VyY2UubWQ1X2hhc2hfYmFzZTY0LCBtZXNzYWdlPVByb3ZpZGVkIE1ENSBoYXNoIFwib3ZaakdsY1hQSmlHT0FmS0ZiSmwxUT09XCIgZG9lc24ndCBtYXRjaCBjYWxjdWxhdGVkIE1ENSBoYXNoIFwib2ZaakdsY1hQSmlHT0FmS0ZiSmwxUT09XCIuLCByZWFzb249aW52YWxpZCwgcnBjQ29kZT00MDB9IFByb3ZpZGVkIE1ENSBoYXNoIFwib3ZaakdsY1hQSmlHT0FmS0ZiSmwxUT09XCIgZG9lc24ndCBtYXRjaCBjYWxjdWxhdGVkIE1ENSBoYXNoIFwib2ZaakdsY1hQSmlHT0FmS0ZiSmwxUT09XCIuXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLkVycm9yQ29sbGVjdG9yLnRvRmF1bHQoRXJyb3JDb2xsZWN0b3IuamF2YTo1NClcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnJlc3QuYWRhcHRlci5yb3N5LlJvc3lFcnJvckNvbnZlcnRlci50b0ZhdWx0KFJvc3lFcnJvckNvbnZlcnRlci5qYXZhOjY3KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIucmVzdC5hZGFwdGVyLnJvc3kuUm9zeUhhbmRsZXIkMi5jYWxsKFJvc3lIYW5kbGVyLmphdmE6MjU4KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIucmVzdC5hZGFwdGVyLnJvc3kuUm9zeUhhbmRsZXIkMi5jYWxsKFJvc3lIYW5kbGVyLmphdmE6MjM4KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS51dGlsLkNhbGxhYmxlRnV0dXJlLnJ1bihDYWxsYWJsZUZ1dHVyZS5qYXZhOjYyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuRGlyZWN0RXhlY3V0b3IuZXhlY3V0ZShEaXJlY3RFeGVjdXRvci5qYXZhOjMwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuZXhlY3V0ZUxpc3RlbmVyKEFic3RyYWN0RnV0dXJlLmphdmE6MTE0Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmNvbXBsZXRlKEFic3RyYWN0RnV0dXJlLmphdmE6OTYzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuc2V0KEFic3RyYWN0RnV0dXJlLmphdmE6NzMxKVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS51dGlsLkNhbGxhYmxlRnV0dXJlLnJ1bihDYWxsYWJsZUZ1dHVyZS5qYXZhOjYyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuRGlyZWN0RXhlY3V0b3IuZXhlY3V0ZShEaXJlY3RFeGVjdXRvci5qYXZhOjMwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuZXhlY3V0ZUxpc3RlbmVyKEFic3RyYWN0RnV0dXJlLmphdmE6MTE0Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmNvbXBsZXRlKEFic3RyYWN0RnV0dXJlLmphdmE6OTYzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuc2V0KEFic3RyYWN0RnV0dXJlLmphdmE6NzMxKVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS51dGlsLkNhbGxhYmxlRnV0dXJlLnJ1bihDYWxsYWJsZUZ1dHVyZS5qYXZhOjYyKVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIudGhyZWFkLlRocmVhZFRyYWNrZXJzJFRocmVhZFRyYWNraW5nUnVubmFibGUucnVuKFRocmVhZFRyYWNrZXJzLmphdmE6MTI2KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JFRyYWNlQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChUcmFjZUNvbnRleHQuamF2YTo0NTUpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5zZXJ2ZXIuQ29tbW9uTW9kdWxlJENvbnRleHRDYXJyeWluZ0V4ZWN1dG9yU2VydmljZSQxLnJ1bkluQ29udGV4dChDb21tb25Nb2R1bGUuamF2YTo4NDYpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkVHJhY2VDb250ZXh0UnVubmFibGUkMS5ydW4oVHJhY2VDb250ZXh0LmphdmE6NDYyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JEFic3RyYWN0VHJhY2VDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihUcmFjZUNvbnRleHQuamF2YTozMjEpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkQWJzdHJhY3RUcmFjZUNvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoVHJhY2VDb250ZXh0LmphdmE6MzEzKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JFRyYWNlQ29udGV4dFJ1bm5hYmxlLnJ1bihUcmFjZUNvbnRleHQuamF2YTo0NTkpXG5cdGF0IGNvbS5nb29nbGUuZ3NlLmludGVybmFsLkRpc3BhdGNoUXVldWVJbXBsJFdvcmtlclRocmVhZC5ydW4oRGlzcGF0Y2hRdWV1ZUltcGwuamF2YTo0MDMpXG4ifV0sImNvZGUiOjQwMCwibWVzc2FnZSI6IlByb3ZpZGVkIE1ENSBoYXNoIFwib3ZaakdsY1hQSmlHT0FmS0ZiSmwxUT09XCIgZG9lc24ndCBtYXRjaCBjYWxjdWxhdGVkIE1ENSBoYXNoIFwib2ZaakdsY1hQSmlHT0FmS0ZiSmwxUT09XCIuIn19"
+ }
+ },
+ {
+ "ID": "a9c389a0eb73daac",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/iam?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "cdb1ae8a9c42469760476bfb84eddd22/8569640074824319720;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/iam?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0, must-revalidate, no-transform"
+ ],
+ "Content-Length": [
+ "341"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:46 GMT"
+ ],
+ "Etag": [
+ "CAk="
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:24:46 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051386000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrae1:4130,/bns/yw/borg/yw/bns/blobstore2/bitpusher/82.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=DsysW_KeFtbyhQTW3Ls4"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yw/borg/yw/bns/blobstore2/bitpusher/82.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yw/borg/yw/bns/blobstore2/bitpusher/82:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRYTRrVFBYeTRJSTVPN2VpalFwWjI0ZFpXMU1Ka1poUnI5WWRHUWg1V1NzZHAzWDh4M0RSZ2pvZ1pUVHJVa0M1ZzJGa2hNY1ZyNVFrTmRLaXdVWjg5UXY0T2hlaUhtR2d3RlU0ekY1djJWVFp3Unh5ZEs2Z1ZpVnRaRG1SZUp6VmkyYlhNVjVlQmdhcVQ1aGlDWEdLUl9VYmdJTDlXOVl5dWUteEpIVXNSR0JiRm0tSFhJN0VTWVhaSzgwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UqBlHo09PoYV5xODCs727aMaz6gcs8xf5X07yZ7EjlXbKW2xwoDRGr4rew96LrtIrP7TfqFxvPETZbtq9gAiKDN8IReWA"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNwb2xpY3kiLCJyZXNvdXJjZUlkIjoicHJvamVjdHMvXy9idWNrZXRzL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsImJpbmRpbmdzIjpbeyJyb2xlIjoicm9sZXMvc3RvcmFnZS5sZWdhY3lCdWNrZXRPd25lciIsIm1lbWJlcnMiOlsicHJvamVjdEVkaXRvcjpkdWxjZXQtcG9ydC03NjIiLCJwcm9qZWN0T3duZXI6ZHVsY2V0LXBvcnQtNzYyIl19LHsicm9sZSI6InJvbGVzL3N0b3JhZ2UubGVnYWN5QnVja2V0UmVhZGVyIiwibWVtYmVycyI6WyJwcm9qZWN0Vmlld2VyOmR1bGNldC1wb3J0LTc2MiJdfV0sImV0YWciOiJDQWs9In0="
+ }
+ },
+ {
+ "ID": "a0c231629f1b0830",
+ "Request": {
+ "Method": "PUT",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/iam?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "317"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "45dd37de1332888471197c7ded953d2b/10160051978874759302;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/iam?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJiaW5kaW5ncyI6W3sibWVtYmVycyI6WyJwcm9qZWN0RWRpdG9yOmR1bGNldC1wb3J0LTc2MiIsInByb2plY3RPd25lcjpkdWxjZXQtcG9ydC03NjIiXSwicm9sZSI6InJvbGVzL3N0b3JhZ2UubGVnYWN5QnVja2V0T3duZXIifSx7Im1lbWJlcnMiOlsicHJvamVjdFZpZXdlcjpkdWxjZXQtcG9ydC03NjIiXSwicm9sZSI6InJvbGVzL3N0b3JhZ2UubGVnYWN5QnVja2V0UmVhZGVyIn0seyJtZW1iZXJzIjpbInByb2plY3RWaWV3ZXI6ZHVsY2V0LXBvcnQtNzYyIl0sInJvbGUiOiJyb2xlcy9zdG9yYWdlLm9iamVjdFZpZXdlciJ9XSwiZXRhZyI6IkNBaz0ifQo="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "423"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:47 GMT"
+ ],
+ "Etag": [
+ "CAo="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051386000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrsn11:4209,/bns/yv/borg/yv/bns/blobstore2/bitpusher/290.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=DsysW5mCJYvRgQTe5JKYDw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/290.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/290:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRYTRrVFBYeTRJSTVPN2VpalFwWjI0ZFpXMU1Ka1poUnI5WWRHUWg1V1NzZHAzWDh4M0RSZ2pvZ1pUVHJVa0M1ZzJGa2hNY1ZyNVFrTmRLaXdVWjg5UXY0T2hlaUhtR2d3RlU0ekY1djJWVFp3Unh5ZEs2Z1ZpVnRaRG1SZUp6VmkyYlhNVjVlQmdhcVQ1aGlDWEdLUl9VYmdJTDlXOVl5dWUteEpIVXNSR0JiRm0tSFhJN0VTWVhaSzgwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UouvH87NAtIZRYuefULe5I19LMPKuAlFjo8gRWzOW2m8ywZl8NHM6ym9LuvwbH0mpAukabVKwFOpi6wbATQSLR6HnJdBw"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNwb2xpY3kiLCJyZXNvdXJjZUlkIjoicHJvamVjdHMvXy9idWNrZXRzL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsImJpbmRpbmdzIjpbeyJyb2xlIjoicm9sZXMvc3RvcmFnZS5sZWdhY3lCdWNrZXRPd25lciIsIm1lbWJlcnMiOlsicHJvamVjdEVkaXRvcjpkdWxjZXQtcG9ydC03NjIiLCJwcm9qZWN0T3duZXI6ZHVsY2V0LXBvcnQtNzYyIl19LHsicm9sZSI6InJvbGVzL3N0b3JhZ2UubGVnYWN5QnVja2V0UmVhZGVyIiwibWVtYmVycyI6WyJwcm9qZWN0Vmlld2VyOmR1bGNldC1wb3J0LTc2MiJdfSx7InJvbGUiOiJyb2xlcy9zdG9yYWdlLm9iamVjdFZpZXdlciIsIm1lbWJlcnMiOlsicHJvamVjdFZpZXdlcjpkdWxjZXQtcG9ydC03NjIiXX1dLCJldGFnIjoiQ0FvPSJ9"
+ }
+ },
+ {
+ "ID": "144b6da1d9241efb",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/iam?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "b1e1650a9d8d34458c16d574cfc635f7/11678125913438965029;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/iam?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0, must-revalidate, no-transform"
+ ],
+ "Content-Length": [
+ "423"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:47 GMT"
+ ],
+ "Etag": [
+ "CAo="
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:24:47 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051386000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrwa10:4354,/bns/yr/borg/yr/bns/blobstore2/bitpusher/24.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=D8ysW6bVKY-7kASf45LYDQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/24.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/24:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRYTRrVFBYeTRJSTVPN2VpalFwWjI0ZFpXMU1Ka1poUnI5WWRHUWg1V1NzZHAzWDh4M0RSZ2pvZ1pUVHJVa0M1ZzJGa2hNY1ZyNVFrTmRLaXdVWjg5UXY0T2hlaUhtR2d3RlU0ekY1djJWVFp3Unh5ZEs2Z1ZpVnRaRG1SZUp6VmkyYlhNVjVlQmdhcVQ1aGlDWEdLUl9VYmdJTDlXOVl5dWUteEpIVXNSR0JiRm0tSFhJN0VTWVhaSzgwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UrORn0AA37Z-krQlzExepj1CiRXgkBL-ohkvMSncFboI2PxjqFbfe-kAqtndNv8kCO8nVJdwF0QL9kTRQsw7Z1UWaou5g"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNwb2xpY3kiLCJyZXNvdXJjZUlkIjoicHJvamVjdHMvXy9idWNrZXRzL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsImJpbmRpbmdzIjpbeyJyb2xlIjoicm9sZXMvc3RvcmFnZS5sZWdhY3lCdWNrZXRPd25lciIsIm1lbWJlcnMiOlsicHJvamVjdEVkaXRvcjpkdWxjZXQtcG9ydC03NjIiLCJwcm9qZWN0T3duZXI6ZHVsY2V0LXBvcnQtNzYyIl19LHsicm9sZSI6InJvbGVzL3N0b3JhZ2UubGVnYWN5QnVja2V0UmVhZGVyIiwibWVtYmVycyI6WyJwcm9qZWN0Vmlld2VyOmR1bGNldC1wb3J0LTc2MiJdfSx7InJvbGUiOiJyb2xlcy9zdG9yYWdlLm9iamVjdFZpZXdlciIsIm1lbWJlcnMiOlsicHJvamVjdFZpZXdlcjpkdWxjZXQtcG9ydC03NjIiXX1dLCJldGFnIjoiQ0FvPSJ9"
+ }
+ },
+ {
+ "ID": "75ef487a8b257113",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/iam/testPermissions?alt=json\u0026permissions=storage.buckets.get\u0026permissions=storage.buckets.delete\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "08ca66e09b16381170a05dabd28c307f/13268537817489404867;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/iam/testPermissions?alt=json\u0026permissions=storage.buckets.get\u0026permissions=storage.buckets.delete\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0, must-revalidate, no-transform"
+ ],
+ "Content-Length": [
+ "108"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:48 GMT"
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:24:48 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051386000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrgb22:4240,/bns/yw/borg/yw/bns/blobstore2/bitpusher/167.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=D8ysW-TXPIPwhAT094D4Cw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yw/borg/yw/bns/blobstore2/bitpusher/167.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yw/borg/yw/bns/blobstore2/bitpusher/167:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRYTRrVFBYeTRJSTVPN2VpalFwWjI0ZFpXMU1Ka1poUnI5WWRHUWg1V1NzZHAzWDh4M0RSZ2pvZ1pUVHJVa0M1ZzJGa2hNY1ZyNVFrTmRLaXdVWjg5UXY0T2hlaUhtR2d3RlU0ekY1djJWVFp3Unh5ZEs2Z1ZpVnRaRG1SZUp6VmkyYlhNVjVlQmdhcVQ1aGlDWEdLUl9VYmdJTDlXOVl5dWUteEpIVXNSR0JiRm0tSFhJN0VTWVhaSzgwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UoC8Y01kEJQMNndrzzPlPKFhvQgzyA3VhI6oytWf7ncjE_esF2ymE5i-_dPkHhV9HepRXk9dgA1pri0GaTC3OIBTsv0UQ"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSN0ZXN0SWFtUGVybWlzc2lvbnNSZXNwb25zZSIsInBlcm1pc3Npb25zIjpbInN0b3JhZ2UuYnVja2V0cy5nZXQiLCJzdG9yYWdlLmJ1Y2tldHMuZGVsZXRlIl19"
+ }
+ },
+ {
+ "ID": "8c636bdcc9eea5d0",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/storage/v1/b?alt=json\u0026prettyPrint=false\u0026project=dulcet-port-762",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "93"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "651a6846b9563d5640c8d4c98b925186/14858948622061705314;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b?alt=json\u0026prettyPrint=false\u0026project=dulcet-port-762"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJiaWxsaW5nIjp7InJlcXVlc3RlclBheXMiOnRydWV9LCJuYW1lIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzIn0K"
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "459"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:49 GMT"
+ ],
+ "Etag": [
+ "CAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051388000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrt186:4143,/bns/yv/borg/yv/bns/blobstore2/bitpusher/50.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=EMysW--5FJHLswb4lL2QAw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/50.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/50:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWVNNdC1OVDFNYTJvWXBrbG1qcDlJMlZaUFZ5bFl5Z2Q3Nk5tQXlXbWR3WVBoMm00dGI3ZmZjOUlzcTU4MmVFcFBhNzhNWGpNZmIzaE9WTE9xRHpNTUFfTG9NQXVJZkdkMGgzSWowZ1dxdW5DS1g3Qk1mQlJxM001TUtMMXBHOWNyU0ZBT29lVkZpTDhpWlBsUDI0VjE5THdzZ0d1ZnVrQTFtVzVJcTJUUkVXeWQyNjRKZC1lS2UxdTAwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UpweAHP2xx7tNgquA6NRVU_gdpSeklRzOtSWuzv7KACvxgqSJo8lMglTq923iAXBathqwAmYY0AXW6tjE4Wv7T6G_TxHw"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMyIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMyIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6NDguODg2WiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjQ4Ljg4NloiLCJtZXRhZ2VuZXJhdGlvbiI6IjEiLCJsb2NhdGlvbiI6IlVTIiwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJiaWxsaW5nIjp7InJlcXVlc3RlclBheXMiOnRydWV9LCJldGFnIjoiQ0FFPSJ9"
+ }
+ },
+ {
+ "ID": "db9e9aa20b3f272d",
+ "Request": {
+ "Method": "PUT",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/acl/user-integration%40gcloud-golang-firestore-tests.iam.gserviceaccount.com?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "159"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "ebbbe915bf015ecfc551f82528f67153/16449360526112079361;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/acl/user-integration%40gcloud-golang-firestore-tests.iam.gserviceaccount.com?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJlbnRpdHkiOiJ1c2VyLWludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIiwicm9sZSI6Ik9XTkVSIn0K"
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "589"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:51 GMT"
+ ],
+ "Etag": [
+ "CAI="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051389000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vnnr1:4426,/bns/yx/borg/yx/bns/blobstore2/bitpusher/74.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=EcysW7CiCYO9zgLGiKCYAQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yx/borg/yx/bns/blobstore2/bitpusher/74.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yx/borg/yx/bns/blobstore2/bitpusher/74:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATpxChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4CtK4wESxgF5YTI5LmMuRW93QkpRWVNNdC1OVDFNYTJvWXBrbG1qcDlJMlZaUFZ5bFl5Z2Q3Nk5tQXlXbWR3WVBoMm00dGI3ZmZjOUlzcTU4MmVFcFBhNzhNWGpNZmIzaE9WTE9xRHpNTUFfTG9NQXVJZkdkMGgzSWowZ1dxdW5DS1g3Qk1mQlJxM001TUtMMXBHOWNyU0ZBT29lVkZpTDhpWlBsUDI0VjE5THdzZ0d1ZnVrQTFtVzVJcTJUUkVXeWQyNjRKZC1lS2UxdTAwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UpWAHw7IVeXEMZ_GnQKXv6PGvEtBLRnR7sTaAivOc7U2HSPZEMQycXnbcXRlp6kH8tsmEqyVTQ8rSia2NHJeoDFpZMwgQ"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMvdXNlci1pbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9hY2wvdXNlci1pbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMyIsImVudGl0eSI6InVzZXItaW50ZWdyYXRpb25AZ2Nsb3VkLWdvbGFuZy1maXJlc3RvcmUtdGVzdHMuaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJyb2xlIjoiT1dORVIiLCJlbWFpbCI6ImludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIiwiZXRhZyI6IkNBST0ifQ=="
+ }
+ },
+ {
+ "ID": "9376ae75abf3dc2d",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "946e42b81d2942871e88dd356cd216c4/18039490955202651039;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0, must-revalidate, no-transform"
+ ],
+ "Content-Length": [
+ "2976"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:51 GMT"
+ ],
+ "Etag": [
+ "CAI="
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:24:51 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051391000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrbd63:4301,/bns/yr/borg/yr/bns/blobstore2/bitpusher/4.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=E8ysW8zbAY-AkATj4oWoBA"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/4.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/4:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRWVNNdC1OVDFNYTJvWXBrbG1qcDlJMlZaUFZ5bFl5Z2Q3Nk5tQXlXbWR3WVBoMm00dGI3ZmZjOUlzcTU4MmVFcFBhNzhNWGpNZmIzaE9WTE9xRHpNTUFfTG9NQXVJZkdkMGgzSWowZ1dxdW5DS1g3Qk1mQlJxM001TUtMMXBHOWNyU0ZBT29lVkZpTDhpWlBsUDI0VjE5THdzZ0d1ZnVrQTFtVzVJcTJUUkVXeWQyNjRKZC1lS2UxdTAwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UqB_1uMwyjpyvhwCFL8KjtRxVDOjP1z4Nu7W0c1hElpAf6YeNBN9lzM-wpX7ZXWj43ntFXdHhlyxVuLLXRQVABWkI6CXA"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMyIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMyIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6NDguODg2WiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjUwLjgxOVoiLCJtZXRhZ2VuZXJhdGlvbiI6IjIiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBST0ifSx7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMyIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDQUk9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNBST0ifSx7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy91c2VyLWludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL2FjbC91c2VyLWludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzIiwiZW50aXR5IjoidXNlci1pbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSIsInJvbGUiOiJPV05FUiIsImVtYWlsIjoiaW50ZWdyYXRpb25AZ2Nsb3VkLWdvbGFuZy1maXJlc3RvcmUtdGVzdHMuaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJldGFnIjoiQ0FJPSJ9XSwiZGVmYXVsdE9iamVjdEFjbCI6W3sia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6Im93bmVycyJ9LCJldGFnIjoiQ0FJPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDQUk9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiZW50aXR5IjoicHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6IlJFQURFUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJ2aWV3ZXJzIn0sImV0YWciOiJDQUk9In1dLCJvd25lciI6eyJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSJ9LCJsb2NhdGlvbiI6IlVTIiwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJiaWxsaW5nIjp7InJlcXVlc3RlclBheXMiOnRydWV9LCJldGFnIjoiQ0FJPSJ9"
+ }
+ },
+ {
+ "ID": "128bb0d838dfcf9f",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003?alt=json\u0026prettyPrint=false\u0026projection=full\u0026userProject=dulcet-port-762",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "58f6f6f433a012e66ccd520abdf51915/1183440260520184126;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003?alt=json\u0026prettyPrint=false\u0026projection=full\u0026userProject=dulcet-port-762"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0, must-revalidate, no-transform"
+ ],
+ "Content-Length": [
+ "2976"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:51 GMT"
+ ],
+ "Etag": [
+ "CAI="
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:24:51 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051391000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrtw20:4200,/bns/yv/borg/yv/bns/blobstore2/bitpusher/233.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=E8ysW6L4GYruggSr-I3oCQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/233.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/233:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRWVNNdC1OVDFNYTJvWXBrbG1qcDlJMlZaUFZ5bFl5Z2Q3Nk5tQXlXbWR3WVBoMm00dGI3ZmZjOUlzcTU4MmVFcFBhNzhNWGpNZmIzaE9WTE9xRHpNTUFfTG9NQXVJZkdkMGgzSWowZ1dxdW5DS1g3Qk1mQlJxM001TUtMMXBHOWNyU0ZBT29lVkZpTDhpWlBsUDI0VjE5THdzZ0d1ZnVrQTFtVzVJcTJUUkVXeWQyNjRKZC1lS2UxdTAwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Ur0_BMChIpY89D5SIxg1IX7Mzvg9U-PsS9-1yP65Iz9rnXfhp367PanBonVPXZeldon4CD6ad3ZHvy-jDfGh2g2kjuDXQ"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMyIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMyIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6NDguODg2WiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjUwLjgxOVoiLCJtZXRhZ2VuZXJhdGlvbiI6IjIiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBST0ifSx7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMyIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDQUk9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNBST0ifSx7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy91c2VyLWludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL2FjbC91c2VyLWludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzIiwiZW50aXR5IjoidXNlci1pbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSIsInJvbGUiOiJPV05FUiIsImVtYWlsIjoiaW50ZWdyYXRpb25AZ2Nsb3VkLWdvbGFuZy1maXJlc3RvcmUtdGVzdHMuaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJldGFnIjoiQ0FJPSJ9XSwiZGVmYXVsdE9iamVjdEFjbCI6W3sia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6Im93bmVycyJ9LCJldGFnIjoiQ0FJPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDQUk9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiZW50aXR5IjoicHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6IlJFQURFUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJ2aWV3ZXJzIn0sImV0YWciOiJDQUk9In1dLCJvd25lciI6eyJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSJ9LCJsb2NhdGlvbiI6IlVTIiwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJiaWxsaW5nIjp7InJlcXVlc3RlclBheXMiOnRydWV9LCJldGFnIjoiQ0FJPSJ9"
+ }
+ },
+ {
+ "ID": "1d28c60b2c1aaa62",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "da28f10a14d9659d366cb18aa5d6d591/2773852164587335389;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 400,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0"
+ ],
+ "Content-Length": [
+ "12071"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:52 GMT"
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:24:52 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051391000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "471383502717"
+ ],
+ "X-Google-Backends": [
+ "vnba207:4324,/bns/yx/borg/yx/bns/blobstore2/bitpusher/135.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=E8ysW53eL8btzAKs_rD4CA"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yx/borg/yx/bns/blobstore2/bitpusher/135.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yx/borg/yx/bns/blobstore2/bitpusher/135:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CP3elYXcDRoCGAYoATpFChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGM6ropHgHCIVMTE3MjM4MDU4ODYxOTM3NTE5MTQ0MOArMOErMOIrSp8BEoIBeWEyOS5jLkVsb2xCcldWbUZlX1AxVDdUOHVpTXdFMHBZUjdTc2NVMDBFdEZkc2tSenBQY0NLWkhUeEZaYXI0Q25tZmR6bXFRLTNVV0kzOF9wdEx5VTZ2Z1Q3dlRBeW42Z3g4dUcyd0szSHIzaTZrV1JBZkozc1pNMGQ1allkNHpWQTAEOhZOT1RfQV9QRVJTSVNURU5UX1RPS0VO"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Upload-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Uq7QZN5rGXMozsX4ASIM0yxatYCGxmDwDjDNFgy0g83ZPIvkJHrneIYGTsC9WssyRG14bT4ipnP5eCcYpLLXd1pLEJK0g"
+ ]
+ },
+ "Body": "eyJlcnJvciI6eyJlcnJvcnMiOlt7ImRvbWFpbiI6Imdsb2JhbCIsInJlYXNvbiI6InJlcXVpcmVkIiwibWVzc2FnZSI6IkJ1Y2tldCBpcyByZXF1ZXN0ZXIgcGF5cyBidWNrZXQgYnV0IG5vIHVzZXIgcHJvamVjdCBwcm92aWRlZC4iLCJkZWJ1Z0luZm8iOiJjb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6VVNFUl9QUk9KRUNUX01JU1NJTkc6IEJ1Y2tldCBpcyBSZXF1ZXN0ZXIgUGF5cyBidWNrZXQgYnV0IG5vIGJpbGxpbmcgcHJvamVjdCBpZCBwcm92aWRlZCBmb3Igbm9uLW93bmVyLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYnVja2V0cy5HZXRCdWNrZXQuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKEdldEJ1Y2tldC5qYXZhOjk5KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmJ1Y2tldHMuR2V0QnVja2V0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChHZXRCdWNrZXQuamF2YTozMSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLkJ1Y2tldHNEZWxlZ2F0b3IuZ2V0KEJ1Y2tldHNEZWxlZ2F0b3IuamF2YTo4Mylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uUnBjUmVjZWl2ZXIubGFtYmRhJHByb2Nlc3NSZXF1ZXN0QXN5bmMkNChScGNSZWNlaXZlci5qYXZhOjIwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uQXN5bmNFeGVjdXRvci5sYW1iZGEkc3VibWl0JDAoQXN5bmNFeGVjdXRvci5qYXZhOjI3Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KENvbnRleHRSdW5uYWJsZS5qYXZhOjUwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZSQxLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozOSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NzIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozNilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRXhlY3V0b3JzJFJ1bm5hYmxlQWRhcHRlci5jYWxsKEV4ZWN1dG9ycy5qYXZhOjUxMSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRnV0dXJlVGFzay5ydW4oRnV0dXJlVGFzay5qYXZhOjI2Nilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yLnJ1bldvcmtlcihUaHJlYWRQb29sRXhlY3V0b3IuamF2YToxMTQ5KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IkV29ya2VyLnJ1bihUaHJlYWRQb29sRXhlY3V0b3IuamF2YTo2MjQpXG5cdGF0IGphdmEubGFuZy5UaHJlYWQucnVuKFRocmVhZC5qYXZhOjc0OClcbkNhdXNlZCBieTogY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb246IEJ1Y2tldCBpcyBSZXF1ZXN0ZXIgUGF5cyBidWNrZXQgYnV0IG5vIGJpbGxpbmcgcHJvamVjdCBpZCBwcm92aWRlZCBmb3Igbm9uLW93bmVyLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxNyBtb3JlXG5cbmNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLkZhdWx0OiBJbW11dGFibGVFcnJvckRlZmluaXRpb257YmFzZT1SRVFVSVJFRCwgY2F0ZWdvcnk9VVNFUl9FUlJPUiwgY2F1c2U9bnVsbCwgZGVidWdJbmZvPWNvbS5nb29nbGUubmV0LnJwYzMuUnBjRXhjZXB0aW9uOiBjbG91ZC5iaWdzdG9yZS5SZXNwb25zZUNvZGUuRXJyb3JDb2RlOjpVU0VSX1BST0pFQ1RfTUlTU0lORzogQnVja2V0IGlzIFJlcXVlc3RlciBQYXlzIGJ1Y2tldCBidXQgbm8gYmlsbGluZyBwcm9qZWN0IGlkIHByb3ZpZGVkIGZvciBub24tb3duZXIuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRvUnBjM0V4Y2VwdGlvbihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjEzNSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5idWNrZXRzLkdldEJ1Y2tldC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoR2V0QnVja2V0LmphdmE6OTkpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYnVja2V0cy5HZXRCdWNrZXQuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKEdldEJ1Y2tldC5qYXZhOjMxKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmZyYW1ld29yay5SZXF1ZXN0SGFuZGxlci5oYW5kbGUoUmVxdWVzdEhhbmRsZXIuamF2YToyOTQpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uQnVja2V0c0RlbGVnYXRvci5nZXQoQnVja2V0c0RlbGVnYXRvci5qYXZhOjgzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5ScGNSZWNlaXZlci5sYW1iZGEkcHJvY2Vzc1JlcXVlc3RBc3luYyQ0KFJwY1JlY2VpdmVyLmphdmE6MjAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5Bc3luY0V4ZWN1dG9yLmxhbWJkYSRzdWJtaXQkMChBc3luY0V4ZWN1dG9yLmphdmE6MjcyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoQ29udGV4dFJ1bm5hYmxlLmphdmE6NTApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlJDEucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM5KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo3Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5FeGVjdXRvcnMkUnVubmFibGVBZGFwdGVyLmNhbGwoRXhlY3V0b3JzLmphdmE6NTExKVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5GdXR1cmVUYXNrLnJ1bihGdXR1cmVUYXNrLmphdmE6MjY2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IucnVuV29ya2VyKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjExNDkpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvciRXb3JrZXIucnVuKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjYyNClcblx0YXQgamF2YS5sYW5nLlRocmVhZC5ydW4oVGhyZWFkLmphdmE6NzQ4KVxuQ2F1c2VkIGJ5OiBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbjogQnVja2V0IGlzIFJlcXVlc3RlciBQYXlzIGJ1Y2tldCBidXQgbm8gYmlsbGluZyBwcm9qZWN0IGlkIHByb3ZpZGVkIGZvciBub24tb3duZXIuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93T25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjI5MClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMSlcblx0Li4uIDE3IG1vcmVcbiwgZG9tYWluPWdsb2JhbCwgZXh0ZW5kZWRIZWxwPW51bGwsIGh0dHBIZWFkZXJzPXt9LCBodHRwU3RhdHVzPWJhZFJlcXVlc3QsIGludGVybmFsUmVhc29uPVJlYXNvbnthcmd1bWVudHM9e30sIGNhdXNlPW51bGwsIGNvZGU9Z2RhdGEuQ29yZUVycm9yRG9tYWluLlJFUVVJUkVELCBjcmVhdGVkQnlCYWNrZW5kPXRydWUsIGRlYnVnTWVzc2FnZT1jb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6VVNFUl9QUk9KRUNUX01JU1NJTkc6IEJ1Y2tldCBpcyBSZXF1ZXN0ZXIgUGF5cyBidWNrZXQgYnV0IG5vIGJpbGxpbmcgcHJvamVjdCBpZCBwcm92aWRlZCBmb3Igbm9uLW93bmVyLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYnVja2V0cy5HZXRCdWNrZXQuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKEdldEJ1Y2tldC5qYXZhOjk5KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmJ1Y2tldHMuR2V0QnVja2V0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChHZXRCdWNrZXQuamF2YTozMSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLkJ1Y2tldHNEZWxlZ2F0b3IuZ2V0KEJ1Y2tldHNEZWxlZ2F0b3IuamF2YTo4Mylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uUnBjUmVjZWl2ZXIubGFtYmRhJHByb2Nlc3NSZXF1ZXN0QXN5bmMkNChScGNSZWNlaXZlci5qYXZhOjIwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uQXN5bmNFeGVjdXRvci5sYW1iZGEkc3VibWl0JDAoQXN5bmNFeGVjdXRvci5qYXZhOjI3Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KENvbnRleHRSdW5uYWJsZS5qYXZhOjUwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZSQxLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozOSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NzIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozNilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRXhlY3V0b3JzJFJ1bm5hYmxlQWRhcHRlci5jYWxsKEV4ZWN1dG9ycy5qYXZhOjUxMSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRnV0dXJlVGFzay5ydW4oRnV0dXJlVGFzay5qYXZhOjI2Nilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yLnJ1bldvcmtlcihUaHJlYWRQb29sRXhlY3V0b3IuamF2YToxMTQ5KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IkV29ya2VyLnJ1bihUaHJlYWRQb29sRXhlY3V0b3IuamF2YTo2MjQpXG5cdGF0IGphdmEubGFuZy5UaHJlYWQucnVuKFRocmVhZC5qYXZhOjc0OClcbkNhdXNlZCBieTogY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb246IEJ1Y2tldCBpcyBSZXF1ZXN0ZXIgUGF5cyBidWNrZXQgYnV0IG5vIGJpbGxpbmcgcHJvamVjdCBpZCBwcm92aWRlZCBmb3Igbm9uLW93bmVyLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxNyBtb3JlXG4sIGVycm9yUHJvdG9Db2RlPVJFUVVJUkVELCBlcnJvclByb3RvRG9tYWluPWdkYXRhLkNvcmVFcnJvckRvbWFpbiwgZmlsdGVyZWRNZXNzYWdlPW51bGwsIGxvY2F0aW9uPW51bGwsIG1lc3NhZ2U9QnVja2V0IGlzIHJlcXVlc3RlciBwYXlzIGJ1Y2tldCBidXQgbm8gdXNlciBwcm9qZWN0IHByb3ZpZGVkLiwgdW5uYW1lZEFyZ3VtZW50cz1bXX0sIGxvY2F0aW9uPW51bGwsIG1lc3NhZ2U9QnVja2V0IGlzIHJlcXVlc3RlciBwYXlzIGJ1Y2tldCBidXQgbm8gdXNlciBwcm9qZWN0IHByb3ZpZGVkLiwgcmVhc29uPXJlcXVpcmVkLCBycGNDb2RlPTQwMH0gQnVja2V0IGlzIHJlcXVlc3RlciBwYXlzIGJ1Y2tldCBidXQgbm8gdXNlciBwcm9qZWN0IHByb3ZpZGVkLjogY29tLmdvb2dsZS5uZXQucnBjMy5ScGNFeGNlcHRpb246IGNsb3VkLmJpZ3N0b3JlLlJlc3BvbnNlQ29kZS5FcnJvckNvZGU6OlVTRVJfUFJPSkVDVF9NSVNTSU5HOiBCdWNrZXQgaXMgUmVxdWVzdGVyIFBheXMgYnVja2V0IGJ1dCBubyBiaWxsaW5nIHByb2plY3QgaWQgcHJvdmlkZWQgZm9yIG5vbi1vd25lci5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udG9ScGMzRXhjZXB0aW9uKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MTM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmJ1Y2tldHMuR2V0QnVja2V0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChHZXRCdWNrZXQuamF2YTo5OSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5idWNrZXRzLkdldEJ1Y2tldC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoR2V0QnVja2V0LmphdmE6MzEpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5CdWNrZXRzRGVsZWdhdG9yLmdldChCdWNrZXRzRGVsZWdhdG9yLmphdmE6ODMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBCdWNrZXQgaXMgUmVxdWVzdGVyIFBheXMgYnVja2V0IGJ1dCBubyBiaWxsaW5nIHByb2plY3QgaWQgcHJvdmlkZWQgZm9yIG5vbi1vd25lci5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MjkwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAxKVxuXHQuLi4gMTcgbW9yZVxuXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLkVycm9yQ29sbGVjdG9yLnRvRmF1bHQoRXJyb3JDb2xsZWN0b3IuamF2YTo1NClcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnJlc3QuYWRhcHRlci5yb3N5LlJvc3lFcnJvckNvbnZlcnRlci50b0ZhdWx0KFJvc3lFcnJvckNvbnZlcnRlci5qYXZhOjY3KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIucmVzdC5hZGFwdGVyLnJvc3kuUm9zeUhhbmRsZXIkMi5jYWxsKFJvc3lIYW5kbGVyLmphdmE6MjU4KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIucmVzdC5hZGFwdGVyLnJvc3kuUm9zeUhhbmRsZXIkMi5jYWxsKFJvc3lIYW5kbGVyLmphdmE6MjM4KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS51dGlsLkNhbGxhYmxlRnV0dXJlLnJ1bihDYWxsYWJsZUZ1dHVyZS5qYXZhOjYyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuRGlyZWN0RXhlY3V0b3IuZXhlY3V0ZShEaXJlY3RFeGVjdXRvci5qYXZhOjMwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuZXhlY3V0ZUxpc3RlbmVyKEFic3RyYWN0RnV0dXJlLmphdmE6MTE0Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmNvbXBsZXRlKEFic3RyYWN0RnV0dXJlLmphdmE6OTYzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuc2V0KEFic3RyYWN0RnV0dXJlLmphdmE6NzMxKVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS51dGlsLkNhbGxhYmxlRnV0dXJlLnJ1bihDYWxsYWJsZUZ1dHVyZS5qYXZhOjYyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuRGlyZWN0RXhlY3V0b3IuZXhlY3V0ZShEaXJlY3RFeGVjdXRvci5qYXZhOjMwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuZXhlY3V0ZUxpc3RlbmVyKEFic3RyYWN0RnV0dXJlLmphdmE6MTE0Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmNvbXBsZXRlKEFic3RyYWN0RnV0dXJlLmphdmE6OTYzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuc2V0KEFic3RyYWN0RnV0dXJlLmphdmE6NzMxKVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS51dGlsLkNhbGxhYmxlRnV0dXJlLnJ1bihDYWxsYWJsZUZ1dHVyZS5qYXZhOjYyKVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIudGhyZWFkLlRocmVhZFRyYWNrZXJzJFRocmVhZFRyYWNraW5nUnVubmFibGUucnVuKFRocmVhZFRyYWNrZXJzLmphdmE6MTI2KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JFRyYWNlQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChUcmFjZUNvbnRleHQuamF2YTo0NTUpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5zZXJ2ZXIuQ29tbW9uTW9kdWxlJENvbnRleHRDYXJyeWluZ0V4ZWN1dG9yU2VydmljZSQxLnJ1bkluQ29udGV4dChDb21tb25Nb2R1bGUuamF2YTo4NDYpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkVHJhY2VDb250ZXh0UnVubmFibGUkMS5ydW4oVHJhY2VDb250ZXh0LmphdmE6NDYyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JEFic3RyYWN0VHJhY2VDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihUcmFjZUNvbnRleHQuamF2YTozMjEpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkQWJzdHJhY3RUcmFjZUNvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoVHJhY2VDb250ZXh0LmphdmE6MzEzKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JFRyYWNlQ29udGV4dFJ1bm5hYmxlLnJ1bihUcmFjZUNvbnRleHQuamF2YTo0NTkpXG5cdGF0IGNvbS5nb29nbGUuZ3NlLmludGVybmFsLkRpc3BhdGNoUXVldWVJbXBsJFdvcmtlclRocmVhZC5ydW4oRGlzcGF0Y2hRdWV1ZUltcGwuamF2YTo0MDMpXG4ifV0sImNvZGUiOjQwMCwibWVzc2FnZSI6IkJ1Y2tldCBpcyByZXF1ZXN0ZXIgcGF5cyBidWNrZXQgYnV0IG5vIHVzZXIgcHJvamVjdCBwcm92aWRlZC4ifX0="
+ }
+ },
+ {
+ "ID": "5ac686ece3e25d68",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003?alt=json\u0026prettyPrint=false\u0026projection=full\u0026userProject=gcloud-golang-firestore-tests",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "bd4deb7c00fc6498c75a32d0d5bf5eef/4364262964848022651;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003?alt=json\u0026prettyPrint=false\u0026projection=full\u0026userProject=gcloud-golang-firestore-tests"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0, must-revalidate, no-transform"
+ ],
+ "Content-Length": [
+ "2976"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:52 GMT"
+ ],
+ "Etag": [
+ "CAI="
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:24:52 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051392000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "471383502717"
+ ],
+ "X-Google-Backends": [
+ "vrcf25:4489,/bns/yr/borg/yr/bns/blobstore2/bitpusher/38.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=FMysW6ObAq-NkAS0m4uIDQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/38.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/38:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CP3elYXcDRoCGAYoATpFChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGM6ropHgHCIVMTE3MjM4MDU4ODYxOTM3NTE5MTQ0MOArMOErMOIrSp8BEoIBeWEyOS5jLkVsb2xCcldWbUZlX1AxVDdUOHVpTXdFMHBZUjdTc2NVMDBFdEZkc2tSenBQY0NLWkhUeEZaYXI0Q25tZmR6bXFRLTNVV0kzOF9wdEx5VTZ2Z1Q3dlRBeW42Z3g4dUcyd0szSHIzaTZrV1JBZkozc1pNMGQ1allkNHpWQTAEOhZOT1RfQV9QRVJTSVNURU5UX1RPS0VO"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UrP1A6KQZYe1fSfdQklQD3Li6UV647Oa2MVILnNtCnDCjzZnmXniTW3emikNnz1oiPQBa6rlnhFSmeh_tUg3Xn7uMcNjw"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMyIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMyIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6NDguODg2WiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjUwLjgxOVoiLCJtZXRhZ2VuZXJhdGlvbiI6IjIiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBST0ifSx7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMyIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDQUk9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNBST0ifSx7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy91c2VyLWludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL2FjbC91c2VyLWludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzIiwiZW50aXR5IjoidXNlci1pbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSIsInJvbGUiOiJPV05FUiIsImVtYWlsIjoiaW50ZWdyYXRpb25AZ2Nsb3VkLWdvbGFuZy1maXJlc3RvcmUtdGVzdHMuaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJldGFnIjoiQ0FJPSJ9XSwiZGVmYXVsdE9iamVjdEFjbCI6W3sia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6Im93bmVycyJ9LCJldGFnIjoiQ0FJPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDQUk9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiZW50aXR5IjoicHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6IlJFQURFUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJ2aWV3ZXJzIn0sImV0YWciOiJDQUk9In1dLCJvd25lciI6eyJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSJ9LCJsb2NhdGlvbiI6IlVTIiwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJiaWxsaW5nIjp7InJlcXVlc3RlclBheXMiOnRydWV9LCJldGFnIjoiQ0FJPSJ9"
+ }
+ },
+ {
+ "ID": "01d97c7a0e0c6ad6",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003?alt=json\u0026prettyPrint=false\u0026projection=full\u0026userProject=veener-jba",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "951a587dc6dd7039ad69e1977096a8c0/5954393398233430298;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003?alt=json\u0026prettyPrint=false\u0026projection=full\u0026userProject=veener-jba"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 403,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0"
+ ],
+ "Content-Length": [
+ "12927"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:52 GMT"
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:24:52 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051392000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "471383502717"
+ ],
+ "X-Google-Backends": [
+ "vray62:4018,/bns/yr/borg/yr/bns/blobstore2/bitpusher/49.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=FMysW8m4B43q4QSDmZy4Ag"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/49.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/49:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CP3elYXcDRoCGAYoATpFChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGM6ropHgHCIVMTE3MjM4MDU4ODYxOTM3NTE5MTQ0MOArMOErMOIrSp8BEoIBeWEyOS5jLkVsb2xCcldWbUZlX1AxVDdUOHVpTXdFMHBZUjdTc2NVMDBFdEZkc2tSenBQY0NLWkhUeEZaYXI0Q25tZmR6bXFRLTNVV0kzOF9wdEx5VTZ2Z1Q3dlRBeW42Z3g4dUcyd0szSHIzaTZrV1JBZkozc1pNMGQ1allkNHpWQTAEOhZOT1RfQV9QRVJTSVNURU5UX1RPS0VO"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Upload-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UpgFD6v6LBuWvl36FBHOwD0dgc-Iy4UFOJ0HZ_er9KgJJtoQwQP7EPy-gBByK6x9f-sOmzxQ_rg9ZJHf6RaVlrEUtRdwQ"
+ ]
+ },
+ "Body": "eyJlcnJvciI6eyJlcnJvcnMiOlt7ImRvbWFpbiI6Imdsb2JhbCIsInJlYXNvbiI6ImZvcmJpZGRlbiIsIm1lc3NhZ2UiOiJpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLiIsImRlYnVnSW5mbyI6ImNvbS5nb29nbGUubmV0LnJwYzMuUnBjRXhjZXB0aW9uOiBjbG91ZC5iaWdzdG9yZS5SZXNwb25zZUNvZGUuRXJyb3JDb2RlOjpVU0VSX1BST0pFQ1RfQUNDRVNTX0RFTklFRDogaW50ZWdyYXRpb25AZ2Nsb3VkLWdvbGFuZy1maXJlc3RvcmUtdGVzdHMuaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20gZG9lcyBub3QgaGF2ZSBzZXJ2aWNldXNhZ2Uuc2VydmljZXMudXNlIGFjY2VzcyB0byBwcm9qZWN0IDY0MjA4MDkxODEwMS5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udG9ScGMzRXhjZXB0aW9uKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MTM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmJ1Y2tldHMuR2V0QnVja2V0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChHZXRCdWNrZXQuamF2YTo5OSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5idWNrZXRzLkdldEJ1Y2tldC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoR2V0QnVja2V0LmphdmE6MzEpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5CdWNrZXRzRGVsZWdhdG9yLmdldChCdWNrZXRzRGVsZWdhdG9yLmphdmE6ODMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxNyBtb3JlXG5cbmNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLkZhdWx0OiBJbW11dGFibGVFcnJvckRlZmluaXRpb257YmFzZT1GT1JCSURERU4sIGNhdGVnb3J5PVVTRVJfRVJST1IsIGNhdXNlPW51bGwsIGRlYnVnSW5mbz1jb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6VVNFUl9QUk9KRUNUX0FDQ0VTU19ERU5JRUQ6IGludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIGRvZXMgbm90IGhhdmUgc2VydmljZXVzYWdlLnNlcnZpY2VzLnVzZSBhY2Nlc3MgdG8gcHJvamVjdCA2NDIwODA5MTgxMDEuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRvUnBjM0V4Y2VwdGlvbihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjEzNSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5idWNrZXRzLkdldEJ1Y2tldC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoR2V0QnVja2V0LmphdmE6OTkpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYnVja2V0cy5HZXRCdWNrZXQuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKEdldEJ1Y2tldC5qYXZhOjMxKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmZyYW1ld29yay5SZXF1ZXN0SGFuZGxlci5oYW5kbGUoUmVxdWVzdEhhbmRsZXIuamF2YToyOTQpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uQnVja2V0c0RlbGVnYXRvci5nZXQoQnVja2V0c0RlbGVnYXRvci5qYXZhOjgzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5ScGNSZWNlaXZlci5sYW1iZGEkcHJvY2Vzc1JlcXVlc3RBc3luYyQ0KFJwY1JlY2VpdmVyLmphdmE6MjAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5Bc3luY0V4ZWN1dG9yLmxhbWJkYSRzdWJtaXQkMChBc3luY0V4ZWN1dG9yLmphdmE6MjcyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoQ29udGV4dFJ1bm5hYmxlLmphdmE6NTApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlJDEucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM5KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo3Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5FeGVjdXRvcnMkUnVubmFibGVBZGFwdGVyLmNhbGwoRXhlY3V0b3JzLmphdmE6NTExKVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5GdXR1cmVUYXNrLnJ1bihGdXR1cmVUYXNrLmphdmE6MjY2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IucnVuV29ya2VyKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjExNDkpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvciRXb3JrZXIucnVuKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjYyNClcblx0YXQgamF2YS5sYW5nLlRocmVhZC5ydW4oVGhyZWFkLmphdmE6NzQ4KVxuQ2F1c2VkIGJ5OiBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbjogaW50ZWdyYXRpb25AZ2Nsb3VkLWdvbGFuZy1maXJlc3RvcmUtdGVzdHMuaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20gZG9lcyBub3QgaGF2ZSBzZXJ2aWNldXNhZ2Uuc2VydmljZXMudXNlIGFjY2VzcyB0byBwcm9qZWN0IDY0MjA4MDkxODEwMS5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MjkwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAxKVxuXHQuLi4gMTcgbW9yZVxuLCBkb21haW49Z2xvYmFsLCBleHRlbmRlZEhlbHA9bnVsbCwgaHR0cEhlYWRlcnM9e30sIGh0dHBTdGF0dXM9Zm9yYmlkZGVuLCBpbnRlcm5hbFJlYXNvbj1SZWFzb257YXJndW1lbnRzPXt9LCBjYXVzZT1udWxsLCBjb2RlPWdkYXRhLkNvcmVFcnJvckRvbWFpbi5GT1JCSURERU4sIGNyZWF0ZWRCeUJhY2tlbmQ9dHJ1ZSwgZGVidWdNZXNzYWdlPWNvbS5nb29nbGUubmV0LnJwYzMuUnBjRXhjZXB0aW9uOiBjbG91ZC5iaWdzdG9yZS5SZXNwb25zZUNvZGUuRXJyb3JDb2RlOjpVU0VSX1BST0pFQ1RfQUNDRVNTX0RFTklFRDogaW50ZWdyYXRpb25AZ2Nsb3VkLWdvbGFuZy1maXJlc3RvcmUtdGVzdHMuaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20gZG9lcyBub3QgaGF2ZSBzZXJ2aWNldXNhZ2Uuc2VydmljZXMudXNlIGFjY2VzcyB0byBwcm9qZWN0IDY0MjA4MDkxODEwMS5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udG9ScGMzRXhjZXB0aW9uKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MTM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmJ1Y2tldHMuR2V0QnVja2V0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChHZXRCdWNrZXQuamF2YTo5OSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5idWNrZXRzLkdldEJ1Y2tldC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoR2V0QnVja2V0LmphdmE6MzEpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5CdWNrZXRzRGVsZWdhdG9yLmdldChCdWNrZXRzRGVsZWdhdG9yLmphdmE6ODMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxNyBtb3JlXG4sIGVycm9yUHJvdG9Db2RlPUZPUkJJRERFTiwgZXJyb3JQcm90b0RvbWFpbj1nZGF0YS5Db3JlRXJyb3JEb21haW4sIGZpbHRlcmVkTWVzc2FnZT1udWxsLCBsb2NhdGlvbj1udWxsLCBtZXNzYWdlPWludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIGRvZXMgbm90IGhhdmUgc2VydmljZXVzYWdlLnNlcnZpY2VzLnVzZSBhY2Nlc3MgdG8gcHJvamVjdCA2NDIwODA5MTgxMDEuLCB1bm5hbWVkQXJndW1lbnRzPVtdfSwgbG9jYXRpb249bnVsbCwgbWVzc2FnZT1pbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLiwgcmVhc29uPWZvcmJpZGRlbiwgcnBjQ29kZT00MDN9IGludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIGRvZXMgbm90IGhhdmUgc2VydmljZXVzYWdlLnNlcnZpY2VzLnVzZSBhY2Nlc3MgdG8gcHJvamVjdCA2NDIwODA5MTgxMDEuOiBjb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6VVNFUl9QUk9KRUNUX0FDQ0VTU19ERU5JRUQ6IGludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIGRvZXMgbm90IGhhdmUgc2VydmljZXVzYWdlLnNlcnZpY2VzLnVzZSBhY2Nlc3MgdG8gcHJvamVjdCA2NDIwODA5MTgxMDEuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRvUnBjM0V4Y2VwdGlvbihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjEzNSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5idWNrZXRzLkdldEJ1Y2tldC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoR2V0QnVja2V0LmphdmE6OTkpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYnVja2V0cy5HZXRCdWNrZXQuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKEdldEJ1Y2tldC5qYXZhOjMxKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmZyYW1ld29yay5SZXF1ZXN0SGFuZGxlci5oYW5kbGUoUmVxdWVzdEhhbmRsZXIuamF2YToyOTQpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uQnVja2V0c0RlbGVnYXRvci5nZXQoQnVja2V0c0RlbGVnYXRvci5qYXZhOjgzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5ScGNSZWNlaXZlci5sYW1iZGEkcHJvY2Vzc1JlcXVlc3RBc3luYyQ0KFJwY1JlY2VpdmVyLmphdmE6MjAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5Bc3luY0V4ZWN1dG9yLmxhbWJkYSRzdWJtaXQkMChBc3luY0V4ZWN1dG9yLmphdmE6MjcyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoQ29udGV4dFJ1bm5hYmxlLmphdmE6NTApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlJDEucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM5KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo3Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5FeGVjdXRvcnMkUnVubmFibGVBZGFwdGVyLmNhbGwoRXhlY3V0b3JzLmphdmE6NTExKVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5GdXR1cmVUYXNrLnJ1bihGdXR1cmVUYXNrLmphdmE6MjY2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IucnVuV29ya2VyKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjExNDkpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvciRXb3JrZXIucnVuKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjYyNClcblx0YXQgamF2YS5sYW5nLlRocmVhZC5ydW4oVGhyZWFkLmphdmE6NzQ4KVxuQ2F1c2VkIGJ5OiBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbjogaW50ZWdyYXRpb25AZ2Nsb3VkLWdvbGFuZy1maXJlc3RvcmUtdGVzdHMuaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20gZG9lcyBub3QgaGF2ZSBzZXJ2aWNldXNhZ2Uuc2VydmljZXMudXNlIGFjY2VzcyB0byBwcm9qZWN0IDY0MjA4MDkxODEwMS5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MjkwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAxKVxuXHQuLi4gMTcgbW9yZVxuXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLkVycm9yQ29sbGVjdG9yLnRvRmF1bHQoRXJyb3JDb2xsZWN0b3IuamF2YTo1NClcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnJlc3QuYWRhcHRlci5yb3N5LlJvc3lFcnJvckNvbnZlcnRlci50b0ZhdWx0KFJvc3lFcnJvckNvbnZlcnRlci5qYXZhOjY3KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIucmVzdC5hZGFwdGVyLnJvc3kuUm9zeUhhbmRsZXIkMi5jYWxsKFJvc3lIYW5kbGVyLmphdmE6MjU4KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIucmVzdC5hZGFwdGVyLnJvc3kuUm9zeUhhbmRsZXIkMi5jYWxsKFJvc3lIYW5kbGVyLmphdmE6MjM4KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS51dGlsLkNhbGxhYmxlRnV0dXJlLnJ1bihDYWxsYWJsZUZ1dHVyZS5qYXZhOjYyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuRGlyZWN0RXhlY3V0b3IuZXhlY3V0ZShEaXJlY3RFeGVjdXRvci5qYXZhOjMwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuZXhlY3V0ZUxpc3RlbmVyKEFic3RyYWN0RnV0dXJlLmphdmE6MTE0Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmNvbXBsZXRlKEFic3RyYWN0RnV0dXJlLmphdmE6OTYzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuc2V0KEFic3RyYWN0RnV0dXJlLmphdmE6NzMxKVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS51dGlsLkNhbGxhYmxlRnV0dXJlLnJ1bihDYWxsYWJsZUZ1dHVyZS5qYXZhOjYyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuRGlyZWN0RXhlY3V0b3IuZXhlY3V0ZShEaXJlY3RFeGVjdXRvci5qYXZhOjMwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuZXhlY3V0ZUxpc3RlbmVyKEFic3RyYWN0RnV0dXJlLmphdmE6MTE0Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmNvbXBsZXRlKEFic3RyYWN0RnV0dXJlLmphdmE6OTYzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuc2V0KEFic3RyYWN0RnV0dXJlLmphdmE6NzMxKVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS51dGlsLkNhbGxhYmxlRnV0dXJlLnJ1bihDYWxsYWJsZUZ1dHVyZS5qYXZhOjYyKVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIudGhyZWFkLlRocmVhZFRyYWNrZXJzJFRocmVhZFRyYWNraW5nUnVubmFibGUucnVuKFRocmVhZFRyYWNrZXJzLmphdmE6MTI2KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JFRyYWNlQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChUcmFjZUNvbnRleHQuamF2YTo0NTUpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5zZXJ2ZXIuQ29tbW9uTW9kdWxlJENvbnRleHRDYXJyeWluZ0V4ZWN1dG9yU2VydmljZSQxLnJ1bkluQ29udGV4dChDb21tb25Nb2R1bGUuamF2YTo4NDYpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkVHJhY2VDb250ZXh0UnVubmFibGUkMS5ydW4oVHJhY2VDb250ZXh0LmphdmE6NDYyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JEFic3RyYWN0VHJhY2VDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihUcmFjZUNvbnRleHQuamF2YTozMjEpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkQWJzdHJhY3RUcmFjZUNvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoVHJhY2VDb250ZXh0LmphdmE6MzEzKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JFRyYWNlQ29udGV4dFJ1bm5hYmxlLnJ1bihUcmFjZUNvbnRleHQuamF2YTo0NTkpXG5cdGF0IGNvbS5nb29nbGUuZ3NlLmludGVybmFsLkRpc3BhdGNoUXVldWVJbXBsJFdvcmtlclRocmVhZC5ydW4oRGlzcGF0Y2hRdWV1ZUltcGwuamF2YTo0MDMpXG4ifV0sImNvZGUiOjQwMywibWVzc2FnZSI6ImludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIGRvZXMgbm90IGhhdmUgc2VydmljZXVzYWdlLnNlcnZpY2VzLnVzZSBhY2Nlc3MgdG8gcHJvamVjdCA2NDIwODA5MTgxMDEuIn19"
+ }
+ },
+ {
+ "ID": "f381b18f194a2f5c",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Type": [
+ "multipart/related; boundary=2a42e09cb0222d57d0cdbda1a68340bdb1fdca64a8c063a41cf471868a60"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "cdaf842a27589d153e2b9d276966c883/6713711838336371817;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "LS0yYTQyZTA5Y2IwMjIyZDU3ZDBjZGJkYTFhNjgzNDBiZGIxZmRjYTY0YThjMDYzYTQxY2Y0NzE4NjhhNjANCkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vanNvbg0KDQp7ImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMyIsImNhY2hlQ29udHJvbCI6InB1YmxpYywgbWF4LWFnZT02MCIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbiIsIm5hbWUiOiJmb28ifQoNCi0tMmE0MmUwOWNiMDIyMmQ1N2QwY2RiZGExYTY4MzQwYmRiMWZkY2E2NGE4YzA2M2E0MWNmNDcxODY4YTYwDQpDb250ZW50LVR5cGU6IHRleHQvcGxhaW4NCg0KaGVsbG8NCi0tMmE0MmUwOWNiMDIyMmQ1N2QwY2RiZGExYTY4MzQwYmRiMWZkY2E2NGE4YzA2M2E0MWNmNDcxODY4YTYwLS0NCg=="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3226"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:52 GMT"
+ ],
+ "Etag": [
+ "COSsl+iW290CEAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051388000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrqm14:4229,/bns/yw/borg/yw/bns/blobstore2/bitpusher/203.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=FMysW-C5FJW6N5Kzm8gE"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yw/borg/yw/bns/blobstore2/bitpusher/203.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yw/borg/yw/bns/blobstore2/bitpusher/203:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWVNNdC1OVDFNYTJvWXBrbG1qcDlJMlZaUFZ5bFl5Z2Q3Nk5tQXlXbWR3WVBoMm00dGI3ZmZjOUlzcTU4MmVFcFBhNzhNWGpNZmIzaE9WTE9xRHpNTUFfTG9NQXVJZkdkMGgzSWowZ1dxdW5DS1g3Qk1mQlJxM001TUtMMXBHOWNyU0ZBT29lVkZpTDhpWlBsUDI0VjE5THdzZ0d1ZnVrQTFtVzVJcTJUUkVXeWQyNjRKZC1lS2UxdTAwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_single_post_uploads"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UqkxLDMvcle5zEJBY34RLPtNVKJ1fnbATAahxz6t3qxFKd95_AEw1vsPKhIMG-xQA9v7eqd3F12o1YJnnGyCUclEv4f-A"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9mb28vMTUzODA1MTA5MjYzMzE4OCIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9vL2ZvbyIsIm5hbWUiOiJmb28iLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA5MjYzMzE4OCIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbiIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDo1Mi42MzNaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6NTIuNjMzWiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjUyLjYzM1oiLCJzaXplIjoiNSIsIm1kNUhhc2giOiJYVUZBS3J4TEtuYTVjWjJSRUJmRmtnPT0iLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL28vZm9vP2dlbmVyYXRpb249MTUzODA1MTA5MjYzMzE4OCZhbHQ9bWVkaWEiLCJjYWNoZUNvbnRyb2wiOiJwdWJsaWMsIG1heC1hZ2U9NjAiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9mb28vMTUzODA1MTA5MjYzMzE4OC9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9vL2Zvby9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJvYmplY3QiOiJmb28iLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA5MjYzMzE4OCIsImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6Im93bmVycyJ9LCJldGFnIjoiQ09Tc2wraVcyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL2Zvby8xNTM4MDUxMDkyNjMzMTg4L3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9vL2Zvby9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzIiwib2JqZWN0IjoiZm9vIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwOTI2MzMxODgiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ09Tc2wraVcyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL2Zvby8xNTM4MDUxMDkyNjMzMTg4L3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9vL2Zvby9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzIiwib2JqZWN0IjoiZm9vIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwOTI2MzMxODgiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNPU3NsK2lXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9mb28vMTUzODA1MTA5MjYzMzE4OC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL28vZm9vL2FjbC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzIiwib2JqZWN0IjoiZm9vIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwOTI2MzMxODgiLCJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwicm9sZSI6Ik9XTkVSIiwiZW1haWwiOiIzNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImV0YWciOiJDT1NzbCtpVzI5MENFQUU9In1dLCJvd25lciI6eyJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIn0sImNyYzMyYyI6Im1uRzdUQT09IiwiZXRhZyI6IkNPU3NsK2lXMjkwQ0VBRT0ifQ=="
+ }
+ },
+ {
+ "ID": "adbe5cfd07f61e80",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart\u0026userProject=dulcet-port-762",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Type": [
+ "multipart/related; boundary=7106bfacec7d6a09fd14fd37931b02367585ee2e8c64645316750dfde543"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "238f7c250ffab02d2bd5182bfd9cc71f/7544805302283804601;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart\u0026userProject=dulcet-port-762"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "LS03MTA2YmZhY2VjN2Q2YTA5ZmQxNGZkMzc5MzFiMDIzNjc1ODVlZTJlOGM2NDY0NTMxNjc1MGRmZGU1NDMNCkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vanNvbg0KDQp7ImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMyIsImNhY2hlQ29udHJvbCI6InB1YmxpYywgbWF4LWFnZT02MCIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbiIsIm5hbWUiOiJmb28ifQoNCi0tNzEwNmJmYWNlYzdkNmEwOWZkMTRmZDM3OTMxYjAyMzY3NTg1ZWUyZThjNjQ2NDUzMTY3NTBkZmRlNTQzDQpDb250ZW50LVR5cGU6IHRleHQvcGxhaW4NCg0KaGVsbG8NCi0tNzEwNmJmYWNlYzdkNmEwOWZkMTRmZDM3OTMxYjAyMzY3NTg1ZWUyZThjNjQ2NDUzMTY3NTBkZmRlNTQzLS0NCg=="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3226"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:53 GMT"
+ ],
+ "Etag": [
+ "CMT2r+iW290CEAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051388000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrbp5:4114,/bns/yr/borg/yr/bns/blobstore2/bitpusher/105.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=FMysW-CJLpCMkATtpaSoDA"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/105.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/105:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWVNNdC1OVDFNYTJvWXBrbG1qcDlJMlZaUFZ5bFl5Z2Q3Nk5tQXlXbWR3WVBoMm00dGI3ZmZjOUlzcTU4MmVFcFBhNzhNWGpNZmIzaE9WTE9xRHpNTUFfTG9NQXVJZkdkMGgzSWowZ1dxdW5DS1g3Qk1mQlJxM001TUtMMXBHOWNyU0ZBT29lVkZpTDhpWlBsUDI0VjE5THdzZ0d1ZnVrQTFtVzVJcTJUUkVXeWQyNjRKZC1lS2UxdTAwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_single_post_uploads"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Urq35CFbyHuYnJMS9wNKdQPD54VQ9oePAyRAi6YWIppfLMcQ_Wiub0-7o8EIeaVGmFFTRiO_XIo5Btdzb2K3DwSZJNqXg"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9mb28vMTUzODA1MTA5MzAzNTg0NCIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9vL2ZvbyIsIm5hbWUiOiJmb28iLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA5MzAzNTg0NCIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbiIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDo1My4wMzRaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6NTMuMDM0WiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjUzLjAzNFoiLCJzaXplIjoiNSIsIm1kNUhhc2giOiJYVUZBS3J4TEtuYTVjWjJSRUJmRmtnPT0iLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL28vZm9vP2dlbmVyYXRpb249MTUzODA1MTA5MzAzNTg0NCZhbHQ9bWVkaWEiLCJjYWNoZUNvbnRyb2wiOiJwdWJsaWMsIG1heC1hZ2U9NjAiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9mb28vMTUzODA1MTA5MzAzNTg0NC9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9vL2Zvby9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJvYmplY3QiOiJmb28iLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA5MzAzNTg0NCIsImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6Im93bmVycyJ9LCJldGFnIjoiQ01UMnIraVcyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL2Zvby8xNTM4MDUxMDkzMDM1ODQ0L3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9vL2Zvby9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzIiwib2JqZWN0IjoiZm9vIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwOTMwMzU4NDQiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ01UMnIraVcyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL2Zvby8xNTM4MDUxMDkzMDM1ODQ0L3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9vL2Zvby9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzIiwib2JqZWN0IjoiZm9vIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwOTMwMzU4NDQiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNNVDJyK2lXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9mb28vMTUzODA1MTA5MzAzNTg0NC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL28vZm9vL2FjbC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzIiwib2JqZWN0IjoiZm9vIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwOTMwMzU4NDQiLCJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwicm9sZSI6Ik9XTkVSIiwiZW1haWwiOiIzNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImV0YWciOiJDTVQycitpVzI5MENFQUU9In1dLCJvd25lciI6eyJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIn0sImNyYzMyYyI6Im1uRzdUQT09IiwiZXRhZyI6IkNNVDJyK2lXMjkwQ0VBRT0ifQ=="
+ }
+ },
+ {
+ "ID": "6974381989098ccd",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Type": [
+ "multipart/related; boundary=237260ec54bf8dc245243faeb66dd61b18510d622730eeecd6b6a1afcc5d"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "1aed5d989e814f60adeabf2f067063e6/8303842271721779464;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "LS0yMzcyNjBlYzU0YmY4ZGMyNDUyNDNmYWViNjZkZDYxYjE4NTEwZDYyMjczMGVlZWNkNmI2YTFhZmNjNWQNCkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vanNvbg0KDQp7ImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMyIsImNhY2hlQ29udHJvbCI6InB1YmxpYywgbWF4LWFnZT02MCIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbiIsIm5hbWUiOiJmb28ifQoNCi0tMjM3MjYwZWM1NGJmOGRjMjQ1MjQzZmFlYjY2ZGQ2MWIxODUxMGQ2MjI3MzBlZWVjZDZiNmExYWZjYzVkDQpDb250ZW50LVR5cGU6IHRleHQvcGxhaW4NCg0KaGVsbG8NCi0tMjM3MjYwZWM1NGJmOGRjMjQ1MjQzZmFlYjY2ZGQ2MWIxODUxMGQ2MjI3MzBlZWVjZDZiNmExYWZjYzVkLS0NCg=="
+ },
+ "Response": {
+ "StatusCode": 400,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Content-Length": [
+ "12135"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:53 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051393000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "471383502717"
+ ],
+ "X-Google-Backends": [
+ "vrow18:4419,/bns/yv/borg/yv/bns/blobstore2/bitpusher/140.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=FcysW6OhCpKCgwS2iqKgDw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/140.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/140:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CP3elYXcDRoCGAYoATpFChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGM6ropHgHCIVMTE3MjM4MDU4ODYxOTM3NTE5MTQ0MOArMOErMOMrSp8BEoIBeWEyOS5jLkVsb2xCcldWbUZlX1AxVDdUOHVpTXdFMHBZUjdTc2NVMDBFdEZkc2tSenBQY0NLWkhUeEZaYXI0Q25tZmR6bXFRLTNVV0kzOF9wdEx5VTZ2Z1Q3dlRBeW42Z3g4dUcyd0szSHIzaTZrV1JBZkozc1pNMGQ1allkNHpWQTAEOhZOT1RfQV9QRVJTSVNURU5UX1RPS0VO"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_single_post_uploads"
+ ],
+ "X-Guploader-Request-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Upload-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Uq7BisLbYLLhOtKX-mgm0uHF_EpDdlc9SsVqVhxUDic-GBgzAoE7XUNzqShAPyuJo_tMYfFtXlNE0F8qnAFCl579XxCCw"
+ ]
+ },
+ "Body": "eyJlcnJvciI6eyJlcnJvcnMiOlt7ImRvbWFpbiI6Imdsb2JhbCIsInJlYXNvbiI6InJlcXVpcmVkIiwibWVzc2FnZSI6IkJ1Y2tldCBpcyByZXF1ZXN0ZXIgcGF5cyBidWNrZXQgYnV0IG5vIHVzZXIgcHJvamVjdCBwcm92aWRlZC4iLCJkZWJ1Z0luZm8iOiJjb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6VVNFUl9QUk9KRUNUX01JU1NJTkc6IEJ1Y2tldCBpcyBSZXF1ZXN0ZXIgUGF5cyBidWNrZXQgYnV0IG5vIGJpbGxpbmcgcHJvamVjdCBpZCBwcm92aWRlZCBmb3Igbm9uLW93bmVyLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5JbnNlcnRPYmplY3QuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKEluc2VydE9iamVjdC5qYXZhOjIxNylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5vYmplY3RzLkluc2VydE9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoSW5zZXJ0T2JqZWN0LmphdmE6NTEpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5PYmplY3RzRGVsZWdhdG9yLmluc2VydChPYmplY3RzRGVsZWdhdG9yLmphdmE6OTUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBCdWNrZXQgaXMgUmVxdWVzdGVyIFBheXMgYnVja2V0IGJ1dCBubyBiaWxsaW5nIHByb2plY3QgaWQgcHJvdmlkZWQgZm9yIG5vbi1vd25lci5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MjkwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAxKVxuXHQuLi4gMTcgbW9yZVxuXG5jb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS5GYXVsdDogSW1tdXRhYmxlRXJyb3JEZWZpbml0aW9ue2Jhc2U9UkVRVUlSRUQsIGNhdGVnb3J5PVVTRVJfRVJST1IsIGNhdXNlPW51bGwsIGRlYnVnSW5mbz1jb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6VVNFUl9QUk9KRUNUX01JU1NJTkc6IEJ1Y2tldCBpcyBSZXF1ZXN0ZXIgUGF5cyBidWNrZXQgYnV0IG5vIGJpbGxpbmcgcHJvamVjdCBpZCBwcm92aWRlZCBmb3Igbm9uLW93bmVyLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5JbnNlcnRPYmplY3QuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKEluc2VydE9iamVjdC5qYXZhOjIxNylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5vYmplY3RzLkluc2VydE9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoSW5zZXJ0T2JqZWN0LmphdmE6NTEpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5PYmplY3RzRGVsZWdhdG9yLmluc2VydChPYmplY3RzRGVsZWdhdG9yLmphdmE6OTUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBCdWNrZXQgaXMgUmVxdWVzdGVyIFBheXMgYnVja2V0IGJ1dCBubyBiaWxsaW5nIHByb2plY3QgaWQgcHJvdmlkZWQgZm9yIG5vbi1vd25lci5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MjkwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAxKVxuXHQuLi4gMTcgbW9yZVxuLCBkb21haW49Z2xvYmFsLCBleHRlbmRlZEhlbHA9bnVsbCwgaHR0cEhlYWRlcnM9e30sIGh0dHBTdGF0dXM9YmFkUmVxdWVzdCwgaW50ZXJuYWxSZWFzb249UmVhc29ue2FyZ3VtZW50cz17fSwgY2F1c2U9bnVsbCwgY29kZT1nZGF0YS5Db3JlRXJyb3JEb21haW4uUkVRVUlSRUQsIGNyZWF0ZWRCeUJhY2tlbmQ9dHJ1ZSwgZGVidWdNZXNzYWdlPWNvbS5nb29nbGUubmV0LnJwYzMuUnBjRXhjZXB0aW9uOiBjbG91ZC5iaWdzdG9yZS5SZXNwb25zZUNvZGUuRXJyb3JDb2RlOjpVU0VSX1BST0pFQ1RfTUlTU0lORzogQnVja2V0IGlzIFJlcXVlc3RlciBQYXlzIGJ1Y2tldCBidXQgbm8gYmlsbGluZyBwcm9qZWN0IGlkIHByb3ZpZGVkIGZvciBub24tb3duZXIuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRvUnBjM0V4Y2VwdGlvbihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjEzNSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5vYmplY3RzLkluc2VydE9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoSW5zZXJ0T2JqZWN0LmphdmE6MjE3KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuSW5zZXJ0T2JqZWN0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChJbnNlcnRPYmplY3QuamF2YTo1MSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLk9iamVjdHNEZWxlZ2F0b3IuaW5zZXJ0KE9iamVjdHNEZWxlZ2F0b3IuamF2YTo5NSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uUnBjUmVjZWl2ZXIubGFtYmRhJHByb2Nlc3NSZXF1ZXN0QXN5bmMkNChScGNSZWNlaXZlci5qYXZhOjIwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uQXN5bmNFeGVjdXRvci5sYW1iZGEkc3VibWl0JDAoQXN5bmNFeGVjdXRvci5qYXZhOjI3Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KENvbnRleHRSdW5uYWJsZS5qYXZhOjUwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZSQxLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozOSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NzIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozNilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRXhlY3V0b3JzJFJ1bm5hYmxlQWRhcHRlci5jYWxsKEV4ZWN1dG9ycy5qYXZhOjUxMSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRnV0dXJlVGFzay5ydW4oRnV0dXJlVGFzay5qYXZhOjI2Nilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yLnJ1bldvcmtlcihUaHJlYWRQb29sRXhlY3V0b3IuamF2YToxMTQ5KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IkV29ya2VyLnJ1bihUaHJlYWRQb29sRXhlY3V0b3IuamF2YTo2MjQpXG5cdGF0IGphdmEubGFuZy5UaHJlYWQucnVuKFRocmVhZC5qYXZhOjc0OClcbkNhdXNlZCBieTogY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb246IEJ1Y2tldCBpcyBSZXF1ZXN0ZXIgUGF5cyBidWNrZXQgYnV0IG5vIGJpbGxpbmcgcHJvamVjdCBpZCBwcm92aWRlZCBmb3Igbm9uLW93bmVyLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxNyBtb3JlXG4sIGVycm9yUHJvdG9Db2RlPVJFUVVJUkVELCBlcnJvclByb3RvRG9tYWluPWdkYXRhLkNvcmVFcnJvckRvbWFpbiwgZmlsdGVyZWRNZXNzYWdlPW51bGwsIGxvY2F0aW9uPW51bGwsIG1lc3NhZ2U9QnVja2V0IGlzIHJlcXVlc3RlciBwYXlzIGJ1Y2tldCBidXQgbm8gdXNlciBwcm9qZWN0IHByb3ZpZGVkLiwgdW5uYW1lZEFyZ3VtZW50cz1bXX0sIGxvY2F0aW9uPW51bGwsIG1lc3NhZ2U9QnVja2V0IGlzIHJlcXVlc3RlciBwYXlzIGJ1Y2tldCBidXQgbm8gdXNlciBwcm9qZWN0IHByb3ZpZGVkLiwgcmVhc29uPXJlcXVpcmVkLCBycGNDb2RlPTQwMH0gQnVja2V0IGlzIHJlcXVlc3RlciBwYXlzIGJ1Y2tldCBidXQgbm8gdXNlciBwcm9qZWN0IHByb3ZpZGVkLjogY29tLmdvb2dsZS5uZXQucnBjMy5ScGNFeGNlcHRpb246IGNsb3VkLmJpZ3N0b3JlLlJlc3BvbnNlQ29kZS5FcnJvckNvZGU6OlVTRVJfUFJPSkVDVF9NSVNTSU5HOiBCdWNrZXQgaXMgUmVxdWVzdGVyIFBheXMgYnVja2V0IGJ1dCBubyBiaWxsaW5nIHByb2plY3QgaWQgcHJvdmlkZWQgZm9yIG5vbi1vd25lci5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udG9ScGMzRXhjZXB0aW9uKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MTM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuSW5zZXJ0T2JqZWN0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChJbnNlcnRPYmplY3QuamF2YToyMTcpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5JbnNlcnRPYmplY3QuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKEluc2VydE9iamVjdC5qYXZhOjUxKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmZyYW1ld29yay5SZXF1ZXN0SGFuZGxlci5oYW5kbGUoUmVxdWVzdEhhbmRsZXIuamF2YToyOTQpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uT2JqZWN0c0RlbGVnYXRvci5pbnNlcnQoT2JqZWN0c0RlbGVnYXRvci5qYXZhOjk1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5ScGNSZWNlaXZlci5sYW1iZGEkcHJvY2Vzc1JlcXVlc3RBc3luYyQ0KFJwY1JlY2VpdmVyLmphdmE6MjAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5Bc3luY0V4ZWN1dG9yLmxhbWJkYSRzdWJtaXQkMChBc3luY0V4ZWN1dG9yLmphdmE6MjcyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoQ29udGV4dFJ1bm5hYmxlLmphdmE6NTApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlJDEucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM5KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo3Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5FeGVjdXRvcnMkUnVubmFibGVBZGFwdGVyLmNhbGwoRXhlY3V0b3JzLmphdmE6NTExKVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5GdXR1cmVUYXNrLnJ1bihGdXR1cmVUYXNrLmphdmE6MjY2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IucnVuV29ya2VyKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjExNDkpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvciRXb3JrZXIucnVuKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjYyNClcblx0YXQgamF2YS5sYW5nLlRocmVhZC5ydW4oVGhyZWFkLmphdmE6NzQ4KVxuQ2F1c2VkIGJ5OiBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbjogQnVja2V0IGlzIFJlcXVlc3RlciBQYXlzIGJ1Y2tldCBidXQgbm8gYmlsbGluZyBwcm9qZWN0IGlkIHByb3ZpZGVkIGZvciBub24tb3duZXIuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93T25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjI5MClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMSlcblx0Li4uIDE3IG1vcmVcblxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS5FcnJvckNvbGxlY3Rvci50b0ZhdWx0KEVycm9yQ29sbGVjdG9yLmphdmE6NTQpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5yZXN0LmFkYXB0ZXIucm9zeS5Sb3N5RXJyb3JDb252ZXJ0ZXIudG9GYXVsdChSb3N5RXJyb3JDb252ZXJ0ZXIuamF2YTo2Nylcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnJlc3QuYWRhcHRlci5yb3N5LlJvc3lIYW5kbGVyJDIuY2FsbChSb3N5SGFuZGxlci5qYXZhOjI1OClcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnJlc3QuYWRhcHRlci5yb3N5LlJvc3lIYW5kbGVyJDIuY2FsbChSb3N5SGFuZGxlci5qYXZhOjIzOClcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkRpcmVjdEV4ZWN1dG9yLmV4ZWN1dGUoRGlyZWN0RXhlY3V0b3IuamF2YTozMClcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmV4ZWN1dGVMaXN0ZW5lcihBYnN0cmFjdEZ1dHVyZS5qYXZhOjExNDMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5jb21wbGV0ZShBYnN0cmFjdEZ1dHVyZS5qYXZhOjk2Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLnNldChBYnN0cmFjdEZ1dHVyZS5qYXZhOjczMSlcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkRpcmVjdEV4ZWN1dG9yLmV4ZWN1dGUoRGlyZWN0RXhlY3V0b3IuamF2YTozMClcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmV4ZWN1dGVMaXN0ZW5lcihBYnN0cmFjdEZ1dHVyZS5qYXZhOjExNDMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5jb21wbGV0ZShBYnN0cmFjdEZ1dHVyZS5qYXZhOjk2Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLnNldChBYnN0cmFjdEZ1dHVyZS5qYXZhOjczMSlcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnRocmVhZC5UaHJlYWRUcmFja2VycyRUaHJlYWRUcmFja2luZ1J1bm5hYmxlLnJ1bihUaHJlYWRUcmFja2Vycy5qYXZhOjEyNilcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRUcmFjZUNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoVHJhY2VDb250ZXh0LmphdmE6NDU1KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuc2VydmVyLkNvbW1vbk1vZHVsZSRDb250ZXh0Q2FycnlpbmdFeGVjdXRvclNlcnZpY2UkMS5ydW5JbkNvbnRleHQoQ29tbW9uTW9kdWxlLmphdmE6ODQ2KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JFRyYWNlQ29udGV4dFJ1bm5hYmxlJDEucnVuKFRyYWNlQ29udGV4dC5qYXZhOjQ2Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRBYnN0cmFjdFRyYWNlQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoVHJhY2VDb250ZXh0LmphdmE6MzIxKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JEFic3RyYWN0VHJhY2VDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KFRyYWNlQ29udGV4dC5qYXZhOjMxMylcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRUcmFjZUNvbnRleHRSdW5uYWJsZS5ydW4oVHJhY2VDb250ZXh0LmphdmE6NDU5KVxuXHRhdCBjb20uZ29vZ2xlLmdzZS5pbnRlcm5hbC5EaXNwYXRjaFF1ZXVlSW1wbCRXb3JrZXJUaHJlYWQucnVuKERpc3BhdGNoUXVldWVJbXBsLmphdmE6NDAzKVxuIn1dLCJjb2RlIjo0MDAsIm1lc3NhZ2UiOiJCdWNrZXQgaXMgcmVxdWVzdGVyIHBheXMgYnVja2V0IGJ1dCBubyB1c2VyIHByb2plY3QgcHJvdmlkZWQuIn19"
+ }
+ },
+ {
+ "ID": "2708a38f17248e4e",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart\u0026userProject=gcloud-golang-firestore-tests",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Type": [
+ "multipart/related; boundary=21fc50710a2e85a9df16ae976a592eee89a3bf61d5a3cc00d589f4ea436b"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "c835286d2a2f023e4587c8da313787d1/9135217202056119383;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart\u0026userProject=gcloud-golang-firestore-tests"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "LS0yMWZjNTA3MTBhMmU4NWE5ZGYxNmFlOTc2YTU5MmVlZTg5YTNiZjYxZDVhM2NjMDBkNTg5ZjRlYTQzNmINCkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vanNvbg0KDQp7ImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMyIsImNhY2hlQ29udHJvbCI6InB1YmxpYywgbWF4LWFnZT02MCIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbiIsIm5hbWUiOiJmb28ifQoNCi0tMjFmYzUwNzEwYTJlODVhOWRmMTZhZTk3NmE1OTJlZWU4OWEzYmY2MWQ1YTNjYzAwZDU4OWY0ZWE0MzZiDQpDb250ZW50LVR5cGU6IHRleHQvcGxhaW4NCg0KaGVsbG8NCi0tMjFmYzUwNzEwYTJlODVhOWRmMTZhZTk3NmE1OTJlZWU4OWEzYmY2MWQ1YTNjYzAwZDU4OWY0ZWE0MzZiLS0NCg=="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3181"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:53 GMT"
+ ],
+ "Etag": [
+ "CISC0OiW290CEAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051393000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "471383502717"
+ ],
+ "X-Google-Backends": [
+ "vnpb10:4017,/bns/yx/borg/yx/bns/blobstore2/bitpusher/49.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=FcysW-mhGoqIzQKVwKT4Aw"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yx/borg/yx/bns/blobstore2/bitpusher/49.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yx/borg/yx/bns/blobstore2/bitpusher/49:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CP3elYXcDRoCGAYoATpFChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGM6ropHgHCIVMTE3MjM4MDU4ODYxOTM3NTE5MTQ0MOArMOErMOMrSp8BEoIBeWEyOS5jLkVsb2xCcldWbUZlX1AxVDdUOHVpTXdFMHBZUjdTc2NVMDBFdEZkc2tSenBQY0NLWkhUeEZaYXI0Q25tZmR6bXFRLTNVV0kzOF9wdEx5VTZ2Z1Q3dlRBeW42Z3g4dUcyd0szSHIzaTZrV1JBZkozc1pNMGQ1allkNHpWQTAEOhZOT1RfQV9QRVJTSVNURU5UX1RPS0VO"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_single_post_uploads"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UoNEzfQSF71KAopZ_IPoXU_ysPiMxX66AcMFT8VzLfFCCP-ZNcVBHqt60lvdWZMihDQq4TALbx_UZJwzMoH7ZB-Y7tmfg"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9mb28vMTUzODA1MTA5MzU2MTYwNCIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9vL2ZvbyIsIm5hbWUiOiJmb28iLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA5MzU2MTYwNCIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbiIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDo1My41NjFaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6NTMuNTYxWiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjUzLjU2MVoiLCJzaXplIjoiNSIsIm1kNUhhc2giOiJYVUZBS3J4TEtuYTVjWjJSRUJmRmtnPT0iLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL28vZm9vP2dlbmVyYXRpb249MTUzODA1MTA5MzU2MTYwNCZhbHQ9bWVkaWEiLCJjYWNoZUNvbnRyb2wiOiJwdWJsaWMsIG1heC1hZ2U9NjAiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9mb28vMTUzODA1MTA5MzU2MTYwNC9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9vL2Zvby9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJvYmplY3QiOiJmb28iLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA5MzU2MTYwNCIsImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6Im93bmVycyJ9LCJldGFnIjoiQ0lTQzBPaVcyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL2Zvby8xNTM4MDUxMDkzNTYxNjA0L3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9vL2Zvby9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzIiwib2JqZWN0IjoiZm9vIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwOTM1NjE2MDQiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0lTQzBPaVcyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL2Zvby8xNTM4MDUxMDkzNTYxNjA0L3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9vL2Zvby9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzIiwib2JqZWN0IjoiZm9vIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwOTM1NjE2MDQiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNJU0MwT2lXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9mb28vMTUzODA1MTA5MzU2MTYwNC91c2VyLWludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL28vZm9vL2FjbC91c2VyLWludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzIiwib2JqZWN0IjoiZm9vIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwOTM1NjE2MDQiLCJlbnRpdHkiOiJ1c2VyLWludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIiwicm9sZSI6Ik9XTkVSIiwiZW1haWwiOiJpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSIsImV0YWciOiJDSVNDME9pVzI5MENFQUU9In1dLCJvd25lciI6eyJlbnRpdHkiOiJ1c2VyLWludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIn0sImNyYzMyYyI6Im1uRzdUQT09IiwiZXRhZyI6IkNJU0MwT2lXMjkwQ0VBRT0ifQ=="
+ }
+ },
+ {
+ "ID": "3528b2e1f97481d7",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart\u0026userProject=veener-jba",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Type": [
+ "multipart/related; boundary=1683011057ae3f3e81c417873b5bac49a2246cb943117ba7e6822fbe4dba"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "18ff62e9ecc16f2dd761505112b6b3f2/9894254171477252007;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart\u0026userProject=veener-jba"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "LS0xNjgzMDExMDU3YWUzZjNlODFjNDE3ODczYjViYWM0OWEyMjQ2Y2I5NDMxMTdiYTdlNjgyMmZiZTRkYmENCkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vanNvbg0KDQp7ImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMyIsImNhY2hlQ29udHJvbCI6InB1YmxpYywgbWF4LWFnZT02MCIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbiIsIm5hbWUiOiJmb28ifQoNCi0tMTY4MzAxMTA1N2FlM2YzZTgxYzQxNzg3M2I1YmFjNDlhMjI0NmNiOTQzMTE3YmE3ZTY4MjJmYmU0ZGJhDQpDb250ZW50LVR5cGU6IHRleHQvcGxhaW4NCg0KaGVsbG8NCi0tMTY4MzAxMTA1N2FlM2YzZTgxYzQxNzg3M2I1YmFjNDlhMjI0NmNiOTQzMTE3YmE3ZTY4MjJmYmU0ZGJhLS0NCg=="
+ },
+ "Response": {
+ "StatusCode": 403,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Content-Length": [
+ "12991"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:53 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051393000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "471383502717"
+ ],
+ "X-Google-Backends": [
+ "vnbe67:4474,/bns/yx/borg/yx/bns/blobstore2/bitpusher/55.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=FcysW9bbKcKPzALhvZOIDA"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yx/borg/yx/bns/blobstore2/bitpusher/55.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yx/borg/yx/bns/blobstore2/bitpusher/55:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CP3elYXcDRoCGAYoATpFChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGM6ropHgHCIVMTE3MjM4MDU4ODYxOTM3NTE5MTQ0MOArMOErMOMrSp8BEoIBeWEyOS5jLkVsb2xCcldWbUZlX1AxVDdUOHVpTXdFMHBZUjdTc2NVMDBFdEZkc2tSenBQY0NLWkhUeEZaYXI0Q25tZmR6bXFRLTNVV0kzOF9wdEx5VTZ2Z1Q3dlRBeW42Z3g4dUcyd0szSHIzaTZrV1JBZkozc1pNMGQ1allkNHpWQTAEOhZOT1RfQV9QRVJTSVNURU5UX1RPS0VO"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_single_post_uploads"
+ ],
+ "X-Guploader-Request-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Upload-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UryciEENEv-7rhlVHwecRoi4eIpPLkD9snDJxBdIg21D_qc_UQsZpaChX7XUPxFv4qrYSgtLftJ_LWGxBvbvjJBToeaqg"
+ ]
+ },
+ "Body": "eyJlcnJvciI6eyJlcnJvcnMiOlt7ImRvbWFpbiI6Imdsb2JhbCIsInJlYXNvbiI6ImZvcmJpZGRlbiIsIm1lc3NhZ2UiOiJpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLiIsImRlYnVnSW5mbyI6ImNvbS5nb29nbGUubmV0LnJwYzMuUnBjRXhjZXB0aW9uOiBjbG91ZC5iaWdzdG9yZS5SZXNwb25zZUNvZGUuRXJyb3JDb2RlOjpVU0VSX1BST0pFQ1RfQUNDRVNTX0RFTklFRDogaW50ZWdyYXRpb25AZ2Nsb3VkLWdvbGFuZy1maXJlc3RvcmUtdGVzdHMuaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20gZG9lcyBub3QgaGF2ZSBzZXJ2aWNldXNhZ2Uuc2VydmljZXMudXNlIGFjY2VzcyB0byBwcm9qZWN0IDY0MjA4MDkxODEwMS5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udG9ScGMzRXhjZXB0aW9uKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MTM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuSW5zZXJ0T2JqZWN0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChJbnNlcnRPYmplY3QuamF2YToyMTcpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5JbnNlcnRPYmplY3QuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKEluc2VydE9iamVjdC5qYXZhOjUxKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmZyYW1ld29yay5SZXF1ZXN0SGFuZGxlci5oYW5kbGUoUmVxdWVzdEhhbmRsZXIuamF2YToyOTQpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uT2JqZWN0c0RlbGVnYXRvci5pbnNlcnQoT2JqZWN0c0RlbGVnYXRvci5qYXZhOjk1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5ScGNSZWNlaXZlci5sYW1iZGEkcHJvY2Vzc1JlcXVlc3RBc3luYyQ0KFJwY1JlY2VpdmVyLmphdmE6MjAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5Bc3luY0V4ZWN1dG9yLmxhbWJkYSRzdWJtaXQkMChBc3luY0V4ZWN1dG9yLmphdmE6MjcyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoQ29udGV4dFJ1bm5hYmxlLmphdmE6NTApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlJDEucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM5KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo3Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5FeGVjdXRvcnMkUnVubmFibGVBZGFwdGVyLmNhbGwoRXhlY3V0b3JzLmphdmE6NTExKVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5GdXR1cmVUYXNrLnJ1bihGdXR1cmVUYXNrLmphdmE6MjY2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IucnVuV29ya2VyKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjExNDkpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvciRXb3JrZXIucnVuKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjYyNClcblx0YXQgamF2YS5sYW5nLlRocmVhZC5ydW4oVGhyZWFkLmphdmE6NzQ4KVxuQ2F1c2VkIGJ5OiBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbjogaW50ZWdyYXRpb25AZ2Nsb3VkLWdvbGFuZy1maXJlc3RvcmUtdGVzdHMuaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20gZG9lcyBub3QgaGF2ZSBzZXJ2aWNldXNhZ2Uuc2VydmljZXMudXNlIGFjY2VzcyB0byBwcm9qZWN0IDY0MjA4MDkxODEwMS5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MjkwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAxKVxuXHQuLi4gMTcgbW9yZVxuXG5jb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS5GYXVsdDogSW1tdXRhYmxlRXJyb3JEZWZpbml0aW9ue2Jhc2U9Rk9SQklEREVOLCBjYXRlZ29yeT1VU0VSX0VSUk9SLCBjYXVzZT1udWxsLCBkZWJ1Z0luZm89Y29tLmdvb2dsZS5uZXQucnBjMy5ScGNFeGNlcHRpb246IGNsb3VkLmJpZ3N0b3JlLlJlc3BvbnNlQ29kZS5FcnJvckNvZGU6OlVTRVJfUFJPSkVDVF9BQ0NFU1NfREVOSUVEOiBpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5JbnNlcnRPYmplY3QuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKEluc2VydE9iamVjdC5qYXZhOjIxNylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5vYmplY3RzLkluc2VydE9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoSW5zZXJ0T2JqZWN0LmphdmE6NTEpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5PYmplY3RzRGVsZWdhdG9yLmluc2VydChPYmplY3RzRGVsZWdhdG9yLmphdmE6OTUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxNyBtb3JlXG4sIGRvbWFpbj1nbG9iYWwsIGV4dGVuZGVkSGVscD1udWxsLCBodHRwSGVhZGVycz17fSwgaHR0cFN0YXR1cz1mb3JiaWRkZW4sIGludGVybmFsUmVhc29uPVJlYXNvbnthcmd1bWVudHM9e30sIGNhdXNlPW51bGwsIGNvZGU9Z2RhdGEuQ29yZUVycm9yRG9tYWluLkZPUkJJRERFTiwgY3JlYXRlZEJ5QmFja2VuZD10cnVlLCBkZWJ1Z01lc3NhZ2U9Y29tLmdvb2dsZS5uZXQucnBjMy5ScGNFeGNlcHRpb246IGNsb3VkLmJpZ3N0b3JlLlJlc3BvbnNlQ29kZS5FcnJvckNvZGU6OlVTRVJfUFJPSkVDVF9BQ0NFU1NfREVOSUVEOiBpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5JbnNlcnRPYmplY3QuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKEluc2VydE9iamVjdC5qYXZhOjIxNylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5vYmplY3RzLkluc2VydE9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoSW5zZXJ0T2JqZWN0LmphdmE6NTEpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5PYmplY3RzRGVsZWdhdG9yLmluc2VydChPYmplY3RzRGVsZWdhdG9yLmphdmE6OTUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxNyBtb3JlXG4sIGVycm9yUHJvdG9Db2RlPUZPUkJJRERFTiwgZXJyb3JQcm90b0RvbWFpbj1nZGF0YS5Db3JlRXJyb3JEb21haW4sIGZpbHRlcmVkTWVzc2FnZT1udWxsLCBsb2NhdGlvbj1udWxsLCBtZXNzYWdlPWludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIGRvZXMgbm90IGhhdmUgc2VydmljZXVzYWdlLnNlcnZpY2VzLnVzZSBhY2Nlc3MgdG8gcHJvamVjdCA2NDIwODA5MTgxMDEuLCB1bm5hbWVkQXJndW1lbnRzPVtdfSwgbG9jYXRpb249bnVsbCwgbWVzc2FnZT1pbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLiwgcmVhc29uPWZvcmJpZGRlbiwgcnBjQ29kZT00MDN9IGludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIGRvZXMgbm90IGhhdmUgc2VydmljZXVzYWdlLnNlcnZpY2VzLnVzZSBhY2Nlc3MgdG8gcHJvamVjdCA2NDIwODA5MTgxMDEuOiBjb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6VVNFUl9QUk9KRUNUX0FDQ0VTU19ERU5JRUQ6IGludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIGRvZXMgbm90IGhhdmUgc2VydmljZXVzYWdlLnNlcnZpY2VzLnVzZSBhY2Nlc3MgdG8gcHJvamVjdCA2NDIwODA5MTgxMDEuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRvUnBjM0V4Y2VwdGlvbihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjEzNSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5vYmplY3RzLkluc2VydE9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoSW5zZXJ0T2JqZWN0LmphdmE6MjE3KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuSW5zZXJ0T2JqZWN0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChJbnNlcnRPYmplY3QuamF2YTo1MSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLk9iamVjdHNEZWxlZ2F0b3IuaW5zZXJ0KE9iamVjdHNEZWxlZ2F0b3IuamF2YTo5NSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uUnBjUmVjZWl2ZXIubGFtYmRhJHByb2Nlc3NSZXF1ZXN0QXN5bmMkNChScGNSZWNlaXZlci5qYXZhOjIwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uQXN5bmNFeGVjdXRvci5sYW1iZGEkc3VibWl0JDAoQXN5bmNFeGVjdXRvci5qYXZhOjI3Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KENvbnRleHRSdW5uYWJsZS5qYXZhOjUwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZSQxLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozOSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NzIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozNilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRXhlY3V0b3JzJFJ1bm5hYmxlQWRhcHRlci5jYWxsKEV4ZWN1dG9ycy5qYXZhOjUxMSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRnV0dXJlVGFzay5ydW4oRnV0dXJlVGFzay5qYXZhOjI2Nilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yLnJ1bldvcmtlcihUaHJlYWRQb29sRXhlY3V0b3IuamF2YToxMTQ5KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IkV29ya2VyLnJ1bihUaHJlYWRQb29sRXhlY3V0b3IuamF2YTo2MjQpXG5cdGF0IGphdmEubGFuZy5UaHJlYWQucnVuKFRocmVhZC5qYXZhOjc0OClcbkNhdXNlZCBieTogY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb246IGludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIGRvZXMgbm90IGhhdmUgc2VydmljZXVzYWdlLnNlcnZpY2VzLnVzZSBhY2Nlc3MgdG8gcHJvamVjdCA2NDIwODA5MTgxMDEuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93T25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjI5MClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMSlcblx0Li4uIDE3IG1vcmVcblxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS5FcnJvckNvbGxlY3Rvci50b0ZhdWx0KEVycm9yQ29sbGVjdG9yLmphdmE6NTQpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5yZXN0LmFkYXB0ZXIucm9zeS5Sb3N5RXJyb3JDb252ZXJ0ZXIudG9GYXVsdChSb3N5RXJyb3JDb252ZXJ0ZXIuamF2YTo2Nylcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnJlc3QuYWRhcHRlci5yb3N5LlJvc3lIYW5kbGVyJDIuY2FsbChSb3N5SGFuZGxlci5qYXZhOjI1OClcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnJlc3QuYWRhcHRlci5yb3N5LlJvc3lIYW5kbGVyJDIuY2FsbChSb3N5SGFuZGxlci5qYXZhOjIzOClcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkRpcmVjdEV4ZWN1dG9yLmV4ZWN1dGUoRGlyZWN0RXhlY3V0b3IuamF2YTozMClcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmV4ZWN1dGVMaXN0ZW5lcihBYnN0cmFjdEZ1dHVyZS5qYXZhOjExNDMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5jb21wbGV0ZShBYnN0cmFjdEZ1dHVyZS5qYXZhOjk2Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLnNldChBYnN0cmFjdEZ1dHVyZS5qYXZhOjczMSlcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkRpcmVjdEV4ZWN1dG9yLmV4ZWN1dGUoRGlyZWN0RXhlY3V0b3IuamF2YTozMClcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmV4ZWN1dGVMaXN0ZW5lcihBYnN0cmFjdEZ1dHVyZS5qYXZhOjExNDMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5jb21wbGV0ZShBYnN0cmFjdEZ1dHVyZS5qYXZhOjk2Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLnNldChBYnN0cmFjdEZ1dHVyZS5qYXZhOjczMSlcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnRocmVhZC5UaHJlYWRUcmFja2VycyRUaHJlYWRUcmFja2luZ1J1bm5hYmxlLnJ1bihUaHJlYWRUcmFja2Vycy5qYXZhOjEyNilcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRUcmFjZUNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoVHJhY2VDb250ZXh0LmphdmE6NDU1KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuc2VydmVyLkNvbW1vbk1vZHVsZSRDb250ZXh0Q2FycnlpbmdFeGVjdXRvclNlcnZpY2UkMS5ydW5JbkNvbnRleHQoQ29tbW9uTW9kdWxlLmphdmE6ODQ2KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JFRyYWNlQ29udGV4dFJ1bm5hYmxlJDEucnVuKFRyYWNlQ29udGV4dC5qYXZhOjQ2Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRBYnN0cmFjdFRyYWNlQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoVHJhY2VDb250ZXh0LmphdmE6MzIxKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JEFic3RyYWN0VHJhY2VDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KFRyYWNlQ29udGV4dC5qYXZhOjMxMylcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRUcmFjZUNvbnRleHRSdW5uYWJsZS5ydW4oVHJhY2VDb250ZXh0LmphdmE6NDU5KVxuXHRhdCBjb20uZ29vZ2xlLmdzZS5pbnRlcm5hbC5EaXNwYXRjaFF1ZXVlSW1wbCRXb3JrZXJUaHJlYWQucnVuKERpc3BhdGNoUXVldWVJbXBsLmphdmE6NDAzKVxuIn1dLCJjb2RlIjo0MDMsIm1lc3NhZ2UiOiJpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLiJ9fQ=="
+ }
+ },
+ {
+ "ID": "93dbfc48d4e0ae67",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://storage.googleapis.com/go-integration-test-20180927-44630911863640-0003/foo",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "Go-http-client/1.1"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "b7f3940371552e2fe7340e3824bb07ef/11484666075544468549;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "storage.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://storage.googleapis.com/go-integration-test-20180927-44630911863640-0003/foo"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Accept-Ranges": [
+ "bytes"
+ ],
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "5"
+ ],
+ "Content-Type": [
+ "text/plain"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:53 GMT"
+ ],
+ "Etag": [
+ "\"5d41402abc4b2a76b9719d911017c592\""
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Last-Modified": [
+ "Thu, 27 Sep 2018 12:24:53 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "X-Goog-Generation": [
+ "1538051093561604"
+ ],
+ "X-Goog-Hash": [
+ "crc32c=mnG7TA==",
+ "md5=XUFAKrxLKna5cZ2REBfFkg=="
+ ],
+ "X-Goog-Metageneration": [
+ "1"
+ ],
+ "X-Goog-Storage-Class": [
+ "STANDARD"
+ ],
+ "X-Goog-Stored-Content-Encoding": [
+ "identity"
+ ],
+ "X-Goog-Stored-Content-Length": [
+ "5"
+ ],
+ "X-Google-Backends": [
+ "/bns/xh/borg/xh/bns/cloud-storage/prod-cloud-storage-frontend.frontend/43,/bns/xh/borg/xh/bns/blobstore2/bitpusher/64.scotty,aclgag19:443"
+ ],
+ "X-Google-Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=FcysW_nbOMKmswayqIGIDg"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "aclgag19:443,/bns/xh/borg/xh/bns/blobstore2/bitpusher/64.scotty,aclgag19:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/xh/borg/xh/bns/blobstore2/bitpusher/64:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBJ"
+ ],
+ "X-Google-Storage-Location": [
+ "US"
+ ],
+ "X-Guploader-Customer": [
+ "cloud-storage"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UobYLQCVAXDkWBxGuaLG3DcCe_4MnWObiBBQ3HESP7N-QS5GnqnFP4_tMrgvjZ9QyyllwC0UGwfoeVUplyqoPXVM8af3w"
+ ]
+ },
+ "Body": "aGVsbG8="
+ }
+ },
+ {
+ "ID": "ed6543d15a309ca2",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://storage.googleapis.com/go-integration-test-20180927-44630911863640-0003/foo",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "Go-http-client/1.1"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "74c8e0a2cd370f802a2c638fad744a1e/13074795409418248932;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "storage.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://storage.googleapis.com/go-integration-test-20180927-44630911863640-0003/foo"
+ ],
+ "X-Goog-User-Project": [
+ "dulcet-port-762"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Accept-Ranges": [
+ "bytes"
+ ],
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "5"
+ ],
+ "Content-Type": [
+ "text/plain"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:54 GMT"
+ ],
+ "Etag": [
+ "\"5d41402abc4b2a76b9719d911017c592\""
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Last-Modified": [
+ "Thu, 27 Sep 2018 12:24:53 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "X-Goog-Generation": [
+ "1538051093561604"
+ ],
+ "X-Goog-Hash": [
+ "crc32c=mnG7TA==",
+ "md5=XUFAKrxLKna5cZ2REBfFkg=="
+ ],
+ "X-Goog-Metageneration": [
+ "1"
+ ],
+ "X-Goog-Storage-Class": [
+ "STANDARD"
+ ],
+ "X-Goog-Stored-Content-Encoding": [
+ "identity"
+ ],
+ "X-Goog-Stored-Content-Length": [
+ "5"
+ ],
+ "X-Google-Backends": [
+ "/bns/xh/borg/xh/bns/cloud-storage/prod-cloud-storage-frontend.frontend/12,/bns/xh/borg/xh/bns/blobstore2/bitpusher/28.scotty,aclgag19:443"
+ ],
+ "X-Google-Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=FsysW4mqAouhswbl1qKYBg"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "aclgag19:443,/bns/xh/borg/xh/bns/blobstore2/bitpusher/28.scotty,aclgag19:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/xh/borg/xh/bns/blobstore2/bitpusher/28:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBJ"
+ ],
+ "X-Google-Storage-Location": [
+ "US"
+ ],
+ "X-Guploader-Customer": [
+ "cloud-storage"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Ur7qo9qqOxLPqeOJg3_hC6Lw6aEFXRvIfjwfeJ60wJcvPZkkUlHiIGTpY9BY1Av4e8U2DJH2LL0G6dUQ9iYWAqlb0GiIA"
+ ]
+ },
+ "Body": "aGVsbG8="
+ }
+ },
+ {
+ "ID": "e1568d1781fe6674",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://storage.googleapis.com/go-integration-test-20180927-44630911863640-0003/foo",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "Go-http-client/1.1"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "14d9ea9e4c04369d531fe44c64494f92/14665207309190498179;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "storage.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://storage.googleapis.com/go-integration-test-20180927-44630911863640-0003/foo"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 400,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0"
+ ],
+ "Content-Length": [
+ "266"
+ ],
+ "Content-Type": [
+ "application/xml; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:54 GMT"
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:24:54 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "X-Google-Backends": [
+ "/bns/xh/borg/xh/bns/cloud-storage/prod-cloud-storage-frontend.frontend/45,/bns/xh/borg/xh/bns/blobstore2/bitpusher/52.scotty,aclgag19:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=FsysW-vABbCqswa-pIPADw"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "aclgag19:443,/bns/xh/borg/xh/bns/blobstore2/bitpusher/52.scotty,aclgag19:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/xh/borg/xh/bns/blobstore2/bitpusher/52:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBJ"
+ ],
+ "X-Guploader-Customer": [
+ "cloud-storage"
+ ],
+ "X-Guploader-Request-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Upload-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UrhJXGAWNxkg2lwZ7HPMDSI-cZdGgnrHDLOt-Vn4GIt6Py6SXjBikyUW--bL8PD6_H-VDdhf90i-L0t6SMFjJvfOx4vaQ"
+ ]
+ },
+ "Body": "PD94bWwgdmVyc2lvbj0nMS4wJyBlbmNvZGluZz0nVVRGLTgnPz48RXJyb3I+PENvZGU+VXNlclByb2plY3RNaXNzaW5nPC9Db2RlPjxNZXNzYWdlPkJ1Y2tldCBpcyBhIHJlcXVlc3RlciBwYXlzIGJ1Y2tldCBidXQgbm8gdXNlciBwcm9qZWN0IHByb3ZpZGVkLjwvTWVzc2FnZT48RGV0YWlscz5CdWNrZXQgaXMgUmVxdWVzdGVyIFBheXMgYnVja2V0IGJ1dCBubyBiaWxsaW5nIHByb2plY3QgaWQgcHJvdmlkZWQgZm9yIG5vbi1vd25lci48L0RldGFpbHM+PC9FcnJvcj4="
+ }
+ },
+ {
+ "ID": "6408084335935ff1",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://storage.googleapis.com/go-integration-test-20180927-44630911863640-0003/foo",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "Go-http-client/1.1"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "e96ce5b68f60f903ab1b5198c8f9f580/16255619213240937761;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "storage.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://storage.googleapis.com/go-integration-test-20180927-44630911863640-0003/foo"
+ ],
+ "X-Goog-User-Project": [
+ "gcloud-golang-firestore-tests"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Accept-Ranges": [
+ "bytes"
+ ],
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "5"
+ ],
+ "Content-Type": [
+ "text/plain"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:54 GMT"
+ ],
+ "Etag": [
+ "\"5d41402abc4b2a76b9719d911017c592\""
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Last-Modified": [
+ "Thu, 27 Sep 2018 12:24:53 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "X-Goog-Generation": [
+ "1538051093561604"
+ ],
+ "X-Goog-Hash": [
+ "crc32c=mnG7TA==",
+ "md5=XUFAKrxLKna5cZ2REBfFkg=="
+ ],
+ "X-Goog-Metageneration": [
+ "1"
+ ],
+ "X-Goog-Storage-Class": [
+ "STANDARD"
+ ],
+ "X-Goog-Stored-Content-Encoding": [
+ "identity"
+ ],
+ "X-Goog-Stored-Content-Length": [
+ "5"
+ ],
+ "X-Google-Backends": [
+ "/bns/xh/borg/xh/bns/cloud-storage/prod-cloud-storage-frontend.frontend/12,/bns/xh/borg/xh/bns/blobstore2/bitpusher/79.scotty,aclgag19:443"
+ ],
+ "X-Google-Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=FsysW7bnE-6jswbStIHACg"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "aclgag19:443,/bns/xh/borg/xh/bns/blobstore2/bitpusher/79.scotty,aclgag19:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/xh/borg/xh/bns/blobstore2/bitpusher/79:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBJ"
+ ],
+ "X-Google-Storage-Location": [
+ "US"
+ ],
+ "X-Guploader-Customer": [
+ "cloud-storage"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UoVhfv-eFV4ZRHB30hin-A2fc9MasLv3xA4ppkx8fs1rqGq5kaqhAwHg2LHt1HBr-7TjnfZTbDFTpfyUBdCX42usFy41w"
+ ]
+ },
+ "Body": "aGVsbG8="
+ }
+ },
+ {
+ "ID": "c5b24411d8fb2531",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://storage.googleapis.com/go-integration-test-20180927-44630911863640-0003/foo",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "Go-http-client/1.1"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "9733323f0f15db56551241ac7d27e645/17846031117308089024;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "storage.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://storage.googleapis.com/go-integration-test-20180927-44630911863640-0003/foo"
+ ],
+ "X-Goog-User-Project": [
+ "veener-jba"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 403,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0"
+ ],
+ "Content-Length": [
+ "342"
+ ],
+ "Content-Type": [
+ "application/xml; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:54 GMT"
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:24:54 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "X-Google-Backends": [
+ "/bns/xh/borg/xh/bns/cloud-storage/prod-cloud-storage-frontend.frontend/47,/bns/xh/borg/xh/bns/blobstore2/bitpusher/62.scotty,aclgag19:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=FsysW6CcF8SmswaLopWwDA"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "aclgag19:443,/bns/xh/borg/xh/bns/blobstore2/bitpusher/62.scotty,aclgag19:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/xh/borg/xh/bns/blobstore2/bitpusher/62:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBJ"
+ ],
+ "X-Guploader-Customer": [
+ "cloud-storage"
+ ],
+ "X-Guploader-Request-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Upload-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UpUnfRLufy7QUE_x8D4JMhXS7A6KYYHAUkUJA-0_EiWVsKAOCcy6GDqTTNo_wExvSNqJq_MgNWUhaA1shGpfMMAXVCxsA"
+ ]
+ },
+ "Body": "PD94bWwgdmVyc2lvbj0nMS4wJyBlbmNvZGluZz0nVVRGLTgnPz48RXJyb3I+PENvZGU+VXNlclByb2plY3RBY2Nlc3NEZW5pZWQ8L0NvZGU+PE1lc3NhZ2U+UmVxdWVzdGVyIGRvZXMgbm90IGhhdmUgc2VydmljZXVzYWdlLnNlcnZpY2VzLnVzZSBwZXJtaXNzaW9ucyBvbiB1c2VyIHByb2plY3QuPC9NZXNzYWdlPjxEZXRhaWxzPmludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIGRvZXMgbm90IGhhdmUgc2VydmljZXVzYWdlLnNlcnZpY2VzLnVzZSBhY2Nlc3MgdG8gcHJvamVjdCA2NDIwODA5MTgxMDEuPC9EZXRhaWxzPjwvRXJyb3I+"
+ }
+ },
+ {
+ "ID": "8df5a8e8cb3018e1",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/foo?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "4ba0fb6a6b4f3829036eec3ca23cbeda/989698947649042526;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/foo?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3181"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:54 GMT"
+ ],
+ "Etag": [
+ "CISC0OiW290CEAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051394000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vncd130:4493,/bns/yx/borg/yx/bns/blobstore2/bitpusher/122.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=FsysW5auJsGRzgLopLngBA"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yx/borg/yx/bns/blobstore2/bitpusher/122.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yx/borg/yx/bns/blobstore2/bitpusher/122:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRWVNNdC1OVDFNYTJvWXBrbG1qcDlJMlZaUFZ5bFl5Z2Q3Nk5tQXlXbWR3WVBoMm00dGI3ZmZjOUlzcTU4MmVFcFBhNzhNWGpNZmIzaE9WTE9xRHpNTUFfTG9NQXVJZkdkMGgzSWowZ1dxdW5DS1g3Qk1mQlJxM001TUtMMXBHOWNyU0ZBT29lVkZpTDhpWlBsUDI0VjE5THdzZ0d1ZnVrQTFtVzVJcTJUUkVXeWQyNjRKZC1lS2UxdTAwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Upoxk0CnjyS_LCHnK0OHBf9KRPtZkRYgFF1U7mN-8kApCVZhYjcu-mLlcXBuZcvu5XZmu6xV1i3kiwVJ0chtx9tsfqucQ"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9mb28vMTUzODA1MTA5MzU2MTYwNCIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9vL2ZvbyIsIm5hbWUiOiJmb28iLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA5MzU2MTYwNCIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbiIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDo1My41NjFaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6NTMuNTYxWiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjUzLjU2MVoiLCJzaXplIjoiNSIsIm1kNUhhc2giOiJYVUZBS3J4TEtuYTVjWjJSRUJmRmtnPT0iLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL28vZm9vP2dlbmVyYXRpb249MTUzODA1MTA5MzU2MTYwNCZhbHQ9bWVkaWEiLCJjYWNoZUNvbnRyb2wiOiJwdWJsaWMsIG1heC1hZ2U9NjAiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9mb28vMTUzODA1MTA5MzU2MTYwNC9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9vL2Zvby9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJvYmplY3QiOiJmb28iLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA5MzU2MTYwNCIsImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6Im93bmVycyJ9LCJldGFnIjoiQ0lTQzBPaVcyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL2Zvby8xNTM4MDUxMDkzNTYxNjA0L3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9vL2Zvby9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzIiwib2JqZWN0IjoiZm9vIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwOTM1NjE2MDQiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0lTQzBPaVcyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL2Zvby8xNTM4MDUxMDkzNTYxNjA0L3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9vL2Zvby9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzIiwib2JqZWN0IjoiZm9vIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwOTM1NjE2MDQiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNJU0MwT2lXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9mb28vMTUzODA1MTA5MzU2MTYwNC91c2VyLWludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL28vZm9vL2FjbC91c2VyLWludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzIiwib2JqZWN0IjoiZm9vIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwOTM1NjE2MDQiLCJlbnRpdHkiOiJ1c2VyLWludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIiwicm9sZSI6Ik9XTkVSIiwiZW1haWwiOiJpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSIsImV0YWciOiJDSVNDME9pVzI5MENFQUU9In1dLCJvd25lciI6eyJlbnRpdHkiOiJ1c2VyLWludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIn0sImNyYzMyYyI6Im1uRzdUQT09IiwiZXRhZyI6IkNJU0MwT2lXMjkwQ0VBRT0ifQ=="
+ }
+ },
+ {
+ "ID": "c9a00d099267754b",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/foo?alt=json\u0026prettyPrint=false\u0026projection=full\u0026userProject=dulcet-port-762",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "12bc837e44bbea07fcd1c9cae382a949/2580109752221343229;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/foo?alt=json\u0026prettyPrint=false\u0026projection=full\u0026userProject=dulcet-port-762"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3181"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:54 GMT"
+ ],
+ "Etag": [
+ "CISC0OiW290CEAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051391000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrti20:4165,/bns/yv/borg/yv/bns/blobstore2/bitpusher/243.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=FsysW6vgK4GngASMt5uwAw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/243.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/243:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRWVNNdC1OVDFNYTJvWXBrbG1qcDlJMlZaUFZ5bFl5Z2Q3Nk5tQXlXbWR3WVBoMm00dGI3ZmZjOUlzcTU4MmVFcFBhNzhNWGpNZmIzaE9WTE9xRHpNTUFfTG9NQXVJZkdkMGgzSWowZ1dxdW5DS1g3Qk1mQlJxM001TUtMMXBHOWNyU0ZBT29lVkZpTDhpWlBsUDI0VjE5THdzZ0d1ZnVrQTFtVzVJcTJUUkVXeWQyNjRKZC1lS2UxdTAwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Ur7tVi6j5IKT88SZhVKIWnUX_O-9IBWvMpw9b7nG_MsOiFfb_ZAEJ8WMbvtPnRCuooB3MuHPNjvgYUM7iqQNkeEK-O7hA"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9mb28vMTUzODA1MTA5MzU2MTYwNCIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9vL2ZvbyIsIm5hbWUiOiJmb28iLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA5MzU2MTYwNCIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbiIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDo1My41NjFaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6NTMuNTYxWiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjUzLjU2MVoiLCJzaXplIjoiNSIsIm1kNUhhc2giOiJYVUZBS3J4TEtuYTVjWjJSRUJmRmtnPT0iLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL28vZm9vP2dlbmVyYXRpb249MTUzODA1MTA5MzU2MTYwNCZhbHQ9bWVkaWEiLCJjYWNoZUNvbnRyb2wiOiJwdWJsaWMsIG1heC1hZ2U9NjAiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9mb28vMTUzODA1MTA5MzU2MTYwNC9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9vL2Zvby9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJvYmplY3QiOiJmb28iLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA5MzU2MTYwNCIsImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6Im93bmVycyJ9LCJldGFnIjoiQ0lTQzBPaVcyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL2Zvby8xNTM4MDUxMDkzNTYxNjA0L3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9vL2Zvby9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzIiwib2JqZWN0IjoiZm9vIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwOTM1NjE2MDQiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0lTQzBPaVcyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL2Zvby8xNTM4MDUxMDkzNTYxNjA0L3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9vL2Zvby9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzIiwib2JqZWN0IjoiZm9vIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwOTM1NjE2MDQiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNJU0MwT2lXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9mb28vMTUzODA1MTA5MzU2MTYwNC91c2VyLWludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL28vZm9vL2FjbC91c2VyLWludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzIiwib2JqZWN0IjoiZm9vIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwOTM1NjE2MDQiLCJlbnRpdHkiOiJ1c2VyLWludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIiwicm9sZSI6Ik9XTkVSIiwiZW1haWwiOiJpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSIsImV0YWciOiJDSVNDME9pVzI5MENFQUU9In1dLCJvd25lciI6eyJlbnRpdHkiOiJ1c2VyLWludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIn0sImNyYzMyYyI6Im1uRzdUQT09IiwiZXRhZyI6IkNJU0MwT2lXMjkwQ0VBRT0ifQ=="
+ }
+ },
+ {
+ "ID": "9a3b957752d48171",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/foo?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "ecd1f92caab5532b924399a8f7e47269/4170521656271717276;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/foo?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 400,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0"
+ ],
+ "Content-Length": [
+ "12075"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:55 GMT"
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:24:55 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051392000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "471383502717"
+ ],
+ "X-Google-Backends": [
+ "vraf24:4012,/bns/yv/borg/yv/bns/blobstore2/bitpusher/260.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=FsysW6_EMMSZggTQn4ToBw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/260.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/260:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CP3elYXcDRoCGAYoATpFChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGM6ropHgHCIVMTE3MjM4MDU4ODYxOTM3NTE5MTQ0MOArMOErMOIrSp8BEoIBeWEyOS5jLkVsb2xCcldWbUZlX1AxVDdUOHVpTXdFMHBZUjdTc2NVMDBFdEZkc2tSenBQY0NLWkhUeEZaYXI0Q25tZmR6bXFRLTNVV0kzOF9wdEx5VTZ2Z1Q3dlRBeW42Z3g4dUcyd0szSHIzaTZrV1JBZkozc1pNMGQ1allkNHpWQTAEOhZOT1RfQV9QRVJTSVNURU5UX1RPS0VO"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Upload-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UowTKPdmDqhsfA5eNzNslz7TvPHBzdXXEvZjn8SG_TrCALt9fBKzEgyUmaz3PySAxarLaEjBXM_ON7hUxuKkEmt4YKC0z4Z8_aZWNQbjHp7V9tptTY"
+ ]
+ },
+ "Body": "eyJlcnJvciI6eyJlcnJvcnMiOlt7ImRvbWFpbiI6Imdsb2JhbCIsInJlYXNvbiI6InJlcXVpcmVkIiwibWVzc2FnZSI6IkJ1Y2tldCBpcyByZXF1ZXN0ZXIgcGF5cyBidWNrZXQgYnV0IG5vIHVzZXIgcHJvamVjdCBwcm92aWRlZC4iLCJkZWJ1Z0luZm8iOiJjb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6VVNFUl9QUk9KRUNUX01JU1NJTkc6IEJ1Y2tldCBpcyBSZXF1ZXN0ZXIgUGF5cyBidWNrZXQgYnV0IG5vIGJpbGxpbmcgcHJvamVjdCBpZCBwcm92aWRlZCBmb3Igbm9uLW93bmVyLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5HZXRPYmplY3QuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKEdldE9iamVjdC5qYXZhOjI5OClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5vYmplY3RzLkdldE9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoR2V0T2JqZWN0LmphdmE6NzEpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5PYmplY3RzRGVsZWdhdG9yLmdldChPYmplY3RzRGVsZWdhdG9yLmphdmE6ODEpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBCdWNrZXQgaXMgUmVxdWVzdGVyIFBheXMgYnVja2V0IGJ1dCBubyBiaWxsaW5nIHByb2plY3QgaWQgcHJvdmlkZWQgZm9yIG5vbi1vd25lci5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MjkwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAxKVxuXHQuLi4gMTcgbW9yZVxuXG5jb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS5GYXVsdDogSW1tdXRhYmxlRXJyb3JEZWZpbml0aW9ue2Jhc2U9UkVRVUlSRUQsIGNhdGVnb3J5PVVTRVJfRVJST1IsIGNhdXNlPW51bGwsIGRlYnVnSW5mbz1jb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6VVNFUl9QUk9KRUNUX01JU1NJTkc6IEJ1Y2tldCBpcyBSZXF1ZXN0ZXIgUGF5cyBidWNrZXQgYnV0IG5vIGJpbGxpbmcgcHJvamVjdCBpZCBwcm92aWRlZCBmb3Igbm9uLW93bmVyLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5HZXRPYmplY3QuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKEdldE9iamVjdC5qYXZhOjI5OClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5vYmplY3RzLkdldE9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoR2V0T2JqZWN0LmphdmE6NzEpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5PYmplY3RzRGVsZWdhdG9yLmdldChPYmplY3RzRGVsZWdhdG9yLmphdmE6ODEpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBCdWNrZXQgaXMgUmVxdWVzdGVyIFBheXMgYnVja2V0IGJ1dCBubyBiaWxsaW5nIHByb2plY3QgaWQgcHJvdmlkZWQgZm9yIG5vbi1vd25lci5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MjkwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAxKVxuXHQuLi4gMTcgbW9yZVxuLCBkb21haW49Z2xvYmFsLCBleHRlbmRlZEhlbHA9bnVsbCwgaHR0cEhlYWRlcnM9e30sIGh0dHBTdGF0dXM9YmFkUmVxdWVzdCwgaW50ZXJuYWxSZWFzb249UmVhc29ue2FyZ3VtZW50cz17fSwgY2F1c2U9bnVsbCwgY29kZT1nZGF0YS5Db3JlRXJyb3JEb21haW4uUkVRVUlSRUQsIGNyZWF0ZWRCeUJhY2tlbmQ9dHJ1ZSwgZGVidWdNZXNzYWdlPWNvbS5nb29nbGUubmV0LnJwYzMuUnBjRXhjZXB0aW9uOiBjbG91ZC5iaWdzdG9yZS5SZXNwb25zZUNvZGUuRXJyb3JDb2RlOjpVU0VSX1BST0pFQ1RfTUlTU0lORzogQnVja2V0IGlzIFJlcXVlc3RlciBQYXlzIGJ1Y2tldCBidXQgbm8gYmlsbGluZyBwcm9qZWN0IGlkIHByb3ZpZGVkIGZvciBub24tb3duZXIuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRvUnBjM0V4Y2VwdGlvbihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjEzNSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5vYmplY3RzLkdldE9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoR2V0T2JqZWN0LmphdmE6Mjk4KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuR2V0T2JqZWN0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChHZXRPYmplY3QuamF2YTo3MSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLk9iamVjdHNEZWxlZ2F0b3IuZ2V0KE9iamVjdHNEZWxlZ2F0b3IuamF2YTo4MSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uUnBjUmVjZWl2ZXIubGFtYmRhJHByb2Nlc3NSZXF1ZXN0QXN5bmMkNChScGNSZWNlaXZlci5qYXZhOjIwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uQXN5bmNFeGVjdXRvci5sYW1iZGEkc3VibWl0JDAoQXN5bmNFeGVjdXRvci5qYXZhOjI3Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KENvbnRleHRSdW5uYWJsZS5qYXZhOjUwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZSQxLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozOSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NzIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozNilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRXhlY3V0b3JzJFJ1bm5hYmxlQWRhcHRlci5jYWxsKEV4ZWN1dG9ycy5qYXZhOjUxMSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRnV0dXJlVGFzay5ydW4oRnV0dXJlVGFzay5qYXZhOjI2Nilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yLnJ1bldvcmtlcihUaHJlYWRQb29sRXhlY3V0b3IuamF2YToxMTQ5KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IkV29ya2VyLnJ1bihUaHJlYWRQb29sRXhlY3V0b3IuamF2YTo2MjQpXG5cdGF0IGphdmEubGFuZy5UaHJlYWQucnVuKFRocmVhZC5qYXZhOjc0OClcbkNhdXNlZCBieTogY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb246IEJ1Y2tldCBpcyBSZXF1ZXN0ZXIgUGF5cyBidWNrZXQgYnV0IG5vIGJpbGxpbmcgcHJvamVjdCBpZCBwcm92aWRlZCBmb3Igbm9uLW93bmVyLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxNyBtb3JlXG4sIGVycm9yUHJvdG9Db2RlPVJFUVVJUkVELCBlcnJvclByb3RvRG9tYWluPWdkYXRhLkNvcmVFcnJvckRvbWFpbiwgZmlsdGVyZWRNZXNzYWdlPW51bGwsIGxvY2F0aW9uPW51bGwsIG1lc3NhZ2U9QnVja2V0IGlzIHJlcXVlc3RlciBwYXlzIGJ1Y2tldCBidXQgbm8gdXNlciBwcm9qZWN0IHByb3ZpZGVkLiwgdW5uYW1lZEFyZ3VtZW50cz1bXX0sIGxvY2F0aW9uPW51bGwsIG1lc3NhZ2U9QnVja2V0IGlzIHJlcXVlc3RlciBwYXlzIGJ1Y2tldCBidXQgbm8gdXNlciBwcm9qZWN0IHByb3ZpZGVkLiwgcmVhc29uPXJlcXVpcmVkLCBycGNDb2RlPTQwMH0gQnVja2V0IGlzIHJlcXVlc3RlciBwYXlzIGJ1Y2tldCBidXQgbm8gdXNlciBwcm9qZWN0IHByb3ZpZGVkLjogY29tLmdvb2dsZS5uZXQucnBjMy5ScGNFeGNlcHRpb246IGNsb3VkLmJpZ3N0b3JlLlJlc3BvbnNlQ29kZS5FcnJvckNvZGU6OlVTRVJfUFJPSkVDVF9NSVNTSU5HOiBCdWNrZXQgaXMgUmVxdWVzdGVyIFBheXMgYnVja2V0IGJ1dCBubyBiaWxsaW5nIHByb2plY3QgaWQgcHJvdmlkZWQgZm9yIG5vbi1vd25lci5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udG9ScGMzRXhjZXB0aW9uKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MTM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuR2V0T2JqZWN0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChHZXRPYmplY3QuamF2YToyOTgpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5HZXRPYmplY3QuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKEdldE9iamVjdC5qYXZhOjcxKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmZyYW1ld29yay5SZXF1ZXN0SGFuZGxlci5oYW5kbGUoUmVxdWVzdEhhbmRsZXIuamF2YToyOTQpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uT2JqZWN0c0RlbGVnYXRvci5nZXQoT2JqZWN0c0RlbGVnYXRvci5qYXZhOjgxKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5ScGNSZWNlaXZlci5sYW1iZGEkcHJvY2Vzc1JlcXVlc3RBc3luYyQ0KFJwY1JlY2VpdmVyLmphdmE6MjAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5Bc3luY0V4ZWN1dG9yLmxhbWJkYSRzdWJtaXQkMChBc3luY0V4ZWN1dG9yLmphdmE6MjcyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoQ29udGV4dFJ1bm5hYmxlLmphdmE6NTApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlJDEucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM5KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo3Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5FeGVjdXRvcnMkUnVubmFibGVBZGFwdGVyLmNhbGwoRXhlY3V0b3JzLmphdmE6NTExKVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5GdXR1cmVUYXNrLnJ1bihGdXR1cmVUYXNrLmphdmE6MjY2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IucnVuV29ya2VyKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjExNDkpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvciRXb3JrZXIucnVuKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjYyNClcblx0YXQgamF2YS5sYW5nLlRocmVhZC5ydW4oVGhyZWFkLmphdmE6NzQ4KVxuQ2F1c2VkIGJ5OiBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbjogQnVja2V0IGlzIFJlcXVlc3RlciBQYXlzIGJ1Y2tldCBidXQgbm8gYmlsbGluZyBwcm9qZWN0IGlkIHByb3ZpZGVkIGZvciBub24tb3duZXIuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93T25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjI5MClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMSlcblx0Li4uIDE3IG1vcmVcblxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS5FcnJvckNvbGxlY3Rvci50b0ZhdWx0KEVycm9yQ29sbGVjdG9yLmphdmE6NTQpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5yZXN0LmFkYXB0ZXIucm9zeS5Sb3N5RXJyb3JDb252ZXJ0ZXIudG9GYXVsdChSb3N5RXJyb3JDb252ZXJ0ZXIuamF2YTo2Nylcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnJlc3QuYWRhcHRlci5yb3N5LlJvc3lIYW5kbGVyJDIuY2FsbChSb3N5SGFuZGxlci5qYXZhOjI1OClcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnJlc3QuYWRhcHRlci5yb3N5LlJvc3lIYW5kbGVyJDIuY2FsbChSb3N5SGFuZGxlci5qYXZhOjIzOClcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkRpcmVjdEV4ZWN1dG9yLmV4ZWN1dGUoRGlyZWN0RXhlY3V0b3IuamF2YTozMClcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmV4ZWN1dGVMaXN0ZW5lcihBYnN0cmFjdEZ1dHVyZS5qYXZhOjExNDMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5jb21wbGV0ZShBYnN0cmFjdEZ1dHVyZS5qYXZhOjk2Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLnNldChBYnN0cmFjdEZ1dHVyZS5qYXZhOjczMSlcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkRpcmVjdEV4ZWN1dG9yLmV4ZWN1dGUoRGlyZWN0RXhlY3V0b3IuamF2YTozMClcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmV4ZWN1dGVMaXN0ZW5lcihBYnN0cmFjdEZ1dHVyZS5qYXZhOjExNDMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5jb21wbGV0ZShBYnN0cmFjdEZ1dHVyZS5qYXZhOjk2Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLnNldChBYnN0cmFjdEZ1dHVyZS5qYXZhOjczMSlcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnRocmVhZC5UaHJlYWRUcmFja2VycyRUaHJlYWRUcmFja2luZ1J1bm5hYmxlLnJ1bihUaHJlYWRUcmFja2Vycy5qYXZhOjEyNilcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRUcmFjZUNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoVHJhY2VDb250ZXh0LmphdmE6NDU1KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuc2VydmVyLkNvbW1vbk1vZHVsZSRDb250ZXh0Q2FycnlpbmdFeGVjdXRvclNlcnZpY2UkMS5ydW5JbkNvbnRleHQoQ29tbW9uTW9kdWxlLmphdmE6ODQ2KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JFRyYWNlQ29udGV4dFJ1bm5hYmxlJDEucnVuKFRyYWNlQ29udGV4dC5qYXZhOjQ2Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRBYnN0cmFjdFRyYWNlQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoVHJhY2VDb250ZXh0LmphdmE6MzIxKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JEFic3RyYWN0VHJhY2VDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KFRyYWNlQ29udGV4dC5qYXZhOjMxMylcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRUcmFjZUNvbnRleHRSdW5uYWJsZS5ydW4oVHJhY2VDb250ZXh0LmphdmE6NDU5KVxuXHRhdCBjb20uZ29vZ2xlLmdzZS5pbnRlcm5hbC5EaXNwYXRjaFF1ZXVlSW1wbCRXb3JrZXJUaHJlYWQucnVuKERpc3BhdGNoUXVldWVJbXBsLmphdmE6NDAzKVxuIn1dLCJjb2RlIjo0MDAsIm1lc3NhZ2UiOiJCdWNrZXQgaXMgcmVxdWVzdGVyIHBheXMgYnVja2V0IGJ1dCBubyB1c2VyIHByb2plY3QgcHJvdmlkZWQuIn19"
+ }
+ },
+ {
+ "ID": "3bc47ee9c62df6c9",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/foo?alt=json\u0026prettyPrint=false\u0026projection=full\u0026userProject=gcloud-golang-firestore-tests",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "112b4515ed2175eacbd1552e9e0df785/5760933560338933818;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/foo?alt=json\u0026prettyPrint=false\u0026projection=full\u0026userProject=gcloud-golang-firestore-tests"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3181"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:55 GMT"
+ ],
+ "Etag": [
+ "CISC0OiW290CEAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051392000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "471383502717"
+ ],
+ "X-Google-Backends": [
+ "vrpz1:4175,/bns/yr/borg/yr/bns/blobstore2/bitpusher/50.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=F8ysW5LoAc_44QSlq4TwBA"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/50.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/50:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CP3elYXcDRoCGAYoATpFChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGM6ropHgHCIVMTE3MjM4MDU4ODYxOTM3NTE5MTQ0MOArMOErMOIrSp8BEoIBeWEyOS5jLkVsb2xCcldWbUZlX1AxVDdUOHVpTXdFMHBZUjdTc2NVMDBFdEZkc2tSenBQY0NLWkhUeEZaYXI0Q25tZmR6bXFRLTNVV0kzOF9wdEx5VTZ2Z1Q3dlRBeW42Z3g4dUcyd0szSHIzaTZrV1JBZkozc1pNMGQ1allkNHpWQTAEOhZOT1RfQV9QRVJTSVNURU5UX1RPS0VO"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UpBML43rDsc3BbW5t3GZgCV1N2yVVsV3lXOGGpwJ6pnuDNngAuI9haDrqdayPI4-QWT_n2MLiw9D7weWUPzXkOmFExouA"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9mb28vMTUzODA1MTA5MzU2MTYwNCIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9vL2ZvbyIsIm5hbWUiOiJmb28iLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA5MzU2MTYwNCIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbiIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDo1My41NjFaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6NTMuNTYxWiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjUzLjU2MVoiLCJzaXplIjoiNSIsIm1kNUhhc2giOiJYVUZBS3J4TEtuYTVjWjJSRUJmRmtnPT0iLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL28vZm9vP2dlbmVyYXRpb249MTUzODA1MTA5MzU2MTYwNCZhbHQ9bWVkaWEiLCJjYWNoZUNvbnRyb2wiOiJwdWJsaWMsIG1heC1hZ2U9NjAiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9mb28vMTUzODA1MTA5MzU2MTYwNC9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9vL2Zvby9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJvYmplY3QiOiJmb28iLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA5MzU2MTYwNCIsImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6Im93bmVycyJ9LCJldGFnIjoiQ0lTQzBPaVcyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL2Zvby8xNTM4MDUxMDkzNTYxNjA0L3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9vL2Zvby9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzIiwib2JqZWN0IjoiZm9vIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwOTM1NjE2MDQiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0lTQzBPaVcyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL2Zvby8xNTM4MDUxMDkzNTYxNjA0L3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9vL2Zvby9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzIiwib2JqZWN0IjoiZm9vIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwOTM1NjE2MDQiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNJU0MwT2lXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9mb28vMTUzODA1MTA5MzU2MTYwNC91c2VyLWludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL28vZm9vL2FjbC91c2VyLWludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzIiwib2JqZWN0IjoiZm9vIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwOTM1NjE2MDQiLCJlbnRpdHkiOiJ1c2VyLWludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIiwicm9sZSI6Ik9XTkVSIiwiZW1haWwiOiJpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSIsImV0YWciOiJDSVNDME9pVzI5MENFQUU9In1dLCJvd25lciI6eyJlbnRpdHkiOiJ1c2VyLWludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIn0sImNyYzMyYyI6Im1uRzdUQT09IiwiZXRhZyI6IkNJU0MwT2lXMjkwQ0VBRT0ifQ=="
+ }
+ },
+ {
+ "ID": "f8fb7a2aa56abc06",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/foo?alt=json\u0026prettyPrint=false\u0026projection=full\u0026userProject=veener-jba",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "744a7cbe721801da11024f6426d65bbf/7279007494886362841;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/foo?alt=json\u0026prettyPrint=false\u0026projection=full\u0026userProject=veener-jba"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 403,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0"
+ ],
+ "Content-Length": [
+ "12931"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:55 GMT"
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:24:55 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051392000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "471383502717"
+ ],
+ "X-Google-Backends": [
+ "vran71:4007,/bns/yr/borg/yr/bns/blobstore2/bitpusher/10.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=F8ysW43DBtHnkAOQzqSwAQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/10.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/10:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CP3elYXcDRoCGAYoATpFChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGM6ropHgHCIVMTE3MjM4MDU4ODYxOTM3NTE5MTQ0MOArMOErMOIrSp8BEoIBeWEyOS5jLkVsb2xCcldWbUZlX1AxVDdUOHVpTXdFMHBZUjdTc2NVMDBFdEZkc2tSenBQY0NLWkhUeEZaYXI0Q25tZmR6bXFRLTNVV0kzOF9wdEx5VTZ2Z1Q3dlRBeW42Z3g4dUcyd0szSHIzaTZrV1JBZkozc1pNMGQ1allkNHpWQTAEOhZOT1RfQV9QRVJTSVNURU5UX1RPS0VO"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Upload-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UrTKHn4uUFleoyjMlSfAfhUxBkxAtGuk7BwCbGrjX9yU3lyN0fySLoL5-MG2kB4m1KtKVbociQOQbbtm4xEHIs5yByaYw"
+ ]
+ },
+ "Body": "eyJlcnJvciI6eyJlcnJvcnMiOlt7ImRvbWFpbiI6Imdsb2JhbCIsInJlYXNvbiI6ImZvcmJpZGRlbiIsIm1lc3NhZ2UiOiJpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLiIsImRlYnVnSW5mbyI6ImNvbS5nb29nbGUubmV0LnJwYzMuUnBjRXhjZXB0aW9uOiBjbG91ZC5iaWdzdG9yZS5SZXNwb25zZUNvZGUuRXJyb3JDb2RlOjpVU0VSX1BST0pFQ1RfQUNDRVNTX0RFTklFRDogaW50ZWdyYXRpb25AZ2Nsb3VkLWdvbGFuZy1maXJlc3RvcmUtdGVzdHMuaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20gZG9lcyBub3QgaGF2ZSBzZXJ2aWNldXNhZ2Uuc2VydmljZXMudXNlIGFjY2VzcyB0byBwcm9qZWN0IDY0MjA4MDkxODEwMS5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udG9ScGMzRXhjZXB0aW9uKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MTM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuR2V0T2JqZWN0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChHZXRPYmplY3QuamF2YToyOTgpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5HZXRPYmplY3QuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKEdldE9iamVjdC5qYXZhOjcxKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmZyYW1ld29yay5SZXF1ZXN0SGFuZGxlci5oYW5kbGUoUmVxdWVzdEhhbmRsZXIuamF2YToyOTQpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uT2JqZWN0c0RlbGVnYXRvci5nZXQoT2JqZWN0c0RlbGVnYXRvci5qYXZhOjgxKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5ScGNSZWNlaXZlci5sYW1iZGEkcHJvY2Vzc1JlcXVlc3RBc3luYyQ0KFJwY1JlY2VpdmVyLmphdmE6MjAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5Bc3luY0V4ZWN1dG9yLmxhbWJkYSRzdWJtaXQkMChBc3luY0V4ZWN1dG9yLmphdmE6MjcyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoQ29udGV4dFJ1bm5hYmxlLmphdmE6NTApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlJDEucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM5KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo3Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5FeGVjdXRvcnMkUnVubmFibGVBZGFwdGVyLmNhbGwoRXhlY3V0b3JzLmphdmE6NTExKVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5GdXR1cmVUYXNrLnJ1bihGdXR1cmVUYXNrLmphdmE6MjY2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IucnVuV29ya2VyKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjExNDkpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvciRXb3JrZXIucnVuKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjYyNClcblx0YXQgamF2YS5sYW5nLlRocmVhZC5ydW4oVGhyZWFkLmphdmE6NzQ4KVxuQ2F1c2VkIGJ5OiBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbjogaW50ZWdyYXRpb25AZ2Nsb3VkLWdvbGFuZy1maXJlc3RvcmUtdGVzdHMuaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20gZG9lcyBub3QgaGF2ZSBzZXJ2aWNldXNhZ2Uuc2VydmljZXMudXNlIGFjY2VzcyB0byBwcm9qZWN0IDY0MjA4MDkxODEwMS5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MjkwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAxKVxuXHQuLi4gMTcgbW9yZVxuXG5jb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS5GYXVsdDogSW1tdXRhYmxlRXJyb3JEZWZpbml0aW9ue2Jhc2U9Rk9SQklEREVOLCBjYXRlZ29yeT1VU0VSX0VSUk9SLCBjYXVzZT1udWxsLCBkZWJ1Z0luZm89Y29tLmdvb2dsZS5uZXQucnBjMy5ScGNFeGNlcHRpb246IGNsb3VkLmJpZ3N0b3JlLlJlc3BvbnNlQ29kZS5FcnJvckNvZGU6OlVTRVJfUFJPSkVDVF9BQ0NFU1NfREVOSUVEOiBpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5HZXRPYmplY3QuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKEdldE9iamVjdC5qYXZhOjI5OClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5vYmplY3RzLkdldE9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoR2V0T2JqZWN0LmphdmE6NzEpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5PYmplY3RzRGVsZWdhdG9yLmdldChPYmplY3RzRGVsZWdhdG9yLmphdmE6ODEpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxNyBtb3JlXG4sIGRvbWFpbj1nbG9iYWwsIGV4dGVuZGVkSGVscD1udWxsLCBodHRwSGVhZGVycz17fSwgaHR0cFN0YXR1cz1mb3JiaWRkZW4sIGludGVybmFsUmVhc29uPVJlYXNvbnthcmd1bWVudHM9e30sIGNhdXNlPW51bGwsIGNvZGU9Z2RhdGEuQ29yZUVycm9yRG9tYWluLkZPUkJJRERFTiwgY3JlYXRlZEJ5QmFja2VuZD10cnVlLCBkZWJ1Z01lc3NhZ2U9Y29tLmdvb2dsZS5uZXQucnBjMy5ScGNFeGNlcHRpb246IGNsb3VkLmJpZ3N0b3JlLlJlc3BvbnNlQ29kZS5FcnJvckNvZGU6OlVTRVJfUFJPSkVDVF9BQ0NFU1NfREVOSUVEOiBpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5HZXRPYmplY3QuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKEdldE9iamVjdC5qYXZhOjI5OClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5vYmplY3RzLkdldE9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoR2V0T2JqZWN0LmphdmE6NzEpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5PYmplY3RzRGVsZWdhdG9yLmdldChPYmplY3RzRGVsZWdhdG9yLmphdmE6ODEpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxNyBtb3JlXG4sIGVycm9yUHJvdG9Db2RlPUZPUkJJRERFTiwgZXJyb3JQcm90b0RvbWFpbj1nZGF0YS5Db3JlRXJyb3JEb21haW4sIGZpbHRlcmVkTWVzc2FnZT1udWxsLCBsb2NhdGlvbj1udWxsLCBtZXNzYWdlPWludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIGRvZXMgbm90IGhhdmUgc2VydmljZXVzYWdlLnNlcnZpY2VzLnVzZSBhY2Nlc3MgdG8gcHJvamVjdCA2NDIwODA5MTgxMDEuLCB1bm5hbWVkQXJndW1lbnRzPVtdfSwgbG9jYXRpb249bnVsbCwgbWVzc2FnZT1pbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLiwgcmVhc29uPWZvcmJpZGRlbiwgcnBjQ29kZT00MDN9IGludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIGRvZXMgbm90IGhhdmUgc2VydmljZXVzYWdlLnNlcnZpY2VzLnVzZSBhY2Nlc3MgdG8gcHJvamVjdCA2NDIwODA5MTgxMDEuOiBjb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6VVNFUl9QUk9KRUNUX0FDQ0VTU19ERU5JRUQ6IGludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIGRvZXMgbm90IGhhdmUgc2VydmljZXVzYWdlLnNlcnZpY2VzLnVzZSBhY2Nlc3MgdG8gcHJvamVjdCA2NDIwODA5MTgxMDEuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRvUnBjM0V4Y2VwdGlvbihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjEzNSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5vYmplY3RzLkdldE9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoR2V0T2JqZWN0LmphdmE6Mjk4KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuR2V0T2JqZWN0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChHZXRPYmplY3QuamF2YTo3MSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLk9iamVjdHNEZWxlZ2F0b3IuZ2V0KE9iamVjdHNEZWxlZ2F0b3IuamF2YTo4MSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uUnBjUmVjZWl2ZXIubGFtYmRhJHByb2Nlc3NSZXF1ZXN0QXN5bmMkNChScGNSZWNlaXZlci5qYXZhOjIwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uQXN5bmNFeGVjdXRvci5sYW1iZGEkc3VibWl0JDAoQXN5bmNFeGVjdXRvci5qYXZhOjI3Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KENvbnRleHRSdW5uYWJsZS5qYXZhOjUwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZSQxLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozOSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NzIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozNilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRXhlY3V0b3JzJFJ1bm5hYmxlQWRhcHRlci5jYWxsKEV4ZWN1dG9ycy5qYXZhOjUxMSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRnV0dXJlVGFzay5ydW4oRnV0dXJlVGFzay5qYXZhOjI2Nilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yLnJ1bldvcmtlcihUaHJlYWRQb29sRXhlY3V0b3IuamF2YToxMTQ5KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IkV29ya2VyLnJ1bihUaHJlYWRQb29sRXhlY3V0b3IuamF2YTo2MjQpXG5cdGF0IGphdmEubGFuZy5UaHJlYWQucnVuKFRocmVhZC5qYXZhOjc0OClcbkNhdXNlZCBieTogY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb246IGludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIGRvZXMgbm90IGhhdmUgc2VydmljZXVzYWdlLnNlcnZpY2VzLnVzZSBhY2Nlc3MgdG8gcHJvamVjdCA2NDIwODA5MTgxMDEuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93T25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjI5MClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMSlcblx0Li4uIDE3IG1vcmVcblxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS5FcnJvckNvbGxlY3Rvci50b0ZhdWx0KEVycm9yQ29sbGVjdG9yLmphdmE6NTQpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5yZXN0LmFkYXB0ZXIucm9zeS5Sb3N5RXJyb3JDb252ZXJ0ZXIudG9GYXVsdChSb3N5RXJyb3JDb252ZXJ0ZXIuamF2YTo2Nylcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnJlc3QuYWRhcHRlci5yb3N5LlJvc3lIYW5kbGVyJDIuY2FsbChSb3N5SGFuZGxlci5qYXZhOjI1OClcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnJlc3QuYWRhcHRlci5yb3N5LlJvc3lIYW5kbGVyJDIuY2FsbChSb3N5SGFuZGxlci5qYXZhOjIzOClcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkRpcmVjdEV4ZWN1dG9yLmV4ZWN1dGUoRGlyZWN0RXhlY3V0b3IuamF2YTozMClcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmV4ZWN1dGVMaXN0ZW5lcihBYnN0cmFjdEZ1dHVyZS5qYXZhOjExNDMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5jb21wbGV0ZShBYnN0cmFjdEZ1dHVyZS5qYXZhOjk2Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLnNldChBYnN0cmFjdEZ1dHVyZS5qYXZhOjczMSlcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkRpcmVjdEV4ZWN1dG9yLmV4ZWN1dGUoRGlyZWN0RXhlY3V0b3IuamF2YTozMClcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmV4ZWN1dGVMaXN0ZW5lcihBYnN0cmFjdEZ1dHVyZS5qYXZhOjExNDMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5jb21wbGV0ZShBYnN0cmFjdEZ1dHVyZS5qYXZhOjk2Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLnNldChBYnN0cmFjdEZ1dHVyZS5qYXZhOjczMSlcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnRocmVhZC5UaHJlYWRUcmFja2VycyRUaHJlYWRUcmFja2luZ1J1bm5hYmxlLnJ1bihUaHJlYWRUcmFja2Vycy5qYXZhOjEyNilcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRUcmFjZUNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoVHJhY2VDb250ZXh0LmphdmE6NDU1KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuc2VydmVyLkNvbW1vbk1vZHVsZSRDb250ZXh0Q2FycnlpbmdFeGVjdXRvclNlcnZpY2UkMS5ydW5JbkNvbnRleHQoQ29tbW9uTW9kdWxlLmphdmE6ODQ2KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JFRyYWNlQ29udGV4dFJ1bm5hYmxlJDEucnVuKFRyYWNlQ29udGV4dC5qYXZhOjQ2Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRBYnN0cmFjdFRyYWNlQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoVHJhY2VDb250ZXh0LmphdmE6MzIxKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JEFic3RyYWN0VHJhY2VDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KFRyYWNlQ29udGV4dC5qYXZhOjMxMylcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRUcmFjZUNvbnRleHRSdW5uYWJsZS5ydW4oVHJhY2VDb250ZXh0LmphdmE6NDU5KVxuXHRhdCBjb20uZ29vZ2xlLmdzZS5pbnRlcm5hbC5EaXNwYXRjaFF1ZXVlSW1wbCRXb3JrZXJUaHJlYWQucnVuKERpc3BhdGNoUXVldWVJbXBsLmphdmE6NDAzKVxuIn1dLCJjb2RlIjo0MDMsIm1lc3NhZ2UiOiJpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLiJ9fQ=="
+ }
+ },
+ {
+ "ID": "2b1325dbeea3872c",
+ "Request": {
+ "Method": "PATCH",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/foo?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "85"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "dc89e7f65b102435e4a85a2c6f3d0fe1/8869419398953513848;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/foo?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJjb250ZW50TGFuZ3VhZ2UiOiJlbiJ9Cg=="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3204"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:55 GMT"
+ ],
+ "Etag": [
+ "CISC0OiW290CEAI="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051389000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vnap189:4365,/bns/yx/borg/yx/bns/blobstore2/bitpusher/57.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=F8ysW5T4E4qJzAKRg7nIAg"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yx/borg/yx/bns/blobstore2/bitpusher/57.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yx/borg/yx/bns/blobstore2/bitpusher/57:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATpxChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4CtK4wESxgF5YTI5LmMuRW93QkpRWVNNdC1OVDFNYTJvWXBrbG1qcDlJMlZaUFZ5bFl5Z2Q3Nk5tQXlXbWR3WVBoMm00dGI3ZmZjOUlzcTU4MmVFcFBhNzhNWGpNZmIzaE9WTE9xRHpNTUFfTG9NQXVJZkdkMGgzSWowZ1dxdW5DS1g3Qk1mQlJxM001TUtMMXBHOWNyU0ZBT29lVkZpTDhpWlBsUDI0VjE5THdzZ0d1ZnVrQTFtVzVJcTJUUkVXeWQyNjRKZC1lS2UxdTAwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Up-47Gg-U0R8d-RLZoqr0iirAWrSZKYpf1bvmSFFRKVEL0OT2hoDOMTUj46Ame11lFsY3aGMuv14up8TGKyQKvdhnCqqQ"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9mb28vMTUzODA1MTA5MzU2MTYwNCIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9vL2ZvbyIsIm5hbWUiOiJmb28iLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA5MzU2MTYwNCIsIm1ldGFnZW5lcmF0aW9uIjoiMiIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbiIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDo1My41NjFaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6NTUuNDMwWiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjUzLjU2MVoiLCJzaXplIjoiNSIsIm1kNUhhc2giOiJYVUZBS3J4TEtuYTVjWjJSRUJmRmtnPT0iLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL28vZm9vP2dlbmVyYXRpb249MTUzODA1MTA5MzU2MTYwNCZhbHQ9bWVkaWEiLCJjb250ZW50TGFuZ3VhZ2UiOiJlbiIsImNhY2hlQ29udHJvbCI6InB1YmxpYywgbWF4LWFnZT02MCIsImFjbCI6W3sia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL2Zvby8xNTM4MDUxMDkzNTYxNjA0L3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL28vZm9vL2FjbC9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMyIsIm9iamVjdCI6ImZvbyIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDkzNTYxNjA0IiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDSVNDME9pVzI5MENFQUk9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMvZm9vLzE1MzgwNTEwOTM1NjE2MDQvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL28vZm9vL2FjbC9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJvYmplY3QiOiJmb28iLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA5MzU2MTYwNCIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDSVNDME9pVzI5MENFQUk9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMvZm9vLzE1MzgwNTEwOTM1NjE2MDQvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL28vZm9vL2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJvYmplY3QiOiJmb28iLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA5MzU2MTYwNCIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0lTQzBPaVcyOTBDRUFJPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL2Zvby8xNTM4MDUxMDkzNTYxNjA0L3VzZXItaW50ZWdyYXRpb25AZ2Nsb3VkLWdvbGFuZy1maXJlc3RvcmUtdGVzdHMuaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMvby9mb28vYWNsL3VzZXItaW50ZWdyYXRpb25AZ2Nsb3VkLWdvbGFuZy1maXJlc3RvcmUtdGVzdHMuaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJvYmplY3QiOiJmb28iLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA5MzU2MTYwNCIsImVudGl0eSI6InVzZXItaW50ZWdyYXRpb25AZ2Nsb3VkLWdvbGFuZy1maXJlc3RvcmUtdGVzdHMuaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJyb2xlIjoiT1dORVIiLCJlbWFpbCI6ImludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIiwiZXRhZyI6IkNJU0MwT2lXMjkwQ0VBST0ifV0sIm93bmVyIjp7ImVudGl0eSI6InVzZXItaW50ZWdyYXRpb25AZ2Nsb3VkLWdvbGFuZy1maXJlc3RvcmUtdGVzdHMuaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20ifSwiY3JjMzJjIjoibW5HN1RBPT0iLCJldGFnIjoiQ0lTQzBPaVcyOTBDRUFJPSJ9"
+ }
+ },
+ {
+ "ID": "a519c18e9f0f3556",
+ "Request": {
+ "Method": "PATCH",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/foo?alt=json\u0026prettyPrint=false\u0026projection=full\u0026userProject=dulcet-port-762",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "85"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "00762968e68ef9b348fedb6bec219c24/10459830203509102870;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/foo?alt=json\u0026prettyPrint=false\u0026projection=full\u0026userProject=dulcet-port-762"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJjb250ZW50TGFuZ3VhZ2UiOiJlbiJ9Cg=="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3204"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:55 GMT"
+ ],
+ "Etag": [
+ "CISC0OiW290CEAM="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051395000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrcf25:4489,/bns/yv/borg/yv/bns/blobstore2/bitpusher/358.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=F8ysW-WHIsSCgQTU6r3QDw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/358.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/358:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATpxChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4CtK4wESxgF5YTI5LmMuRW93QkpRWVNNdC1OVDFNYTJvWXBrbG1qcDlJMlZaUFZ5bFl5Z2Q3Nk5tQXlXbWR3WVBoMm00dGI3ZmZjOUlzcTU4MmVFcFBhNzhNWGpNZmIzaE9WTE9xRHpNTUFfTG9NQXVJZkdkMGgzSWowZ1dxdW5DS1g3Qk1mQlJxM001TUtMMXBHOWNyU0ZBT29lVkZpTDhpWlBsUDI0VjE5THdzZ0d1ZnVrQTFtVzVJcTJUUkVXeWQyNjRKZC1lS2UxdTAwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Uq0-3_a-xcQuKPTmZwhCGyz98TpMddMzH9WhBX0BX6-pSaBjKeo6G2eV8LS7gmCZBLp0Rj2EXkBswc12Wecd0Ecw3Dv8Q"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9mb28vMTUzODA1MTA5MzU2MTYwNCIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9vL2ZvbyIsIm5hbWUiOiJmb28iLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA5MzU2MTYwNCIsIm1ldGFnZW5lcmF0aW9uIjoiMyIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbiIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDo1My41NjFaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6NTUuNjUyWiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjUzLjU2MVoiLCJzaXplIjoiNSIsIm1kNUhhc2giOiJYVUZBS3J4TEtuYTVjWjJSRUJmRmtnPT0iLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL28vZm9vP2dlbmVyYXRpb249MTUzODA1MTA5MzU2MTYwNCZhbHQ9bWVkaWEiLCJjb250ZW50TGFuZ3VhZ2UiOiJlbiIsImNhY2hlQ29udHJvbCI6InB1YmxpYywgbWF4LWFnZT02MCIsImFjbCI6W3sia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL2Zvby8xNTM4MDUxMDkzNTYxNjA0L3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL28vZm9vL2FjbC9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMyIsIm9iamVjdCI6ImZvbyIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDkzNTYxNjA0IiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDSVNDME9pVzI5MENFQU09In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMvZm9vLzE1MzgwNTEwOTM1NjE2MDQvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL28vZm9vL2FjbC9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJvYmplY3QiOiJmb28iLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA5MzU2MTYwNCIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDSVNDME9pVzI5MENFQU09In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMvZm9vLzE1MzgwNTEwOTM1NjE2MDQvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL28vZm9vL2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJvYmplY3QiOiJmb28iLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA5MzU2MTYwNCIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0lTQzBPaVcyOTBDRUFNPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL2Zvby8xNTM4MDUxMDkzNTYxNjA0L3VzZXItaW50ZWdyYXRpb25AZ2Nsb3VkLWdvbGFuZy1maXJlc3RvcmUtdGVzdHMuaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMvby9mb28vYWNsL3VzZXItaW50ZWdyYXRpb25AZ2Nsb3VkLWdvbGFuZy1maXJlc3RvcmUtdGVzdHMuaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJvYmplY3QiOiJmb28iLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA5MzU2MTYwNCIsImVudGl0eSI6InVzZXItaW50ZWdyYXRpb25AZ2Nsb3VkLWdvbGFuZy1maXJlc3RvcmUtdGVzdHMuaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJyb2xlIjoiT1dORVIiLCJlbWFpbCI6ImludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIiwiZXRhZyI6IkNJU0MwT2lXMjkwQ0VBTT0ifV0sIm93bmVyIjp7ImVudGl0eSI6InVzZXItaW50ZWdyYXRpb25AZ2Nsb3VkLWdvbGFuZy1maXJlc3RvcmUtdGVzdHMuaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20ifSwiY3JjMzJjIjoibW5HN1RBPT0iLCJldGFnIjoiQ0lTQzBPaVcyOTBDRUFNPSJ9"
+ }
+ },
+ {
+ "ID": "c3cce5ec7cc787d6",
+ "Request": {
+ "Method": "PATCH",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/foo?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "85"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "9e18d8b893776dab3395aa50220c672a/12049960632599609013;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/foo?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJjb250ZW50TGFuZ3VhZ2UiOiJlbiJ9Cg=="
+ },
+ "Response": {
+ "StatusCode": 400,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Content-Length": [
+ "12267"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:56 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051395000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "471383502717"
+ ],
+ "X-Google-Backends": [
+ "vraz3:4225,/bns/yw/borg/yw/bns/blobstore2/bitpusher/168.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=F8ysW6y0L4bShQS_rrGoAQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yw/borg/yw/bns/blobstore2/bitpusher/168.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yw/borg/yw/bns/blobstore2/bitpusher/168:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CP3elYXcDRoCGAYoATo_ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGM6ropHgHCIVMTE3MjM4MDU4ODYxOTM3NTE5MTQ0MOArSp8BEoIBeWEyOS5jLkVsb2xCcldWbUZlX1AxVDdUOHVpTXdFMHBZUjdTc2NVMDBFdEZkc2tSenBQY0NLWkhUeEZaYXI0Q25tZmR6bXFRLTNVV0kzOF9wdEx5VTZ2Z1Q3dlRBeW42Z3g4dUcyd0szSHIzaTZrV1JBZkozc1pNMGQ1allkNHpWQTAEOhZOT1RfQV9QRVJTSVNURU5UX1RPS0VO"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Upload-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UqCww9J5OJXbjsyOgthOsXt3HmpChxjzf0o2zldcFmEHWWogW74ItLioX44a7LE8TOEIeVT5b5F8Woc-pDN1uqe3PXA__eDRxpoQtcr9JUpytjdAIo"
+ ]
+ },
+ "Body": "eyJlcnJvciI6eyJlcnJvcnMiOlt7ImRvbWFpbiI6Imdsb2JhbCIsInJlYXNvbiI6InJlcXVpcmVkIiwibWVzc2FnZSI6IkJ1Y2tldCBpcyByZXF1ZXN0ZXIgcGF5cyBidWNrZXQgYnV0IG5vIHVzZXIgcHJvamVjdCBwcm92aWRlZC4iLCJkZWJ1Z0luZm8iOiJjb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6VVNFUl9QUk9KRUNUX01JU1NJTkc6IEJ1Y2tldCBpcyBSZXF1ZXN0ZXIgUGF5cyBidWNrZXQgYnV0IG5vIGJpbGxpbmcgcHJvamVjdCBpZCBwcm92aWRlZCBmb3Igbm9uLW93bmVyLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5VcGRhdGVBbmRQYXRjaE9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoVXBkYXRlQW5kUGF0Y2hPYmplY3QuamF2YTozMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5VcGRhdGVBbmRQYXRjaE9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoVXBkYXRlQW5kUGF0Y2hPYmplY3QuamF2YTo1Milcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLk9iamVjdHNEZWxlZ2F0b3IudXBkYXRlKE9iamVjdHNEZWxlZ2F0b3IuamF2YToxMDYpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBCdWNrZXQgaXMgUmVxdWVzdGVyIFBheXMgYnVja2V0IGJ1dCBubyBiaWxsaW5nIHByb2plY3QgaWQgcHJvdmlkZWQgZm9yIG5vbi1vd25lci5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MjkwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAxKVxuXHQuLi4gMTcgbW9yZVxuXG5jb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS5GYXVsdDogSW1tdXRhYmxlRXJyb3JEZWZpbml0aW9ue2Jhc2U9UkVRVUlSRUQsIGNhdGVnb3J5PVVTRVJfRVJST1IsIGNhdXNlPW51bGwsIGRlYnVnSW5mbz1jb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6VVNFUl9QUk9KRUNUX01JU1NJTkc6IEJ1Y2tldCBpcyBSZXF1ZXN0ZXIgUGF5cyBidWNrZXQgYnV0IG5vIGJpbGxpbmcgcHJvamVjdCBpZCBwcm92aWRlZCBmb3Igbm9uLW93bmVyLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5VcGRhdGVBbmRQYXRjaE9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoVXBkYXRlQW5kUGF0Y2hPYmplY3QuamF2YTozMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5VcGRhdGVBbmRQYXRjaE9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoVXBkYXRlQW5kUGF0Y2hPYmplY3QuamF2YTo1Milcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLk9iamVjdHNEZWxlZ2F0b3IudXBkYXRlKE9iamVjdHNEZWxlZ2F0b3IuamF2YToxMDYpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBCdWNrZXQgaXMgUmVxdWVzdGVyIFBheXMgYnVja2V0IGJ1dCBubyBiaWxsaW5nIHByb2plY3QgaWQgcHJvdmlkZWQgZm9yIG5vbi1vd25lci5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MjkwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAxKVxuXHQuLi4gMTcgbW9yZVxuLCBkb21haW49Z2xvYmFsLCBleHRlbmRlZEhlbHA9bnVsbCwgaHR0cEhlYWRlcnM9e30sIGh0dHBTdGF0dXM9YmFkUmVxdWVzdCwgaW50ZXJuYWxSZWFzb249UmVhc29ue2FyZ3VtZW50cz17fSwgY2F1c2U9bnVsbCwgY29kZT1nZGF0YS5Db3JlRXJyb3JEb21haW4uUkVRVUlSRUQsIGNyZWF0ZWRCeUJhY2tlbmQ9dHJ1ZSwgZGVidWdNZXNzYWdlPWNvbS5nb29nbGUubmV0LnJwYzMuUnBjRXhjZXB0aW9uOiBjbG91ZC5iaWdzdG9yZS5SZXNwb25zZUNvZGUuRXJyb3JDb2RlOjpVU0VSX1BST0pFQ1RfTUlTU0lORzogQnVja2V0IGlzIFJlcXVlc3RlciBQYXlzIGJ1Y2tldCBidXQgbm8gYmlsbGluZyBwcm9qZWN0IGlkIHByb3ZpZGVkIGZvciBub24tb3duZXIuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRvUnBjM0V4Y2VwdGlvbihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjEzNSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5vYmplY3RzLlVwZGF0ZUFuZFBhdGNoT2JqZWN0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChVcGRhdGVBbmRQYXRjaE9iamVjdC5qYXZhOjMzNSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5vYmplY3RzLlVwZGF0ZUFuZFBhdGNoT2JqZWN0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChVcGRhdGVBbmRQYXRjaE9iamVjdC5qYXZhOjUyKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmZyYW1ld29yay5SZXF1ZXN0SGFuZGxlci5oYW5kbGUoUmVxdWVzdEhhbmRsZXIuamF2YToyOTQpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uT2JqZWN0c0RlbGVnYXRvci51cGRhdGUoT2JqZWN0c0RlbGVnYXRvci5qYXZhOjEwNilcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uUnBjUmVjZWl2ZXIubGFtYmRhJHByb2Nlc3NSZXF1ZXN0QXN5bmMkNChScGNSZWNlaXZlci5qYXZhOjIwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uQXN5bmNFeGVjdXRvci5sYW1iZGEkc3VibWl0JDAoQXN5bmNFeGVjdXRvci5qYXZhOjI3Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KENvbnRleHRSdW5uYWJsZS5qYXZhOjUwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZSQxLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozOSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NzIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozNilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRXhlY3V0b3JzJFJ1bm5hYmxlQWRhcHRlci5jYWxsKEV4ZWN1dG9ycy5qYXZhOjUxMSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRnV0dXJlVGFzay5ydW4oRnV0dXJlVGFzay5qYXZhOjI2Nilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yLnJ1bldvcmtlcihUaHJlYWRQb29sRXhlY3V0b3IuamF2YToxMTQ5KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IkV29ya2VyLnJ1bihUaHJlYWRQb29sRXhlY3V0b3IuamF2YTo2MjQpXG5cdGF0IGphdmEubGFuZy5UaHJlYWQucnVuKFRocmVhZC5qYXZhOjc0OClcbkNhdXNlZCBieTogY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb246IEJ1Y2tldCBpcyBSZXF1ZXN0ZXIgUGF5cyBidWNrZXQgYnV0IG5vIGJpbGxpbmcgcHJvamVjdCBpZCBwcm92aWRlZCBmb3Igbm9uLW93bmVyLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxNyBtb3JlXG4sIGVycm9yUHJvdG9Db2RlPVJFUVVJUkVELCBlcnJvclByb3RvRG9tYWluPWdkYXRhLkNvcmVFcnJvckRvbWFpbiwgZmlsdGVyZWRNZXNzYWdlPW51bGwsIGxvY2F0aW9uPW51bGwsIG1lc3NhZ2U9QnVja2V0IGlzIHJlcXVlc3RlciBwYXlzIGJ1Y2tldCBidXQgbm8gdXNlciBwcm9qZWN0IHByb3ZpZGVkLiwgdW5uYW1lZEFyZ3VtZW50cz1bXX0sIGxvY2F0aW9uPW51bGwsIG1lc3NhZ2U9QnVja2V0IGlzIHJlcXVlc3RlciBwYXlzIGJ1Y2tldCBidXQgbm8gdXNlciBwcm9qZWN0IHByb3ZpZGVkLiwgcmVhc29uPXJlcXVpcmVkLCBycGNDb2RlPTQwMH0gQnVja2V0IGlzIHJlcXVlc3RlciBwYXlzIGJ1Y2tldCBidXQgbm8gdXNlciBwcm9qZWN0IHByb3ZpZGVkLjogY29tLmdvb2dsZS5uZXQucnBjMy5ScGNFeGNlcHRpb246IGNsb3VkLmJpZ3N0b3JlLlJlc3BvbnNlQ29kZS5FcnJvckNvZGU6OlVTRVJfUFJPSkVDVF9NSVNTSU5HOiBCdWNrZXQgaXMgUmVxdWVzdGVyIFBheXMgYnVja2V0IGJ1dCBubyBiaWxsaW5nIHByb2plY3QgaWQgcHJvdmlkZWQgZm9yIG5vbi1vd25lci5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udG9ScGMzRXhjZXB0aW9uKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MTM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuVXBkYXRlQW5kUGF0Y2hPYmplY3QuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKFVwZGF0ZUFuZFBhdGNoT2JqZWN0LmphdmE6MzM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuVXBkYXRlQW5kUGF0Y2hPYmplY3QuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKFVwZGF0ZUFuZFBhdGNoT2JqZWN0LmphdmE6NTIpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5PYmplY3RzRGVsZWdhdG9yLnVwZGF0ZShPYmplY3RzRGVsZWdhdG9yLmphdmE6MTA2KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5ScGNSZWNlaXZlci5sYW1iZGEkcHJvY2Vzc1JlcXVlc3RBc3luYyQ0KFJwY1JlY2VpdmVyLmphdmE6MjAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5Bc3luY0V4ZWN1dG9yLmxhbWJkYSRzdWJtaXQkMChBc3luY0V4ZWN1dG9yLmphdmE6MjcyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoQ29udGV4dFJ1bm5hYmxlLmphdmE6NTApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlJDEucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM5KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo3Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5FeGVjdXRvcnMkUnVubmFibGVBZGFwdGVyLmNhbGwoRXhlY3V0b3JzLmphdmE6NTExKVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5GdXR1cmVUYXNrLnJ1bihGdXR1cmVUYXNrLmphdmE6MjY2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IucnVuV29ya2VyKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjExNDkpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvciRXb3JrZXIucnVuKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjYyNClcblx0YXQgamF2YS5sYW5nLlRocmVhZC5ydW4oVGhyZWFkLmphdmE6NzQ4KVxuQ2F1c2VkIGJ5OiBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbjogQnVja2V0IGlzIFJlcXVlc3RlciBQYXlzIGJ1Y2tldCBidXQgbm8gYmlsbGluZyBwcm9qZWN0IGlkIHByb3ZpZGVkIGZvciBub24tb3duZXIuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93T25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjI5MClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMSlcblx0Li4uIDE3IG1vcmVcblxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS5FcnJvckNvbGxlY3Rvci50b0ZhdWx0KEVycm9yQ29sbGVjdG9yLmphdmE6NTQpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5yZXN0LmFkYXB0ZXIucm9zeS5Sb3N5RXJyb3JDb252ZXJ0ZXIudG9GYXVsdChSb3N5RXJyb3JDb252ZXJ0ZXIuamF2YTo2Nylcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnJlc3QuYWRhcHRlci5yb3N5LlJvc3lIYW5kbGVyJDIuY2FsbChSb3N5SGFuZGxlci5qYXZhOjI1OClcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnJlc3QuYWRhcHRlci5yb3N5LlJvc3lIYW5kbGVyJDIuY2FsbChSb3N5SGFuZGxlci5qYXZhOjIzOClcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkRpcmVjdEV4ZWN1dG9yLmV4ZWN1dGUoRGlyZWN0RXhlY3V0b3IuamF2YTozMClcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmV4ZWN1dGVMaXN0ZW5lcihBYnN0cmFjdEZ1dHVyZS5qYXZhOjExNDMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5jb21wbGV0ZShBYnN0cmFjdEZ1dHVyZS5qYXZhOjk2Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLnNldChBYnN0cmFjdEZ1dHVyZS5qYXZhOjczMSlcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkRpcmVjdEV4ZWN1dG9yLmV4ZWN1dGUoRGlyZWN0RXhlY3V0b3IuamF2YTozMClcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmV4ZWN1dGVMaXN0ZW5lcihBYnN0cmFjdEZ1dHVyZS5qYXZhOjExNDMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5jb21wbGV0ZShBYnN0cmFjdEZ1dHVyZS5qYXZhOjk2Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLnNldChBYnN0cmFjdEZ1dHVyZS5qYXZhOjczMSlcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnRocmVhZC5UaHJlYWRUcmFja2VycyRUaHJlYWRUcmFja2luZ1J1bm5hYmxlLnJ1bihUaHJlYWRUcmFja2Vycy5qYXZhOjEyNilcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRUcmFjZUNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoVHJhY2VDb250ZXh0LmphdmE6NDU1KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuc2VydmVyLkNvbW1vbk1vZHVsZSRDb250ZXh0Q2FycnlpbmdFeGVjdXRvclNlcnZpY2UkMS5ydW5JbkNvbnRleHQoQ29tbW9uTW9kdWxlLmphdmE6ODQ2KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JFRyYWNlQ29udGV4dFJ1bm5hYmxlJDEucnVuKFRyYWNlQ29udGV4dC5qYXZhOjQ2Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRBYnN0cmFjdFRyYWNlQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoVHJhY2VDb250ZXh0LmphdmE6MzIxKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JEFic3RyYWN0VHJhY2VDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KFRyYWNlQ29udGV4dC5qYXZhOjMxMylcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRUcmFjZUNvbnRleHRSdW5uYWJsZS5ydW4oVHJhY2VDb250ZXh0LmphdmE6NDU5KVxuXHRhdCBjb20uZ29vZ2xlLmdzZS5pbnRlcm5hbC5EaXNwYXRjaFF1ZXVlSW1wbCRXb3JrZXJUaHJlYWQucnVuKERpc3BhdGNoUXVldWVJbXBsLmphdmE6NDAzKVxuIn1dLCJjb2RlIjo0MDAsIm1lc3NhZ2UiOiJCdWNrZXQgaXMgcmVxdWVzdGVyIHBheXMgYnVja2V0IGJ1dCBubyB1c2VyIHByb2plY3QgcHJvdmlkZWQuIn19"
+ }
+ },
+ {
+ "ID": "752f44d89c504490",
+ "Request": {
+ "Method": "PATCH",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/foo?alt=json\u0026prettyPrint=false\u0026projection=full\u0026userProject=gcloud-golang-firestore-tests",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "85"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "fbf85c1c6cad40a2542fd31defb3775c/13640372536649983060;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/foo?alt=json\u0026prettyPrint=false\u0026projection=full\u0026userProject=gcloud-golang-firestore-tests"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJjb250ZW50TGFuZ3VhZ2UiOiJlbiJ9Cg=="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3204"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:56 GMT"
+ ],
+ "Etag": [
+ "CISC0OiW290CEAQ="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051395000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "471383502717"
+ ],
+ "X-Google-Backends": [
+ "vral124:4458,/bns/yv/borg/yv/bns/blobstore2/bitpusher/270.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=GMysW77MAoykNvW7uMAB"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/270.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/270:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CP3elYXcDRoCGAYoATo_ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGM6ropHgHCIVMTE3MjM4MDU4ODYxOTM3NTE5MTQ0MOArSp8BEoIBeWEyOS5jLkVsb2xCcldWbUZlX1AxVDdUOHVpTXdFMHBZUjdTc2NVMDBFdEZkc2tSenBQY0NLWkhUeEZaYXI0Q25tZmR6bXFRLTNVV0kzOF9wdEx5VTZ2Z1Q3dlRBeW42Z3g4dUcyd0szSHIzaTZrV1JBZkozc1pNMGQ1allkNHpWQTAEOhZOT1RfQV9QRVJTSVNURU5UX1RPS0VO"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Uq5s8h_ClmvAT1wvmhEg6lcQZi4y5nQBDFtjp5Xc8aSPQ1d_Gzr4jPlw6R6Mh2t9Rmm2BQsim7mcgUzDhWSkberqA9QoA"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9mb28vMTUzODA1MTA5MzU2MTYwNCIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9vL2ZvbyIsIm5hbWUiOiJmb28iLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA5MzU2MTYwNCIsIm1ldGFnZW5lcmF0aW9uIjoiNCIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbiIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDo1My41NjFaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6NTYuMTI2WiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjUzLjU2MVoiLCJzaXplIjoiNSIsIm1kNUhhc2giOiJYVUZBS3J4TEtuYTVjWjJSRUJmRmtnPT0iLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL28vZm9vP2dlbmVyYXRpb249MTUzODA1MTA5MzU2MTYwNCZhbHQ9bWVkaWEiLCJjb250ZW50TGFuZ3VhZ2UiOiJlbiIsImNhY2hlQ29udHJvbCI6InB1YmxpYywgbWF4LWFnZT02MCIsImFjbCI6W3sia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL2Zvby8xNTM4MDUxMDkzNTYxNjA0L3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL28vZm9vL2FjbC9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMyIsIm9iamVjdCI6ImZvbyIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDkzNTYxNjA0IiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDSVNDME9pVzI5MENFQVE9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMvZm9vLzE1MzgwNTEwOTM1NjE2MDQvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL28vZm9vL2FjbC9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJvYmplY3QiOiJmb28iLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA5MzU2MTYwNCIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDSVNDME9pVzI5MENFQVE9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMvZm9vLzE1MzgwNTEwOTM1NjE2MDQvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL28vZm9vL2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJvYmplY3QiOiJmb28iLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA5MzU2MTYwNCIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0lTQzBPaVcyOTBDRUFRPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL2Zvby8xNTM4MDUxMDkzNTYxNjA0L3VzZXItaW50ZWdyYXRpb25AZ2Nsb3VkLWdvbGFuZy1maXJlc3RvcmUtdGVzdHMuaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMvby9mb28vYWNsL3VzZXItaW50ZWdyYXRpb25AZ2Nsb3VkLWdvbGFuZy1maXJlc3RvcmUtdGVzdHMuaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJvYmplY3QiOiJmb28iLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA5MzU2MTYwNCIsImVudGl0eSI6InVzZXItaW50ZWdyYXRpb25AZ2Nsb3VkLWdvbGFuZy1maXJlc3RvcmUtdGVzdHMuaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJyb2xlIjoiT1dORVIiLCJlbWFpbCI6ImludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIiwiZXRhZyI6IkNJU0MwT2lXMjkwQ0VBUT0ifV0sIm93bmVyIjp7ImVudGl0eSI6InVzZXItaW50ZWdyYXRpb25AZ2Nsb3VkLWdvbGFuZy1maXJlc3RvcmUtdGVzdHMuaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20ifSwiY3JjMzJjIjoibW5HN1RBPT0iLCJldGFnIjoiQ0lTQzBPaVcyOTBDRUFRPSJ9"
+ }
+ },
+ {
+ "ID": "fdf00574ab80e155",
+ "Request": {
+ "Method": "PATCH",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/foo?alt=json\u0026prettyPrint=false\u0026projection=full\u0026userProject=veener-jba",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "85"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "8d2a0740d223b423b497bc4917e09558/15230784440717199858;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/foo?alt=json\u0026prettyPrint=false\u0026projection=full\u0026userProject=veener-jba"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJjb250ZW50TGFuZ3VhZ2UiOiJlbiJ9Cg=="
+ },
+ "Response": {
+ "StatusCode": 403,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Content-Length": [
+ "13123"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:56 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051395000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "471383502717"
+ ],
+ "X-Google-Backends": [
+ "vrbj128:4260,/bns/yv/borg/yv/bns/blobstore2/bitpusher/266.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=GMysW8aBD5CcNsOPmzA"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/266.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/266:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CP3elYXcDRoCGAYoATo_ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGM6ropHgHCIVMTE3MjM4MDU4ODYxOTM3NTE5MTQ0MOArSp8BEoIBeWEyOS5jLkVsb2xCcldWbUZlX1AxVDdUOHVpTXdFMHBZUjdTc2NVMDBFdEZkc2tSenBQY0NLWkhUeEZaYXI0Q25tZmR6bXFRLTNVV0kzOF9wdEx5VTZ2Z1Q3dlRBeW42Z3g4dUcyd0szSHIzaTZrV1JBZkozc1pNMGQ1allkNHpWQTAEOhZOT1RfQV9QRVJTSVNURU5UX1RPS0VO"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Upload-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UqbgqQTG9YR1fSqJ3ZOa8nTDVoLdEfeP_eYQL1M9VymnALeOi2fekzhEIS0D2KbKg0S1c0AE1i0UoUcDhzaysqUcZcVaA"
+ ]
+ },
+ "Body": "eyJlcnJvciI6eyJlcnJvcnMiOlt7ImRvbWFpbiI6Imdsb2JhbCIsInJlYXNvbiI6ImZvcmJpZGRlbiIsIm1lc3NhZ2UiOiJpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLiIsImRlYnVnSW5mbyI6ImNvbS5nb29nbGUubmV0LnJwYzMuUnBjRXhjZXB0aW9uOiBjbG91ZC5iaWdzdG9yZS5SZXNwb25zZUNvZGUuRXJyb3JDb2RlOjpVU0VSX1BST0pFQ1RfQUNDRVNTX0RFTklFRDogaW50ZWdyYXRpb25AZ2Nsb3VkLWdvbGFuZy1maXJlc3RvcmUtdGVzdHMuaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20gZG9lcyBub3QgaGF2ZSBzZXJ2aWNldXNhZ2Uuc2VydmljZXMudXNlIGFjY2VzcyB0byBwcm9qZWN0IDY0MjA4MDkxODEwMS5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udG9ScGMzRXhjZXB0aW9uKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MTM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuVXBkYXRlQW5kUGF0Y2hPYmplY3QuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKFVwZGF0ZUFuZFBhdGNoT2JqZWN0LmphdmE6MzM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuVXBkYXRlQW5kUGF0Y2hPYmplY3QuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKFVwZGF0ZUFuZFBhdGNoT2JqZWN0LmphdmE6NTIpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5PYmplY3RzRGVsZWdhdG9yLnVwZGF0ZShPYmplY3RzRGVsZWdhdG9yLmphdmE6MTA2KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5ScGNSZWNlaXZlci5sYW1iZGEkcHJvY2Vzc1JlcXVlc3RBc3luYyQ0KFJwY1JlY2VpdmVyLmphdmE6MjAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5Bc3luY0V4ZWN1dG9yLmxhbWJkYSRzdWJtaXQkMChBc3luY0V4ZWN1dG9yLmphdmE6MjcyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoQ29udGV4dFJ1bm5hYmxlLmphdmE6NTApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlJDEucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM5KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo3Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5FeGVjdXRvcnMkUnVubmFibGVBZGFwdGVyLmNhbGwoRXhlY3V0b3JzLmphdmE6NTExKVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5GdXR1cmVUYXNrLnJ1bihGdXR1cmVUYXNrLmphdmE6MjY2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IucnVuV29ya2VyKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjExNDkpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvciRXb3JrZXIucnVuKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjYyNClcblx0YXQgamF2YS5sYW5nLlRocmVhZC5ydW4oVGhyZWFkLmphdmE6NzQ4KVxuQ2F1c2VkIGJ5OiBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbjogaW50ZWdyYXRpb25AZ2Nsb3VkLWdvbGFuZy1maXJlc3RvcmUtdGVzdHMuaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20gZG9lcyBub3QgaGF2ZSBzZXJ2aWNldXNhZ2Uuc2VydmljZXMudXNlIGFjY2VzcyB0byBwcm9qZWN0IDY0MjA4MDkxODEwMS5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MjkwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAxKVxuXHQuLi4gMTcgbW9yZVxuXG5jb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS5GYXVsdDogSW1tdXRhYmxlRXJyb3JEZWZpbml0aW9ue2Jhc2U9Rk9SQklEREVOLCBjYXRlZ29yeT1VU0VSX0VSUk9SLCBjYXVzZT1udWxsLCBkZWJ1Z0luZm89Y29tLmdvb2dsZS5uZXQucnBjMy5ScGNFeGNlcHRpb246IGNsb3VkLmJpZ3N0b3JlLlJlc3BvbnNlQ29kZS5FcnJvckNvZGU6OlVTRVJfUFJPSkVDVF9BQ0NFU1NfREVOSUVEOiBpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5VcGRhdGVBbmRQYXRjaE9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoVXBkYXRlQW5kUGF0Y2hPYmplY3QuamF2YTozMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5VcGRhdGVBbmRQYXRjaE9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoVXBkYXRlQW5kUGF0Y2hPYmplY3QuamF2YTo1Milcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLk9iamVjdHNEZWxlZ2F0b3IudXBkYXRlKE9iamVjdHNEZWxlZ2F0b3IuamF2YToxMDYpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxNyBtb3JlXG4sIGRvbWFpbj1nbG9iYWwsIGV4dGVuZGVkSGVscD1udWxsLCBodHRwSGVhZGVycz17fSwgaHR0cFN0YXR1cz1mb3JiaWRkZW4sIGludGVybmFsUmVhc29uPVJlYXNvbnthcmd1bWVudHM9e30sIGNhdXNlPW51bGwsIGNvZGU9Z2RhdGEuQ29yZUVycm9yRG9tYWluLkZPUkJJRERFTiwgY3JlYXRlZEJ5QmFja2VuZD10cnVlLCBkZWJ1Z01lc3NhZ2U9Y29tLmdvb2dsZS5uZXQucnBjMy5ScGNFeGNlcHRpb246IGNsb3VkLmJpZ3N0b3JlLlJlc3BvbnNlQ29kZS5FcnJvckNvZGU6OlVTRVJfUFJPSkVDVF9BQ0NFU1NfREVOSUVEOiBpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5VcGRhdGVBbmRQYXRjaE9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoVXBkYXRlQW5kUGF0Y2hPYmplY3QuamF2YTozMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5VcGRhdGVBbmRQYXRjaE9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoVXBkYXRlQW5kUGF0Y2hPYmplY3QuamF2YTo1Milcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLk9iamVjdHNEZWxlZ2F0b3IudXBkYXRlKE9iamVjdHNEZWxlZ2F0b3IuamF2YToxMDYpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxNyBtb3JlXG4sIGVycm9yUHJvdG9Db2RlPUZPUkJJRERFTiwgZXJyb3JQcm90b0RvbWFpbj1nZGF0YS5Db3JlRXJyb3JEb21haW4sIGZpbHRlcmVkTWVzc2FnZT1udWxsLCBsb2NhdGlvbj1udWxsLCBtZXNzYWdlPWludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIGRvZXMgbm90IGhhdmUgc2VydmljZXVzYWdlLnNlcnZpY2VzLnVzZSBhY2Nlc3MgdG8gcHJvamVjdCA2NDIwODA5MTgxMDEuLCB1bm5hbWVkQXJndW1lbnRzPVtdfSwgbG9jYXRpb249bnVsbCwgbWVzc2FnZT1pbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLiwgcmVhc29uPWZvcmJpZGRlbiwgcnBjQ29kZT00MDN9IGludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIGRvZXMgbm90IGhhdmUgc2VydmljZXVzYWdlLnNlcnZpY2VzLnVzZSBhY2Nlc3MgdG8gcHJvamVjdCA2NDIwODA5MTgxMDEuOiBjb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6VVNFUl9QUk9KRUNUX0FDQ0VTU19ERU5JRUQ6IGludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIGRvZXMgbm90IGhhdmUgc2VydmljZXVzYWdlLnNlcnZpY2VzLnVzZSBhY2Nlc3MgdG8gcHJvamVjdCA2NDIwODA5MTgxMDEuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRvUnBjM0V4Y2VwdGlvbihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjEzNSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5vYmplY3RzLlVwZGF0ZUFuZFBhdGNoT2JqZWN0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChVcGRhdGVBbmRQYXRjaE9iamVjdC5qYXZhOjMzNSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5vYmplY3RzLlVwZGF0ZUFuZFBhdGNoT2JqZWN0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChVcGRhdGVBbmRQYXRjaE9iamVjdC5qYXZhOjUyKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmZyYW1ld29yay5SZXF1ZXN0SGFuZGxlci5oYW5kbGUoUmVxdWVzdEhhbmRsZXIuamF2YToyOTQpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uT2JqZWN0c0RlbGVnYXRvci51cGRhdGUoT2JqZWN0c0RlbGVnYXRvci5qYXZhOjEwNilcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uUnBjUmVjZWl2ZXIubGFtYmRhJHByb2Nlc3NSZXF1ZXN0QXN5bmMkNChScGNSZWNlaXZlci5qYXZhOjIwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uQXN5bmNFeGVjdXRvci5sYW1iZGEkc3VibWl0JDAoQXN5bmNFeGVjdXRvci5qYXZhOjI3Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KENvbnRleHRSdW5uYWJsZS5qYXZhOjUwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZSQxLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozOSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NzIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozNilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRXhlY3V0b3JzJFJ1bm5hYmxlQWRhcHRlci5jYWxsKEV4ZWN1dG9ycy5qYXZhOjUxMSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRnV0dXJlVGFzay5ydW4oRnV0dXJlVGFzay5qYXZhOjI2Nilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yLnJ1bldvcmtlcihUaHJlYWRQb29sRXhlY3V0b3IuamF2YToxMTQ5KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IkV29ya2VyLnJ1bihUaHJlYWRQb29sRXhlY3V0b3IuamF2YTo2MjQpXG5cdGF0IGphdmEubGFuZy5UaHJlYWQucnVuKFRocmVhZC5qYXZhOjc0OClcbkNhdXNlZCBieTogY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb246IGludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIGRvZXMgbm90IGhhdmUgc2VydmljZXVzYWdlLnNlcnZpY2VzLnVzZSBhY2Nlc3MgdG8gcHJvamVjdCA2NDIwODA5MTgxMDEuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93T25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjI5MClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMSlcblx0Li4uIDE3IG1vcmVcblxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS5FcnJvckNvbGxlY3Rvci50b0ZhdWx0KEVycm9yQ29sbGVjdG9yLmphdmE6NTQpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5yZXN0LmFkYXB0ZXIucm9zeS5Sb3N5RXJyb3JDb252ZXJ0ZXIudG9GYXVsdChSb3N5RXJyb3JDb252ZXJ0ZXIuamF2YTo2Nylcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnJlc3QuYWRhcHRlci5yb3N5LlJvc3lIYW5kbGVyJDIuY2FsbChSb3N5SGFuZGxlci5qYXZhOjI1OClcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnJlc3QuYWRhcHRlci5yb3N5LlJvc3lIYW5kbGVyJDIuY2FsbChSb3N5SGFuZGxlci5qYXZhOjIzOClcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkRpcmVjdEV4ZWN1dG9yLmV4ZWN1dGUoRGlyZWN0RXhlY3V0b3IuamF2YTozMClcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmV4ZWN1dGVMaXN0ZW5lcihBYnN0cmFjdEZ1dHVyZS5qYXZhOjExNDMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5jb21wbGV0ZShBYnN0cmFjdEZ1dHVyZS5qYXZhOjk2Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLnNldChBYnN0cmFjdEZ1dHVyZS5qYXZhOjczMSlcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkRpcmVjdEV4ZWN1dG9yLmV4ZWN1dGUoRGlyZWN0RXhlY3V0b3IuamF2YTozMClcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmV4ZWN1dGVMaXN0ZW5lcihBYnN0cmFjdEZ1dHVyZS5qYXZhOjExNDMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5jb21wbGV0ZShBYnN0cmFjdEZ1dHVyZS5qYXZhOjk2Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLnNldChBYnN0cmFjdEZ1dHVyZS5qYXZhOjczMSlcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnRocmVhZC5UaHJlYWRUcmFja2VycyRUaHJlYWRUcmFja2luZ1J1bm5hYmxlLnJ1bihUaHJlYWRUcmFja2Vycy5qYXZhOjEyNilcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRUcmFjZUNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoVHJhY2VDb250ZXh0LmphdmE6NDU1KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuc2VydmVyLkNvbW1vbk1vZHVsZSRDb250ZXh0Q2FycnlpbmdFeGVjdXRvclNlcnZpY2UkMS5ydW5JbkNvbnRleHQoQ29tbW9uTW9kdWxlLmphdmE6ODQ2KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JFRyYWNlQ29udGV4dFJ1bm5hYmxlJDEucnVuKFRyYWNlQ29udGV4dC5qYXZhOjQ2Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRBYnN0cmFjdFRyYWNlQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoVHJhY2VDb250ZXh0LmphdmE6MzIxKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JEFic3RyYWN0VHJhY2VDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KFRyYWNlQ29udGV4dC5qYXZhOjMxMylcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRUcmFjZUNvbnRleHRSdW5uYWJsZS5ydW4oVHJhY2VDb250ZXh0LmphdmE6NDU5KVxuXHRhdCBjb20uZ29vZ2xlLmdzZS5pbnRlcm5hbC5EaXNwYXRjaFF1ZXVlSW1wbCRXb3JrZXJUaHJlYWQucnVuKERpc3BhdGNoUXVldWVJbXBsLmphdmE6NDAzKVxuIn1dLCJjb2RlIjo0MDMsIm1lc3NhZ2UiOiJpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLiJ9fQ=="
+ }
+ },
+ {
+ "ID": "733f05aa99a1b338",
+ "Request": {
+ "Method": "PUT",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/acl/domain-google.com?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "107"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "7439171b6a0e81d123cfb2ed26494232/16821196344784350865;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/acl/domain-google.com?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJlbnRpdHkiOiJkb21haW4tZ29vZ2xlLmNvbSIsInJvbGUiOiJSRUFERVIifQo="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "377"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:57 GMT"
+ ],
+ "Etag": [
+ "CAM="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051395000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrm69:4161,/bns/yr/borg/yr/bns/blobstore2/bitpusher/88.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=GMysW6ewGpLM4QSw77fYDA"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/88.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/88:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATpxChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4CtK4wESxgF5YTI5LmMuRW93QkpRWVNNdC1OVDFNYTJvWXBrbG1qcDlJMlZaUFZ5bFl5Z2Q3Nk5tQXlXbWR3WVBoMm00dGI3ZmZjOUlzcTU4MmVFcFBhNzhNWGpNZmIzaE9WTE9xRHpNTUFfTG9NQXVJZkdkMGgzSWowZ1dxdW5DS1g3Qk1mQlJxM001TUtMMXBHOWNyU0ZBT29lVkZpTDhpWlBsUDI0VjE5THdzZ0d1ZnVrQTFtVzVJcTJUUkVXeWQyNjRKZC1lS2UxdTAwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UoG9K7qu7HNcJwAGEehEQ7PUq-KVQmO_y1KTGmEbkmtpzFkaLuby68m1a_c81S2oFw1zwOVQ2XyO6zIEyfnUccAQNv2oA"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMvZG9tYWluLWdvb2dsZS5jb20iLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMvYWNsL2RvbWFpbi1nb29nbGUuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzIiwiZW50aXR5IjoiZG9tYWluLWdvb2dsZS5jb20iLCJyb2xlIjoiUkVBREVSIiwiZG9tYWluIjoiZ29vZ2xlLmNvbSIsImV0YWciOiJDQU09In0="
+ }
+ },
+ {
+ "ID": "2a8d19324f3c9a1b",
+ "Request": {
+ "Method": "PUT",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/acl/domain-google.com?alt=json\u0026prettyPrint=false\u0026userProject=dulcet-port-762",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "107"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "1012d9e9a711e5d8ac2dfaae707d9658/18411325674363229232;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/acl/domain-google.com?alt=json\u0026prettyPrint=false\u0026userProject=dulcet-port-762"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJlbnRpdHkiOiJkb21haW4tZ29vZ2xlLmNvbSIsInJvbGUiOiJSRUFERVIifQo="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "377"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:58 GMT"
+ ],
+ "Etag": [
+ "CAM="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051395000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrhq15:4330,/bns/yr/borg/yr/bns/blobstore2/bitpusher/66.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=GsysW_uuAYj8kAPe152IBg"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/66.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/66:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATpxChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4CtK4wESxgF5YTI5LmMuRW93QkpRWVNNdC1OVDFNYTJvWXBrbG1qcDlJMlZaUFZ5bFl5Z2Q3Nk5tQXlXbWR3WVBoMm00dGI3ZmZjOUlzcTU4MmVFcFBhNzhNWGpNZmIzaE9WTE9xRHpNTUFfTG9NQXVJZkdkMGgzSWowZ1dxdW5DS1g3Qk1mQlJxM001TUtMMXBHOWNyU0ZBT29lVkZpTDhpWlBsUDI0VjE5THdzZ0d1ZnVrQTFtVzVJcTJUUkVXeWQyNjRKZC1lS2UxdTAwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UruXPkBA8n56dNnA2rFK5H30i18sXuEkReZ5SWOkW0lzsEVNDxsFREolod7ciOW26miWa0UTbY1kmC930gm5bLHNzxb-A"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMvZG9tYWluLWdvb2dsZS5jb20iLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMvYWNsL2RvbWFpbi1nb29nbGUuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzIiwiZW50aXR5IjoiZG9tYWluLWdvb2dsZS5jb20iLCJyb2xlIjoiUkVBREVSIiwiZG9tYWluIjoiZ29vZ2xlLmNvbSIsImV0YWciOiJDQU09In0="
+ }
+ },
+ {
+ "ID": "a94b33412193c147",
+ "Request": {
+ "Method": "PUT",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/acl/domain-google.com?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "107"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "3a2fbf6422f153a7d7cb3057fd94190d/1555274979697605070;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/acl/domain-google.com?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJlbnRpdHkiOiJkb21haW4tZ29vZ2xlLmNvbSIsInJvbGUiOiJSRUFERVIifQo="
+ },
+ "Response": {
+ "StatusCode": 400,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Content-Length": [
+ "13131"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:58 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051395000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "471383502717"
+ ],
+ "X-Google-Backends": [
+ "vrru15:4107,/bns/yw/borg/yw/bns/blobstore2/bitpusher/57.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=GsysW8q9GZLLhATvipagBg"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yw/borg/yw/bns/blobstore2/bitpusher/57.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yw/borg/yw/bns/blobstore2/bitpusher/57:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CP3elYXcDRoCGAYoATo_ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGM6ropHgHCIVMTE3MjM4MDU4ODYxOTM3NTE5MTQ0MOArSp8BEoIBeWEyOS5jLkVsb2xCcldWbUZlX1AxVDdUOHVpTXdFMHBZUjdTc2NVMDBFdEZkc2tSenBQY0NLWkhUeEZaYXI0Q25tZmR6bXFRLTNVV0kzOF9wdEx5VTZ2Z1Q3dlRBeW42Z3g4dUcyd0szSHIzaTZrV1JBZkozc1pNMGQ1allkNHpWQTAEOhZOT1RfQV9QRVJTSVNURU5UX1RPS0VO"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Upload-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UrOao8jJ1teh9dHDWUI-K-002Cucy8JK26kUqzzX2lLUno91zLpC5q-rHAJh4WsGcxLelf_fw9-EY14Ojls4JjYzY71SQ"
+ ]
+ },
+ "Body": "eyJlcnJvciI6eyJlcnJvcnMiOlt7ImRvbWFpbiI6Imdsb2JhbCIsInJlYXNvbiI6InJlcXVpcmVkIiwibWVzc2FnZSI6IkJ1Y2tldCBpcyByZXF1ZXN0ZXIgcGF5cyBidWNrZXQgYnV0IG5vIHVzZXIgcHJvamVjdCBwcm92aWRlZC4iLCJkZWJ1Z0luZm8iOiJjb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6VVNFUl9QUk9KRUNUX01JU1NJTkc6IEJ1Y2tldCBpcyBSZXF1ZXN0ZXIgUGF5cyBidWNrZXQgYnV0IG5vIGJpbGxpbmcgcHJvamVjdCBpZCBwcm92aWRlZCBmb3Igbm9uLW93bmVyLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5BY2Nlc3NDb250cm9sc0hlbHBlci5sb2FkQnVja2V0KEFjY2Vzc0NvbnRyb2xzSGVscGVyLmphdmE6MzAyKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuQWNjZXNzQ29udHJvbHNIZWxwZXIuZ2V0QWNsUmVzb3VyY2VGb3JSZXF1ZXN0KEFjY2Vzc0NvbnRyb2xzSGVscGVyLmphdmE6NzMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5VcGRhdGVBY2xzLmhhbmRsZVJlcXVlc3RSZWNlaXZlZChVcGRhdGVBY2xzLmphdmE6NjIpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5VcGRhdGVBY2xzLmhhbmRsZVJlcXVlc3RSZWNlaXZlZChVcGRhdGVBY2xzLmphdmE6MTYpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5BY2Nlc3NDb250cm9sc0RlbGVnYXRvci51cGRhdGUoQWNjZXNzQ29udHJvbHNEZWxlZ2F0b3IuamF2YToxMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBCdWNrZXQgaXMgUmVxdWVzdGVyIFBheXMgYnVja2V0IGJ1dCBubyBiaWxsaW5nIHByb2plY3QgaWQgcHJvdmlkZWQgZm9yIG5vbi1vd25lci5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MjkwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAxKVxuXHQuLi4gMTkgbW9yZVxuXG5jb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS5GYXVsdDogSW1tdXRhYmxlRXJyb3JEZWZpbml0aW9ue2Jhc2U9UkVRVUlSRUQsIGNhdGVnb3J5PVVTRVJfRVJST1IsIGNhdXNlPW51bGwsIGRlYnVnSW5mbz1jb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6VVNFUl9QUk9KRUNUX01JU1NJTkc6IEJ1Y2tldCBpcyBSZXF1ZXN0ZXIgUGF5cyBidWNrZXQgYnV0IG5vIGJpbGxpbmcgcHJvamVjdCBpZCBwcm92aWRlZCBmb3Igbm9uLW93bmVyLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5BY2Nlc3NDb250cm9sc0hlbHBlci5sb2FkQnVja2V0KEFjY2Vzc0NvbnRyb2xzSGVscGVyLmphdmE6MzAyKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuQWNjZXNzQ29udHJvbHNIZWxwZXIuZ2V0QWNsUmVzb3VyY2VGb3JSZXF1ZXN0KEFjY2Vzc0NvbnRyb2xzSGVscGVyLmphdmE6NzMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5VcGRhdGVBY2xzLmhhbmRsZVJlcXVlc3RSZWNlaXZlZChVcGRhdGVBY2xzLmphdmE6NjIpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5VcGRhdGVBY2xzLmhhbmRsZVJlcXVlc3RSZWNlaXZlZChVcGRhdGVBY2xzLmphdmE6MTYpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5BY2Nlc3NDb250cm9sc0RlbGVnYXRvci51cGRhdGUoQWNjZXNzQ29udHJvbHNEZWxlZ2F0b3IuamF2YToxMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBCdWNrZXQgaXMgUmVxdWVzdGVyIFBheXMgYnVja2V0IGJ1dCBubyBiaWxsaW5nIHByb2plY3QgaWQgcHJvdmlkZWQgZm9yIG5vbi1vd25lci5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MjkwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAxKVxuXHQuLi4gMTkgbW9yZVxuLCBkb21haW49Z2xvYmFsLCBleHRlbmRlZEhlbHA9bnVsbCwgaHR0cEhlYWRlcnM9e30sIGh0dHBTdGF0dXM9YmFkUmVxdWVzdCwgaW50ZXJuYWxSZWFzb249UmVhc29ue2FyZ3VtZW50cz17fSwgY2F1c2U9bnVsbCwgY29kZT1nZGF0YS5Db3JlRXJyb3JEb21haW4uUkVRVUlSRUQsIGNyZWF0ZWRCeUJhY2tlbmQ9dHJ1ZSwgZGVidWdNZXNzYWdlPWNvbS5nb29nbGUubmV0LnJwYzMuUnBjRXhjZXB0aW9uOiBjbG91ZC5iaWdzdG9yZS5SZXNwb25zZUNvZGUuRXJyb3JDb2RlOjpVU0VSX1BST0pFQ1RfTUlTU0lORzogQnVja2V0IGlzIFJlcXVlc3RlciBQYXlzIGJ1Y2tldCBidXQgbm8gYmlsbGluZyBwcm9qZWN0IGlkIHByb3ZpZGVkIGZvciBub24tb3duZXIuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRvUnBjM0V4Y2VwdGlvbihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjEzNSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLkFjY2Vzc0NvbnRyb2xzSGVscGVyLmxvYWRCdWNrZXQoQWNjZXNzQ29udHJvbHNIZWxwZXIuamF2YTozMDIpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5BY2Nlc3NDb250cm9sc0hlbHBlci5nZXRBY2xSZXNvdXJjZUZvclJlcXVlc3QoQWNjZXNzQ29udHJvbHNIZWxwZXIuamF2YTo3Mylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLlVwZGF0ZUFjbHMuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKFVwZGF0ZUFjbHMuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLlVwZGF0ZUFjbHMuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKFVwZGF0ZUFjbHMuamF2YToxNilcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLkFjY2Vzc0NvbnRyb2xzRGVsZWdhdG9yLnVwZGF0ZShBY2Nlc3NDb250cm9sc0RlbGVnYXRvci5qYXZhOjEwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uUnBjUmVjZWl2ZXIubGFtYmRhJHByb2Nlc3NSZXF1ZXN0QXN5bmMkNChScGNSZWNlaXZlci5qYXZhOjIwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uQXN5bmNFeGVjdXRvci5sYW1iZGEkc3VibWl0JDAoQXN5bmNFeGVjdXRvci5qYXZhOjI3Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KENvbnRleHRSdW5uYWJsZS5qYXZhOjUwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZSQxLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozOSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NzIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozNilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRXhlY3V0b3JzJFJ1bm5hYmxlQWRhcHRlci5jYWxsKEV4ZWN1dG9ycy5qYXZhOjUxMSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRnV0dXJlVGFzay5ydW4oRnV0dXJlVGFzay5qYXZhOjI2Nilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yLnJ1bldvcmtlcihUaHJlYWRQb29sRXhlY3V0b3IuamF2YToxMTQ5KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IkV29ya2VyLnJ1bihUaHJlYWRQb29sRXhlY3V0b3IuamF2YTo2MjQpXG5cdGF0IGphdmEubGFuZy5UaHJlYWQucnVuKFRocmVhZC5qYXZhOjc0OClcbkNhdXNlZCBieTogY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb246IEJ1Y2tldCBpcyBSZXF1ZXN0ZXIgUGF5cyBidWNrZXQgYnV0IG5vIGJpbGxpbmcgcHJvamVjdCBpZCBwcm92aWRlZCBmb3Igbm9uLW93bmVyLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxOSBtb3JlXG4sIGVycm9yUHJvdG9Db2RlPVJFUVVJUkVELCBlcnJvclByb3RvRG9tYWluPWdkYXRhLkNvcmVFcnJvckRvbWFpbiwgZmlsdGVyZWRNZXNzYWdlPW51bGwsIGxvY2F0aW9uPW51bGwsIG1lc3NhZ2U9QnVja2V0IGlzIHJlcXVlc3RlciBwYXlzIGJ1Y2tldCBidXQgbm8gdXNlciBwcm9qZWN0IHByb3ZpZGVkLiwgdW5uYW1lZEFyZ3VtZW50cz1bXX0sIGxvY2F0aW9uPW51bGwsIG1lc3NhZ2U9QnVja2V0IGlzIHJlcXVlc3RlciBwYXlzIGJ1Y2tldCBidXQgbm8gdXNlciBwcm9qZWN0IHByb3ZpZGVkLiwgcmVhc29uPXJlcXVpcmVkLCBycGNDb2RlPTQwMH0gQnVja2V0IGlzIHJlcXVlc3RlciBwYXlzIGJ1Y2tldCBidXQgbm8gdXNlciBwcm9qZWN0IHByb3ZpZGVkLjogY29tLmdvb2dsZS5uZXQucnBjMy5ScGNFeGNlcHRpb246IGNsb3VkLmJpZ3N0b3JlLlJlc3BvbnNlQ29kZS5FcnJvckNvZGU6OlVTRVJfUFJPSkVDVF9NSVNTSU5HOiBCdWNrZXQgaXMgUmVxdWVzdGVyIFBheXMgYnVja2V0IGJ1dCBubyBiaWxsaW5nIHByb2plY3QgaWQgcHJvdmlkZWQgZm9yIG5vbi1vd25lci5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udG9ScGMzRXhjZXB0aW9uKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MTM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuQWNjZXNzQ29udHJvbHNIZWxwZXIubG9hZEJ1Y2tldChBY2Nlc3NDb250cm9sc0hlbHBlci5qYXZhOjMwMilcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLkFjY2Vzc0NvbnRyb2xzSGVscGVyLmdldEFjbFJlc291cmNlRm9yUmVxdWVzdChBY2Nlc3NDb250cm9sc0hlbHBlci5qYXZhOjczKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuVXBkYXRlQWNscy5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoVXBkYXRlQWNscy5qYXZhOjYyKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuVXBkYXRlQWNscy5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoVXBkYXRlQWNscy5qYXZhOjE2KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmZyYW1ld29yay5SZXF1ZXN0SGFuZGxlci5oYW5kbGUoUmVxdWVzdEhhbmRsZXIuamF2YToyOTQpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uQWNjZXNzQ29udHJvbHNEZWxlZ2F0b3IudXBkYXRlKEFjY2Vzc0NvbnRyb2xzRGVsZWdhdG9yLmphdmE6MTAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5ScGNSZWNlaXZlci5sYW1iZGEkcHJvY2Vzc1JlcXVlc3RBc3luYyQ0KFJwY1JlY2VpdmVyLmphdmE6MjAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5Bc3luY0V4ZWN1dG9yLmxhbWJkYSRzdWJtaXQkMChBc3luY0V4ZWN1dG9yLmphdmE6MjcyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoQ29udGV4dFJ1bm5hYmxlLmphdmE6NTApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlJDEucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM5KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo3Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5FeGVjdXRvcnMkUnVubmFibGVBZGFwdGVyLmNhbGwoRXhlY3V0b3JzLmphdmE6NTExKVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5GdXR1cmVUYXNrLnJ1bihGdXR1cmVUYXNrLmphdmE6MjY2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IucnVuV29ya2VyKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjExNDkpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvciRXb3JrZXIucnVuKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjYyNClcblx0YXQgamF2YS5sYW5nLlRocmVhZC5ydW4oVGhyZWFkLmphdmE6NzQ4KVxuQ2F1c2VkIGJ5OiBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbjogQnVja2V0IGlzIFJlcXVlc3RlciBQYXlzIGJ1Y2tldCBidXQgbm8gYmlsbGluZyBwcm9qZWN0IGlkIHByb3ZpZGVkIGZvciBub24tb3duZXIuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93T25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjI5MClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMSlcblx0Li4uIDE5IG1vcmVcblxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS5FcnJvckNvbGxlY3Rvci50b0ZhdWx0KEVycm9yQ29sbGVjdG9yLmphdmE6NTQpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5yZXN0LmFkYXB0ZXIucm9zeS5Sb3N5RXJyb3JDb252ZXJ0ZXIudG9GYXVsdChSb3N5RXJyb3JDb252ZXJ0ZXIuamF2YTo2Nylcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnJlc3QuYWRhcHRlci5yb3N5LlJvc3lIYW5kbGVyJDIuY2FsbChSb3N5SGFuZGxlci5qYXZhOjI1OClcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnJlc3QuYWRhcHRlci5yb3N5LlJvc3lIYW5kbGVyJDIuY2FsbChSb3N5SGFuZGxlci5qYXZhOjIzOClcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkRpcmVjdEV4ZWN1dG9yLmV4ZWN1dGUoRGlyZWN0RXhlY3V0b3IuamF2YTozMClcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmV4ZWN1dGVMaXN0ZW5lcihBYnN0cmFjdEZ1dHVyZS5qYXZhOjExNDMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5jb21wbGV0ZShBYnN0cmFjdEZ1dHVyZS5qYXZhOjk2Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLnNldChBYnN0cmFjdEZ1dHVyZS5qYXZhOjczMSlcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkRpcmVjdEV4ZWN1dG9yLmV4ZWN1dGUoRGlyZWN0RXhlY3V0b3IuamF2YTozMClcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmV4ZWN1dGVMaXN0ZW5lcihBYnN0cmFjdEZ1dHVyZS5qYXZhOjExNDMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5jb21wbGV0ZShBYnN0cmFjdEZ1dHVyZS5qYXZhOjk2Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLnNldChBYnN0cmFjdEZ1dHVyZS5qYXZhOjczMSlcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnRocmVhZC5UaHJlYWRUcmFja2VycyRUaHJlYWRUcmFja2luZ1J1bm5hYmxlLnJ1bihUaHJlYWRUcmFja2Vycy5qYXZhOjEyNilcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRUcmFjZUNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoVHJhY2VDb250ZXh0LmphdmE6NDU1KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuc2VydmVyLkNvbW1vbk1vZHVsZSRDb250ZXh0Q2FycnlpbmdFeGVjdXRvclNlcnZpY2UkMS5ydW5JbkNvbnRleHQoQ29tbW9uTW9kdWxlLmphdmE6ODQ2KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JFRyYWNlQ29udGV4dFJ1bm5hYmxlJDEucnVuKFRyYWNlQ29udGV4dC5qYXZhOjQ2Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRBYnN0cmFjdFRyYWNlQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoVHJhY2VDb250ZXh0LmphdmE6MzIxKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JEFic3RyYWN0VHJhY2VDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KFRyYWNlQ29udGV4dC5qYXZhOjMxMylcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRUcmFjZUNvbnRleHRSdW5uYWJsZS5ydW4oVHJhY2VDb250ZXh0LmphdmE6NDU5KVxuXHRhdCBjb20uZ29vZ2xlLmdzZS5pbnRlcm5hbC5EaXNwYXRjaFF1ZXVlSW1wbCRXb3JrZXJUaHJlYWQucnVuKERpc3BhdGNoUXVldWVJbXBsLmphdmE6NDAzKVxuIn1dLCJjb2RlIjo0MDAsIm1lc3NhZ2UiOiJCdWNrZXQgaXMgcmVxdWVzdGVyIHBheXMgYnVja2V0IGJ1dCBubyB1c2VyIHByb2plY3QgcHJvdmlkZWQuIn19"
+ }
+ },
+ {
+ "ID": "d84fb6a7fe4c8fad",
+ "Request": {
+ "Method": "PUT",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/acl/domain-google.com?alt=json\u0026prettyPrint=false\u0026userProject=gcloud-golang-firestore-tests",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "107"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "81a103413c23ff6cf6de52c36bbf5f9a/3145686883747979117;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/acl/domain-google.com?alt=json\u0026prettyPrint=false\u0026userProject=gcloud-golang-firestore-tests"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJlbnRpdHkiOiJkb21haW4tZ29vZ2xlLmNvbSIsInJvbGUiOiJSRUFERVIifQo="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "377"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:58 GMT"
+ ],
+ "Etag": [
+ "CAM="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051395000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "471383502717"
+ ],
+ "X-Google-Backends": [
+ "vru185:4374,/bns/yv/borg/yv/bns/blobstore2/bitpusher/273.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=GsysW8LPJ5CgNoeNtLgB"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/273.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/273:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CP3elYXcDRoCGAYoATo_ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGM6ropHgHCIVMTE3MjM4MDU4ODYxOTM3NTE5MTQ0MOArSp8BEoIBeWEyOS5jLkVsb2xCcldWbUZlX1AxVDdUOHVpTXdFMHBZUjdTc2NVMDBFdEZkc2tSenBQY0NLWkhUeEZaYXI0Q25tZmR6bXFRLTNVV0kzOF9wdEx5VTZ2Z1Q3dlRBeW42Z3g4dUcyd0szSHIzaTZrV1JBZkozc1pNMGQ1allkNHpWQTAEOhZOT1RfQV9QRVJTSVNURU5UX1RPS0VO"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UpDBLUF8C0Y8OC3VIC_pa2-kudAgnEbLAaOCeCCraNcDIKCBS3elQhDKmQpnUPnIgJxUysgDOZc2NNdT2EYaUdRumPFig"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMvZG9tYWluLWdvb2dsZS5jb20iLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMvYWNsL2RvbWFpbi1nb29nbGUuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzIiwiZW50aXR5IjoiZG9tYWluLWdvb2dsZS5jb20iLCJyb2xlIjoiUkVBREVSIiwiZG9tYWluIjoiZ29vZ2xlLmNvbSIsImV0YWciOiJDQU09In0="
+ }
+ },
+ {
+ "ID": "223d5c2655c135ad",
+ "Request": {
+ "Method": "PUT",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/acl/domain-google.com?alt=json\u0026prettyPrint=false\u0026userProject=veener-jba",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "107"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "a2acc7d03c2bb940dcf519dcff4d5ef8/4735817312838485004;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/acl/domain-google.com?alt=json\u0026prettyPrint=false\u0026userProject=veener-jba"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJlbnRpdHkiOiJkb21haW4tZ29vZ2xlLmNvbSIsInJvbGUiOiJSRUFERVIifQo="
+ },
+ "Response": {
+ "StatusCode": 403,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Content-Length": [
+ "13987"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:58 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051395000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "471383502717"
+ ],
+ "X-Google-Backends": [
+ "vreu27:4180,/bns/yv/borg/yv/bns/blobstore2/bitpusher/323.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=GsysW8mRLZXYgQTfuLnICg"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/323.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/323:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CP3elYXcDRoCGAYoATo_ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGM6ropHgHCIVMTE3MjM4MDU4ODYxOTM3NTE5MTQ0MOArSp8BEoIBeWEyOS5jLkVsb2xCcldWbUZlX1AxVDdUOHVpTXdFMHBZUjdTc2NVMDBFdEZkc2tSenBQY0NLWkhUeEZaYXI0Q25tZmR6bXFRLTNVV0kzOF9wdEx5VTZ2Z1Q3dlRBeW42Z3g4dUcyd0szSHIzaTZrV1JBZkozc1pNMGQ1allkNHpWQTAEOhZOT1RfQV9QRVJTSVNURU5UX1RPS0VO"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Upload-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UrYarqP1zBRQ0XDrYASRc0_1B57L8sj9h2pl4o_doKHgHbXjF3neb2cqJU3Rkjs8fPNt0lJz_oqqlN2oiieVgExrvyHxA"
+ ]
+ },
+ "Body": "eyJlcnJvciI6eyJlcnJvcnMiOlt7ImRvbWFpbiI6Imdsb2JhbCIsInJlYXNvbiI6ImZvcmJpZGRlbiIsIm1lc3NhZ2UiOiJpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLiIsImRlYnVnSW5mbyI6ImNvbS5nb29nbGUubmV0LnJwYzMuUnBjRXhjZXB0aW9uOiBjbG91ZC5iaWdzdG9yZS5SZXNwb25zZUNvZGUuRXJyb3JDb2RlOjpVU0VSX1BST0pFQ1RfQUNDRVNTX0RFTklFRDogaW50ZWdyYXRpb25AZ2Nsb3VkLWdvbGFuZy1maXJlc3RvcmUtdGVzdHMuaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20gZG9lcyBub3QgaGF2ZSBzZXJ2aWNldXNhZ2Uuc2VydmljZXMudXNlIGFjY2VzcyB0byBwcm9qZWN0IDY0MjA4MDkxODEwMS5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udG9ScGMzRXhjZXB0aW9uKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MTM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuQWNjZXNzQ29udHJvbHNIZWxwZXIubG9hZEJ1Y2tldChBY2Nlc3NDb250cm9sc0hlbHBlci5qYXZhOjMwMilcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLkFjY2Vzc0NvbnRyb2xzSGVscGVyLmdldEFjbFJlc291cmNlRm9yUmVxdWVzdChBY2Nlc3NDb250cm9sc0hlbHBlci5qYXZhOjczKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuVXBkYXRlQWNscy5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoVXBkYXRlQWNscy5qYXZhOjYyKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuVXBkYXRlQWNscy5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoVXBkYXRlQWNscy5qYXZhOjE2KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmZyYW1ld29yay5SZXF1ZXN0SGFuZGxlci5oYW5kbGUoUmVxdWVzdEhhbmRsZXIuamF2YToyOTQpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uQWNjZXNzQ29udHJvbHNEZWxlZ2F0b3IudXBkYXRlKEFjY2Vzc0NvbnRyb2xzRGVsZWdhdG9yLmphdmE6MTAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5ScGNSZWNlaXZlci5sYW1iZGEkcHJvY2Vzc1JlcXVlc3RBc3luYyQ0KFJwY1JlY2VpdmVyLmphdmE6MjAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5Bc3luY0V4ZWN1dG9yLmxhbWJkYSRzdWJtaXQkMChBc3luY0V4ZWN1dG9yLmphdmE6MjcyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoQ29udGV4dFJ1bm5hYmxlLmphdmE6NTApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlJDEucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM5KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo3Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5FeGVjdXRvcnMkUnVubmFibGVBZGFwdGVyLmNhbGwoRXhlY3V0b3JzLmphdmE6NTExKVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5GdXR1cmVUYXNrLnJ1bihGdXR1cmVUYXNrLmphdmE6MjY2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IucnVuV29ya2VyKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjExNDkpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvciRXb3JrZXIucnVuKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjYyNClcblx0YXQgamF2YS5sYW5nLlRocmVhZC5ydW4oVGhyZWFkLmphdmE6NzQ4KVxuQ2F1c2VkIGJ5OiBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbjogaW50ZWdyYXRpb25AZ2Nsb3VkLWdvbGFuZy1maXJlc3RvcmUtdGVzdHMuaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20gZG9lcyBub3QgaGF2ZSBzZXJ2aWNldXNhZ2Uuc2VydmljZXMudXNlIGFjY2VzcyB0byBwcm9qZWN0IDY0MjA4MDkxODEwMS5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MjkwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAxKVxuXHQuLi4gMTkgbW9yZVxuXG5jb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS5GYXVsdDogSW1tdXRhYmxlRXJyb3JEZWZpbml0aW9ue2Jhc2U9Rk9SQklEREVOLCBjYXRlZ29yeT1VU0VSX0VSUk9SLCBjYXVzZT1udWxsLCBkZWJ1Z0luZm89Y29tLmdvb2dsZS5uZXQucnBjMy5ScGNFeGNlcHRpb246IGNsb3VkLmJpZ3N0b3JlLlJlc3BvbnNlQ29kZS5FcnJvckNvZGU6OlVTRVJfUFJPSkVDVF9BQ0NFU1NfREVOSUVEOiBpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5BY2Nlc3NDb250cm9sc0hlbHBlci5sb2FkQnVja2V0KEFjY2Vzc0NvbnRyb2xzSGVscGVyLmphdmE6MzAyKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuQWNjZXNzQ29udHJvbHNIZWxwZXIuZ2V0QWNsUmVzb3VyY2VGb3JSZXF1ZXN0KEFjY2Vzc0NvbnRyb2xzSGVscGVyLmphdmE6NzMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5VcGRhdGVBY2xzLmhhbmRsZVJlcXVlc3RSZWNlaXZlZChVcGRhdGVBY2xzLmphdmE6NjIpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5VcGRhdGVBY2xzLmhhbmRsZVJlcXVlc3RSZWNlaXZlZChVcGRhdGVBY2xzLmphdmE6MTYpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5BY2Nlc3NDb250cm9sc0RlbGVnYXRvci51cGRhdGUoQWNjZXNzQ29udHJvbHNEZWxlZ2F0b3IuamF2YToxMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxOSBtb3JlXG4sIGRvbWFpbj1nbG9iYWwsIGV4dGVuZGVkSGVscD1udWxsLCBodHRwSGVhZGVycz17fSwgaHR0cFN0YXR1cz1mb3JiaWRkZW4sIGludGVybmFsUmVhc29uPVJlYXNvbnthcmd1bWVudHM9e30sIGNhdXNlPW51bGwsIGNvZGU9Z2RhdGEuQ29yZUVycm9yRG9tYWluLkZPUkJJRERFTiwgY3JlYXRlZEJ5QmFja2VuZD10cnVlLCBkZWJ1Z01lc3NhZ2U9Y29tLmdvb2dsZS5uZXQucnBjMy5ScGNFeGNlcHRpb246IGNsb3VkLmJpZ3N0b3JlLlJlc3BvbnNlQ29kZS5FcnJvckNvZGU6OlVTRVJfUFJPSkVDVF9BQ0NFU1NfREVOSUVEOiBpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5BY2Nlc3NDb250cm9sc0hlbHBlci5sb2FkQnVja2V0KEFjY2Vzc0NvbnRyb2xzSGVscGVyLmphdmE6MzAyKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuQWNjZXNzQ29udHJvbHNIZWxwZXIuZ2V0QWNsUmVzb3VyY2VGb3JSZXF1ZXN0KEFjY2Vzc0NvbnRyb2xzSGVscGVyLmphdmE6NzMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5VcGRhdGVBY2xzLmhhbmRsZVJlcXVlc3RSZWNlaXZlZChVcGRhdGVBY2xzLmphdmE6NjIpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5VcGRhdGVBY2xzLmhhbmRsZVJlcXVlc3RSZWNlaXZlZChVcGRhdGVBY2xzLmphdmE6MTYpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5BY2Nlc3NDb250cm9sc0RlbGVnYXRvci51cGRhdGUoQWNjZXNzQ29udHJvbHNEZWxlZ2F0b3IuamF2YToxMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxOSBtb3JlXG4sIGVycm9yUHJvdG9Db2RlPUZPUkJJRERFTiwgZXJyb3JQcm90b0RvbWFpbj1nZGF0YS5Db3JlRXJyb3JEb21haW4sIGZpbHRlcmVkTWVzc2FnZT1udWxsLCBsb2NhdGlvbj1udWxsLCBtZXNzYWdlPWludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIGRvZXMgbm90IGhhdmUgc2VydmljZXVzYWdlLnNlcnZpY2VzLnVzZSBhY2Nlc3MgdG8gcHJvamVjdCA2NDIwODA5MTgxMDEuLCB1bm5hbWVkQXJndW1lbnRzPVtdfSwgbG9jYXRpb249bnVsbCwgbWVzc2FnZT1pbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLiwgcmVhc29uPWZvcmJpZGRlbiwgcnBjQ29kZT00MDN9IGludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIGRvZXMgbm90IGhhdmUgc2VydmljZXVzYWdlLnNlcnZpY2VzLnVzZSBhY2Nlc3MgdG8gcHJvamVjdCA2NDIwODA5MTgxMDEuOiBjb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6VVNFUl9QUk9KRUNUX0FDQ0VTU19ERU5JRUQ6IGludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIGRvZXMgbm90IGhhdmUgc2VydmljZXVzYWdlLnNlcnZpY2VzLnVzZSBhY2Nlc3MgdG8gcHJvamVjdCA2NDIwODA5MTgxMDEuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRvUnBjM0V4Y2VwdGlvbihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjEzNSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLkFjY2Vzc0NvbnRyb2xzSGVscGVyLmxvYWRCdWNrZXQoQWNjZXNzQ29udHJvbHNIZWxwZXIuamF2YTozMDIpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5BY2Nlc3NDb250cm9sc0hlbHBlci5nZXRBY2xSZXNvdXJjZUZvclJlcXVlc3QoQWNjZXNzQ29udHJvbHNIZWxwZXIuamF2YTo3Mylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLlVwZGF0ZUFjbHMuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKFVwZGF0ZUFjbHMuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLlVwZGF0ZUFjbHMuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKFVwZGF0ZUFjbHMuamF2YToxNilcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLkFjY2Vzc0NvbnRyb2xzRGVsZWdhdG9yLnVwZGF0ZShBY2Nlc3NDb250cm9sc0RlbGVnYXRvci5qYXZhOjEwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uUnBjUmVjZWl2ZXIubGFtYmRhJHByb2Nlc3NSZXF1ZXN0QXN5bmMkNChScGNSZWNlaXZlci5qYXZhOjIwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uQXN5bmNFeGVjdXRvci5sYW1iZGEkc3VibWl0JDAoQXN5bmNFeGVjdXRvci5qYXZhOjI3Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KENvbnRleHRSdW5uYWJsZS5qYXZhOjUwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZSQxLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozOSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NzIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozNilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRXhlY3V0b3JzJFJ1bm5hYmxlQWRhcHRlci5jYWxsKEV4ZWN1dG9ycy5qYXZhOjUxMSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRnV0dXJlVGFzay5ydW4oRnV0dXJlVGFzay5qYXZhOjI2Nilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yLnJ1bldvcmtlcihUaHJlYWRQb29sRXhlY3V0b3IuamF2YToxMTQ5KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IkV29ya2VyLnJ1bihUaHJlYWRQb29sRXhlY3V0b3IuamF2YTo2MjQpXG5cdGF0IGphdmEubGFuZy5UaHJlYWQucnVuKFRocmVhZC5qYXZhOjc0OClcbkNhdXNlZCBieTogY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb246IGludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIGRvZXMgbm90IGhhdmUgc2VydmljZXVzYWdlLnNlcnZpY2VzLnVzZSBhY2Nlc3MgdG8gcHJvamVjdCA2NDIwODA5MTgxMDEuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93T25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjI5MClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMSlcblx0Li4uIDE5IG1vcmVcblxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS5FcnJvckNvbGxlY3Rvci50b0ZhdWx0KEVycm9yQ29sbGVjdG9yLmphdmE6NTQpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5yZXN0LmFkYXB0ZXIucm9zeS5Sb3N5RXJyb3JDb252ZXJ0ZXIudG9GYXVsdChSb3N5RXJyb3JDb252ZXJ0ZXIuamF2YTo2Nylcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnJlc3QuYWRhcHRlci5yb3N5LlJvc3lIYW5kbGVyJDIuY2FsbChSb3N5SGFuZGxlci5qYXZhOjI1OClcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnJlc3QuYWRhcHRlci5yb3N5LlJvc3lIYW5kbGVyJDIuY2FsbChSb3N5SGFuZGxlci5qYXZhOjIzOClcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkRpcmVjdEV4ZWN1dG9yLmV4ZWN1dGUoRGlyZWN0RXhlY3V0b3IuamF2YTozMClcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmV4ZWN1dGVMaXN0ZW5lcihBYnN0cmFjdEZ1dHVyZS5qYXZhOjExNDMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5jb21wbGV0ZShBYnN0cmFjdEZ1dHVyZS5qYXZhOjk2Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLnNldChBYnN0cmFjdEZ1dHVyZS5qYXZhOjczMSlcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkRpcmVjdEV4ZWN1dG9yLmV4ZWN1dGUoRGlyZWN0RXhlY3V0b3IuamF2YTozMClcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmV4ZWN1dGVMaXN0ZW5lcihBYnN0cmFjdEZ1dHVyZS5qYXZhOjExNDMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5jb21wbGV0ZShBYnN0cmFjdEZ1dHVyZS5qYXZhOjk2Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLnNldChBYnN0cmFjdEZ1dHVyZS5qYXZhOjczMSlcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnRocmVhZC5UaHJlYWRUcmFja2VycyRUaHJlYWRUcmFja2luZ1J1bm5hYmxlLnJ1bihUaHJlYWRUcmFja2Vycy5qYXZhOjEyNilcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRUcmFjZUNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoVHJhY2VDb250ZXh0LmphdmE6NDU1KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuc2VydmVyLkNvbW1vbk1vZHVsZSRDb250ZXh0Q2FycnlpbmdFeGVjdXRvclNlcnZpY2UkMS5ydW5JbkNvbnRleHQoQ29tbW9uTW9kdWxlLmphdmE6ODQ2KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JFRyYWNlQ29udGV4dFJ1bm5hYmxlJDEucnVuKFRyYWNlQ29udGV4dC5qYXZhOjQ2Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRBYnN0cmFjdFRyYWNlQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoVHJhY2VDb250ZXh0LmphdmE6MzIxKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JEFic3RyYWN0VHJhY2VDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KFRyYWNlQ29udGV4dC5qYXZhOjMxMylcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRUcmFjZUNvbnRleHRSdW5uYWJsZS5ydW4oVHJhY2VDb250ZXh0LmphdmE6NDU5KVxuXHRhdCBjb20uZ29vZ2xlLmdzZS5pbnRlcm5hbC5EaXNwYXRjaFF1ZXVlSW1wbCRXb3JrZXJUaHJlYWQucnVuKERpc3BhdGNoUXVldWVJbXBsLmphdmE6NDAzKVxuIn1dLCJjb2RlIjo0MDMsIm1lc3NhZ2UiOiJpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLiJ9fQ=="
+ }
+ },
+ {
+ "ID": "fd2973ecddb39533",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/acl?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "684a595153fa158043719a1da2804263/6326229216888924842;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/acl?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0, must-revalidate, no-transform"
+ ],
+ "Content-Length": [
+ "2358"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:59 GMT"
+ ],
+ "Etag": [
+ "CAM="
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:24:59 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051395000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrw127:4318,/bns/yv/borg/yv/bns/blobstore2/bitpusher/374.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=GsysW7bJOI3yggSq27_4CQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/374.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/374:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATpxChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4CtK4wESxgF5YTI5LmMuRW93QkpRWVNNdC1OVDFNYTJvWXBrbG1qcDlJMlZaUFZ5bFl5Z2Q3Nk5tQXlXbWR3WVBoMm00dGI3ZmZjOUlzcTU4MmVFcFBhNzhNWGpNZmIzaE9WTE9xRHpNTUFfTG9NQXVJZkdkMGgzSWowZ1dxdW5DS1g3Qk1mQlJxM001TUtMMXBHOWNyU0ZBT29lVkZpTDhpWlBsUDI0VjE5THdzZ0d1ZnVrQTFtVzVJcTJUUkVXeWQyNjRKZC1lS2UxdTAwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UrQx-txpbMl8OqvGmdlxHHfAZg3zsAgfwVcRJG2cKduZ2fIHtPj9qC9G80sPT15MxGu97kkUtzdWLrv9KOcVWR-Q8LPGA"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9scyIsIml0ZW1zIjpbeyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMvYWNsL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzIiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDQU09In0seyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL2FjbC9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0FNPSJ9LHsia2luZCI6InN0b3JhZ2UjYnVja2V0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzIiwiZW50aXR5IjoicHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6IlJFQURFUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJ2aWV3ZXJzIn0sImV0YWciOiJDQU09In0seyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMvdXNlci1pbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9hY2wvdXNlci1pbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMyIsImVudGl0eSI6InVzZXItaW50ZWdyYXRpb25AZ2Nsb3VkLWdvbGFuZy1maXJlc3RvcmUtdGVzdHMuaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJyb2xlIjoiT1dORVIiLCJlbWFpbCI6ImludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIiwiZXRhZyI6IkNBTT0ifSx7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9kb21haW4tZ29vZ2xlLmNvbSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9hY2wvZG9tYWluLWdvb2dsZS5jb20iLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJlbnRpdHkiOiJkb21haW4tZ29vZ2xlLmNvbSIsInJvbGUiOiJSRUFERVIiLCJkb21haW4iOiJnb29nbGUuY29tIiwiZXRhZyI6IkNBTT0ifV19"
+ }
+ },
+ {
+ "ID": "e12f623c305cecb4",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/acl?alt=json\u0026prettyPrint=false\u0026userProject=dulcet-port-762",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "4f93cb578b023a363759bb2cf52452d7/7916640021461225289;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/acl?alt=json\u0026prettyPrint=false\u0026userProject=dulcet-port-762"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0, must-revalidate, no-transform"
+ ],
+ "Content-Length": [
+ "2358"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:59 GMT"
+ ],
+ "Etag": [
+ "CAM="
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:24:59 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051395000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrgm3:4392,/bns/yr/borg/yr/bns/blobstore2/bitpusher/68.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=G8ysW-GCD4-FkATrn62QAw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/68.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/68:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATpxChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4CtK4wESxgF5YTI5LmMuRW93QkpRWVNNdC1OVDFNYTJvWXBrbG1qcDlJMlZaUFZ5bFl5Z2Q3Nk5tQXlXbWR3WVBoMm00dGI3ZmZjOUlzcTU4MmVFcFBhNzhNWGpNZmIzaE9WTE9xRHpNTUFfTG9NQXVJZkdkMGgzSWowZ1dxdW5DS1g3Qk1mQlJxM001TUtMMXBHOWNyU0ZBT29lVkZpTDhpWlBsUDI0VjE5THdzZ0d1ZnVrQTFtVzVJcTJUUkVXeWQyNjRKZC1lS2UxdTAwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Uqm3U3bqQ3x6UMYoVpEZxvM0-E1gmInWQXEj9VeCg4Bwv6SPEjSsnR1OCjqVhJoRCs3b_cghZ_Y7i8c_0ZsR-kcE4X_tjx1ucHO5cJrkZs9XL1xglo"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9scyIsIml0ZW1zIjpbeyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMvYWNsL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzIiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDQU09In0seyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL2FjbC9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0FNPSJ9LHsia2luZCI6InN0b3JhZ2UjYnVja2V0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzIiwiZW50aXR5IjoicHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6IlJFQURFUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJ2aWV3ZXJzIn0sImV0YWciOiJDQU09In0seyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMvdXNlci1pbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9hY2wvdXNlci1pbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMyIsImVudGl0eSI6InVzZXItaW50ZWdyYXRpb25AZ2Nsb3VkLWdvbGFuZy1maXJlc3RvcmUtdGVzdHMuaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJyb2xlIjoiT1dORVIiLCJlbWFpbCI6ImludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIiwiZXRhZyI6IkNBTT0ifSx7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9kb21haW4tZ29vZ2xlLmNvbSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9hY2wvZG9tYWluLWdvb2dsZS5jb20iLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJlbnRpdHkiOiJkb21haW4tZ29vZ2xlLmNvbSIsInJvbGUiOiJSRUFERVIiLCJkb21haW4iOiJnb29nbGUuY29tIiwiZXRhZyI6IkNBTT0ifV19"
+ }
+ },
+ {
+ "ID": "ad0ba2871af45600",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/acl?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "c9dff7f46b3df0aa1bbccf636668360a/9507051921216763367;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/acl?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 400,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0"
+ ],
+ "Content-Length": [
+ "13087"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:59 GMT"
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:24:59 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051395000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "471383502717"
+ ],
+ "X-Google-Backends": [
+ "vrnc2:4232,/bns/yw/borg/yw/bns/blobstore2/bitpusher/132.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=G8ysW9WlIdXDhgSTua7ADg"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yw/borg/yw/bns/blobstore2/bitpusher/132.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yw/borg/yw/bns/blobstore2/bitpusher/132:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CP3elYXcDRoCGAYoATo_ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGM6ropHgHCIVMTE3MjM4MDU4ODYxOTM3NTE5MTQ0MOArSp8BEoIBeWEyOS5jLkVsb2xCcldWbUZlX1AxVDdUOHVpTXdFMHBZUjdTc2NVMDBFdEZkc2tSenBQY0NLWkhUeEZaYXI0Q25tZmR6bXFRLTNVV0kzOF9wdEx5VTZ2Z1Q3dlRBeW42Z3g4dUcyd0szSHIzaTZrV1JBZkozc1pNMGQ1allkNHpWQTAEOhZOT1RfQV9QRVJTSVNURU5UX1RPS0VO"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Upload-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UpVPdoAQNx8mY5oiRnxgWk2nkKFdrVTTRq29jCQvw3554R8GGx0yM4GUdPkPYoKGeP3BSqNKhpYLO9kbLMih062cmL5fA"
+ ]
+ },
+ "Body": "eyJlcnJvciI6eyJlcnJvcnMiOlt7ImRvbWFpbiI6Imdsb2JhbCIsInJlYXNvbiI6InJlcXVpcmVkIiwibWVzc2FnZSI6IkJ1Y2tldCBpcyByZXF1ZXN0ZXIgcGF5cyBidWNrZXQgYnV0IG5vIHVzZXIgcHJvamVjdCBwcm92aWRlZC4iLCJkZWJ1Z0luZm8iOiJjb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6VVNFUl9QUk9KRUNUX01JU1NJTkc6IEJ1Y2tldCBpcyBSZXF1ZXN0ZXIgUGF5cyBidWNrZXQgYnV0IG5vIGJpbGxpbmcgcHJvamVjdCBpZCBwcm92aWRlZCBmb3Igbm9uLW93bmVyLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5BY2Nlc3NDb250cm9sc0hlbHBlci5sb2FkQnVja2V0KEFjY2Vzc0NvbnRyb2xzSGVscGVyLmphdmE6MzAyKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuQWNjZXNzQ29udHJvbHNIZWxwZXIuZ2V0QWNsUmVzb3VyY2VGb3JSZXF1ZXN0KEFjY2Vzc0NvbnRyb2xzSGVscGVyLmphdmE6NzMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5MaXN0QWNscy5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoTGlzdEFjbHMuamF2YTo4NSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLkxpc3RBY2xzLmhhbmRsZVJlcXVlc3RSZWNlaXZlZChMaXN0QWNscy5qYXZhOjIwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmZyYW1ld29yay5SZXF1ZXN0SGFuZGxlci5oYW5kbGUoUmVxdWVzdEhhbmRsZXIuamF2YToyOTQpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uQWNjZXNzQ29udHJvbHNEZWxlZ2F0b3IubGlzdChBY2Nlc3NDb250cm9sc0RlbGVnYXRvci5qYXZhOjg5KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5ScGNSZWNlaXZlci5sYW1iZGEkcHJvY2Vzc1JlcXVlc3RBc3luYyQ0KFJwY1JlY2VpdmVyLmphdmE6MjAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5Bc3luY0V4ZWN1dG9yLmxhbWJkYSRzdWJtaXQkMChBc3luY0V4ZWN1dG9yLmphdmE6MjcyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoQ29udGV4dFJ1bm5hYmxlLmphdmE6NTApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlJDEucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM5KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo3Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5FeGVjdXRvcnMkUnVubmFibGVBZGFwdGVyLmNhbGwoRXhlY3V0b3JzLmphdmE6NTExKVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5GdXR1cmVUYXNrLnJ1bihGdXR1cmVUYXNrLmphdmE6MjY2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IucnVuV29ya2VyKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjExNDkpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvciRXb3JrZXIucnVuKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjYyNClcblx0YXQgamF2YS5sYW5nLlRocmVhZC5ydW4oVGhyZWFkLmphdmE6NzQ4KVxuQ2F1c2VkIGJ5OiBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbjogQnVja2V0IGlzIFJlcXVlc3RlciBQYXlzIGJ1Y2tldCBidXQgbm8gYmlsbGluZyBwcm9qZWN0IGlkIHByb3ZpZGVkIGZvciBub24tb3duZXIuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93T25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjI5MClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMSlcblx0Li4uIDE5IG1vcmVcblxuY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUuRmF1bHQ6IEltbXV0YWJsZUVycm9yRGVmaW5pdGlvbntiYXNlPVJFUVVJUkVELCBjYXRlZ29yeT1VU0VSX0VSUk9SLCBjYXVzZT1udWxsLCBkZWJ1Z0luZm89Y29tLmdvb2dsZS5uZXQucnBjMy5ScGNFeGNlcHRpb246IGNsb3VkLmJpZ3N0b3JlLlJlc3BvbnNlQ29kZS5FcnJvckNvZGU6OlVTRVJfUFJPSkVDVF9NSVNTSU5HOiBCdWNrZXQgaXMgUmVxdWVzdGVyIFBheXMgYnVja2V0IGJ1dCBubyBiaWxsaW5nIHByb2plY3QgaWQgcHJvdmlkZWQgZm9yIG5vbi1vd25lci5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udG9ScGMzRXhjZXB0aW9uKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MTM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuQWNjZXNzQ29udHJvbHNIZWxwZXIubG9hZEJ1Y2tldChBY2Nlc3NDb250cm9sc0hlbHBlci5qYXZhOjMwMilcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLkFjY2Vzc0NvbnRyb2xzSGVscGVyLmdldEFjbFJlc291cmNlRm9yUmVxdWVzdChBY2Nlc3NDb250cm9sc0hlbHBlci5qYXZhOjczKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuTGlzdEFjbHMuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKExpc3RBY2xzLmphdmE6ODUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5MaXN0QWNscy5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoTGlzdEFjbHMuamF2YToyMClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLkFjY2Vzc0NvbnRyb2xzRGVsZWdhdG9yLmxpc3QoQWNjZXNzQ29udHJvbHNEZWxlZ2F0b3IuamF2YTo4OSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uUnBjUmVjZWl2ZXIubGFtYmRhJHByb2Nlc3NSZXF1ZXN0QXN5bmMkNChScGNSZWNlaXZlci5qYXZhOjIwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uQXN5bmNFeGVjdXRvci5sYW1iZGEkc3VibWl0JDAoQXN5bmNFeGVjdXRvci5qYXZhOjI3Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KENvbnRleHRSdW5uYWJsZS5qYXZhOjUwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZSQxLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozOSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NzIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozNilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRXhlY3V0b3JzJFJ1bm5hYmxlQWRhcHRlci5jYWxsKEV4ZWN1dG9ycy5qYXZhOjUxMSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRnV0dXJlVGFzay5ydW4oRnV0dXJlVGFzay5qYXZhOjI2Nilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yLnJ1bldvcmtlcihUaHJlYWRQb29sRXhlY3V0b3IuamF2YToxMTQ5KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IkV29ya2VyLnJ1bihUaHJlYWRQb29sRXhlY3V0b3IuamF2YTo2MjQpXG5cdGF0IGphdmEubGFuZy5UaHJlYWQucnVuKFRocmVhZC5qYXZhOjc0OClcbkNhdXNlZCBieTogY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb246IEJ1Y2tldCBpcyBSZXF1ZXN0ZXIgUGF5cyBidWNrZXQgYnV0IG5vIGJpbGxpbmcgcHJvamVjdCBpZCBwcm92aWRlZCBmb3Igbm9uLW93bmVyLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxOSBtb3JlXG4sIGRvbWFpbj1nbG9iYWwsIGV4dGVuZGVkSGVscD1udWxsLCBodHRwSGVhZGVycz17fSwgaHR0cFN0YXR1cz1iYWRSZXF1ZXN0LCBpbnRlcm5hbFJlYXNvbj1SZWFzb257YXJndW1lbnRzPXt9LCBjYXVzZT1udWxsLCBjb2RlPWdkYXRhLkNvcmVFcnJvckRvbWFpbi5SRVFVSVJFRCwgY3JlYXRlZEJ5QmFja2VuZD10cnVlLCBkZWJ1Z01lc3NhZ2U9Y29tLmdvb2dsZS5uZXQucnBjMy5ScGNFeGNlcHRpb246IGNsb3VkLmJpZ3N0b3JlLlJlc3BvbnNlQ29kZS5FcnJvckNvZGU6OlVTRVJfUFJPSkVDVF9NSVNTSU5HOiBCdWNrZXQgaXMgUmVxdWVzdGVyIFBheXMgYnVja2V0IGJ1dCBubyBiaWxsaW5nIHByb2plY3QgaWQgcHJvdmlkZWQgZm9yIG5vbi1vd25lci5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udG9ScGMzRXhjZXB0aW9uKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MTM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuQWNjZXNzQ29udHJvbHNIZWxwZXIubG9hZEJ1Y2tldChBY2Nlc3NDb250cm9sc0hlbHBlci5qYXZhOjMwMilcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLkFjY2Vzc0NvbnRyb2xzSGVscGVyLmdldEFjbFJlc291cmNlRm9yUmVxdWVzdChBY2Nlc3NDb250cm9sc0hlbHBlci5qYXZhOjczKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuTGlzdEFjbHMuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKExpc3RBY2xzLmphdmE6ODUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5MaXN0QWNscy5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoTGlzdEFjbHMuamF2YToyMClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLkFjY2Vzc0NvbnRyb2xzRGVsZWdhdG9yLmxpc3QoQWNjZXNzQ29udHJvbHNEZWxlZ2F0b3IuamF2YTo4OSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uUnBjUmVjZWl2ZXIubGFtYmRhJHByb2Nlc3NSZXF1ZXN0QXN5bmMkNChScGNSZWNlaXZlci5qYXZhOjIwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uQXN5bmNFeGVjdXRvci5sYW1iZGEkc3VibWl0JDAoQXN5bmNFeGVjdXRvci5qYXZhOjI3Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KENvbnRleHRSdW5uYWJsZS5qYXZhOjUwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZSQxLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozOSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NzIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozNilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRXhlY3V0b3JzJFJ1bm5hYmxlQWRhcHRlci5jYWxsKEV4ZWN1dG9ycy5qYXZhOjUxMSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRnV0dXJlVGFzay5ydW4oRnV0dXJlVGFzay5qYXZhOjI2Nilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yLnJ1bldvcmtlcihUaHJlYWRQb29sRXhlY3V0b3IuamF2YToxMTQ5KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IkV29ya2VyLnJ1bihUaHJlYWRQb29sRXhlY3V0b3IuamF2YTo2MjQpXG5cdGF0IGphdmEubGFuZy5UaHJlYWQucnVuKFRocmVhZC5qYXZhOjc0OClcbkNhdXNlZCBieTogY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb246IEJ1Y2tldCBpcyBSZXF1ZXN0ZXIgUGF5cyBidWNrZXQgYnV0IG5vIGJpbGxpbmcgcHJvamVjdCBpZCBwcm92aWRlZCBmb3Igbm9uLW93bmVyLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxOSBtb3JlXG4sIGVycm9yUHJvdG9Db2RlPVJFUVVJUkVELCBlcnJvclByb3RvRG9tYWluPWdkYXRhLkNvcmVFcnJvckRvbWFpbiwgZmlsdGVyZWRNZXNzYWdlPW51bGwsIGxvY2F0aW9uPW51bGwsIG1lc3NhZ2U9QnVja2V0IGlzIHJlcXVlc3RlciBwYXlzIGJ1Y2tldCBidXQgbm8gdXNlciBwcm9qZWN0IHByb3ZpZGVkLiwgdW5uYW1lZEFyZ3VtZW50cz1bXX0sIGxvY2F0aW9uPW51bGwsIG1lc3NhZ2U9QnVja2V0IGlzIHJlcXVlc3RlciBwYXlzIGJ1Y2tldCBidXQgbm8gdXNlciBwcm9qZWN0IHByb3ZpZGVkLiwgcmVhc29uPXJlcXVpcmVkLCBycGNDb2RlPTQwMH0gQnVja2V0IGlzIHJlcXVlc3RlciBwYXlzIGJ1Y2tldCBidXQgbm8gdXNlciBwcm9qZWN0IHByb3ZpZGVkLjogY29tLmdvb2dsZS5uZXQucnBjMy5ScGNFeGNlcHRpb246IGNsb3VkLmJpZ3N0b3JlLlJlc3BvbnNlQ29kZS5FcnJvckNvZGU6OlVTRVJfUFJPSkVDVF9NSVNTSU5HOiBCdWNrZXQgaXMgUmVxdWVzdGVyIFBheXMgYnVja2V0IGJ1dCBubyBiaWxsaW5nIHByb2plY3QgaWQgcHJvdmlkZWQgZm9yIG5vbi1vd25lci5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udG9ScGMzRXhjZXB0aW9uKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MTM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuQWNjZXNzQ29udHJvbHNIZWxwZXIubG9hZEJ1Y2tldChBY2Nlc3NDb250cm9sc0hlbHBlci5qYXZhOjMwMilcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLkFjY2Vzc0NvbnRyb2xzSGVscGVyLmdldEFjbFJlc291cmNlRm9yUmVxdWVzdChBY2Nlc3NDb250cm9sc0hlbHBlci5qYXZhOjczKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuTGlzdEFjbHMuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKExpc3RBY2xzLmphdmE6ODUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5MaXN0QWNscy5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoTGlzdEFjbHMuamF2YToyMClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLkFjY2Vzc0NvbnRyb2xzRGVsZWdhdG9yLmxpc3QoQWNjZXNzQ29udHJvbHNEZWxlZ2F0b3IuamF2YTo4OSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uUnBjUmVjZWl2ZXIubGFtYmRhJHByb2Nlc3NSZXF1ZXN0QXN5bmMkNChScGNSZWNlaXZlci5qYXZhOjIwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uQXN5bmNFeGVjdXRvci5sYW1iZGEkc3VibWl0JDAoQXN5bmNFeGVjdXRvci5qYXZhOjI3Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KENvbnRleHRSdW5uYWJsZS5qYXZhOjUwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZSQxLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozOSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NzIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozNilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRXhlY3V0b3JzJFJ1bm5hYmxlQWRhcHRlci5jYWxsKEV4ZWN1dG9ycy5qYXZhOjUxMSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRnV0dXJlVGFzay5ydW4oRnV0dXJlVGFzay5qYXZhOjI2Nilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yLnJ1bldvcmtlcihUaHJlYWRQb29sRXhlY3V0b3IuamF2YToxMTQ5KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IkV29ya2VyLnJ1bihUaHJlYWRQb29sRXhlY3V0b3IuamF2YTo2MjQpXG5cdGF0IGphdmEubGFuZy5UaHJlYWQucnVuKFRocmVhZC5qYXZhOjc0OClcbkNhdXNlZCBieTogY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb246IEJ1Y2tldCBpcyBSZXF1ZXN0ZXIgUGF5cyBidWNrZXQgYnV0IG5vIGJpbGxpbmcgcHJvamVjdCBpZCBwcm92aWRlZCBmb3Igbm9uLW93bmVyLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxOSBtb3JlXG5cblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUuRXJyb3JDb2xsZWN0b3IudG9GYXVsdChFcnJvckNvbGxlY3Rvci5qYXZhOjU0KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIucmVzdC5hZGFwdGVyLnJvc3kuUm9zeUVycm9yQ29udmVydGVyLnRvRmF1bHQoUm9zeUVycm9yQ29udmVydGVyLmphdmE6NjcpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5yZXN0LmFkYXB0ZXIucm9zeS5Sb3N5SGFuZGxlciQyLmNhbGwoUm9zeUhhbmRsZXIuamF2YToyNTgpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5yZXN0LmFkYXB0ZXIucm9zeS5Sb3N5SGFuZGxlciQyLmNhbGwoUm9zeUhhbmRsZXIuamF2YToyMzgpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLnV0aWwuQ2FsbGFibGVGdXR1cmUucnVuKENhbGxhYmxlRnV0dXJlLmphdmE6NjIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5EaXJlY3RFeGVjdXRvci5leGVjdXRlKERpcmVjdEV4ZWN1dG9yLmphdmE6MzApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5leGVjdXRlTGlzdGVuZXIoQWJzdHJhY3RGdXR1cmUuamF2YToxMTQzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuY29tcGxldGUoQWJzdHJhY3RGdXR1cmUuamF2YTo5NjMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5zZXQoQWJzdHJhY3RGdXR1cmUuamF2YTo3MzEpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLnV0aWwuQ2FsbGFibGVGdXR1cmUucnVuKENhbGxhYmxlRnV0dXJlLmphdmE6NjIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5EaXJlY3RFeGVjdXRvci5leGVjdXRlKERpcmVjdEV4ZWN1dG9yLmphdmE6MzApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5leGVjdXRlTGlzdGVuZXIoQWJzdHJhY3RGdXR1cmUuamF2YToxMTQzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuY29tcGxldGUoQWJzdHJhY3RGdXR1cmUuamF2YTo5NjMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5zZXQoQWJzdHJhY3RGdXR1cmUuamF2YTo3MzEpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLnV0aWwuQ2FsbGFibGVGdXR1cmUucnVuKENhbGxhYmxlRnV0dXJlLmphdmE6NjIpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci50aHJlYWQuVGhyZWFkVHJhY2tlcnMkVGhyZWFkVHJhY2tpbmdSdW5uYWJsZS5ydW4oVGhyZWFkVHJhY2tlcnMuamF2YToxMjYpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkVHJhY2VDb250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KFRyYWNlQ29udGV4dC5qYXZhOjQ1NSlcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnNlcnZlci5Db21tb25Nb2R1bGUkQ29udGV4dENhcnJ5aW5nRXhlY3V0b3JTZXJ2aWNlJDEucnVuSW5Db250ZXh0KENvbW1vbk1vZHVsZS5qYXZhOjg0Nilcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRUcmFjZUNvbnRleHRSdW5uYWJsZSQxLnJ1bihUcmFjZUNvbnRleHQuamF2YTo0NjIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkQWJzdHJhY3RUcmFjZUNvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKFRyYWNlQ29udGV4dC5qYXZhOjMyMSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRBYnN0cmFjdFRyYWNlQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChUcmFjZUNvbnRleHQuamF2YTozMTMpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkVHJhY2VDb250ZXh0UnVubmFibGUucnVuKFRyYWNlQ29udGV4dC5qYXZhOjQ1OSlcblx0YXQgY29tLmdvb2dsZS5nc2UuaW50ZXJuYWwuRGlzcGF0Y2hRdWV1ZUltcGwkV29ya2VyVGhyZWFkLnJ1bihEaXNwYXRjaFF1ZXVlSW1wbC5qYXZhOjQwMylcbiJ9XSwiY29kZSI6NDAwLCJtZXNzYWdlIjoiQnVja2V0IGlzIHJlcXVlc3RlciBwYXlzIGJ1Y2tldCBidXQgbm8gdXNlciBwcm9qZWN0IHByb3ZpZGVkLiJ9fQ=="
+ }
+ },
+ {
+ "ID": "fbc79d3e312230b2",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/acl?alt=json\u0026prettyPrint=false\u0026userProject=gcloud-golang-firestore-tests",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "6aa77ecbf8f3d32317e07bd499079dc0/11025125860075870854;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/acl?alt=json\u0026prettyPrint=false\u0026userProject=gcloud-golang-firestore-tests"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0, must-revalidate, no-transform"
+ ],
+ "Content-Length": [
+ "2358"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:24:59 GMT"
+ ],
+ "Etag": [
+ "CAM="
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:24:59 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051395000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "471383502717"
+ ],
+ "X-Google-Backends": [
+ "vrbo128:4296,/bns/yv/borg/yv/bns/blobstore2/bitpusher/384.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=G8ysW73lLNiiggSxqYa4Dw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/384.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/384:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CP3elYXcDRoCGAYoATo_ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGM6ropHgHCIVMTE3MjM4MDU4ODYxOTM3NTE5MTQ0MOArSp8BEoIBeWEyOS5jLkVsb2xCcldWbUZlX1AxVDdUOHVpTXdFMHBZUjdTc2NVMDBFdEZkc2tSenBQY0NLWkhUeEZaYXI0Q25tZmR6bXFRLTNVV0kzOF9wdEx5VTZ2Z1Q3dlRBeW42Z3g4dUcyd0szSHIzaTZrV1JBZkozc1pNMGQ1allkNHpWQTAEOhZOT1RfQV9QRVJTSVNURU5UX1RPS0VO"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Urb__NQ3g47uGEfOrLr43toLu4FlQw7kkLcnl-COQ--VPh4esMxEf4Sesu6sfGKnw5u8WTCQzQ0j3mgfoeReN5DW1PhlQ"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9scyIsIml0ZW1zIjpbeyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMvYWNsL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzIiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDQU09In0seyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL2FjbC9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0FNPSJ9LHsia2luZCI6InN0b3JhZ2UjYnVja2V0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzIiwiZW50aXR5IjoicHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6IlJFQURFUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJ2aWV3ZXJzIn0sImV0YWciOiJDQU09In0seyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMvdXNlci1pbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9hY2wvdXNlci1pbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMyIsImVudGl0eSI6InVzZXItaW50ZWdyYXRpb25AZ2Nsb3VkLWdvbGFuZy1maXJlc3RvcmUtdGVzdHMuaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJyb2xlIjoiT1dORVIiLCJlbWFpbCI6ImludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIiwiZXRhZyI6IkNBTT0ifSx7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9kb21haW4tZ29vZ2xlLmNvbSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9hY2wvZG9tYWluLWdvb2dsZS5jb20iLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJlbnRpdHkiOiJkb21haW4tZ29vZ2xlLmNvbSIsInJvbGUiOiJSRUFERVIiLCJkb21haW4iOiJnb29nbGUuY29tIiwiZXRhZyI6IkNBTT0ifV19"
+ }
+ },
+ {
+ "ID": "8ff0e0d3db0c20a4",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/acl?alt=json\u0026prettyPrint=false\u0026userProject=veener-jba",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "bdc8a5e50646d0f066f3d3c96d71c25e/12615537764126244901;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/acl?alt=json\u0026prettyPrint=false\u0026userProject=veener-jba"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 403,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0"
+ ],
+ "Content-Length": [
+ "13943"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:00 GMT"
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:25:00 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051395000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "471383502717"
+ ],
+ "X-Google-Backends": [
+ "vrmm19:4379,/bns/yr/borg/yr/bns/blobstore2/bitpusher/52.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=G8ysW-XWMYT7kAOk1pngDA"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/52.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/52:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CP3elYXcDRoCGAYoATo_ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGM6ropHgHCIVMTE3MjM4MDU4ODYxOTM3NTE5MTQ0MOArSp8BEoIBeWEyOS5jLkVsb2xCcldWbUZlX1AxVDdUOHVpTXdFMHBZUjdTc2NVMDBFdEZkc2tSenBQY0NLWkhUeEZaYXI0Q25tZmR6bXFRLTNVV0kzOF9wdEx5VTZ2Z1Q3dlRBeW42Z3g4dUcyd0szSHIzaTZrV1JBZkozc1pNMGQ1allkNHpWQTAEOhZOT1RfQV9QRVJTSVNURU5UX1RPS0VO"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Upload-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Up4dLfyWyLDoGO56z8m9cKIZ3k2wRD5rnKGG7y--EG92D6uEWqzCq--42QVg9CHbcNtTAYUb4Qif8m7V5O-8s5jW9v63A"
+ ]
+ },
+ "Body": "eyJlcnJvciI6eyJlcnJvcnMiOlt7ImRvbWFpbiI6Imdsb2JhbCIsInJlYXNvbiI6ImZvcmJpZGRlbiIsIm1lc3NhZ2UiOiJpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLiIsImRlYnVnSW5mbyI6ImNvbS5nb29nbGUubmV0LnJwYzMuUnBjRXhjZXB0aW9uOiBjbG91ZC5iaWdzdG9yZS5SZXNwb25zZUNvZGUuRXJyb3JDb2RlOjpVU0VSX1BST0pFQ1RfQUNDRVNTX0RFTklFRDogaW50ZWdyYXRpb25AZ2Nsb3VkLWdvbGFuZy1maXJlc3RvcmUtdGVzdHMuaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20gZG9lcyBub3QgaGF2ZSBzZXJ2aWNldXNhZ2Uuc2VydmljZXMudXNlIGFjY2VzcyB0byBwcm9qZWN0IDY0MjA4MDkxODEwMS5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udG9ScGMzRXhjZXB0aW9uKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MTM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuQWNjZXNzQ29udHJvbHNIZWxwZXIubG9hZEJ1Y2tldChBY2Nlc3NDb250cm9sc0hlbHBlci5qYXZhOjMwMilcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLkFjY2Vzc0NvbnRyb2xzSGVscGVyLmdldEFjbFJlc291cmNlRm9yUmVxdWVzdChBY2Nlc3NDb250cm9sc0hlbHBlci5qYXZhOjczKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuTGlzdEFjbHMuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKExpc3RBY2xzLmphdmE6ODUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5MaXN0QWNscy5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoTGlzdEFjbHMuamF2YToyMClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLkFjY2Vzc0NvbnRyb2xzRGVsZWdhdG9yLmxpc3QoQWNjZXNzQ29udHJvbHNEZWxlZ2F0b3IuamF2YTo4OSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uUnBjUmVjZWl2ZXIubGFtYmRhJHByb2Nlc3NSZXF1ZXN0QXN5bmMkNChScGNSZWNlaXZlci5qYXZhOjIwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uQXN5bmNFeGVjdXRvci5sYW1iZGEkc3VibWl0JDAoQXN5bmNFeGVjdXRvci5qYXZhOjI3Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KENvbnRleHRSdW5uYWJsZS5qYXZhOjUwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZSQxLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozOSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NzIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozNilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRXhlY3V0b3JzJFJ1bm5hYmxlQWRhcHRlci5jYWxsKEV4ZWN1dG9ycy5qYXZhOjUxMSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRnV0dXJlVGFzay5ydW4oRnV0dXJlVGFzay5qYXZhOjI2Nilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yLnJ1bldvcmtlcihUaHJlYWRQb29sRXhlY3V0b3IuamF2YToxMTQ5KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IkV29ya2VyLnJ1bihUaHJlYWRQb29sRXhlY3V0b3IuamF2YTo2MjQpXG5cdGF0IGphdmEubGFuZy5UaHJlYWQucnVuKFRocmVhZC5qYXZhOjc0OClcbkNhdXNlZCBieTogY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb246IGludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIGRvZXMgbm90IGhhdmUgc2VydmljZXVzYWdlLnNlcnZpY2VzLnVzZSBhY2Nlc3MgdG8gcHJvamVjdCA2NDIwODA5MTgxMDEuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93T25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjI5MClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMSlcblx0Li4uIDE5IG1vcmVcblxuY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUuRmF1bHQ6IEltbXV0YWJsZUVycm9yRGVmaW5pdGlvbntiYXNlPUZPUkJJRERFTiwgY2F0ZWdvcnk9VVNFUl9FUlJPUiwgY2F1c2U9bnVsbCwgZGVidWdJbmZvPWNvbS5nb29nbGUubmV0LnJwYzMuUnBjRXhjZXB0aW9uOiBjbG91ZC5iaWdzdG9yZS5SZXNwb25zZUNvZGUuRXJyb3JDb2RlOjpVU0VSX1BST0pFQ1RfQUNDRVNTX0RFTklFRDogaW50ZWdyYXRpb25AZ2Nsb3VkLWdvbGFuZy1maXJlc3RvcmUtdGVzdHMuaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20gZG9lcyBub3QgaGF2ZSBzZXJ2aWNldXNhZ2Uuc2VydmljZXMudXNlIGFjY2VzcyB0byBwcm9qZWN0IDY0MjA4MDkxODEwMS5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udG9ScGMzRXhjZXB0aW9uKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MTM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuQWNjZXNzQ29udHJvbHNIZWxwZXIubG9hZEJ1Y2tldChBY2Nlc3NDb250cm9sc0hlbHBlci5qYXZhOjMwMilcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLkFjY2Vzc0NvbnRyb2xzSGVscGVyLmdldEFjbFJlc291cmNlRm9yUmVxdWVzdChBY2Nlc3NDb250cm9sc0hlbHBlci5qYXZhOjczKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuTGlzdEFjbHMuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKExpc3RBY2xzLmphdmE6ODUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5MaXN0QWNscy5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoTGlzdEFjbHMuamF2YToyMClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLkFjY2Vzc0NvbnRyb2xzRGVsZWdhdG9yLmxpc3QoQWNjZXNzQ29udHJvbHNEZWxlZ2F0b3IuamF2YTo4OSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uUnBjUmVjZWl2ZXIubGFtYmRhJHByb2Nlc3NSZXF1ZXN0QXN5bmMkNChScGNSZWNlaXZlci5qYXZhOjIwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uQXN5bmNFeGVjdXRvci5sYW1iZGEkc3VibWl0JDAoQXN5bmNFeGVjdXRvci5qYXZhOjI3Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KENvbnRleHRSdW5uYWJsZS5qYXZhOjUwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZSQxLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozOSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NzIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozNilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRXhlY3V0b3JzJFJ1bm5hYmxlQWRhcHRlci5jYWxsKEV4ZWN1dG9ycy5qYXZhOjUxMSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRnV0dXJlVGFzay5ydW4oRnV0dXJlVGFzay5qYXZhOjI2Nilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yLnJ1bldvcmtlcihUaHJlYWRQb29sRXhlY3V0b3IuamF2YToxMTQ5KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IkV29ya2VyLnJ1bihUaHJlYWRQb29sRXhlY3V0b3IuamF2YTo2MjQpXG5cdGF0IGphdmEubGFuZy5UaHJlYWQucnVuKFRocmVhZC5qYXZhOjc0OClcbkNhdXNlZCBieTogY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb246IGludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIGRvZXMgbm90IGhhdmUgc2VydmljZXVzYWdlLnNlcnZpY2VzLnVzZSBhY2Nlc3MgdG8gcHJvamVjdCA2NDIwODA5MTgxMDEuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93T25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjI5MClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMSlcblx0Li4uIDE5IG1vcmVcbiwgZG9tYWluPWdsb2JhbCwgZXh0ZW5kZWRIZWxwPW51bGwsIGh0dHBIZWFkZXJzPXt9LCBodHRwU3RhdHVzPWZvcmJpZGRlbiwgaW50ZXJuYWxSZWFzb249UmVhc29ue2FyZ3VtZW50cz17fSwgY2F1c2U9bnVsbCwgY29kZT1nZGF0YS5Db3JlRXJyb3JEb21haW4uRk9SQklEREVOLCBjcmVhdGVkQnlCYWNrZW5kPXRydWUsIGRlYnVnTWVzc2FnZT1jb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6VVNFUl9QUk9KRUNUX0FDQ0VTU19ERU5JRUQ6IGludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIGRvZXMgbm90IGhhdmUgc2VydmljZXVzYWdlLnNlcnZpY2VzLnVzZSBhY2Nlc3MgdG8gcHJvamVjdCA2NDIwODA5MTgxMDEuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRvUnBjM0V4Y2VwdGlvbihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjEzNSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLkFjY2Vzc0NvbnRyb2xzSGVscGVyLmxvYWRCdWNrZXQoQWNjZXNzQ29udHJvbHNIZWxwZXIuamF2YTozMDIpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5BY2Nlc3NDb250cm9sc0hlbHBlci5nZXRBY2xSZXNvdXJjZUZvclJlcXVlc3QoQWNjZXNzQ29udHJvbHNIZWxwZXIuamF2YTo3Mylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLkxpc3RBY2xzLmhhbmRsZVJlcXVlc3RSZWNlaXZlZChMaXN0QWNscy5qYXZhOjg1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuTGlzdEFjbHMuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKExpc3RBY2xzLmphdmE6MjApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5BY2Nlc3NDb250cm9sc0RlbGVnYXRvci5saXN0KEFjY2Vzc0NvbnRyb2xzRGVsZWdhdG9yLmphdmE6ODkpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxOSBtb3JlXG4sIGVycm9yUHJvdG9Db2RlPUZPUkJJRERFTiwgZXJyb3JQcm90b0RvbWFpbj1nZGF0YS5Db3JlRXJyb3JEb21haW4sIGZpbHRlcmVkTWVzc2FnZT1udWxsLCBsb2NhdGlvbj1udWxsLCBtZXNzYWdlPWludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIGRvZXMgbm90IGhhdmUgc2VydmljZXVzYWdlLnNlcnZpY2VzLnVzZSBhY2Nlc3MgdG8gcHJvamVjdCA2NDIwODA5MTgxMDEuLCB1bm5hbWVkQXJndW1lbnRzPVtdfSwgbG9jYXRpb249bnVsbCwgbWVzc2FnZT1pbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLiwgcmVhc29uPWZvcmJpZGRlbiwgcnBjQ29kZT00MDN9IGludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIGRvZXMgbm90IGhhdmUgc2VydmljZXVzYWdlLnNlcnZpY2VzLnVzZSBhY2Nlc3MgdG8gcHJvamVjdCA2NDIwODA5MTgxMDEuOiBjb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6VVNFUl9QUk9KRUNUX0FDQ0VTU19ERU5JRUQ6IGludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIGRvZXMgbm90IGhhdmUgc2VydmljZXVzYWdlLnNlcnZpY2VzLnVzZSBhY2Nlc3MgdG8gcHJvamVjdCA2NDIwODA5MTgxMDEuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRvUnBjM0V4Y2VwdGlvbihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjEzNSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLkFjY2Vzc0NvbnRyb2xzSGVscGVyLmxvYWRCdWNrZXQoQWNjZXNzQ29udHJvbHNIZWxwZXIuamF2YTozMDIpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5BY2Nlc3NDb250cm9sc0hlbHBlci5nZXRBY2xSZXNvdXJjZUZvclJlcXVlc3QoQWNjZXNzQ29udHJvbHNIZWxwZXIuamF2YTo3Mylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLkxpc3RBY2xzLmhhbmRsZVJlcXVlc3RSZWNlaXZlZChMaXN0QWNscy5qYXZhOjg1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuTGlzdEFjbHMuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKExpc3RBY2xzLmphdmE6MjApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5BY2Nlc3NDb250cm9sc0RlbGVnYXRvci5saXN0KEFjY2Vzc0NvbnRyb2xzRGVsZWdhdG9yLmphdmE6ODkpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxOSBtb3JlXG5cblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUuRXJyb3JDb2xsZWN0b3IudG9GYXVsdChFcnJvckNvbGxlY3Rvci5qYXZhOjU0KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIucmVzdC5hZGFwdGVyLnJvc3kuUm9zeUVycm9yQ29udmVydGVyLnRvRmF1bHQoUm9zeUVycm9yQ29udmVydGVyLmphdmE6NjcpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5yZXN0LmFkYXB0ZXIucm9zeS5Sb3N5SGFuZGxlciQyLmNhbGwoUm9zeUhhbmRsZXIuamF2YToyNTgpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5yZXN0LmFkYXB0ZXIucm9zeS5Sb3N5SGFuZGxlciQyLmNhbGwoUm9zeUhhbmRsZXIuamF2YToyMzgpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLnV0aWwuQ2FsbGFibGVGdXR1cmUucnVuKENhbGxhYmxlRnV0dXJlLmphdmE6NjIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5EaXJlY3RFeGVjdXRvci5leGVjdXRlKERpcmVjdEV4ZWN1dG9yLmphdmE6MzApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5leGVjdXRlTGlzdGVuZXIoQWJzdHJhY3RGdXR1cmUuamF2YToxMTQzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuY29tcGxldGUoQWJzdHJhY3RGdXR1cmUuamF2YTo5NjMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5zZXQoQWJzdHJhY3RGdXR1cmUuamF2YTo3MzEpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLnV0aWwuQ2FsbGFibGVGdXR1cmUucnVuKENhbGxhYmxlRnV0dXJlLmphdmE6NjIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5EaXJlY3RFeGVjdXRvci5leGVjdXRlKERpcmVjdEV4ZWN1dG9yLmphdmE6MzApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5leGVjdXRlTGlzdGVuZXIoQWJzdHJhY3RGdXR1cmUuamF2YToxMTQzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuY29tcGxldGUoQWJzdHJhY3RGdXR1cmUuamF2YTo5NjMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5zZXQoQWJzdHJhY3RGdXR1cmUuamF2YTo3MzEpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLnV0aWwuQ2FsbGFibGVGdXR1cmUucnVuKENhbGxhYmxlRnV0dXJlLmphdmE6NjIpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci50aHJlYWQuVGhyZWFkVHJhY2tlcnMkVGhyZWFkVHJhY2tpbmdSdW5uYWJsZS5ydW4oVGhyZWFkVHJhY2tlcnMuamF2YToxMjYpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkVHJhY2VDb250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KFRyYWNlQ29udGV4dC5qYXZhOjQ1NSlcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnNlcnZlci5Db21tb25Nb2R1bGUkQ29udGV4dENhcnJ5aW5nRXhlY3V0b3JTZXJ2aWNlJDEucnVuSW5Db250ZXh0KENvbW1vbk1vZHVsZS5qYXZhOjg0Nilcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRUcmFjZUNvbnRleHRSdW5uYWJsZSQxLnJ1bihUcmFjZUNvbnRleHQuamF2YTo0NjIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkQWJzdHJhY3RUcmFjZUNvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKFRyYWNlQ29udGV4dC5qYXZhOjMyMSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRBYnN0cmFjdFRyYWNlQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChUcmFjZUNvbnRleHQuamF2YTozMTMpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkVHJhY2VDb250ZXh0UnVubmFibGUucnVuKFRyYWNlQ29udGV4dC5qYXZhOjQ1OSlcblx0YXQgY29tLmdvb2dsZS5nc2UuaW50ZXJuYWwuRGlzcGF0Y2hRdWV1ZUltcGwkV29ya2VyVGhyZWFkLnJ1bihEaXNwYXRjaFF1ZXVlSW1wbC5qYXZhOjQwMylcbiJ9XSwiY29kZSI6NDAzLCJtZXNzYWdlIjoiaW50ZWdyYXRpb25AZ2Nsb3VkLWdvbGFuZy1maXJlc3RvcmUtdGVzdHMuaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20gZG9lcyBub3QgaGF2ZSBzZXJ2aWNldXNhZ2Uuc2VydmljZXMudXNlIGFjY2VzcyB0byBwcm9qZWN0IDY0MjA4MDkxODEwMS4ifX0="
+ }
+ },
+ {
+ "ID": "a482ab45717781c9",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/acl/domain-google.com?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "3e8fda45931e40ef507c08cfe5a4d675/14205949668193461699;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/acl/domain-google.com?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 204,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "0"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:01 GMT"
+ ],
+ "Etag": [
+ "CAQ="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051395000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrdv10:4196,/bns/yr/borg/yr/bns/blobstore2/bitpusher/13.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=HMysW7nnAc7xkAPuvp3IAg"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/13.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/13:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATpxChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4CtK4wESxgF5YTI5LmMuRW93QkpRWVNNdC1OVDFNYTJvWXBrbG1qcDlJMlZaUFZ5bFl5Z2Q3Nk5tQXlXbWR3WVBoMm00dGI3ZmZjOUlzcTU4MmVFcFBhNzhNWGpNZmIzaE9WTE9xRHpNTUFfTG9NQXVJZkdkMGgzSWowZ1dxdW5DS1g3Qk1mQlJxM001TUtMMXBHOWNyU0ZBT29lVkZpTDhpWlBsUDI0VjE5THdzZ0d1ZnVrQTFtVzVJcTJUUkVXeWQyNjRKZC1lS2UxdTAwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Uqq7-AXWbJ0OfAwZWNX54cXmSHu9KZetg5qN7jzZYUwihM1Q9OZ-NssVvQwAjUhAUaOA2FZ2gFK919FB3RX8_XohAQlqA"
+ ]
+ },
+ "Body": ""
+ }
+ },
+ {
+ "ID": "8d610a271816662c",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/acl/domain-google.com?alt=json\u0026prettyPrint=false\u0026userProject=dulcet-port-762",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "8616123ddfd273b957e5fab502ff479b/15796360468454083426;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/acl/domain-google.com?alt=json\u0026prettyPrint=false\u0026userProject=dulcet-port-762"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 404,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0"
+ ],
+ "Content-Length": [
+ "2911"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:01 GMT"
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:25:01 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051389000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vngv135:4098,/bns/yw/borg/yw/bns/blobstore2/bitpusher/222.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=HcysW7PZLIXohQTO7ZzgCw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yw/borg/yw/bns/blobstore2/bitpusher/222.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yw/borg/yw/bns/blobstore2/bitpusher/222:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATpxChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4CtK4wESxgF5YTI5LmMuRW93QkpRWVNNdC1OVDFNYTJvWXBrbG1qcDlJMlZaUFZ5bFl5Z2Q3Nk5tQXlXbWR3WVBoMm00dGI3ZmZjOUlzcTU4MmVFcFBhNzhNWGpNZmIzaE9WTE9xRHpNTUFfTG9NQXVJZkdkMGgzSWowZ1dxdW5DS1g3Qk1mQlJxM001TUtMMXBHOWNyU0ZBT29lVkZpTDhpWlBsUDI0VjE5THdzZ0d1ZnVrQTFtVzVJcTJUUkVXeWQyNjRKZC1lS2UxdTAwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Upload-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UoshQyC_SknxM5jDHjC2fHZEznd9i3BMQptowju6Ij-NvIoJet5fCn7gQBeLpZJPvyjGLrRfJcYdpM9aQPkSHmfDylkTw"
+ ]
+ },
+ "Body": "eyJlcnJvciI6eyJlcnJvcnMiOlt7ImRvbWFpbiI6Imdsb2JhbCIsInJlYXNvbiI6Im5vdEZvdW5kIiwibWVzc2FnZSI6Ik5vdCBGb3VuZCIsImRlYnVnSW5mbyI6ImNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLkZhdWx0OiBJbW11dGFibGVFcnJvckRlZmluaXRpb257YmFzZT1OT1RfRk9VTkQsIGNhdGVnb3J5PVVTRVJfRVJST1IsIGNhdXNlPW51bGwsIGRlYnVnSW5mbz1udWxsLCBkb21haW49Z2xvYmFsLCBleHRlbmRlZEhlbHA9bnVsbCwgaHR0cEhlYWRlcnM9e30sIGh0dHBTdGF0dXM9bm90Rm91bmQsIGludGVybmFsUmVhc29uPVJlYXNvbnthcmd1bWVudHM9e30sIGNhdXNlPW51bGwsIGNvZGU9Z2RhdGEuQ29yZUVycm9yRG9tYWluLk5PVF9GT1VORCwgY3JlYXRlZEJ5QmFja2VuZD10cnVlLCBkZWJ1Z01lc3NhZ2U9bnVsbCwgZXJyb3JQcm90b0NvZGU9Tk9UX0ZPVU5ELCBlcnJvclByb3RvRG9tYWluPWdkYXRhLkNvcmVFcnJvckRvbWFpbiwgZmlsdGVyZWRNZXNzYWdlPW51bGwsIGxvY2F0aW9uPWVudGl0eS5yZXNvdXJjZV9pZC5zY29wZSwgbWVzc2FnZT1udWxsLCB1bm5hbWVkQXJndW1lbnRzPVtdfSwgbG9jYXRpb249ZW50aXR5LnJlc291cmNlX2lkLnNjb3BlLCBtZXNzYWdlPU5vdCBGb3VuZCwgcmVhc29uPW5vdEZvdW5kLCBycGNDb2RlPTQwNH0gTm90IEZvdW5kXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLkVycm9yQ29sbGVjdG9yLnRvRmF1bHQoRXJyb3JDb2xsZWN0b3IuamF2YTo1NClcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnJlc3QuYWRhcHRlci5yb3N5LlJvc3lFcnJvckNvbnZlcnRlci50b0ZhdWx0KFJvc3lFcnJvckNvbnZlcnRlci5qYXZhOjY3KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIucmVzdC5hZGFwdGVyLnJvc3kuUm9zeUhhbmRsZXIkMi5jYWxsKFJvc3lIYW5kbGVyLmphdmE6MjU4KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIucmVzdC5hZGFwdGVyLnJvc3kuUm9zeUhhbmRsZXIkMi5jYWxsKFJvc3lIYW5kbGVyLmphdmE6MjM4KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS51dGlsLkNhbGxhYmxlRnV0dXJlLnJ1bihDYWxsYWJsZUZ1dHVyZS5qYXZhOjYyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuRGlyZWN0RXhlY3V0b3IuZXhlY3V0ZShEaXJlY3RFeGVjdXRvci5qYXZhOjMwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuZXhlY3V0ZUxpc3RlbmVyKEFic3RyYWN0RnV0dXJlLmphdmE6MTE0Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmNvbXBsZXRlKEFic3RyYWN0RnV0dXJlLmphdmE6OTYzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuc2V0KEFic3RyYWN0RnV0dXJlLmphdmE6NzMxKVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS51dGlsLkNhbGxhYmxlRnV0dXJlLnJ1bihDYWxsYWJsZUZ1dHVyZS5qYXZhOjYyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuRGlyZWN0RXhlY3V0b3IuZXhlY3V0ZShEaXJlY3RFeGVjdXRvci5qYXZhOjMwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuZXhlY3V0ZUxpc3RlbmVyKEFic3RyYWN0RnV0dXJlLmphdmE6MTE0Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmNvbXBsZXRlKEFic3RyYWN0RnV0dXJlLmphdmE6OTYzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuc2V0KEFic3RyYWN0RnV0dXJlLmphdmE6NzMxKVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS51dGlsLkNhbGxhYmxlRnV0dXJlLnJ1bihDYWxsYWJsZUZ1dHVyZS5qYXZhOjYyKVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIudGhyZWFkLlRocmVhZFRyYWNrZXJzJFRocmVhZFRyYWNraW5nUnVubmFibGUucnVuKFRocmVhZFRyYWNrZXJzLmphdmE6MTI2KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JFRyYWNlQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChUcmFjZUNvbnRleHQuamF2YTo0NTUpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5zZXJ2ZXIuQ29tbW9uTW9kdWxlJENvbnRleHRDYXJyeWluZ0V4ZWN1dG9yU2VydmljZSQxLnJ1bkluQ29udGV4dChDb21tb25Nb2R1bGUuamF2YTo4NDYpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkVHJhY2VDb250ZXh0UnVubmFibGUkMS5ydW4oVHJhY2VDb250ZXh0LmphdmE6NDYyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JEFic3RyYWN0VHJhY2VDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihUcmFjZUNvbnRleHQuamF2YTozMjEpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkQWJzdHJhY3RUcmFjZUNvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoVHJhY2VDb250ZXh0LmphdmE6MzEzKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JFRyYWNlQ29udGV4dFJ1bm5hYmxlLnJ1bihUcmFjZUNvbnRleHQuamF2YTo0NTkpXG5cdGF0IGNvbS5nb29nbGUuZ3NlLmludGVybmFsLkRpc3BhdGNoUXVldWVJbXBsJFdvcmtlclRocmVhZC5ydW4oRGlzcGF0Y2hRdWV1ZUltcGwuamF2YTo0MDMpXG4ifV0sImNvZGUiOjQwNCwibWVzc2FnZSI6Ik5vdCBGb3VuZCJ9fQ=="
+ }
+ },
+ {
+ "ID": "da83794caa4cf088",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/acl/domain-google.com?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "16b54007f6478160a8f0ca7d0ea6dfb9/17386490901839491073;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/acl/domain-google.com?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 400,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0"
+ ],
+ "Content-Length": [
+ "13131"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:02 GMT"
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:25:02 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051395000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "471383502717"
+ ],
+ "X-Google-Backends": [
+ "vrpa10:4240,/bns/yr/borg/yr/bns/blobstore2/bitpusher/102.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=HsysW8V0zfXhBJuDq9AG"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/102.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/102:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CP3elYXcDRoCGAYoATo_ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGM6ropHgHCIVMTE3MjM4MDU4ODYxOTM3NTE5MTQ0MOArSp8BEoIBeWEyOS5jLkVsb2xCcldWbUZlX1AxVDdUOHVpTXdFMHBZUjdTc2NVMDBFdEZkc2tSenBQY0NLWkhUeEZaYXI0Q25tZmR6bXFRLTNVV0kzOF9wdEx5VTZ2Z1Q3dlRBeW42Z3g4dUcyd0szSHIzaTZrV1JBZkozc1pNMGQ1allkNHpWQTAEOhZOT1RfQV9QRVJTSVNURU5UX1RPS0VO"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Upload-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UrqtMgL_uL-y75dcnPJSXmWL_i3QakTUsacyGhn2Jerx2hBwWeSxAvHsILqt9BUkmRDPBgnR-FgNxtaPpBH_4UIYWajlQ"
+ ]
+ },
+ "Body": "eyJlcnJvciI6eyJlcnJvcnMiOlt7ImRvbWFpbiI6Imdsb2JhbCIsInJlYXNvbiI6InJlcXVpcmVkIiwibWVzc2FnZSI6IkJ1Y2tldCBpcyByZXF1ZXN0ZXIgcGF5cyBidWNrZXQgYnV0IG5vIHVzZXIgcHJvamVjdCBwcm92aWRlZC4iLCJkZWJ1Z0luZm8iOiJjb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6VVNFUl9QUk9KRUNUX01JU1NJTkc6IEJ1Y2tldCBpcyBSZXF1ZXN0ZXIgUGF5cyBidWNrZXQgYnV0IG5vIGJpbGxpbmcgcHJvamVjdCBpZCBwcm92aWRlZCBmb3Igbm9uLW93bmVyLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5BY2Nlc3NDb250cm9sc0hlbHBlci5sb2FkQnVja2V0KEFjY2Vzc0NvbnRyb2xzSGVscGVyLmphdmE6MzAyKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuQWNjZXNzQ29udHJvbHNIZWxwZXIuZ2V0QWNsUmVzb3VyY2VGb3JSZXF1ZXN0KEFjY2Vzc0NvbnRyb2xzSGVscGVyLmphdmE6NzMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5EZWxldGVBY2xzLmhhbmRsZVJlcXVlc3RSZWNlaXZlZChEZWxldGVBY2xzLmphdmE6NzEpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5EZWxldGVBY2xzLmhhbmRsZVJlcXVlc3RSZWNlaXZlZChEZWxldGVBY2xzLmphdmE6MjApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5BY2Nlc3NDb250cm9sc0RlbGVnYXRvci5kZWxldGUoQWNjZXNzQ29udHJvbHNEZWxlZ2F0b3IuamF2YToxMDkpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBCdWNrZXQgaXMgUmVxdWVzdGVyIFBheXMgYnVja2V0IGJ1dCBubyBiaWxsaW5nIHByb2plY3QgaWQgcHJvdmlkZWQgZm9yIG5vbi1vd25lci5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MjkwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAxKVxuXHQuLi4gMTkgbW9yZVxuXG5jb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS5GYXVsdDogSW1tdXRhYmxlRXJyb3JEZWZpbml0aW9ue2Jhc2U9UkVRVUlSRUQsIGNhdGVnb3J5PVVTRVJfRVJST1IsIGNhdXNlPW51bGwsIGRlYnVnSW5mbz1jb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6VVNFUl9QUk9KRUNUX01JU1NJTkc6IEJ1Y2tldCBpcyBSZXF1ZXN0ZXIgUGF5cyBidWNrZXQgYnV0IG5vIGJpbGxpbmcgcHJvamVjdCBpZCBwcm92aWRlZCBmb3Igbm9uLW93bmVyLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5BY2Nlc3NDb250cm9sc0hlbHBlci5sb2FkQnVja2V0KEFjY2Vzc0NvbnRyb2xzSGVscGVyLmphdmE6MzAyKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuQWNjZXNzQ29udHJvbHNIZWxwZXIuZ2V0QWNsUmVzb3VyY2VGb3JSZXF1ZXN0KEFjY2Vzc0NvbnRyb2xzSGVscGVyLmphdmE6NzMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5EZWxldGVBY2xzLmhhbmRsZVJlcXVlc3RSZWNlaXZlZChEZWxldGVBY2xzLmphdmE6NzEpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5EZWxldGVBY2xzLmhhbmRsZVJlcXVlc3RSZWNlaXZlZChEZWxldGVBY2xzLmphdmE6MjApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5BY2Nlc3NDb250cm9sc0RlbGVnYXRvci5kZWxldGUoQWNjZXNzQ29udHJvbHNEZWxlZ2F0b3IuamF2YToxMDkpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBCdWNrZXQgaXMgUmVxdWVzdGVyIFBheXMgYnVja2V0IGJ1dCBubyBiaWxsaW5nIHByb2plY3QgaWQgcHJvdmlkZWQgZm9yIG5vbi1vd25lci5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MjkwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAxKVxuXHQuLi4gMTkgbW9yZVxuLCBkb21haW49Z2xvYmFsLCBleHRlbmRlZEhlbHA9bnVsbCwgaHR0cEhlYWRlcnM9e30sIGh0dHBTdGF0dXM9YmFkUmVxdWVzdCwgaW50ZXJuYWxSZWFzb249UmVhc29ue2FyZ3VtZW50cz17fSwgY2F1c2U9bnVsbCwgY29kZT1nZGF0YS5Db3JlRXJyb3JEb21haW4uUkVRVUlSRUQsIGNyZWF0ZWRCeUJhY2tlbmQ9dHJ1ZSwgZGVidWdNZXNzYWdlPWNvbS5nb29nbGUubmV0LnJwYzMuUnBjRXhjZXB0aW9uOiBjbG91ZC5iaWdzdG9yZS5SZXNwb25zZUNvZGUuRXJyb3JDb2RlOjpVU0VSX1BST0pFQ1RfTUlTU0lORzogQnVja2V0IGlzIFJlcXVlc3RlciBQYXlzIGJ1Y2tldCBidXQgbm8gYmlsbGluZyBwcm9qZWN0IGlkIHByb3ZpZGVkIGZvciBub24tb3duZXIuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRvUnBjM0V4Y2VwdGlvbihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjEzNSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLkFjY2Vzc0NvbnRyb2xzSGVscGVyLmxvYWRCdWNrZXQoQWNjZXNzQ29udHJvbHNIZWxwZXIuamF2YTozMDIpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5BY2Nlc3NDb250cm9sc0hlbHBlci5nZXRBY2xSZXNvdXJjZUZvclJlcXVlc3QoQWNjZXNzQ29udHJvbHNIZWxwZXIuamF2YTo3Mylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLkRlbGV0ZUFjbHMuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKERlbGV0ZUFjbHMuamF2YTo3MSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLkRlbGV0ZUFjbHMuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKERlbGV0ZUFjbHMuamF2YToyMClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLkFjY2Vzc0NvbnRyb2xzRGVsZWdhdG9yLmRlbGV0ZShBY2Nlc3NDb250cm9sc0RlbGVnYXRvci5qYXZhOjEwOSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uUnBjUmVjZWl2ZXIubGFtYmRhJHByb2Nlc3NSZXF1ZXN0QXN5bmMkNChScGNSZWNlaXZlci5qYXZhOjIwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uQXN5bmNFeGVjdXRvci5sYW1iZGEkc3VibWl0JDAoQXN5bmNFeGVjdXRvci5qYXZhOjI3Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KENvbnRleHRSdW5uYWJsZS5qYXZhOjUwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZSQxLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozOSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NzIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozNilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRXhlY3V0b3JzJFJ1bm5hYmxlQWRhcHRlci5jYWxsKEV4ZWN1dG9ycy5qYXZhOjUxMSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRnV0dXJlVGFzay5ydW4oRnV0dXJlVGFzay5qYXZhOjI2Nilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yLnJ1bldvcmtlcihUaHJlYWRQb29sRXhlY3V0b3IuamF2YToxMTQ5KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IkV29ya2VyLnJ1bihUaHJlYWRQb29sRXhlY3V0b3IuamF2YTo2MjQpXG5cdGF0IGphdmEubGFuZy5UaHJlYWQucnVuKFRocmVhZC5qYXZhOjc0OClcbkNhdXNlZCBieTogY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb246IEJ1Y2tldCBpcyBSZXF1ZXN0ZXIgUGF5cyBidWNrZXQgYnV0IG5vIGJpbGxpbmcgcHJvamVjdCBpZCBwcm92aWRlZCBmb3Igbm9uLW93bmVyLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxOSBtb3JlXG4sIGVycm9yUHJvdG9Db2RlPVJFUVVJUkVELCBlcnJvclByb3RvRG9tYWluPWdkYXRhLkNvcmVFcnJvckRvbWFpbiwgZmlsdGVyZWRNZXNzYWdlPW51bGwsIGxvY2F0aW9uPW51bGwsIG1lc3NhZ2U9QnVja2V0IGlzIHJlcXVlc3RlciBwYXlzIGJ1Y2tldCBidXQgbm8gdXNlciBwcm9qZWN0IHByb3ZpZGVkLiwgdW5uYW1lZEFyZ3VtZW50cz1bXX0sIGxvY2F0aW9uPW51bGwsIG1lc3NhZ2U9QnVja2V0IGlzIHJlcXVlc3RlciBwYXlzIGJ1Y2tldCBidXQgbm8gdXNlciBwcm9qZWN0IHByb3ZpZGVkLiwgcmVhc29uPXJlcXVpcmVkLCBycGNDb2RlPTQwMH0gQnVja2V0IGlzIHJlcXVlc3RlciBwYXlzIGJ1Y2tldCBidXQgbm8gdXNlciBwcm9qZWN0IHByb3ZpZGVkLjogY29tLmdvb2dsZS5uZXQucnBjMy5ScGNFeGNlcHRpb246IGNsb3VkLmJpZ3N0b3JlLlJlc3BvbnNlQ29kZS5FcnJvckNvZGU6OlVTRVJfUFJPSkVDVF9NSVNTSU5HOiBCdWNrZXQgaXMgUmVxdWVzdGVyIFBheXMgYnVja2V0IGJ1dCBubyBiaWxsaW5nIHByb2plY3QgaWQgcHJvdmlkZWQgZm9yIG5vbi1vd25lci5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udG9ScGMzRXhjZXB0aW9uKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MTM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuQWNjZXNzQ29udHJvbHNIZWxwZXIubG9hZEJ1Y2tldChBY2Nlc3NDb250cm9sc0hlbHBlci5qYXZhOjMwMilcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLkFjY2Vzc0NvbnRyb2xzSGVscGVyLmdldEFjbFJlc291cmNlRm9yUmVxdWVzdChBY2Nlc3NDb250cm9sc0hlbHBlci5qYXZhOjczKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuRGVsZXRlQWNscy5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoRGVsZXRlQWNscy5qYXZhOjcxKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuRGVsZXRlQWNscy5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoRGVsZXRlQWNscy5qYXZhOjIwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmZyYW1ld29yay5SZXF1ZXN0SGFuZGxlci5oYW5kbGUoUmVxdWVzdEhhbmRsZXIuamF2YToyOTQpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uQWNjZXNzQ29udHJvbHNEZWxlZ2F0b3IuZGVsZXRlKEFjY2Vzc0NvbnRyb2xzRGVsZWdhdG9yLmphdmE6MTA5KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5ScGNSZWNlaXZlci5sYW1iZGEkcHJvY2Vzc1JlcXVlc3RBc3luYyQ0KFJwY1JlY2VpdmVyLmphdmE6MjAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5Bc3luY0V4ZWN1dG9yLmxhbWJkYSRzdWJtaXQkMChBc3luY0V4ZWN1dG9yLmphdmE6MjcyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoQ29udGV4dFJ1bm5hYmxlLmphdmE6NTApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlJDEucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM5KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo3Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5FeGVjdXRvcnMkUnVubmFibGVBZGFwdGVyLmNhbGwoRXhlY3V0b3JzLmphdmE6NTExKVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5GdXR1cmVUYXNrLnJ1bihGdXR1cmVUYXNrLmphdmE6MjY2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IucnVuV29ya2VyKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjExNDkpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvciRXb3JrZXIucnVuKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjYyNClcblx0YXQgamF2YS5sYW5nLlRocmVhZC5ydW4oVGhyZWFkLmphdmE6NzQ4KVxuQ2F1c2VkIGJ5OiBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbjogQnVja2V0IGlzIFJlcXVlc3RlciBQYXlzIGJ1Y2tldCBidXQgbm8gYmlsbGluZyBwcm9qZWN0IGlkIHByb3ZpZGVkIGZvciBub24tb3duZXIuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93T25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjI5MClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMSlcblx0Li4uIDE5IG1vcmVcblxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS5FcnJvckNvbGxlY3Rvci50b0ZhdWx0KEVycm9yQ29sbGVjdG9yLmphdmE6NTQpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5yZXN0LmFkYXB0ZXIucm9zeS5Sb3N5RXJyb3JDb252ZXJ0ZXIudG9GYXVsdChSb3N5RXJyb3JDb252ZXJ0ZXIuamF2YTo2Nylcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnJlc3QuYWRhcHRlci5yb3N5LlJvc3lIYW5kbGVyJDIuY2FsbChSb3N5SGFuZGxlci5qYXZhOjI1OClcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnJlc3QuYWRhcHRlci5yb3N5LlJvc3lIYW5kbGVyJDIuY2FsbChSb3N5SGFuZGxlci5qYXZhOjIzOClcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkRpcmVjdEV4ZWN1dG9yLmV4ZWN1dGUoRGlyZWN0RXhlY3V0b3IuamF2YTozMClcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmV4ZWN1dGVMaXN0ZW5lcihBYnN0cmFjdEZ1dHVyZS5qYXZhOjExNDMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5jb21wbGV0ZShBYnN0cmFjdEZ1dHVyZS5qYXZhOjk2Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLnNldChBYnN0cmFjdEZ1dHVyZS5qYXZhOjczMSlcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkRpcmVjdEV4ZWN1dG9yLmV4ZWN1dGUoRGlyZWN0RXhlY3V0b3IuamF2YTozMClcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmV4ZWN1dGVMaXN0ZW5lcihBYnN0cmFjdEZ1dHVyZS5qYXZhOjExNDMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5jb21wbGV0ZShBYnN0cmFjdEZ1dHVyZS5qYXZhOjk2Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLnNldChBYnN0cmFjdEZ1dHVyZS5qYXZhOjczMSlcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnRocmVhZC5UaHJlYWRUcmFja2VycyRUaHJlYWRUcmFja2luZ1J1bm5hYmxlLnJ1bihUaHJlYWRUcmFja2Vycy5qYXZhOjEyNilcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRUcmFjZUNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoVHJhY2VDb250ZXh0LmphdmE6NDU1KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuc2VydmVyLkNvbW1vbk1vZHVsZSRDb250ZXh0Q2FycnlpbmdFeGVjdXRvclNlcnZpY2UkMS5ydW5JbkNvbnRleHQoQ29tbW9uTW9kdWxlLmphdmE6ODQ2KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JFRyYWNlQ29udGV4dFJ1bm5hYmxlJDEucnVuKFRyYWNlQ29udGV4dC5qYXZhOjQ2Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRBYnN0cmFjdFRyYWNlQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoVHJhY2VDb250ZXh0LmphdmE6MzIxKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JEFic3RyYWN0VHJhY2VDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KFRyYWNlQ29udGV4dC5qYXZhOjMxMylcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRUcmFjZUNvbnRleHRSdW5uYWJsZS5ydW4oVHJhY2VDb250ZXh0LmphdmE6NDU5KVxuXHRhdCBjb20uZ29vZ2xlLmdzZS5pbnRlcm5hbC5EaXNwYXRjaFF1ZXVlSW1wbCRXb3JrZXJUaHJlYWQucnVuKERpc3BhdGNoUXVldWVJbXBsLmphdmE6NDAzKVxuIn1dLCJjb2RlIjo0MDAsIm1lc3NhZ2UiOiJCdWNrZXQgaXMgcmVxdWVzdGVyIHBheXMgYnVja2V0IGJ1dCBubyB1c2VyIHByb2plY3QgcHJvdmlkZWQuIn19"
+ }
+ },
+ {
+ "ID": "d8dfe5f8f7f4842e",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/acl/domain-google.com?alt=json\u0026prettyPrint=false\u0026userProject=gcloud-golang-firestore-tests",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "0885ca0712dc00c110d60f29bae6a524/530440207157089951;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/acl/domain-google.com?alt=json\u0026prettyPrint=false\u0026userProject=gcloud-golang-firestore-tests"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 404,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0"
+ ],
+ "Content-Length": [
+ "2911"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:02 GMT"
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:25:02 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051402000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "471383502717"
+ ],
+ "X-Google-Backends": [
+ "vns199:4031,/bns/yx/borg/yx/bns/blobstore2/bitpusher/12.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=HsysW-eWDsjSzwKA9KbAAg"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yx/borg/yx/bns/blobstore2/bitpusher/12.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yx/borg/yx/bns/blobstore2/bitpusher/12:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CP3elYXcDRoCGAYoATo_ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGM6ropHgHCIVMTE3MjM4MDU4ODYxOTM3NTE5MTQ0MOArSp8BEoIBeWEyOS5jLkVsb2xCcldWbUZlX1AxVDdUOHVpTXdFMHBZUjdTc2NVMDBFdEZkc2tSenBQY0NLWkhUeEZaYXI0Q25tZmR6bXFRLTNVV0kzOF9wdEx5VTZ2Z1Q3dlRBeW42Z3g4dUcyd0szSHIzaTZrV1JBZkozc1pNMGQ1allkNHpWQTAEOhZOT1RfQV9QRVJTSVNURU5UX1RPS0VO"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Upload-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Uq6oz_XgowJEUjm6QcOHJUWfE1d-fqMb-vVQ9PhPGZ45k5NfaDFpeb0lbznhh-rs-Xl114pu9dF2UJ-zMDkvp8HpggrgQ"
+ ]
+ },
+ "Body": "eyJlcnJvciI6eyJlcnJvcnMiOlt7ImRvbWFpbiI6Imdsb2JhbCIsInJlYXNvbiI6Im5vdEZvdW5kIiwibWVzc2FnZSI6Ik5vdCBGb3VuZCIsImRlYnVnSW5mbyI6ImNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLkZhdWx0OiBJbW11dGFibGVFcnJvckRlZmluaXRpb257YmFzZT1OT1RfRk9VTkQsIGNhdGVnb3J5PVVTRVJfRVJST1IsIGNhdXNlPW51bGwsIGRlYnVnSW5mbz1udWxsLCBkb21haW49Z2xvYmFsLCBleHRlbmRlZEhlbHA9bnVsbCwgaHR0cEhlYWRlcnM9e30sIGh0dHBTdGF0dXM9bm90Rm91bmQsIGludGVybmFsUmVhc29uPVJlYXNvbnthcmd1bWVudHM9e30sIGNhdXNlPW51bGwsIGNvZGU9Z2RhdGEuQ29yZUVycm9yRG9tYWluLk5PVF9GT1VORCwgY3JlYXRlZEJ5QmFja2VuZD10cnVlLCBkZWJ1Z01lc3NhZ2U9bnVsbCwgZXJyb3JQcm90b0NvZGU9Tk9UX0ZPVU5ELCBlcnJvclByb3RvRG9tYWluPWdkYXRhLkNvcmVFcnJvckRvbWFpbiwgZmlsdGVyZWRNZXNzYWdlPW51bGwsIGxvY2F0aW9uPWVudGl0eS5yZXNvdXJjZV9pZC5zY29wZSwgbWVzc2FnZT1udWxsLCB1bm5hbWVkQXJndW1lbnRzPVtdfSwgbG9jYXRpb249ZW50aXR5LnJlc291cmNlX2lkLnNjb3BlLCBtZXNzYWdlPU5vdCBGb3VuZCwgcmVhc29uPW5vdEZvdW5kLCBycGNDb2RlPTQwNH0gTm90IEZvdW5kXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLkVycm9yQ29sbGVjdG9yLnRvRmF1bHQoRXJyb3JDb2xsZWN0b3IuamF2YTo1NClcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnJlc3QuYWRhcHRlci5yb3N5LlJvc3lFcnJvckNvbnZlcnRlci50b0ZhdWx0KFJvc3lFcnJvckNvbnZlcnRlci5qYXZhOjY3KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIucmVzdC5hZGFwdGVyLnJvc3kuUm9zeUhhbmRsZXIkMi5jYWxsKFJvc3lIYW5kbGVyLmphdmE6MjU4KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIucmVzdC5hZGFwdGVyLnJvc3kuUm9zeUhhbmRsZXIkMi5jYWxsKFJvc3lIYW5kbGVyLmphdmE6MjM4KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS51dGlsLkNhbGxhYmxlRnV0dXJlLnJ1bihDYWxsYWJsZUZ1dHVyZS5qYXZhOjYyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuRGlyZWN0RXhlY3V0b3IuZXhlY3V0ZShEaXJlY3RFeGVjdXRvci5qYXZhOjMwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuZXhlY3V0ZUxpc3RlbmVyKEFic3RyYWN0RnV0dXJlLmphdmE6MTE0Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmNvbXBsZXRlKEFic3RyYWN0RnV0dXJlLmphdmE6OTYzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuc2V0KEFic3RyYWN0RnV0dXJlLmphdmE6NzMxKVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS51dGlsLkNhbGxhYmxlRnV0dXJlLnJ1bihDYWxsYWJsZUZ1dHVyZS5qYXZhOjYyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuRGlyZWN0RXhlY3V0b3IuZXhlY3V0ZShEaXJlY3RFeGVjdXRvci5qYXZhOjMwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuZXhlY3V0ZUxpc3RlbmVyKEFic3RyYWN0RnV0dXJlLmphdmE6MTE0Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmNvbXBsZXRlKEFic3RyYWN0RnV0dXJlLmphdmE6OTYzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuc2V0KEFic3RyYWN0RnV0dXJlLmphdmE6NzMxKVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS51dGlsLkNhbGxhYmxlRnV0dXJlLnJ1bihDYWxsYWJsZUZ1dHVyZS5qYXZhOjYyKVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIudGhyZWFkLlRocmVhZFRyYWNrZXJzJFRocmVhZFRyYWNraW5nUnVubmFibGUucnVuKFRocmVhZFRyYWNrZXJzLmphdmE6MTI2KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JFRyYWNlQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChUcmFjZUNvbnRleHQuamF2YTo0NTUpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5zZXJ2ZXIuQ29tbW9uTW9kdWxlJENvbnRleHRDYXJyeWluZ0V4ZWN1dG9yU2VydmljZSQxLnJ1bkluQ29udGV4dChDb21tb25Nb2R1bGUuamF2YTo4NDYpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkVHJhY2VDb250ZXh0UnVubmFibGUkMS5ydW4oVHJhY2VDb250ZXh0LmphdmE6NDYyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JEFic3RyYWN0VHJhY2VDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihUcmFjZUNvbnRleHQuamF2YTozMjEpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkQWJzdHJhY3RUcmFjZUNvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoVHJhY2VDb250ZXh0LmphdmE6MzEzKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JFRyYWNlQ29udGV4dFJ1bm5hYmxlLnJ1bihUcmFjZUNvbnRleHQuamF2YTo0NTkpXG5cdGF0IGNvbS5nb29nbGUuZ3NlLmludGVybmFsLkRpc3BhdGNoUXVldWVJbXBsJFdvcmtlclRocmVhZC5ydW4oRGlzcGF0Y2hRdWV1ZUltcGwuamF2YTo0MDMpXG4ifV0sImNvZGUiOjQwNCwibWVzc2FnZSI6Ik5vdCBGb3VuZCJ9fQ=="
+ }
+ },
+ {
+ "ID": "774de9a795d77c1a",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/acl/domain-google.com?alt=json\u0026prettyPrint=false\u0026userProject=veener-jba",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "e3c01d1072ccb8ae60f233fe68026958/2120852106929339198;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/acl/domain-google.com?alt=json\u0026prettyPrint=false\u0026userProject=veener-jba"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 403,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0"
+ ],
+ "Content-Length": [
+ "13987"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:02 GMT"
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:25:02 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051402000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "471383502717"
+ ],
+ "X-Google-Backends": [
+ "vnay63:4225,/bns/yx/borg/yx/bns/blobstore2/bitpusher/71.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=HsysW63YF9KWzALm4bbIAQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yx/borg/yx/bns/blobstore2/bitpusher/71.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yx/borg/yx/bns/blobstore2/bitpusher/71:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CP3elYXcDRoCGAYoATo_ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGM6ropHgHCIVMTE3MjM4MDU4ODYxOTM3NTE5MTQ0MOArSp8BEoIBeWEyOS5jLkVsb2xCcldWbUZlX1AxVDdUOHVpTXdFMHBZUjdTc2NVMDBFdEZkc2tSenBQY0NLWkhUeEZaYXI0Q25tZmR6bXFRLTNVV0kzOF9wdEx5VTZ2Z1Q3dlRBeW42Z3g4dUcyd0szSHIzaTZrV1JBZkozc1pNMGQ1allkNHpWQTAEOhZOT1RfQV9QRVJTSVNURU5UX1RPS0VO"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Upload-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Uq2nRMSlpzIEyWLHepcu3uZTN0ze61Pgp76Y_QcFtaTBw6XipXJDnMwGvyMr2CctSdUs_T2O78pfbHqJWhG44EGgQQzSg"
+ ]
+ },
+ "Body": "eyJlcnJvciI6eyJlcnJvcnMiOlt7ImRvbWFpbiI6Imdsb2JhbCIsInJlYXNvbiI6ImZvcmJpZGRlbiIsIm1lc3NhZ2UiOiJpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLiIsImRlYnVnSW5mbyI6ImNvbS5nb29nbGUubmV0LnJwYzMuUnBjRXhjZXB0aW9uOiBjbG91ZC5iaWdzdG9yZS5SZXNwb25zZUNvZGUuRXJyb3JDb2RlOjpVU0VSX1BST0pFQ1RfQUNDRVNTX0RFTklFRDogaW50ZWdyYXRpb25AZ2Nsb3VkLWdvbGFuZy1maXJlc3RvcmUtdGVzdHMuaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20gZG9lcyBub3QgaGF2ZSBzZXJ2aWNldXNhZ2Uuc2VydmljZXMudXNlIGFjY2VzcyB0byBwcm9qZWN0IDY0MjA4MDkxODEwMS5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udG9ScGMzRXhjZXB0aW9uKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MTM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuQWNjZXNzQ29udHJvbHNIZWxwZXIubG9hZEJ1Y2tldChBY2Nlc3NDb250cm9sc0hlbHBlci5qYXZhOjMwMilcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLkFjY2Vzc0NvbnRyb2xzSGVscGVyLmdldEFjbFJlc291cmNlRm9yUmVxdWVzdChBY2Nlc3NDb250cm9sc0hlbHBlci5qYXZhOjczKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuRGVsZXRlQWNscy5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoRGVsZXRlQWNscy5qYXZhOjcxKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuRGVsZXRlQWNscy5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoRGVsZXRlQWNscy5qYXZhOjIwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmZyYW1ld29yay5SZXF1ZXN0SGFuZGxlci5oYW5kbGUoUmVxdWVzdEhhbmRsZXIuamF2YToyOTQpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uQWNjZXNzQ29udHJvbHNEZWxlZ2F0b3IuZGVsZXRlKEFjY2Vzc0NvbnRyb2xzRGVsZWdhdG9yLmphdmE6MTA5KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5ScGNSZWNlaXZlci5sYW1iZGEkcHJvY2Vzc1JlcXVlc3RBc3luYyQ0KFJwY1JlY2VpdmVyLmphdmE6MjAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5Bc3luY0V4ZWN1dG9yLmxhbWJkYSRzdWJtaXQkMChBc3luY0V4ZWN1dG9yLmphdmE6MjcyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoQ29udGV4dFJ1bm5hYmxlLmphdmE6NTApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlJDEucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM5KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo3Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5FeGVjdXRvcnMkUnVubmFibGVBZGFwdGVyLmNhbGwoRXhlY3V0b3JzLmphdmE6NTExKVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5GdXR1cmVUYXNrLnJ1bihGdXR1cmVUYXNrLmphdmE6MjY2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IucnVuV29ya2VyKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjExNDkpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvciRXb3JrZXIucnVuKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjYyNClcblx0YXQgamF2YS5sYW5nLlRocmVhZC5ydW4oVGhyZWFkLmphdmE6NzQ4KVxuQ2F1c2VkIGJ5OiBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbjogaW50ZWdyYXRpb25AZ2Nsb3VkLWdvbGFuZy1maXJlc3RvcmUtdGVzdHMuaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20gZG9lcyBub3QgaGF2ZSBzZXJ2aWNldXNhZ2Uuc2VydmljZXMudXNlIGFjY2VzcyB0byBwcm9qZWN0IDY0MjA4MDkxODEwMS5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MjkwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAxKVxuXHQuLi4gMTkgbW9yZVxuXG5jb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS5GYXVsdDogSW1tdXRhYmxlRXJyb3JEZWZpbml0aW9ue2Jhc2U9Rk9SQklEREVOLCBjYXRlZ29yeT1VU0VSX0VSUk9SLCBjYXVzZT1udWxsLCBkZWJ1Z0luZm89Y29tLmdvb2dsZS5uZXQucnBjMy5ScGNFeGNlcHRpb246IGNsb3VkLmJpZ3N0b3JlLlJlc3BvbnNlQ29kZS5FcnJvckNvZGU6OlVTRVJfUFJPSkVDVF9BQ0NFU1NfREVOSUVEOiBpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5BY2Nlc3NDb250cm9sc0hlbHBlci5sb2FkQnVja2V0KEFjY2Vzc0NvbnRyb2xzSGVscGVyLmphdmE6MzAyKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuQWNjZXNzQ29udHJvbHNIZWxwZXIuZ2V0QWNsUmVzb3VyY2VGb3JSZXF1ZXN0KEFjY2Vzc0NvbnRyb2xzSGVscGVyLmphdmE6NzMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5EZWxldGVBY2xzLmhhbmRsZVJlcXVlc3RSZWNlaXZlZChEZWxldGVBY2xzLmphdmE6NzEpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5EZWxldGVBY2xzLmhhbmRsZVJlcXVlc3RSZWNlaXZlZChEZWxldGVBY2xzLmphdmE6MjApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5BY2Nlc3NDb250cm9sc0RlbGVnYXRvci5kZWxldGUoQWNjZXNzQ29udHJvbHNEZWxlZ2F0b3IuamF2YToxMDkpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxOSBtb3JlXG4sIGRvbWFpbj1nbG9iYWwsIGV4dGVuZGVkSGVscD1udWxsLCBodHRwSGVhZGVycz17fSwgaHR0cFN0YXR1cz1mb3JiaWRkZW4sIGludGVybmFsUmVhc29uPVJlYXNvbnthcmd1bWVudHM9e30sIGNhdXNlPW51bGwsIGNvZGU9Z2RhdGEuQ29yZUVycm9yRG9tYWluLkZPUkJJRERFTiwgY3JlYXRlZEJ5QmFja2VuZD10cnVlLCBkZWJ1Z01lc3NhZ2U9Y29tLmdvb2dsZS5uZXQucnBjMy5ScGNFeGNlcHRpb246IGNsb3VkLmJpZ3N0b3JlLlJlc3BvbnNlQ29kZS5FcnJvckNvZGU6OlVTRVJfUFJPSkVDVF9BQ0NFU1NfREVOSUVEOiBpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5BY2Nlc3NDb250cm9sc0hlbHBlci5sb2FkQnVja2V0KEFjY2Vzc0NvbnRyb2xzSGVscGVyLmphdmE6MzAyKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuQWNjZXNzQ29udHJvbHNIZWxwZXIuZ2V0QWNsUmVzb3VyY2VGb3JSZXF1ZXN0KEFjY2Vzc0NvbnRyb2xzSGVscGVyLmphdmE6NzMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5EZWxldGVBY2xzLmhhbmRsZVJlcXVlc3RSZWNlaXZlZChEZWxldGVBY2xzLmphdmE6NzEpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5EZWxldGVBY2xzLmhhbmRsZVJlcXVlc3RSZWNlaXZlZChEZWxldGVBY2xzLmphdmE6MjApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5BY2Nlc3NDb250cm9sc0RlbGVnYXRvci5kZWxldGUoQWNjZXNzQ29udHJvbHNEZWxlZ2F0b3IuamF2YToxMDkpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxOSBtb3JlXG4sIGVycm9yUHJvdG9Db2RlPUZPUkJJRERFTiwgZXJyb3JQcm90b0RvbWFpbj1nZGF0YS5Db3JlRXJyb3JEb21haW4sIGZpbHRlcmVkTWVzc2FnZT1udWxsLCBsb2NhdGlvbj1udWxsLCBtZXNzYWdlPWludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIGRvZXMgbm90IGhhdmUgc2VydmljZXVzYWdlLnNlcnZpY2VzLnVzZSBhY2Nlc3MgdG8gcHJvamVjdCA2NDIwODA5MTgxMDEuLCB1bm5hbWVkQXJndW1lbnRzPVtdfSwgbG9jYXRpb249bnVsbCwgbWVzc2FnZT1pbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLiwgcmVhc29uPWZvcmJpZGRlbiwgcnBjQ29kZT00MDN9IGludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIGRvZXMgbm90IGhhdmUgc2VydmljZXVzYWdlLnNlcnZpY2VzLnVzZSBhY2Nlc3MgdG8gcHJvamVjdCA2NDIwODA5MTgxMDEuOiBjb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6VVNFUl9QUk9KRUNUX0FDQ0VTU19ERU5JRUQ6IGludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIGRvZXMgbm90IGhhdmUgc2VydmljZXVzYWdlLnNlcnZpY2VzLnVzZSBhY2Nlc3MgdG8gcHJvamVjdCA2NDIwODA5MTgxMDEuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRvUnBjM0V4Y2VwdGlvbihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjEzNSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLkFjY2Vzc0NvbnRyb2xzSGVscGVyLmxvYWRCdWNrZXQoQWNjZXNzQ29udHJvbHNIZWxwZXIuamF2YTozMDIpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5BY2Nlc3NDb250cm9sc0hlbHBlci5nZXRBY2xSZXNvdXJjZUZvclJlcXVlc3QoQWNjZXNzQ29udHJvbHNIZWxwZXIuamF2YTo3Mylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLkRlbGV0ZUFjbHMuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKERlbGV0ZUFjbHMuamF2YTo3MSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLkRlbGV0ZUFjbHMuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKERlbGV0ZUFjbHMuamF2YToyMClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLkFjY2Vzc0NvbnRyb2xzRGVsZWdhdG9yLmRlbGV0ZShBY2Nlc3NDb250cm9sc0RlbGVnYXRvci5qYXZhOjEwOSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uUnBjUmVjZWl2ZXIubGFtYmRhJHByb2Nlc3NSZXF1ZXN0QXN5bmMkNChScGNSZWNlaXZlci5qYXZhOjIwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uQXN5bmNFeGVjdXRvci5sYW1iZGEkc3VibWl0JDAoQXN5bmNFeGVjdXRvci5qYXZhOjI3Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KENvbnRleHRSdW5uYWJsZS5qYXZhOjUwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZSQxLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozOSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NzIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozNilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRXhlY3V0b3JzJFJ1bm5hYmxlQWRhcHRlci5jYWxsKEV4ZWN1dG9ycy5qYXZhOjUxMSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRnV0dXJlVGFzay5ydW4oRnV0dXJlVGFzay5qYXZhOjI2Nilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yLnJ1bldvcmtlcihUaHJlYWRQb29sRXhlY3V0b3IuamF2YToxMTQ5KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IkV29ya2VyLnJ1bihUaHJlYWRQb29sRXhlY3V0b3IuamF2YTo2MjQpXG5cdGF0IGphdmEubGFuZy5UaHJlYWQucnVuKFRocmVhZC5qYXZhOjc0OClcbkNhdXNlZCBieTogY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb246IGludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIGRvZXMgbm90IGhhdmUgc2VydmljZXVzYWdlLnNlcnZpY2VzLnVzZSBhY2Nlc3MgdG8gcHJvamVjdCA2NDIwODA5MTgxMDEuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93T25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjI5MClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMSlcblx0Li4uIDE5IG1vcmVcblxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS5FcnJvckNvbGxlY3Rvci50b0ZhdWx0KEVycm9yQ29sbGVjdG9yLmphdmE6NTQpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5yZXN0LmFkYXB0ZXIucm9zeS5Sb3N5RXJyb3JDb252ZXJ0ZXIudG9GYXVsdChSb3N5RXJyb3JDb252ZXJ0ZXIuamF2YTo2Nylcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnJlc3QuYWRhcHRlci5yb3N5LlJvc3lIYW5kbGVyJDIuY2FsbChSb3N5SGFuZGxlci5qYXZhOjI1OClcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnJlc3QuYWRhcHRlci5yb3N5LlJvc3lIYW5kbGVyJDIuY2FsbChSb3N5SGFuZGxlci5qYXZhOjIzOClcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkRpcmVjdEV4ZWN1dG9yLmV4ZWN1dGUoRGlyZWN0RXhlY3V0b3IuamF2YTozMClcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmV4ZWN1dGVMaXN0ZW5lcihBYnN0cmFjdEZ1dHVyZS5qYXZhOjExNDMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5jb21wbGV0ZShBYnN0cmFjdEZ1dHVyZS5qYXZhOjk2Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLnNldChBYnN0cmFjdEZ1dHVyZS5qYXZhOjczMSlcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkRpcmVjdEV4ZWN1dG9yLmV4ZWN1dGUoRGlyZWN0RXhlY3V0b3IuamF2YTozMClcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmV4ZWN1dGVMaXN0ZW5lcihBYnN0cmFjdEZ1dHVyZS5qYXZhOjExNDMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5jb21wbGV0ZShBYnN0cmFjdEZ1dHVyZS5qYXZhOjk2Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLnNldChBYnN0cmFjdEZ1dHVyZS5qYXZhOjczMSlcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnRocmVhZC5UaHJlYWRUcmFja2VycyRUaHJlYWRUcmFja2luZ1J1bm5hYmxlLnJ1bihUaHJlYWRUcmFja2Vycy5qYXZhOjEyNilcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRUcmFjZUNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoVHJhY2VDb250ZXh0LmphdmE6NDU1KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuc2VydmVyLkNvbW1vbk1vZHVsZSRDb250ZXh0Q2FycnlpbmdFeGVjdXRvclNlcnZpY2UkMS5ydW5JbkNvbnRleHQoQ29tbW9uTW9kdWxlLmphdmE6ODQ2KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JFRyYWNlQ29udGV4dFJ1bm5hYmxlJDEucnVuKFRyYWNlQ29udGV4dC5qYXZhOjQ2Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRBYnN0cmFjdFRyYWNlQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoVHJhY2VDb250ZXh0LmphdmE6MzIxKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JEFic3RyYWN0VHJhY2VDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KFRyYWNlQ29udGV4dC5qYXZhOjMxMylcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRUcmFjZUNvbnRleHRSdW5uYWJsZS5ydW4oVHJhY2VDb250ZXh0LmphdmE6NDU5KVxuXHRhdCBjb20uZ29vZ2xlLmdzZS5pbnRlcm5hbC5EaXNwYXRjaFF1ZXVlSW1wbCRXb3JrZXJUaHJlYWQucnVuKERpc3BhdGNoUXVldWVJbXBsLmphdmE6NDAzKVxuIn1dLCJjb2RlIjo0MDMsIm1lc3NhZ2UiOiJpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLiJ9fQ=="
+ }
+ },
+ {
+ "ID": "ab058975d1817bd7",
+ "Request": {
+ "Method": "PUT",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/defaultObjectAcl/domain-google.com?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "107"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "10c17f347603960c73c3c64e530e12f5/3710982540297970141;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/defaultObjectAcl/domain-google.com?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJlbnRpdHkiOiJkb21haW4tZ29vZ2xlLmNvbSIsInJvbGUiOiJSRUFERVIifQo="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "119"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:04 GMT"
+ ],
+ "Etag": [
+ "CAU="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051389000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vngv21:4425,/bns/yx/borg/yx/bns/blobstore2/bitpusher/24.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=HsysW6CSJ5DkzgKJ5ryQBA"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yx/borg/yx/bns/blobstore2/bitpusher/24.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yx/borg/yx/bns/blobstore2/bitpusher/24:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATpxChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4CtK4wESxgF5YTI5LmMuRW93QkpRWVNNdC1OVDFNYTJvWXBrbG1qcDlJMlZaUFZ5bFl5Z2Q3Nk5tQXlXbWR3WVBoMm00dGI3ZmZjOUlzcTU4MmVFcFBhNzhNWGpNZmIzaE9WTE9xRHpNTUFfTG9NQXVJZkdkMGgzSWowZ1dxdW5DS1g3Qk1mQlJxM001TUtMMXBHOWNyU0ZBT29lVkZpTDhpWlBsUDI0VjE5THdzZ0d1ZnVrQTFtVzVJcTJUUkVXeWQyNjRKZC1lS2UxdTAwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UoBF56ICh2ijLjfqU1iq3_fIrTTjexZ2BBn2PaVwVYeg4B5mIEJ7T0U2dnfeafp2dDc2KWpY2mnIvyGKqOYWZhbLoVymA"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiZW50aXR5IjoiZG9tYWluLWdvb2dsZS5jb20iLCJyb2xlIjoiUkVBREVSIiwiZG9tYWluIjoiZ29vZ2xlLmNvbSIsImV0YWciOiJDQVU9In0="
+ }
+ },
+ {
+ "ID": "f1fcc196e93e6463",
+ "Request": {
+ "Method": "PUT",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/defaultObjectAcl/domain-google.com?alt=json\u0026prettyPrint=false\u0026userProject=dulcet-port-762",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "107"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "db1ff6db6ea98613c69f1676559359ef/5301393344870336123;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/defaultObjectAcl/domain-google.com?alt=json\u0026prettyPrint=false\u0026userProject=dulcet-port-762"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJlbnRpdHkiOiJkb21haW4tZ29vZ2xlLmNvbSIsInJvbGUiOiJSRUFERVIifQo="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "119"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:04 GMT"
+ ],
+ "Etag": [
+ "CAU="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051395000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrcw65:4312,/bns/yr/borg/yr/bns/blobstore2/bitpusher/59.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=IMysW4eNFMuLkATz_I_4CQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/59.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/59:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATpxChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4CtK4wESxgF5YTI5LmMuRW93QkpRWVNNdC1OVDFNYTJvWXBrbG1qcDlJMlZaUFZ5bFl5Z2Q3Nk5tQXlXbWR3WVBoMm00dGI3ZmZjOUlzcTU4MmVFcFBhNzhNWGpNZmIzaE9WTE9xRHpNTUFfTG9NQXVJZkdkMGgzSWowZ1dxdW5DS1g3Qk1mQlJxM001TUtMMXBHOWNyU0ZBT29lVkZpTDhpWlBsUDI0VjE5THdzZ0d1ZnVrQTFtVzVJcTJUUkVXeWQyNjRKZC1lS2UxdTAwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Up43Er14jJ287pQViDVRcpFGGZdP0AxcfJ5uR5znBju0lUN0PpfVd170bFXkNJtysbjPOiQ7ogsM9889HB7QTnl8S-ijg"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiZW50aXR5IjoiZG9tYWluLWdvb2dsZS5jb20iLCJyb2xlIjoiUkVBREVSIiwiZG9tYWluIjoiZ29vZ2xlLmNvbSIsImV0YWciOiJDQVU9In0="
+ }
+ },
+ {
+ "ID": "e3ff4129f99086aa",
+ "Request": {
+ "Method": "PUT",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/defaultObjectAcl/domain-google.com?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "107"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "1a701ecf80451edb1613f5c17144086b/6891805244625808410;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/defaultObjectAcl/domain-google.com?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJlbnRpdHkiOiJkb21haW4tZ29vZ2xlLmNvbSIsInJvbGUiOiJSRUFERVIifQo="
+ },
+ "Response": {
+ "StatusCode": 400,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Content-Length": [
+ "13131"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:04 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051395000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "471383502717"
+ ],
+ "X-Google-Backends": [
+ "vrs123:4010,/bns/yr/borg/yr/bns/blobstore2/bitpusher/31.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=IMysW7rFJci84QSQ-ZF4"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/31.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/31:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CP3elYXcDRoCGAYoATo_ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGM6ropHgHCIVMTE3MjM4MDU4ODYxOTM3NTE5MTQ0MOArSp8BEoIBeWEyOS5jLkVsb2xCcldWbUZlX1AxVDdUOHVpTXdFMHBZUjdTc2NVMDBFdEZkc2tSenBQY0NLWkhUeEZaYXI0Q25tZmR6bXFRLTNVV0kzOF9wdEx5VTZ2Z1Q3dlRBeW42Z3g4dUcyd0szSHIzaTZrV1JBZkozc1pNMGQ1allkNHpWQTAEOhZOT1RfQV9QRVJTSVNURU5UX1RPS0VO"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Upload-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UppIr8QoNk9y3W_-3bxKLmujYEgzMdEaN4VVg5rK-gtx1kEwLnh4qW-opHhL80TrnuyGBMpA11rTr2vHaE97_4WXOZDKA"
+ ]
+ },
+ "Body": "eyJlcnJvciI6eyJlcnJvcnMiOlt7ImRvbWFpbiI6Imdsb2JhbCIsInJlYXNvbiI6InJlcXVpcmVkIiwibWVzc2FnZSI6IkJ1Y2tldCBpcyByZXF1ZXN0ZXIgcGF5cyBidWNrZXQgYnV0IG5vIHVzZXIgcHJvamVjdCBwcm92aWRlZC4iLCJkZWJ1Z0luZm8iOiJjb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6VVNFUl9QUk9KRUNUX01JU1NJTkc6IEJ1Y2tldCBpcyBSZXF1ZXN0ZXIgUGF5cyBidWNrZXQgYnV0IG5vIGJpbGxpbmcgcHJvamVjdCBpZCBwcm92aWRlZCBmb3Igbm9uLW93bmVyLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5BY2Nlc3NDb250cm9sc0hlbHBlci5sb2FkQnVja2V0KEFjY2Vzc0NvbnRyb2xzSGVscGVyLmphdmE6MzAyKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuQWNjZXNzQ29udHJvbHNIZWxwZXIuZ2V0QWNsUmVzb3VyY2VGb3JSZXF1ZXN0KEFjY2Vzc0NvbnRyb2xzSGVscGVyLmphdmE6NzMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5VcGRhdGVBY2xzLmhhbmRsZVJlcXVlc3RSZWNlaXZlZChVcGRhdGVBY2xzLmphdmE6NjIpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5VcGRhdGVBY2xzLmhhbmRsZVJlcXVlc3RSZWNlaXZlZChVcGRhdGVBY2xzLmphdmE6MTYpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5BY2Nlc3NDb250cm9sc0RlbGVnYXRvci51cGRhdGUoQWNjZXNzQ29udHJvbHNEZWxlZ2F0b3IuamF2YToxMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBCdWNrZXQgaXMgUmVxdWVzdGVyIFBheXMgYnVja2V0IGJ1dCBubyBiaWxsaW5nIHByb2plY3QgaWQgcHJvdmlkZWQgZm9yIG5vbi1vd25lci5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MjkwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAxKVxuXHQuLi4gMTkgbW9yZVxuXG5jb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS5GYXVsdDogSW1tdXRhYmxlRXJyb3JEZWZpbml0aW9ue2Jhc2U9UkVRVUlSRUQsIGNhdGVnb3J5PVVTRVJfRVJST1IsIGNhdXNlPW51bGwsIGRlYnVnSW5mbz1jb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6VVNFUl9QUk9KRUNUX01JU1NJTkc6IEJ1Y2tldCBpcyBSZXF1ZXN0ZXIgUGF5cyBidWNrZXQgYnV0IG5vIGJpbGxpbmcgcHJvamVjdCBpZCBwcm92aWRlZCBmb3Igbm9uLW93bmVyLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5BY2Nlc3NDb250cm9sc0hlbHBlci5sb2FkQnVja2V0KEFjY2Vzc0NvbnRyb2xzSGVscGVyLmphdmE6MzAyKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuQWNjZXNzQ29udHJvbHNIZWxwZXIuZ2V0QWNsUmVzb3VyY2VGb3JSZXF1ZXN0KEFjY2Vzc0NvbnRyb2xzSGVscGVyLmphdmE6NzMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5VcGRhdGVBY2xzLmhhbmRsZVJlcXVlc3RSZWNlaXZlZChVcGRhdGVBY2xzLmphdmE6NjIpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5VcGRhdGVBY2xzLmhhbmRsZVJlcXVlc3RSZWNlaXZlZChVcGRhdGVBY2xzLmphdmE6MTYpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5BY2Nlc3NDb250cm9sc0RlbGVnYXRvci51cGRhdGUoQWNjZXNzQ29udHJvbHNEZWxlZ2F0b3IuamF2YToxMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBCdWNrZXQgaXMgUmVxdWVzdGVyIFBheXMgYnVja2V0IGJ1dCBubyBiaWxsaW5nIHByb2plY3QgaWQgcHJvdmlkZWQgZm9yIG5vbi1vd25lci5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MjkwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAxKVxuXHQuLi4gMTkgbW9yZVxuLCBkb21haW49Z2xvYmFsLCBleHRlbmRlZEhlbHA9bnVsbCwgaHR0cEhlYWRlcnM9e30sIGh0dHBTdGF0dXM9YmFkUmVxdWVzdCwgaW50ZXJuYWxSZWFzb249UmVhc29ue2FyZ3VtZW50cz17fSwgY2F1c2U9bnVsbCwgY29kZT1nZGF0YS5Db3JlRXJyb3JEb21haW4uUkVRVUlSRUQsIGNyZWF0ZWRCeUJhY2tlbmQ9dHJ1ZSwgZGVidWdNZXNzYWdlPWNvbS5nb29nbGUubmV0LnJwYzMuUnBjRXhjZXB0aW9uOiBjbG91ZC5iaWdzdG9yZS5SZXNwb25zZUNvZGUuRXJyb3JDb2RlOjpVU0VSX1BST0pFQ1RfTUlTU0lORzogQnVja2V0IGlzIFJlcXVlc3RlciBQYXlzIGJ1Y2tldCBidXQgbm8gYmlsbGluZyBwcm9qZWN0IGlkIHByb3ZpZGVkIGZvciBub24tb3duZXIuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRvUnBjM0V4Y2VwdGlvbihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjEzNSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLkFjY2Vzc0NvbnRyb2xzSGVscGVyLmxvYWRCdWNrZXQoQWNjZXNzQ29udHJvbHNIZWxwZXIuamF2YTozMDIpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5BY2Nlc3NDb250cm9sc0hlbHBlci5nZXRBY2xSZXNvdXJjZUZvclJlcXVlc3QoQWNjZXNzQ29udHJvbHNIZWxwZXIuamF2YTo3Mylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLlVwZGF0ZUFjbHMuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKFVwZGF0ZUFjbHMuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLlVwZGF0ZUFjbHMuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKFVwZGF0ZUFjbHMuamF2YToxNilcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLkFjY2Vzc0NvbnRyb2xzRGVsZWdhdG9yLnVwZGF0ZShBY2Nlc3NDb250cm9sc0RlbGVnYXRvci5qYXZhOjEwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uUnBjUmVjZWl2ZXIubGFtYmRhJHByb2Nlc3NSZXF1ZXN0QXN5bmMkNChScGNSZWNlaXZlci5qYXZhOjIwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uQXN5bmNFeGVjdXRvci5sYW1iZGEkc3VibWl0JDAoQXN5bmNFeGVjdXRvci5qYXZhOjI3Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KENvbnRleHRSdW5uYWJsZS5qYXZhOjUwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZSQxLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozOSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NzIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozNilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRXhlY3V0b3JzJFJ1bm5hYmxlQWRhcHRlci5jYWxsKEV4ZWN1dG9ycy5qYXZhOjUxMSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRnV0dXJlVGFzay5ydW4oRnV0dXJlVGFzay5qYXZhOjI2Nilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yLnJ1bldvcmtlcihUaHJlYWRQb29sRXhlY3V0b3IuamF2YToxMTQ5KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IkV29ya2VyLnJ1bihUaHJlYWRQb29sRXhlY3V0b3IuamF2YTo2MjQpXG5cdGF0IGphdmEubGFuZy5UaHJlYWQucnVuKFRocmVhZC5qYXZhOjc0OClcbkNhdXNlZCBieTogY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb246IEJ1Y2tldCBpcyBSZXF1ZXN0ZXIgUGF5cyBidWNrZXQgYnV0IG5vIGJpbGxpbmcgcHJvamVjdCBpZCBwcm92aWRlZCBmb3Igbm9uLW93bmVyLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxOSBtb3JlXG4sIGVycm9yUHJvdG9Db2RlPVJFUVVJUkVELCBlcnJvclByb3RvRG9tYWluPWdkYXRhLkNvcmVFcnJvckRvbWFpbiwgZmlsdGVyZWRNZXNzYWdlPW51bGwsIGxvY2F0aW9uPW51bGwsIG1lc3NhZ2U9QnVja2V0IGlzIHJlcXVlc3RlciBwYXlzIGJ1Y2tldCBidXQgbm8gdXNlciBwcm9qZWN0IHByb3ZpZGVkLiwgdW5uYW1lZEFyZ3VtZW50cz1bXX0sIGxvY2F0aW9uPW51bGwsIG1lc3NhZ2U9QnVja2V0IGlzIHJlcXVlc3RlciBwYXlzIGJ1Y2tldCBidXQgbm8gdXNlciBwcm9qZWN0IHByb3ZpZGVkLiwgcmVhc29uPXJlcXVpcmVkLCBycGNDb2RlPTQwMH0gQnVja2V0IGlzIHJlcXVlc3RlciBwYXlzIGJ1Y2tldCBidXQgbm8gdXNlciBwcm9qZWN0IHByb3ZpZGVkLjogY29tLmdvb2dsZS5uZXQucnBjMy5ScGNFeGNlcHRpb246IGNsb3VkLmJpZ3N0b3JlLlJlc3BvbnNlQ29kZS5FcnJvckNvZGU6OlVTRVJfUFJPSkVDVF9NSVNTSU5HOiBCdWNrZXQgaXMgUmVxdWVzdGVyIFBheXMgYnVja2V0IGJ1dCBubyBiaWxsaW5nIHByb2plY3QgaWQgcHJvdmlkZWQgZm9yIG5vbi1vd25lci5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udG9ScGMzRXhjZXB0aW9uKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MTM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuQWNjZXNzQ29udHJvbHNIZWxwZXIubG9hZEJ1Y2tldChBY2Nlc3NDb250cm9sc0hlbHBlci5qYXZhOjMwMilcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLkFjY2Vzc0NvbnRyb2xzSGVscGVyLmdldEFjbFJlc291cmNlRm9yUmVxdWVzdChBY2Nlc3NDb250cm9sc0hlbHBlci5qYXZhOjczKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuVXBkYXRlQWNscy5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoVXBkYXRlQWNscy5qYXZhOjYyKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuVXBkYXRlQWNscy5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoVXBkYXRlQWNscy5qYXZhOjE2KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmZyYW1ld29yay5SZXF1ZXN0SGFuZGxlci5oYW5kbGUoUmVxdWVzdEhhbmRsZXIuamF2YToyOTQpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uQWNjZXNzQ29udHJvbHNEZWxlZ2F0b3IudXBkYXRlKEFjY2Vzc0NvbnRyb2xzRGVsZWdhdG9yLmphdmE6MTAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5ScGNSZWNlaXZlci5sYW1iZGEkcHJvY2Vzc1JlcXVlc3RBc3luYyQ0KFJwY1JlY2VpdmVyLmphdmE6MjAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5Bc3luY0V4ZWN1dG9yLmxhbWJkYSRzdWJtaXQkMChBc3luY0V4ZWN1dG9yLmphdmE6MjcyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoQ29udGV4dFJ1bm5hYmxlLmphdmE6NTApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlJDEucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM5KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo3Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5FeGVjdXRvcnMkUnVubmFibGVBZGFwdGVyLmNhbGwoRXhlY3V0b3JzLmphdmE6NTExKVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5GdXR1cmVUYXNrLnJ1bihGdXR1cmVUYXNrLmphdmE6MjY2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IucnVuV29ya2VyKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjExNDkpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvciRXb3JrZXIucnVuKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjYyNClcblx0YXQgamF2YS5sYW5nLlRocmVhZC5ydW4oVGhyZWFkLmphdmE6NzQ4KVxuQ2F1c2VkIGJ5OiBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbjogQnVja2V0IGlzIFJlcXVlc3RlciBQYXlzIGJ1Y2tldCBidXQgbm8gYmlsbGluZyBwcm9qZWN0IGlkIHByb3ZpZGVkIGZvciBub24tb3duZXIuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93T25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjI5MClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMSlcblx0Li4uIDE5IG1vcmVcblxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS5FcnJvckNvbGxlY3Rvci50b0ZhdWx0KEVycm9yQ29sbGVjdG9yLmphdmE6NTQpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5yZXN0LmFkYXB0ZXIucm9zeS5Sb3N5RXJyb3JDb252ZXJ0ZXIudG9GYXVsdChSb3N5RXJyb3JDb252ZXJ0ZXIuamF2YTo2Nylcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnJlc3QuYWRhcHRlci5yb3N5LlJvc3lIYW5kbGVyJDIuY2FsbChSb3N5SGFuZGxlci5qYXZhOjI1OClcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnJlc3QuYWRhcHRlci5yb3N5LlJvc3lIYW5kbGVyJDIuY2FsbChSb3N5SGFuZGxlci5qYXZhOjIzOClcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkRpcmVjdEV4ZWN1dG9yLmV4ZWN1dGUoRGlyZWN0RXhlY3V0b3IuamF2YTozMClcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmV4ZWN1dGVMaXN0ZW5lcihBYnN0cmFjdEZ1dHVyZS5qYXZhOjExNDMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5jb21wbGV0ZShBYnN0cmFjdEZ1dHVyZS5qYXZhOjk2Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLnNldChBYnN0cmFjdEZ1dHVyZS5qYXZhOjczMSlcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkRpcmVjdEV4ZWN1dG9yLmV4ZWN1dGUoRGlyZWN0RXhlY3V0b3IuamF2YTozMClcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmV4ZWN1dGVMaXN0ZW5lcihBYnN0cmFjdEZ1dHVyZS5qYXZhOjExNDMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5jb21wbGV0ZShBYnN0cmFjdEZ1dHVyZS5qYXZhOjk2Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLnNldChBYnN0cmFjdEZ1dHVyZS5qYXZhOjczMSlcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnRocmVhZC5UaHJlYWRUcmFja2VycyRUaHJlYWRUcmFja2luZ1J1bm5hYmxlLnJ1bihUaHJlYWRUcmFja2Vycy5qYXZhOjEyNilcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRUcmFjZUNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoVHJhY2VDb250ZXh0LmphdmE6NDU1KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuc2VydmVyLkNvbW1vbk1vZHVsZSRDb250ZXh0Q2FycnlpbmdFeGVjdXRvclNlcnZpY2UkMS5ydW5JbkNvbnRleHQoQ29tbW9uTW9kdWxlLmphdmE6ODQ2KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JFRyYWNlQ29udGV4dFJ1bm5hYmxlJDEucnVuKFRyYWNlQ29udGV4dC5qYXZhOjQ2Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRBYnN0cmFjdFRyYWNlQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoVHJhY2VDb250ZXh0LmphdmE6MzIxKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JEFic3RyYWN0VHJhY2VDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KFRyYWNlQ29udGV4dC5qYXZhOjMxMylcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRUcmFjZUNvbnRleHRSdW5uYWJsZS5ydW4oVHJhY2VDb250ZXh0LmphdmE6NDU5KVxuXHRhdCBjb20uZ29vZ2xlLmdzZS5pbnRlcm5hbC5EaXNwYXRjaFF1ZXVlSW1wbCRXb3JrZXJUaHJlYWQucnVuKERpc3BhdGNoUXVldWVJbXBsLmphdmE6NDAzKVxuIn1dLCJjb2RlIjo0MDAsIm1lc3NhZ2UiOiJCdWNrZXQgaXMgcmVxdWVzdGVyIHBheXMgYnVja2V0IGJ1dCBubyB1c2VyIHByb2plY3QgcHJvdmlkZWQuIn19"
+ }
+ },
+ {
+ "ID": "fd3d4b6eabba272c",
+ "Request": {
+ "Method": "PUT",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/defaultObjectAcl/domain-google.com?alt=json\u0026prettyPrint=false\u0026userProject=gcloud-golang-firestore-tests",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "107"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "6d2983fb613e0d14f1016b3156d1f2c0/8482217148692959673;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/defaultObjectAcl/domain-google.com?alt=json\u0026prettyPrint=false\u0026userProject=gcloud-golang-firestore-tests"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJlbnRpdHkiOiJkb21haW4tZ29vZ2xlLmNvbSIsInJvbGUiOiJSRUFERVIifQo="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "119"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:04 GMT"
+ ],
+ "Etag": [
+ "CAU="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051402000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "471383502717"
+ ],
+ "X-Google-Backends": [
+ "vnnl21:4346,/bns/yx/borg/yx/bns/blobstore2/bitpusher/166.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=IMysW-rKMsHWzALm5oewDg"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yx/borg/yx/bns/blobstore2/bitpusher/166.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yx/borg/yx/bns/blobstore2/bitpusher/166:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CP3elYXcDRoCGAYoATo_ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGM6ropHgHCIVMTE3MjM4MDU4ODYxOTM3NTE5MTQ0MOArSp8BEoIBeWEyOS5jLkVsb2xCcldWbUZlX1AxVDdUOHVpTXdFMHBZUjdTc2NVMDBFdEZkc2tSenBQY0NLWkhUeEZaYXI0Q25tZmR6bXFRLTNVV0kzOF9wdEx5VTZ2Z1Q3dlRBeW42Z3g4dUcyd0szSHIzaTZrV1JBZkozc1pNMGQ1allkNHpWQTAEOhZOT1RfQV9QRVJTSVNURU5UX1RPS0VO"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UpaVesITKhatH2M-FF0nr35PGOmXxdEH2KkpMDZQSj-VyYNi7b4ZCw0_0iVK1Ss5Tk-1YLPbW-N87O94cay4CR2tc15ww"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiZW50aXR5IjoiZG9tYWluLWdvb2dsZS5jb20iLCJyb2xlIjoiUkVBREVSIiwiZG9tYWluIjoiZ29vZ2xlLmNvbSIsImV0YWciOiJDQVU9In0="
+ }
+ },
+ {
+ "ID": "6cef2d0fe616a1cb",
+ "Request": {
+ "Method": "PUT",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/defaultObjectAcl/domain-google.com?alt=json\u0026prettyPrint=false\u0026userProject=veener-jba",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "107"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "41470592c6b358127c9e6adb19653c80/10072347582061655895;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/defaultObjectAcl/domain-google.com?alt=json\u0026prettyPrint=false\u0026userProject=veener-jba"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJlbnRpdHkiOiJkb21haW4tZ29vZ2xlLmNvbSIsInJvbGUiOiJSRUFERVIifQo="
+ },
+ "Response": {
+ "StatusCode": 403,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Content-Length": [
+ "13987"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:05 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051402000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "471383502717"
+ ],
+ "X-Google-Backends": [
+ "vnss23:4187,/bns/yw/borg/yw/bns/blobstore2/bitpusher/119.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=IMysW_vNOND4hASGt7eoDQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yw/borg/yw/bns/blobstore2/bitpusher/119.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yw/borg/yw/bns/blobstore2/bitpusher/119:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CP3elYXcDRoCGAYoATo_ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGM6ropHgHCIVMTE3MjM4MDU4ODYxOTM3NTE5MTQ0MOArSp8BEoIBeWEyOS5jLkVsb2xCcldWbUZlX1AxVDdUOHVpTXdFMHBZUjdTc2NVMDBFdEZkc2tSenBQY0NLWkhUeEZaYXI0Q25tZmR6bXFRLTNVV0kzOF9wdEx5VTZ2Z1Q3dlRBeW42Z3g4dUcyd0szSHIzaTZrV1JBZkozc1pNMGQ1allkNHpWQTAEOhZOT1RfQV9QRVJTSVNURU5UX1RPS0VO"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Upload-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UpJk7sPAiyUYXHIX3b7pUdx9Tbz4oUoggFEX6PGqfqD8OFLdIoKUyPLIjsSqkc_W8s7BaWLDxprHLNVZvlrdNRi8dL25Q"
+ ]
+ },
+ "Body": "eyJlcnJvciI6eyJlcnJvcnMiOlt7ImRvbWFpbiI6Imdsb2JhbCIsInJlYXNvbiI6ImZvcmJpZGRlbiIsIm1lc3NhZ2UiOiJpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLiIsImRlYnVnSW5mbyI6ImNvbS5nb29nbGUubmV0LnJwYzMuUnBjRXhjZXB0aW9uOiBjbG91ZC5iaWdzdG9yZS5SZXNwb25zZUNvZGUuRXJyb3JDb2RlOjpVU0VSX1BST0pFQ1RfQUNDRVNTX0RFTklFRDogaW50ZWdyYXRpb25AZ2Nsb3VkLWdvbGFuZy1maXJlc3RvcmUtdGVzdHMuaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20gZG9lcyBub3QgaGF2ZSBzZXJ2aWNldXNhZ2Uuc2VydmljZXMudXNlIGFjY2VzcyB0byBwcm9qZWN0IDY0MjA4MDkxODEwMS5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udG9ScGMzRXhjZXB0aW9uKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MTM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuQWNjZXNzQ29udHJvbHNIZWxwZXIubG9hZEJ1Y2tldChBY2Nlc3NDb250cm9sc0hlbHBlci5qYXZhOjMwMilcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLkFjY2Vzc0NvbnRyb2xzSGVscGVyLmdldEFjbFJlc291cmNlRm9yUmVxdWVzdChBY2Nlc3NDb250cm9sc0hlbHBlci5qYXZhOjczKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuVXBkYXRlQWNscy5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoVXBkYXRlQWNscy5qYXZhOjYyKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuVXBkYXRlQWNscy5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoVXBkYXRlQWNscy5qYXZhOjE2KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmZyYW1ld29yay5SZXF1ZXN0SGFuZGxlci5oYW5kbGUoUmVxdWVzdEhhbmRsZXIuamF2YToyOTQpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uQWNjZXNzQ29udHJvbHNEZWxlZ2F0b3IudXBkYXRlKEFjY2Vzc0NvbnRyb2xzRGVsZWdhdG9yLmphdmE6MTAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5ScGNSZWNlaXZlci5sYW1iZGEkcHJvY2Vzc1JlcXVlc3RBc3luYyQ0KFJwY1JlY2VpdmVyLmphdmE6MjAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5Bc3luY0V4ZWN1dG9yLmxhbWJkYSRzdWJtaXQkMChBc3luY0V4ZWN1dG9yLmphdmE6MjcyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoQ29udGV4dFJ1bm5hYmxlLmphdmE6NTApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlJDEucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM5KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo3Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5FeGVjdXRvcnMkUnVubmFibGVBZGFwdGVyLmNhbGwoRXhlY3V0b3JzLmphdmE6NTExKVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5GdXR1cmVUYXNrLnJ1bihGdXR1cmVUYXNrLmphdmE6MjY2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IucnVuV29ya2VyKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjExNDkpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvciRXb3JrZXIucnVuKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjYyNClcblx0YXQgamF2YS5sYW5nLlRocmVhZC5ydW4oVGhyZWFkLmphdmE6NzQ4KVxuQ2F1c2VkIGJ5OiBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbjogaW50ZWdyYXRpb25AZ2Nsb3VkLWdvbGFuZy1maXJlc3RvcmUtdGVzdHMuaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20gZG9lcyBub3QgaGF2ZSBzZXJ2aWNldXNhZ2Uuc2VydmljZXMudXNlIGFjY2VzcyB0byBwcm9qZWN0IDY0MjA4MDkxODEwMS5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MjkwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAxKVxuXHQuLi4gMTkgbW9yZVxuXG5jb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS5GYXVsdDogSW1tdXRhYmxlRXJyb3JEZWZpbml0aW9ue2Jhc2U9Rk9SQklEREVOLCBjYXRlZ29yeT1VU0VSX0VSUk9SLCBjYXVzZT1udWxsLCBkZWJ1Z0luZm89Y29tLmdvb2dsZS5uZXQucnBjMy5ScGNFeGNlcHRpb246IGNsb3VkLmJpZ3N0b3JlLlJlc3BvbnNlQ29kZS5FcnJvckNvZGU6OlVTRVJfUFJPSkVDVF9BQ0NFU1NfREVOSUVEOiBpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5BY2Nlc3NDb250cm9sc0hlbHBlci5sb2FkQnVja2V0KEFjY2Vzc0NvbnRyb2xzSGVscGVyLmphdmE6MzAyKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuQWNjZXNzQ29udHJvbHNIZWxwZXIuZ2V0QWNsUmVzb3VyY2VGb3JSZXF1ZXN0KEFjY2Vzc0NvbnRyb2xzSGVscGVyLmphdmE6NzMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5VcGRhdGVBY2xzLmhhbmRsZVJlcXVlc3RSZWNlaXZlZChVcGRhdGVBY2xzLmphdmE6NjIpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5VcGRhdGVBY2xzLmhhbmRsZVJlcXVlc3RSZWNlaXZlZChVcGRhdGVBY2xzLmphdmE6MTYpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5BY2Nlc3NDb250cm9sc0RlbGVnYXRvci51cGRhdGUoQWNjZXNzQ29udHJvbHNEZWxlZ2F0b3IuamF2YToxMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxOSBtb3JlXG4sIGRvbWFpbj1nbG9iYWwsIGV4dGVuZGVkSGVscD1udWxsLCBodHRwSGVhZGVycz17fSwgaHR0cFN0YXR1cz1mb3JiaWRkZW4sIGludGVybmFsUmVhc29uPVJlYXNvbnthcmd1bWVudHM9e30sIGNhdXNlPW51bGwsIGNvZGU9Z2RhdGEuQ29yZUVycm9yRG9tYWluLkZPUkJJRERFTiwgY3JlYXRlZEJ5QmFja2VuZD10cnVlLCBkZWJ1Z01lc3NhZ2U9Y29tLmdvb2dsZS5uZXQucnBjMy5ScGNFeGNlcHRpb246IGNsb3VkLmJpZ3N0b3JlLlJlc3BvbnNlQ29kZS5FcnJvckNvZGU6OlVTRVJfUFJPSkVDVF9BQ0NFU1NfREVOSUVEOiBpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5BY2Nlc3NDb250cm9sc0hlbHBlci5sb2FkQnVja2V0KEFjY2Vzc0NvbnRyb2xzSGVscGVyLmphdmE6MzAyKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuQWNjZXNzQ29udHJvbHNIZWxwZXIuZ2V0QWNsUmVzb3VyY2VGb3JSZXF1ZXN0KEFjY2Vzc0NvbnRyb2xzSGVscGVyLmphdmE6NzMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5VcGRhdGVBY2xzLmhhbmRsZVJlcXVlc3RSZWNlaXZlZChVcGRhdGVBY2xzLmphdmE6NjIpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5VcGRhdGVBY2xzLmhhbmRsZVJlcXVlc3RSZWNlaXZlZChVcGRhdGVBY2xzLmphdmE6MTYpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5BY2Nlc3NDb250cm9sc0RlbGVnYXRvci51cGRhdGUoQWNjZXNzQ29udHJvbHNEZWxlZ2F0b3IuamF2YToxMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxOSBtb3JlXG4sIGVycm9yUHJvdG9Db2RlPUZPUkJJRERFTiwgZXJyb3JQcm90b0RvbWFpbj1nZGF0YS5Db3JlRXJyb3JEb21haW4sIGZpbHRlcmVkTWVzc2FnZT1udWxsLCBsb2NhdGlvbj1udWxsLCBtZXNzYWdlPWludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIGRvZXMgbm90IGhhdmUgc2VydmljZXVzYWdlLnNlcnZpY2VzLnVzZSBhY2Nlc3MgdG8gcHJvamVjdCA2NDIwODA5MTgxMDEuLCB1bm5hbWVkQXJndW1lbnRzPVtdfSwgbG9jYXRpb249bnVsbCwgbWVzc2FnZT1pbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLiwgcmVhc29uPWZvcmJpZGRlbiwgcnBjQ29kZT00MDN9IGludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIGRvZXMgbm90IGhhdmUgc2VydmljZXVzYWdlLnNlcnZpY2VzLnVzZSBhY2Nlc3MgdG8gcHJvamVjdCA2NDIwODA5MTgxMDEuOiBjb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6VVNFUl9QUk9KRUNUX0FDQ0VTU19ERU5JRUQ6IGludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIGRvZXMgbm90IGhhdmUgc2VydmljZXVzYWdlLnNlcnZpY2VzLnVzZSBhY2Nlc3MgdG8gcHJvamVjdCA2NDIwODA5MTgxMDEuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRvUnBjM0V4Y2VwdGlvbihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjEzNSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLkFjY2Vzc0NvbnRyb2xzSGVscGVyLmxvYWRCdWNrZXQoQWNjZXNzQ29udHJvbHNIZWxwZXIuamF2YTozMDIpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5BY2Nlc3NDb250cm9sc0hlbHBlci5nZXRBY2xSZXNvdXJjZUZvclJlcXVlc3QoQWNjZXNzQ29udHJvbHNIZWxwZXIuamF2YTo3Mylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLlVwZGF0ZUFjbHMuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKFVwZGF0ZUFjbHMuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLlVwZGF0ZUFjbHMuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKFVwZGF0ZUFjbHMuamF2YToxNilcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLkFjY2Vzc0NvbnRyb2xzRGVsZWdhdG9yLnVwZGF0ZShBY2Nlc3NDb250cm9sc0RlbGVnYXRvci5qYXZhOjEwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uUnBjUmVjZWl2ZXIubGFtYmRhJHByb2Nlc3NSZXF1ZXN0QXN5bmMkNChScGNSZWNlaXZlci5qYXZhOjIwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uQXN5bmNFeGVjdXRvci5sYW1iZGEkc3VibWl0JDAoQXN5bmNFeGVjdXRvci5qYXZhOjI3Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KENvbnRleHRSdW5uYWJsZS5qYXZhOjUwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZSQxLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozOSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NzIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozNilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRXhlY3V0b3JzJFJ1bm5hYmxlQWRhcHRlci5jYWxsKEV4ZWN1dG9ycy5qYXZhOjUxMSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRnV0dXJlVGFzay5ydW4oRnV0dXJlVGFzay5qYXZhOjI2Nilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yLnJ1bldvcmtlcihUaHJlYWRQb29sRXhlY3V0b3IuamF2YToxMTQ5KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IkV29ya2VyLnJ1bihUaHJlYWRQb29sRXhlY3V0b3IuamF2YTo2MjQpXG5cdGF0IGphdmEubGFuZy5UaHJlYWQucnVuKFRocmVhZC5qYXZhOjc0OClcbkNhdXNlZCBieTogY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb246IGludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIGRvZXMgbm90IGhhdmUgc2VydmljZXVzYWdlLnNlcnZpY2VzLnVzZSBhY2Nlc3MgdG8gcHJvamVjdCA2NDIwODA5MTgxMDEuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93T25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjI5MClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMSlcblx0Li4uIDE5IG1vcmVcblxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS5FcnJvckNvbGxlY3Rvci50b0ZhdWx0KEVycm9yQ29sbGVjdG9yLmphdmE6NTQpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5yZXN0LmFkYXB0ZXIucm9zeS5Sb3N5RXJyb3JDb252ZXJ0ZXIudG9GYXVsdChSb3N5RXJyb3JDb252ZXJ0ZXIuamF2YTo2Nylcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnJlc3QuYWRhcHRlci5yb3N5LlJvc3lIYW5kbGVyJDIuY2FsbChSb3N5SGFuZGxlci5qYXZhOjI1OClcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnJlc3QuYWRhcHRlci5yb3N5LlJvc3lIYW5kbGVyJDIuY2FsbChSb3N5SGFuZGxlci5qYXZhOjIzOClcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkRpcmVjdEV4ZWN1dG9yLmV4ZWN1dGUoRGlyZWN0RXhlY3V0b3IuamF2YTozMClcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmV4ZWN1dGVMaXN0ZW5lcihBYnN0cmFjdEZ1dHVyZS5qYXZhOjExNDMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5jb21wbGV0ZShBYnN0cmFjdEZ1dHVyZS5qYXZhOjk2Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLnNldChBYnN0cmFjdEZ1dHVyZS5qYXZhOjczMSlcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkRpcmVjdEV4ZWN1dG9yLmV4ZWN1dGUoRGlyZWN0RXhlY3V0b3IuamF2YTozMClcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmV4ZWN1dGVMaXN0ZW5lcihBYnN0cmFjdEZ1dHVyZS5qYXZhOjExNDMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5jb21wbGV0ZShBYnN0cmFjdEZ1dHVyZS5qYXZhOjk2Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLnNldChBYnN0cmFjdEZ1dHVyZS5qYXZhOjczMSlcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnRocmVhZC5UaHJlYWRUcmFja2VycyRUaHJlYWRUcmFja2luZ1J1bm5hYmxlLnJ1bihUaHJlYWRUcmFja2Vycy5qYXZhOjEyNilcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRUcmFjZUNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoVHJhY2VDb250ZXh0LmphdmE6NDU1KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuc2VydmVyLkNvbW1vbk1vZHVsZSRDb250ZXh0Q2FycnlpbmdFeGVjdXRvclNlcnZpY2UkMS5ydW5JbkNvbnRleHQoQ29tbW9uTW9kdWxlLmphdmE6ODQ2KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JFRyYWNlQ29udGV4dFJ1bm5hYmxlJDEucnVuKFRyYWNlQ29udGV4dC5qYXZhOjQ2Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRBYnN0cmFjdFRyYWNlQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoVHJhY2VDb250ZXh0LmphdmE6MzIxKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JEFic3RyYWN0VHJhY2VDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KFRyYWNlQ29udGV4dC5qYXZhOjMxMylcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRUcmFjZUNvbnRleHRSdW5uYWJsZS5ydW4oVHJhY2VDb250ZXh0LmphdmE6NDU5KVxuXHRhdCBjb20uZ29vZ2xlLmdzZS5pbnRlcm5hbC5EaXNwYXRjaFF1ZXVlSW1wbCRXb3JrZXJUaHJlYWQucnVuKERpc3BhdGNoUXVldWVJbXBsLmphdmE6NDAzKVxuIn1dLCJjb2RlIjo0MDMsIm1lc3NhZ2UiOiJpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLiJ9fQ=="
+ }
+ },
+ {
+ "ID": "bb9370a582ea35c1",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/defaultObjectAcl?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "8d13bbf15b8d9e35da61ec13ef0e93b3/11662759486128807158;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/defaultObjectAcl?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0, must-revalidate, no-transform"
+ ],
+ "Content-Length": [
+ "678"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:05 GMT"
+ ],
+ "Etag": [
+ "CAU="
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:25:05 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051395000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrb20:4129,/bns/yw/borg/yw/bns/blobstore2/bitpusher/92.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=IcysW9-gCI6ihgSxjr6wDQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yw/borg/yw/bns/blobstore2/bitpusher/92.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yw/borg/yw/bns/blobstore2/bitpusher/92:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATpxChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4CtK4wESxgF5YTI5LmMuRW93QkpRWVNNdC1OVDFNYTJvWXBrbG1qcDlJMlZaUFZ5bFl5Z2Q3Nk5tQXlXbWR3WVBoMm00dGI3ZmZjOUlzcTU4MmVFcFBhNzhNWGpNZmIzaE9WTE9xRHpNTUFfTG9NQXVJZkdkMGgzSWowZ1dxdW5DS1g3Qk1mQlJxM001TUtMMXBHOWNyU0ZBT29lVkZpTDhpWlBsUDI0VjE5THdzZ0d1ZnVrQTFtVzVJcTJUUkVXeWQyNjRKZC1lS2UxdTAwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UrZmpWXIqiS9e6JgaqJiMGL30-HJaSgAUfANzdlVtP-GiI--njgNt8qDy-LT1yu47R5C_f0X4ArHWNC-OXuizlu2OoNHg"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9scyIsIml0ZW1zIjpbeyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDQVU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiZW50aXR5IjoicHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6ImVkaXRvcnMifSwiZXRhZyI6IkNBVT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNBVT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJkb21haW4tZ29vZ2xlLmNvbSIsInJvbGUiOiJSRUFERVIiLCJkb21haW4iOiJnb29nbGUuY29tIiwiZXRhZyI6IkNBVT0ifV19"
+ }
+ },
+ {
+ "ID": "24b48182f16f05b6",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/defaultObjectAcl?alt=json\u0026prettyPrint=false\u0026userProject=dulcet-port-762",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "3bf956ba1efb5a77c3b978c0abf5a331/13253170286389428885;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/defaultObjectAcl?alt=json\u0026prettyPrint=false\u0026userProject=dulcet-port-762"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0, must-revalidate, no-transform"
+ ],
+ "Content-Length": [
+ "678"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:05 GMT"
+ ],
+ "Etag": [
+ "CAU="
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:25:05 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051389000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vnr74:4261,/bns/yx/borg/yx/bns/blobstore2/bitpusher/53.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=IcysW6CoGYKLzgKstYqwBg"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yx/borg/yx/bns/blobstore2/bitpusher/53.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yx/borg/yx/bns/blobstore2/bitpusher/53:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATpxChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4CtK4wESxgF5YTI5LmMuRW93QkpRWVNNdC1OVDFNYTJvWXBrbG1qcDlJMlZaUFZ5bFl5Z2Q3Nk5tQXlXbWR3WVBoMm00dGI3ZmZjOUlzcTU4MmVFcFBhNzhNWGpNZmIzaE9WTE9xRHpNTUFfTG9NQXVJZkdkMGgzSWowZ1dxdW5DS1g3Qk1mQlJxM001TUtMMXBHOWNyU0ZBT29lVkZpTDhpWlBsUDI0VjE5THdzZ0d1ZnVrQTFtVzVJcTJUUkVXeWQyNjRKZC1lS2UxdTAwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UonBZeDWAS_5Xu3_JmgDldw4OBggGFhY08awH4tPbbcjtN2P0YNvAPPRM1Yx9HlZU8iEgUbR7QkE3xFzZaP3Yosb8LYPA"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9scyIsIml0ZW1zIjpbeyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDQVU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiZW50aXR5IjoicHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6ImVkaXRvcnMifSwiZXRhZyI6IkNBVT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNBVT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJkb21haW4tZ29vZ2xlLmNvbSIsInJvbGUiOiJSRUFERVIiLCJkb21haW4iOiJnb29nbGUuY29tIiwiZXRhZyI6IkNBVT0ifV19"
+ }
+ },
+ {
+ "ID": "ce844c26f10c0e3b",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/defaultObjectAcl?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "d5c7b6eaaa27d2b42f81b33c9de5cedc/14843582190456645427;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/defaultObjectAcl?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 400,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0"
+ ],
+ "Content-Length": [
+ "13087"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:06 GMT"
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:25:06 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051395000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "471383502717"
+ ],
+ "X-Google-Backends": [
+ "vrcb130:4200,/bns/yv/borg/yv/bns/blobstore2/bitpusher/26.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=IcysW4DtMZPMgwTatbbQAg"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/26.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/26:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CP3elYXcDRoCGAYoATo_ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGM6ropHgHCIVMTE3MjM4MDU4ODYxOTM3NTE5MTQ0MOArSp8BEoIBeWEyOS5jLkVsb2xCcldWbUZlX1AxVDdUOHVpTXdFMHBZUjdTc2NVMDBFdEZkc2tSenBQY0NLWkhUeEZaYXI0Q25tZmR6bXFRLTNVV0kzOF9wdEx5VTZ2Z1Q3dlRBeW42Z3g4dUcyd0szSHIzaTZrV1JBZkozc1pNMGQ1allkNHpWQTAEOhZOT1RfQV9QRVJTSVNURU5UX1RPS0VO"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Upload-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UotQ-yZb_9zj9TYZYqpQNrytARZW-m2uHS9_ifyhpLIvSqktqIJboultvlXy8j4pdBnvnmfWDDNoyeewfOgLC9XJAOckg"
+ ]
+ },
+ "Body": "eyJlcnJvciI6eyJlcnJvcnMiOlt7ImRvbWFpbiI6Imdsb2JhbCIsInJlYXNvbiI6InJlcXVpcmVkIiwibWVzc2FnZSI6IkJ1Y2tldCBpcyByZXF1ZXN0ZXIgcGF5cyBidWNrZXQgYnV0IG5vIHVzZXIgcHJvamVjdCBwcm92aWRlZC4iLCJkZWJ1Z0luZm8iOiJjb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6VVNFUl9QUk9KRUNUX01JU1NJTkc6IEJ1Y2tldCBpcyBSZXF1ZXN0ZXIgUGF5cyBidWNrZXQgYnV0IG5vIGJpbGxpbmcgcHJvamVjdCBpZCBwcm92aWRlZCBmb3Igbm9uLW93bmVyLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5BY2Nlc3NDb250cm9sc0hlbHBlci5sb2FkQnVja2V0KEFjY2Vzc0NvbnRyb2xzSGVscGVyLmphdmE6MzAyKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuQWNjZXNzQ29udHJvbHNIZWxwZXIuZ2V0QWNsUmVzb3VyY2VGb3JSZXF1ZXN0KEFjY2Vzc0NvbnRyb2xzSGVscGVyLmphdmE6NzMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5MaXN0QWNscy5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoTGlzdEFjbHMuamF2YTo4NSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLkxpc3RBY2xzLmhhbmRsZVJlcXVlc3RSZWNlaXZlZChMaXN0QWNscy5qYXZhOjIwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmZyYW1ld29yay5SZXF1ZXN0SGFuZGxlci5oYW5kbGUoUmVxdWVzdEhhbmRsZXIuamF2YToyOTQpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uQWNjZXNzQ29udHJvbHNEZWxlZ2F0b3IubGlzdChBY2Nlc3NDb250cm9sc0RlbGVnYXRvci5qYXZhOjg5KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5ScGNSZWNlaXZlci5sYW1iZGEkcHJvY2Vzc1JlcXVlc3RBc3luYyQ0KFJwY1JlY2VpdmVyLmphdmE6MjAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5Bc3luY0V4ZWN1dG9yLmxhbWJkYSRzdWJtaXQkMChBc3luY0V4ZWN1dG9yLmphdmE6MjcyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoQ29udGV4dFJ1bm5hYmxlLmphdmE6NTApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlJDEucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM5KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo3Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5FeGVjdXRvcnMkUnVubmFibGVBZGFwdGVyLmNhbGwoRXhlY3V0b3JzLmphdmE6NTExKVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5GdXR1cmVUYXNrLnJ1bihGdXR1cmVUYXNrLmphdmE6MjY2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IucnVuV29ya2VyKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjExNDkpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvciRXb3JrZXIucnVuKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjYyNClcblx0YXQgamF2YS5sYW5nLlRocmVhZC5ydW4oVGhyZWFkLmphdmE6NzQ4KVxuQ2F1c2VkIGJ5OiBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbjogQnVja2V0IGlzIFJlcXVlc3RlciBQYXlzIGJ1Y2tldCBidXQgbm8gYmlsbGluZyBwcm9qZWN0IGlkIHByb3ZpZGVkIGZvciBub24tb3duZXIuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93T25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjI5MClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMSlcblx0Li4uIDE5IG1vcmVcblxuY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUuRmF1bHQ6IEltbXV0YWJsZUVycm9yRGVmaW5pdGlvbntiYXNlPVJFUVVJUkVELCBjYXRlZ29yeT1VU0VSX0VSUk9SLCBjYXVzZT1udWxsLCBkZWJ1Z0luZm89Y29tLmdvb2dsZS5uZXQucnBjMy5ScGNFeGNlcHRpb246IGNsb3VkLmJpZ3N0b3JlLlJlc3BvbnNlQ29kZS5FcnJvckNvZGU6OlVTRVJfUFJPSkVDVF9NSVNTSU5HOiBCdWNrZXQgaXMgUmVxdWVzdGVyIFBheXMgYnVja2V0IGJ1dCBubyBiaWxsaW5nIHByb2plY3QgaWQgcHJvdmlkZWQgZm9yIG5vbi1vd25lci5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udG9ScGMzRXhjZXB0aW9uKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MTM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuQWNjZXNzQ29udHJvbHNIZWxwZXIubG9hZEJ1Y2tldChBY2Nlc3NDb250cm9sc0hlbHBlci5qYXZhOjMwMilcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLkFjY2Vzc0NvbnRyb2xzSGVscGVyLmdldEFjbFJlc291cmNlRm9yUmVxdWVzdChBY2Nlc3NDb250cm9sc0hlbHBlci5qYXZhOjczKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuTGlzdEFjbHMuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKExpc3RBY2xzLmphdmE6ODUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5MaXN0QWNscy5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoTGlzdEFjbHMuamF2YToyMClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLkFjY2Vzc0NvbnRyb2xzRGVsZWdhdG9yLmxpc3QoQWNjZXNzQ29udHJvbHNEZWxlZ2F0b3IuamF2YTo4OSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uUnBjUmVjZWl2ZXIubGFtYmRhJHByb2Nlc3NSZXF1ZXN0QXN5bmMkNChScGNSZWNlaXZlci5qYXZhOjIwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uQXN5bmNFeGVjdXRvci5sYW1iZGEkc3VibWl0JDAoQXN5bmNFeGVjdXRvci5qYXZhOjI3Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KENvbnRleHRSdW5uYWJsZS5qYXZhOjUwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZSQxLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozOSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NzIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozNilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRXhlY3V0b3JzJFJ1bm5hYmxlQWRhcHRlci5jYWxsKEV4ZWN1dG9ycy5qYXZhOjUxMSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRnV0dXJlVGFzay5ydW4oRnV0dXJlVGFzay5qYXZhOjI2Nilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yLnJ1bldvcmtlcihUaHJlYWRQb29sRXhlY3V0b3IuamF2YToxMTQ5KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IkV29ya2VyLnJ1bihUaHJlYWRQb29sRXhlY3V0b3IuamF2YTo2MjQpXG5cdGF0IGphdmEubGFuZy5UaHJlYWQucnVuKFRocmVhZC5qYXZhOjc0OClcbkNhdXNlZCBieTogY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb246IEJ1Y2tldCBpcyBSZXF1ZXN0ZXIgUGF5cyBidWNrZXQgYnV0IG5vIGJpbGxpbmcgcHJvamVjdCBpZCBwcm92aWRlZCBmb3Igbm9uLW93bmVyLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxOSBtb3JlXG4sIGRvbWFpbj1nbG9iYWwsIGV4dGVuZGVkSGVscD1udWxsLCBodHRwSGVhZGVycz17fSwgaHR0cFN0YXR1cz1iYWRSZXF1ZXN0LCBpbnRlcm5hbFJlYXNvbj1SZWFzb257YXJndW1lbnRzPXt9LCBjYXVzZT1udWxsLCBjb2RlPWdkYXRhLkNvcmVFcnJvckRvbWFpbi5SRVFVSVJFRCwgY3JlYXRlZEJ5QmFja2VuZD10cnVlLCBkZWJ1Z01lc3NhZ2U9Y29tLmdvb2dsZS5uZXQucnBjMy5ScGNFeGNlcHRpb246IGNsb3VkLmJpZ3N0b3JlLlJlc3BvbnNlQ29kZS5FcnJvckNvZGU6OlVTRVJfUFJPSkVDVF9NSVNTSU5HOiBCdWNrZXQgaXMgUmVxdWVzdGVyIFBheXMgYnVja2V0IGJ1dCBubyBiaWxsaW5nIHByb2plY3QgaWQgcHJvdmlkZWQgZm9yIG5vbi1vd25lci5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udG9ScGMzRXhjZXB0aW9uKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MTM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuQWNjZXNzQ29udHJvbHNIZWxwZXIubG9hZEJ1Y2tldChBY2Nlc3NDb250cm9sc0hlbHBlci5qYXZhOjMwMilcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLkFjY2Vzc0NvbnRyb2xzSGVscGVyLmdldEFjbFJlc291cmNlRm9yUmVxdWVzdChBY2Nlc3NDb250cm9sc0hlbHBlci5qYXZhOjczKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuTGlzdEFjbHMuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKExpc3RBY2xzLmphdmE6ODUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5MaXN0QWNscy5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoTGlzdEFjbHMuamF2YToyMClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLkFjY2Vzc0NvbnRyb2xzRGVsZWdhdG9yLmxpc3QoQWNjZXNzQ29udHJvbHNEZWxlZ2F0b3IuamF2YTo4OSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uUnBjUmVjZWl2ZXIubGFtYmRhJHByb2Nlc3NSZXF1ZXN0QXN5bmMkNChScGNSZWNlaXZlci5qYXZhOjIwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uQXN5bmNFeGVjdXRvci5sYW1iZGEkc3VibWl0JDAoQXN5bmNFeGVjdXRvci5qYXZhOjI3Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KENvbnRleHRSdW5uYWJsZS5qYXZhOjUwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZSQxLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozOSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NzIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozNilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRXhlY3V0b3JzJFJ1bm5hYmxlQWRhcHRlci5jYWxsKEV4ZWN1dG9ycy5qYXZhOjUxMSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRnV0dXJlVGFzay5ydW4oRnV0dXJlVGFzay5qYXZhOjI2Nilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yLnJ1bldvcmtlcihUaHJlYWRQb29sRXhlY3V0b3IuamF2YToxMTQ5KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IkV29ya2VyLnJ1bihUaHJlYWRQb29sRXhlY3V0b3IuamF2YTo2MjQpXG5cdGF0IGphdmEubGFuZy5UaHJlYWQucnVuKFRocmVhZC5qYXZhOjc0OClcbkNhdXNlZCBieTogY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb246IEJ1Y2tldCBpcyBSZXF1ZXN0ZXIgUGF5cyBidWNrZXQgYnV0IG5vIGJpbGxpbmcgcHJvamVjdCBpZCBwcm92aWRlZCBmb3Igbm9uLW93bmVyLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxOSBtb3JlXG4sIGVycm9yUHJvdG9Db2RlPVJFUVVJUkVELCBlcnJvclByb3RvRG9tYWluPWdkYXRhLkNvcmVFcnJvckRvbWFpbiwgZmlsdGVyZWRNZXNzYWdlPW51bGwsIGxvY2F0aW9uPW51bGwsIG1lc3NhZ2U9QnVja2V0IGlzIHJlcXVlc3RlciBwYXlzIGJ1Y2tldCBidXQgbm8gdXNlciBwcm9qZWN0IHByb3ZpZGVkLiwgdW5uYW1lZEFyZ3VtZW50cz1bXX0sIGxvY2F0aW9uPW51bGwsIG1lc3NhZ2U9QnVja2V0IGlzIHJlcXVlc3RlciBwYXlzIGJ1Y2tldCBidXQgbm8gdXNlciBwcm9qZWN0IHByb3ZpZGVkLiwgcmVhc29uPXJlcXVpcmVkLCBycGNDb2RlPTQwMH0gQnVja2V0IGlzIHJlcXVlc3RlciBwYXlzIGJ1Y2tldCBidXQgbm8gdXNlciBwcm9qZWN0IHByb3ZpZGVkLjogY29tLmdvb2dsZS5uZXQucnBjMy5ScGNFeGNlcHRpb246IGNsb3VkLmJpZ3N0b3JlLlJlc3BvbnNlQ29kZS5FcnJvckNvZGU6OlVTRVJfUFJPSkVDVF9NSVNTSU5HOiBCdWNrZXQgaXMgUmVxdWVzdGVyIFBheXMgYnVja2V0IGJ1dCBubyBiaWxsaW5nIHByb2plY3QgaWQgcHJvdmlkZWQgZm9yIG5vbi1vd25lci5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udG9ScGMzRXhjZXB0aW9uKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MTM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuQWNjZXNzQ29udHJvbHNIZWxwZXIubG9hZEJ1Y2tldChBY2Nlc3NDb250cm9sc0hlbHBlci5qYXZhOjMwMilcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLkFjY2Vzc0NvbnRyb2xzSGVscGVyLmdldEFjbFJlc291cmNlRm9yUmVxdWVzdChBY2Nlc3NDb250cm9sc0hlbHBlci5qYXZhOjczKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuTGlzdEFjbHMuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKExpc3RBY2xzLmphdmE6ODUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5MaXN0QWNscy5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoTGlzdEFjbHMuamF2YToyMClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLkFjY2Vzc0NvbnRyb2xzRGVsZWdhdG9yLmxpc3QoQWNjZXNzQ29udHJvbHNEZWxlZ2F0b3IuamF2YTo4OSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uUnBjUmVjZWl2ZXIubGFtYmRhJHByb2Nlc3NSZXF1ZXN0QXN5bmMkNChScGNSZWNlaXZlci5qYXZhOjIwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uQXN5bmNFeGVjdXRvci5sYW1iZGEkc3VibWl0JDAoQXN5bmNFeGVjdXRvci5qYXZhOjI3Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KENvbnRleHRSdW5uYWJsZS5qYXZhOjUwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZSQxLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozOSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NzIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozNilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRXhlY3V0b3JzJFJ1bm5hYmxlQWRhcHRlci5jYWxsKEV4ZWN1dG9ycy5qYXZhOjUxMSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRnV0dXJlVGFzay5ydW4oRnV0dXJlVGFzay5qYXZhOjI2Nilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yLnJ1bldvcmtlcihUaHJlYWRQb29sRXhlY3V0b3IuamF2YToxMTQ5KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IkV29ya2VyLnJ1bihUaHJlYWRQb29sRXhlY3V0b3IuamF2YTo2MjQpXG5cdGF0IGphdmEubGFuZy5UaHJlYWQucnVuKFRocmVhZC5qYXZhOjc0OClcbkNhdXNlZCBieTogY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb246IEJ1Y2tldCBpcyBSZXF1ZXN0ZXIgUGF5cyBidWNrZXQgYnV0IG5vIGJpbGxpbmcgcHJvamVjdCBpZCBwcm92aWRlZCBmb3Igbm9uLW93bmVyLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxOSBtb3JlXG5cblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUuRXJyb3JDb2xsZWN0b3IudG9GYXVsdChFcnJvckNvbGxlY3Rvci5qYXZhOjU0KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIucmVzdC5hZGFwdGVyLnJvc3kuUm9zeUVycm9yQ29udmVydGVyLnRvRmF1bHQoUm9zeUVycm9yQ29udmVydGVyLmphdmE6NjcpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5yZXN0LmFkYXB0ZXIucm9zeS5Sb3N5SGFuZGxlciQyLmNhbGwoUm9zeUhhbmRsZXIuamF2YToyNTgpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5yZXN0LmFkYXB0ZXIucm9zeS5Sb3N5SGFuZGxlciQyLmNhbGwoUm9zeUhhbmRsZXIuamF2YToyMzgpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLnV0aWwuQ2FsbGFibGVGdXR1cmUucnVuKENhbGxhYmxlRnV0dXJlLmphdmE6NjIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5EaXJlY3RFeGVjdXRvci5leGVjdXRlKERpcmVjdEV4ZWN1dG9yLmphdmE6MzApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5leGVjdXRlTGlzdGVuZXIoQWJzdHJhY3RGdXR1cmUuamF2YToxMTQzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuY29tcGxldGUoQWJzdHJhY3RGdXR1cmUuamF2YTo5NjMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5zZXQoQWJzdHJhY3RGdXR1cmUuamF2YTo3MzEpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLnV0aWwuQ2FsbGFibGVGdXR1cmUucnVuKENhbGxhYmxlRnV0dXJlLmphdmE6NjIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5EaXJlY3RFeGVjdXRvci5leGVjdXRlKERpcmVjdEV4ZWN1dG9yLmphdmE6MzApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5leGVjdXRlTGlzdGVuZXIoQWJzdHJhY3RGdXR1cmUuamF2YToxMTQzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuY29tcGxldGUoQWJzdHJhY3RGdXR1cmUuamF2YTo5NjMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5zZXQoQWJzdHJhY3RGdXR1cmUuamF2YTo3MzEpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLnV0aWwuQ2FsbGFibGVGdXR1cmUucnVuKENhbGxhYmxlRnV0dXJlLmphdmE6NjIpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci50aHJlYWQuVGhyZWFkVHJhY2tlcnMkVGhyZWFkVHJhY2tpbmdSdW5uYWJsZS5ydW4oVGhyZWFkVHJhY2tlcnMuamF2YToxMjYpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkVHJhY2VDb250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KFRyYWNlQ29udGV4dC5qYXZhOjQ1NSlcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnNlcnZlci5Db21tb25Nb2R1bGUkQ29udGV4dENhcnJ5aW5nRXhlY3V0b3JTZXJ2aWNlJDEucnVuSW5Db250ZXh0KENvbW1vbk1vZHVsZS5qYXZhOjg0Nilcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRUcmFjZUNvbnRleHRSdW5uYWJsZSQxLnJ1bihUcmFjZUNvbnRleHQuamF2YTo0NjIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkQWJzdHJhY3RUcmFjZUNvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKFRyYWNlQ29udGV4dC5qYXZhOjMyMSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRBYnN0cmFjdFRyYWNlQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChUcmFjZUNvbnRleHQuamF2YTozMTMpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkVHJhY2VDb250ZXh0UnVubmFibGUucnVuKFRyYWNlQ29udGV4dC5qYXZhOjQ1OSlcblx0YXQgY29tLmdvb2dsZS5nc2UuaW50ZXJuYWwuRGlzcGF0Y2hRdWV1ZUltcGwkV29ya2VyVGhyZWFkLnJ1bihEaXNwYXRjaFF1ZXVlSW1wbC5qYXZhOjQwMylcbiJ9XSwiY29kZSI6NDAwLCJtZXNzYWdlIjoiQnVja2V0IGlzIHJlcXVlc3RlciBwYXlzIGJ1Y2tldCBidXQgbm8gdXNlciBwcm9qZWN0IHByb3ZpZGVkLiJ9fQ=="
+ }
+ },
+ {
+ "ID": "ff92114e4faebe3b",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/defaultObjectAcl?alt=json\u0026prettyPrint=false\u0026userProject=gcloud-golang-firestore-tests",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "06faed11abba0b027858e49c6ddf6a29/16361656129315753170;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/defaultObjectAcl?alt=json\u0026prettyPrint=false\u0026userProject=gcloud-golang-firestore-tests"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0, must-revalidate, no-transform"
+ ],
+ "Content-Length": [
+ "678"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:06 GMT"
+ ],
+ "Etag": [
+ "CAU="
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:25:06 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051395000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "471383502717"
+ ],
+ "X-Google-Backends": [
+ "vrbd63:4301,/bns/yr/borg/yr/bns/blobstore2/bitpusher/21.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=IsysW5DQAc-M4QTB1K2YAw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/21.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/21:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CP3elYXcDRoCGAYoATo_ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGM6ropHgHCIVMTE3MjM4MDU4ODYxOTM3NTE5MTQ0MOArSp8BEoIBeWEyOS5jLkVsb2xCcldWbUZlX1AxVDdUOHVpTXdFMHBZUjdTc2NVMDBFdEZkc2tSenBQY0NLWkhUeEZaYXI0Q25tZmR6bXFRLTNVV0kzOF9wdEx5VTZ2Z1Q3dlRBeW42Z3g4dUcyd0szSHIzaTZrV1JBZkozc1pNMGQ1allkNHpWQTAEOhZOT1RfQV9QRVJTSVNURU5UX1RPS0VO"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Uq9Kb4Jr0nsQHMgXynyXRsWFwmHcVDFVL1weQDJIiWnadnHl4wU7pIGAbTmZ7GL9YeHKX4nLJL8GPuTkz3DQSh-z9WXfw"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9scyIsIml0ZW1zIjpbeyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDQVU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiZW50aXR5IjoicHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6ImVkaXRvcnMifSwiZXRhZyI6IkNBVT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNBVT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJkb21haW4tZ29vZ2xlLmNvbSIsInJvbGUiOiJSRUFERVIiLCJkb21haW4iOiJnb29nbGUuY29tIiwiZXRhZyI6IkNBVT0ifV19"
+ }
+ },
+ {
+ "ID": "7f3358fa545fcd20",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/defaultObjectAcl?alt=json\u0026prettyPrint=false\u0026userProject=veener-jba",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "4d8caf7f58e94fb261d8a3d56590928b/17952068029071290992;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/defaultObjectAcl?alt=json\u0026prettyPrint=false\u0026userProject=veener-jba"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 403,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0"
+ ],
+ "Content-Length": [
+ "13943"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:06 GMT"
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:25:06 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051395000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "471383502717"
+ ],
+ "X-Google-Backends": [
+ "vrwa10:4354,/bns/yv/borg/yv/bns/blobstore2/bitpusher/182.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=IsysW42tBtWFgQSM1K-oDQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/182.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/182:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CP3elYXcDRoCGAYoATo_ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGM6ropHgHCIVMTE3MjM4MDU4ODYxOTM3NTE5MTQ0MOArSp8BEoIBeWEyOS5jLkVsb2xCcldWbUZlX1AxVDdUOHVpTXdFMHBZUjdTc2NVMDBFdEZkc2tSenBQY0NLWkhUeEZaYXI0Q25tZmR6bXFRLTNVV0kzOF9wdEx5VTZ2Z1Q3dlRBeW42Z3g4dUcyd0szSHIzaTZrV1JBZkozc1pNMGQ1allkNHpWQTAEOhZOT1RfQV9QRVJTSVNURU5UX1RPS0VO"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Upload-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UrpCrljVA9hmFfcCUZ6ginYuMdaH-ak_I_6bNEq0ajgeC9v9yvTUmHRt5JF9futhNCB1d2AgmMOvfvjrT0q38ONS_dGhojwkaJq1TthxI2Q3GFSu_M"
+ ]
+ },
+ "Body": "eyJlcnJvciI6eyJlcnJvcnMiOlt7ImRvbWFpbiI6Imdsb2JhbCIsInJlYXNvbiI6ImZvcmJpZGRlbiIsIm1lc3NhZ2UiOiJpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLiIsImRlYnVnSW5mbyI6ImNvbS5nb29nbGUubmV0LnJwYzMuUnBjRXhjZXB0aW9uOiBjbG91ZC5iaWdzdG9yZS5SZXNwb25zZUNvZGUuRXJyb3JDb2RlOjpVU0VSX1BST0pFQ1RfQUNDRVNTX0RFTklFRDogaW50ZWdyYXRpb25AZ2Nsb3VkLWdvbGFuZy1maXJlc3RvcmUtdGVzdHMuaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20gZG9lcyBub3QgaGF2ZSBzZXJ2aWNldXNhZ2Uuc2VydmljZXMudXNlIGFjY2VzcyB0byBwcm9qZWN0IDY0MjA4MDkxODEwMS5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udG9ScGMzRXhjZXB0aW9uKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MTM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuQWNjZXNzQ29udHJvbHNIZWxwZXIubG9hZEJ1Y2tldChBY2Nlc3NDb250cm9sc0hlbHBlci5qYXZhOjMwMilcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLkFjY2Vzc0NvbnRyb2xzSGVscGVyLmdldEFjbFJlc291cmNlRm9yUmVxdWVzdChBY2Nlc3NDb250cm9sc0hlbHBlci5qYXZhOjczKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuTGlzdEFjbHMuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKExpc3RBY2xzLmphdmE6ODUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5MaXN0QWNscy5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoTGlzdEFjbHMuamF2YToyMClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLkFjY2Vzc0NvbnRyb2xzRGVsZWdhdG9yLmxpc3QoQWNjZXNzQ29udHJvbHNEZWxlZ2F0b3IuamF2YTo4OSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uUnBjUmVjZWl2ZXIubGFtYmRhJHByb2Nlc3NSZXF1ZXN0QXN5bmMkNChScGNSZWNlaXZlci5qYXZhOjIwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uQXN5bmNFeGVjdXRvci5sYW1iZGEkc3VibWl0JDAoQXN5bmNFeGVjdXRvci5qYXZhOjI3Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KENvbnRleHRSdW5uYWJsZS5qYXZhOjUwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZSQxLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozOSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NzIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozNilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRXhlY3V0b3JzJFJ1bm5hYmxlQWRhcHRlci5jYWxsKEV4ZWN1dG9ycy5qYXZhOjUxMSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRnV0dXJlVGFzay5ydW4oRnV0dXJlVGFzay5qYXZhOjI2Nilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yLnJ1bldvcmtlcihUaHJlYWRQb29sRXhlY3V0b3IuamF2YToxMTQ5KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IkV29ya2VyLnJ1bihUaHJlYWRQb29sRXhlY3V0b3IuamF2YTo2MjQpXG5cdGF0IGphdmEubGFuZy5UaHJlYWQucnVuKFRocmVhZC5qYXZhOjc0OClcbkNhdXNlZCBieTogY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb246IGludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIGRvZXMgbm90IGhhdmUgc2VydmljZXVzYWdlLnNlcnZpY2VzLnVzZSBhY2Nlc3MgdG8gcHJvamVjdCA2NDIwODA5MTgxMDEuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93T25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjI5MClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMSlcblx0Li4uIDE5IG1vcmVcblxuY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUuRmF1bHQ6IEltbXV0YWJsZUVycm9yRGVmaW5pdGlvbntiYXNlPUZPUkJJRERFTiwgY2F0ZWdvcnk9VVNFUl9FUlJPUiwgY2F1c2U9bnVsbCwgZGVidWdJbmZvPWNvbS5nb29nbGUubmV0LnJwYzMuUnBjRXhjZXB0aW9uOiBjbG91ZC5iaWdzdG9yZS5SZXNwb25zZUNvZGUuRXJyb3JDb2RlOjpVU0VSX1BST0pFQ1RfQUNDRVNTX0RFTklFRDogaW50ZWdyYXRpb25AZ2Nsb3VkLWdvbGFuZy1maXJlc3RvcmUtdGVzdHMuaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20gZG9lcyBub3QgaGF2ZSBzZXJ2aWNldXNhZ2Uuc2VydmljZXMudXNlIGFjY2VzcyB0byBwcm9qZWN0IDY0MjA4MDkxODEwMS5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udG9ScGMzRXhjZXB0aW9uKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MTM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuQWNjZXNzQ29udHJvbHNIZWxwZXIubG9hZEJ1Y2tldChBY2Nlc3NDb250cm9sc0hlbHBlci5qYXZhOjMwMilcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLkFjY2Vzc0NvbnRyb2xzSGVscGVyLmdldEFjbFJlc291cmNlRm9yUmVxdWVzdChBY2Nlc3NDb250cm9sc0hlbHBlci5qYXZhOjczKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuTGlzdEFjbHMuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKExpc3RBY2xzLmphdmE6ODUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5MaXN0QWNscy5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoTGlzdEFjbHMuamF2YToyMClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLkFjY2Vzc0NvbnRyb2xzRGVsZWdhdG9yLmxpc3QoQWNjZXNzQ29udHJvbHNEZWxlZ2F0b3IuamF2YTo4OSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uUnBjUmVjZWl2ZXIubGFtYmRhJHByb2Nlc3NSZXF1ZXN0QXN5bmMkNChScGNSZWNlaXZlci5qYXZhOjIwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uQXN5bmNFeGVjdXRvci5sYW1iZGEkc3VibWl0JDAoQXN5bmNFeGVjdXRvci5qYXZhOjI3Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KENvbnRleHRSdW5uYWJsZS5qYXZhOjUwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZSQxLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozOSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NzIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozNilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRXhlY3V0b3JzJFJ1bm5hYmxlQWRhcHRlci5jYWxsKEV4ZWN1dG9ycy5qYXZhOjUxMSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRnV0dXJlVGFzay5ydW4oRnV0dXJlVGFzay5qYXZhOjI2Nilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yLnJ1bldvcmtlcihUaHJlYWRQb29sRXhlY3V0b3IuamF2YToxMTQ5KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IkV29ya2VyLnJ1bihUaHJlYWRQb29sRXhlY3V0b3IuamF2YTo2MjQpXG5cdGF0IGphdmEubGFuZy5UaHJlYWQucnVuKFRocmVhZC5qYXZhOjc0OClcbkNhdXNlZCBieTogY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb246IGludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIGRvZXMgbm90IGhhdmUgc2VydmljZXVzYWdlLnNlcnZpY2VzLnVzZSBhY2Nlc3MgdG8gcHJvamVjdCA2NDIwODA5MTgxMDEuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93T25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjI5MClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMSlcblx0Li4uIDE5IG1vcmVcbiwgZG9tYWluPWdsb2JhbCwgZXh0ZW5kZWRIZWxwPW51bGwsIGh0dHBIZWFkZXJzPXt9LCBodHRwU3RhdHVzPWZvcmJpZGRlbiwgaW50ZXJuYWxSZWFzb249UmVhc29ue2FyZ3VtZW50cz17fSwgY2F1c2U9bnVsbCwgY29kZT1nZGF0YS5Db3JlRXJyb3JEb21haW4uRk9SQklEREVOLCBjcmVhdGVkQnlCYWNrZW5kPXRydWUsIGRlYnVnTWVzc2FnZT1jb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6VVNFUl9QUk9KRUNUX0FDQ0VTU19ERU5JRUQ6IGludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIGRvZXMgbm90IGhhdmUgc2VydmljZXVzYWdlLnNlcnZpY2VzLnVzZSBhY2Nlc3MgdG8gcHJvamVjdCA2NDIwODA5MTgxMDEuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRvUnBjM0V4Y2VwdGlvbihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjEzNSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLkFjY2Vzc0NvbnRyb2xzSGVscGVyLmxvYWRCdWNrZXQoQWNjZXNzQ29udHJvbHNIZWxwZXIuamF2YTozMDIpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5BY2Nlc3NDb250cm9sc0hlbHBlci5nZXRBY2xSZXNvdXJjZUZvclJlcXVlc3QoQWNjZXNzQ29udHJvbHNIZWxwZXIuamF2YTo3Mylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLkxpc3RBY2xzLmhhbmRsZVJlcXVlc3RSZWNlaXZlZChMaXN0QWNscy5qYXZhOjg1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuTGlzdEFjbHMuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKExpc3RBY2xzLmphdmE6MjApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5BY2Nlc3NDb250cm9sc0RlbGVnYXRvci5saXN0KEFjY2Vzc0NvbnRyb2xzRGVsZWdhdG9yLmphdmE6ODkpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxOSBtb3JlXG4sIGVycm9yUHJvdG9Db2RlPUZPUkJJRERFTiwgZXJyb3JQcm90b0RvbWFpbj1nZGF0YS5Db3JlRXJyb3JEb21haW4sIGZpbHRlcmVkTWVzc2FnZT1udWxsLCBsb2NhdGlvbj1udWxsLCBtZXNzYWdlPWludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIGRvZXMgbm90IGhhdmUgc2VydmljZXVzYWdlLnNlcnZpY2VzLnVzZSBhY2Nlc3MgdG8gcHJvamVjdCA2NDIwODA5MTgxMDEuLCB1bm5hbWVkQXJndW1lbnRzPVtdfSwgbG9jYXRpb249bnVsbCwgbWVzc2FnZT1pbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLiwgcmVhc29uPWZvcmJpZGRlbiwgcnBjQ29kZT00MDN9IGludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIGRvZXMgbm90IGhhdmUgc2VydmljZXVzYWdlLnNlcnZpY2VzLnVzZSBhY2Nlc3MgdG8gcHJvamVjdCA2NDIwODA5MTgxMDEuOiBjb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6VVNFUl9QUk9KRUNUX0FDQ0VTU19ERU5JRUQ6IGludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIGRvZXMgbm90IGhhdmUgc2VydmljZXVzYWdlLnNlcnZpY2VzLnVzZSBhY2Nlc3MgdG8gcHJvamVjdCA2NDIwODA5MTgxMDEuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRvUnBjM0V4Y2VwdGlvbihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjEzNSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLkFjY2Vzc0NvbnRyb2xzSGVscGVyLmxvYWRCdWNrZXQoQWNjZXNzQ29udHJvbHNIZWxwZXIuamF2YTozMDIpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5BY2Nlc3NDb250cm9sc0hlbHBlci5nZXRBY2xSZXNvdXJjZUZvclJlcXVlc3QoQWNjZXNzQ29udHJvbHNIZWxwZXIuamF2YTo3Mylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLkxpc3RBY2xzLmhhbmRsZVJlcXVlc3RSZWNlaXZlZChMaXN0QWNscy5qYXZhOjg1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuTGlzdEFjbHMuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKExpc3RBY2xzLmphdmE6MjApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5BY2Nlc3NDb250cm9sc0RlbGVnYXRvci5saXN0KEFjY2Vzc0NvbnRyb2xzRGVsZWdhdG9yLmphdmE6ODkpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxOSBtb3JlXG5cblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUuRXJyb3JDb2xsZWN0b3IudG9GYXVsdChFcnJvckNvbGxlY3Rvci5qYXZhOjU0KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIucmVzdC5hZGFwdGVyLnJvc3kuUm9zeUVycm9yQ29udmVydGVyLnRvRmF1bHQoUm9zeUVycm9yQ29udmVydGVyLmphdmE6NjcpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5yZXN0LmFkYXB0ZXIucm9zeS5Sb3N5SGFuZGxlciQyLmNhbGwoUm9zeUhhbmRsZXIuamF2YToyNTgpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5yZXN0LmFkYXB0ZXIucm9zeS5Sb3N5SGFuZGxlciQyLmNhbGwoUm9zeUhhbmRsZXIuamF2YToyMzgpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLnV0aWwuQ2FsbGFibGVGdXR1cmUucnVuKENhbGxhYmxlRnV0dXJlLmphdmE6NjIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5EaXJlY3RFeGVjdXRvci5leGVjdXRlKERpcmVjdEV4ZWN1dG9yLmphdmE6MzApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5leGVjdXRlTGlzdGVuZXIoQWJzdHJhY3RGdXR1cmUuamF2YToxMTQzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuY29tcGxldGUoQWJzdHJhY3RGdXR1cmUuamF2YTo5NjMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5zZXQoQWJzdHJhY3RGdXR1cmUuamF2YTo3MzEpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLnV0aWwuQ2FsbGFibGVGdXR1cmUucnVuKENhbGxhYmxlRnV0dXJlLmphdmE6NjIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5EaXJlY3RFeGVjdXRvci5leGVjdXRlKERpcmVjdEV4ZWN1dG9yLmphdmE6MzApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5leGVjdXRlTGlzdGVuZXIoQWJzdHJhY3RGdXR1cmUuamF2YToxMTQzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuY29tcGxldGUoQWJzdHJhY3RGdXR1cmUuamF2YTo5NjMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5zZXQoQWJzdHJhY3RGdXR1cmUuamF2YTo3MzEpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLnV0aWwuQ2FsbGFibGVGdXR1cmUucnVuKENhbGxhYmxlRnV0dXJlLmphdmE6NjIpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci50aHJlYWQuVGhyZWFkVHJhY2tlcnMkVGhyZWFkVHJhY2tpbmdSdW5uYWJsZS5ydW4oVGhyZWFkVHJhY2tlcnMuamF2YToxMjYpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkVHJhY2VDb250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KFRyYWNlQ29udGV4dC5qYXZhOjQ1NSlcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnNlcnZlci5Db21tb25Nb2R1bGUkQ29udGV4dENhcnJ5aW5nRXhlY3V0b3JTZXJ2aWNlJDEucnVuSW5Db250ZXh0KENvbW1vbk1vZHVsZS5qYXZhOjg0Nilcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRUcmFjZUNvbnRleHRSdW5uYWJsZSQxLnJ1bihUcmFjZUNvbnRleHQuamF2YTo0NjIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkQWJzdHJhY3RUcmFjZUNvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKFRyYWNlQ29udGV4dC5qYXZhOjMyMSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRBYnN0cmFjdFRyYWNlQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChUcmFjZUNvbnRleHQuamF2YTozMTMpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkVHJhY2VDb250ZXh0UnVubmFibGUucnVuKFRyYWNlQ29udGV4dC5qYXZhOjQ1OSlcblx0YXQgY29tLmdvb2dsZS5nc2UuaW50ZXJuYWwuRGlzcGF0Y2hRdWV1ZUltcGwkV29ya2VyVGhyZWFkLnJ1bihEaXNwYXRjaFF1ZXVlSW1wbC5qYXZhOjQwMylcbiJ9XSwiY29kZSI6NDAzLCJtZXNzYWdlIjoiaW50ZWdyYXRpb25AZ2Nsb3VkLWdvbGFuZy1maXJlc3RvcmUtdGVzdHMuaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20gZG9lcyBub3QgaGF2ZSBzZXJ2aWNldXNhZ2Uuc2VydmljZXMudXNlIGFjY2VzcyB0byBwcm9qZWN0IDY0MjA4MDkxODEwMS4ifX0="
+ }
+ },
+ {
+ "ID": "4e0072677d6e9243",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/defaultObjectAcl/domain-google.com?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "1410259a9e5a5a3240d8b80567abc4dd/1096017334405601039;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/defaultObjectAcl/domain-google.com?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 204,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "0"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:07 GMT"
+ ],
+ "Etag": [
+ "CAY="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051395000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vris74:4141,/bns/yr/borg/yr/bns/blobstore2/bitpusher/87.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=IsysW_CqFMmu4QTjqoH4BQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/87.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/87:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATpxChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4CtK4wESxgF5YTI5LmMuRW93QkpRWVNNdC1OVDFNYTJvWXBrbG1qcDlJMlZaUFZ5bFl5Z2Q3Nk5tQXlXbWR3WVBoMm00dGI3ZmZjOUlzcTU4MmVFcFBhNzhNWGpNZmIzaE9WTE9xRHpNTUFfTG9NQXVJZkdkMGgzSWowZ1dxdW5DS1g3Qk1mQlJxM001TUtMMXBHOWNyU0ZBT29lVkZpTDhpWlBsUDI0VjE5THdzZ0d1ZnVrQTFtVzVJcTJUUkVXeWQyNjRKZC1lS2UxdTAwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UqcfHghFeLYicAx1xZoOFYz9sF8hHTKLCp36QA9xhiJZ2VRR0CNnO0sZ9owfC8KLGPOVfAfuS8ZxhUTIwxoV96BHRwAcg"
+ ]
+ },
+ "Body": ""
+ }
+ },
+ {
+ "ID": "bdca30b60af963e6",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/defaultObjectAcl/domain-google.com?alt=json\u0026prettyPrint=false\u0026userProject=dulcet-port-762",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "6227da00c3d57bbb80499c2419e84418/2686146668279381422;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/defaultObjectAcl/domain-google.com?alt=json\u0026prettyPrint=false\u0026userProject=dulcet-port-762"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 404,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0"
+ ],
+ "Content-Length": [
+ "2911"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:08 GMT"
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:25:08 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051395000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrqv16:4123,/bns/yr/borg/yr/bns/blobstore2/bitpusher/16.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=JMysW7ZCw_WQA6PVsMAN"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/16.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/16:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATpxChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4CtK4wESxgF5YTI5LmMuRW93QkpRWVNNdC1OVDFNYTJvWXBrbG1qcDlJMlZaUFZ5bFl5Z2Q3Nk5tQXlXbWR3WVBoMm00dGI3ZmZjOUlzcTU4MmVFcFBhNzhNWGpNZmIzaE9WTE9xRHpNTUFfTG9NQXVJZkdkMGgzSWowZ1dxdW5DS1g3Qk1mQlJxM001TUtMMXBHOWNyU0ZBT29lVkZpTDhpWlBsUDI0VjE5THdzZ0d1ZnVrQTFtVzVJcTJUUkVXeWQyNjRKZC1lS2UxdTAwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Upload-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Urb2qaGQHZsAxqnNJP3mvqPEQOiw0ZQHSCAgKtSJqPZoEKN8Wz2vXlUt2zQH0okIVgs0A2_XxWrSvUf6p4YiN9wc3fv5g"
+ ]
+ },
+ "Body": "eyJlcnJvciI6eyJlcnJvcnMiOlt7ImRvbWFpbiI6Imdsb2JhbCIsInJlYXNvbiI6Im5vdEZvdW5kIiwibWVzc2FnZSI6Ik5vdCBGb3VuZCIsImRlYnVnSW5mbyI6ImNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLkZhdWx0OiBJbW11dGFibGVFcnJvckRlZmluaXRpb257YmFzZT1OT1RfRk9VTkQsIGNhdGVnb3J5PVVTRVJfRVJST1IsIGNhdXNlPW51bGwsIGRlYnVnSW5mbz1udWxsLCBkb21haW49Z2xvYmFsLCBleHRlbmRlZEhlbHA9bnVsbCwgaHR0cEhlYWRlcnM9e30sIGh0dHBTdGF0dXM9bm90Rm91bmQsIGludGVybmFsUmVhc29uPVJlYXNvbnthcmd1bWVudHM9e30sIGNhdXNlPW51bGwsIGNvZGU9Z2RhdGEuQ29yZUVycm9yRG9tYWluLk5PVF9GT1VORCwgY3JlYXRlZEJ5QmFja2VuZD10cnVlLCBkZWJ1Z01lc3NhZ2U9bnVsbCwgZXJyb3JQcm90b0NvZGU9Tk9UX0ZPVU5ELCBlcnJvclByb3RvRG9tYWluPWdkYXRhLkNvcmVFcnJvckRvbWFpbiwgZmlsdGVyZWRNZXNzYWdlPW51bGwsIGxvY2F0aW9uPWVudGl0eS5yZXNvdXJjZV9pZC5zY29wZSwgbWVzc2FnZT1udWxsLCB1bm5hbWVkQXJndW1lbnRzPVtdfSwgbG9jYXRpb249ZW50aXR5LnJlc291cmNlX2lkLnNjb3BlLCBtZXNzYWdlPU5vdCBGb3VuZCwgcmVhc29uPW5vdEZvdW5kLCBycGNDb2RlPTQwNH0gTm90IEZvdW5kXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLkVycm9yQ29sbGVjdG9yLnRvRmF1bHQoRXJyb3JDb2xsZWN0b3IuamF2YTo1NClcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnJlc3QuYWRhcHRlci5yb3N5LlJvc3lFcnJvckNvbnZlcnRlci50b0ZhdWx0KFJvc3lFcnJvckNvbnZlcnRlci5qYXZhOjY3KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIucmVzdC5hZGFwdGVyLnJvc3kuUm9zeUhhbmRsZXIkMi5jYWxsKFJvc3lIYW5kbGVyLmphdmE6MjU4KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIucmVzdC5hZGFwdGVyLnJvc3kuUm9zeUhhbmRsZXIkMi5jYWxsKFJvc3lIYW5kbGVyLmphdmE6MjM4KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS51dGlsLkNhbGxhYmxlRnV0dXJlLnJ1bihDYWxsYWJsZUZ1dHVyZS5qYXZhOjYyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuRGlyZWN0RXhlY3V0b3IuZXhlY3V0ZShEaXJlY3RFeGVjdXRvci5qYXZhOjMwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuZXhlY3V0ZUxpc3RlbmVyKEFic3RyYWN0RnV0dXJlLmphdmE6MTE0Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmNvbXBsZXRlKEFic3RyYWN0RnV0dXJlLmphdmE6OTYzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuc2V0KEFic3RyYWN0RnV0dXJlLmphdmE6NzMxKVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS51dGlsLkNhbGxhYmxlRnV0dXJlLnJ1bihDYWxsYWJsZUZ1dHVyZS5qYXZhOjYyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuRGlyZWN0RXhlY3V0b3IuZXhlY3V0ZShEaXJlY3RFeGVjdXRvci5qYXZhOjMwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuZXhlY3V0ZUxpc3RlbmVyKEFic3RyYWN0RnV0dXJlLmphdmE6MTE0Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmNvbXBsZXRlKEFic3RyYWN0RnV0dXJlLmphdmE6OTYzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuc2V0KEFic3RyYWN0RnV0dXJlLmphdmE6NzMxKVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS51dGlsLkNhbGxhYmxlRnV0dXJlLnJ1bihDYWxsYWJsZUZ1dHVyZS5qYXZhOjYyKVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIudGhyZWFkLlRocmVhZFRyYWNrZXJzJFRocmVhZFRyYWNraW5nUnVubmFibGUucnVuKFRocmVhZFRyYWNrZXJzLmphdmE6MTI2KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JFRyYWNlQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChUcmFjZUNvbnRleHQuamF2YTo0NTUpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5zZXJ2ZXIuQ29tbW9uTW9kdWxlJENvbnRleHRDYXJyeWluZ0V4ZWN1dG9yU2VydmljZSQxLnJ1bkluQ29udGV4dChDb21tb25Nb2R1bGUuamF2YTo4NDYpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkVHJhY2VDb250ZXh0UnVubmFibGUkMS5ydW4oVHJhY2VDb250ZXh0LmphdmE6NDYyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JEFic3RyYWN0VHJhY2VDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihUcmFjZUNvbnRleHQuamF2YTozMjEpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkQWJzdHJhY3RUcmFjZUNvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoVHJhY2VDb250ZXh0LmphdmE6MzEzKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JFRyYWNlQ29udGV4dFJ1bm5hYmxlLnJ1bihUcmFjZUNvbnRleHQuamF2YTo0NTkpXG5cdGF0IGNvbS5nb29nbGUuZ3NlLmludGVybmFsLkRpc3BhdGNoUXVldWVJbXBsJFdvcmtlclRocmVhZC5ydW4oRGlzcGF0Y2hRdWV1ZUltcGwuamF2YTo0MDMpXG4ifV0sImNvZGUiOjQwNCwibWVzc2FnZSI6Ik5vdCBGb3VuZCJ9fQ=="
+ }
+ },
+ {
+ "ID": "9452e5677cd8763e",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/defaultObjectAcl/domain-google.com?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "70a998644dfcd91da217e42b1d7b2d2e/4276558568051696204;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/defaultObjectAcl/domain-google.com?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 400,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0"
+ ],
+ "Content-Length": [
+ "13131"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:08 GMT"
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:25:08 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051395000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "471383502717"
+ ],
+ "X-Google-Backends": [
+ "vrls9:4235,/bns/yv/borg/yv/bns/blobstore2/bitpusher/272.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=JMysW5CsE4WYNtLmguAE"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/272.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/272:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CP3elYXcDRoCGAYoATo_ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGM6ropHgHCIVMTE3MjM4MDU4ODYxOTM3NTE5MTQ0MOArSp8BEoIBeWEyOS5jLkVsb2xCcldWbUZlX1AxVDdUOHVpTXdFMHBZUjdTc2NVMDBFdEZkc2tSenBQY0NLWkhUeEZaYXI0Q25tZmR6bXFRLTNVV0kzOF9wdEx5VTZ2Z1Q3dlRBeW42Z3g4dUcyd0szSHIzaTZrV1JBZkozc1pNMGQ1allkNHpWQTAEOhZOT1RfQV9QRVJTSVNURU5UX1RPS0VO"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Upload-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UoS5A_Ur5pecY5WkXvVZ-WyFRTYSKqumzpHMDRUS9GQU_9lswTJztBB3jyIuq6dqAIGQlJi3ZvEGCcbumiiyxDu31QPAg"
+ ]
+ },
+ "Body": "eyJlcnJvciI6eyJlcnJvcnMiOlt7ImRvbWFpbiI6Imdsb2JhbCIsInJlYXNvbiI6InJlcXVpcmVkIiwibWVzc2FnZSI6IkJ1Y2tldCBpcyByZXF1ZXN0ZXIgcGF5cyBidWNrZXQgYnV0IG5vIHVzZXIgcHJvamVjdCBwcm92aWRlZC4iLCJkZWJ1Z0luZm8iOiJjb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6VVNFUl9QUk9KRUNUX01JU1NJTkc6IEJ1Y2tldCBpcyBSZXF1ZXN0ZXIgUGF5cyBidWNrZXQgYnV0IG5vIGJpbGxpbmcgcHJvamVjdCBpZCBwcm92aWRlZCBmb3Igbm9uLW93bmVyLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5BY2Nlc3NDb250cm9sc0hlbHBlci5sb2FkQnVja2V0KEFjY2Vzc0NvbnRyb2xzSGVscGVyLmphdmE6MzAyKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuQWNjZXNzQ29udHJvbHNIZWxwZXIuZ2V0QWNsUmVzb3VyY2VGb3JSZXF1ZXN0KEFjY2Vzc0NvbnRyb2xzSGVscGVyLmphdmE6NzMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5EZWxldGVBY2xzLmhhbmRsZVJlcXVlc3RSZWNlaXZlZChEZWxldGVBY2xzLmphdmE6NzEpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5EZWxldGVBY2xzLmhhbmRsZVJlcXVlc3RSZWNlaXZlZChEZWxldGVBY2xzLmphdmE6MjApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5BY2Nlc3NDb250cm9sc0RlbGVnYXRvci5kZWxldGUoQWNjZXNzQ29udHJvbHNEZWxlZ2F0b3IuamF2YToxMDkpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBCdWNrZXQgaXMgUmVxdWVzdGVyIFBheXMgYnVja2V0IGJ1dCBubyBiaWxsaW5nIHByb2plY3QgaWQgcHJvdmlkZWQgZm9yIG5vbi1vd25lci5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MjkwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAxKVxuXHQuLi4gMTkgbW9yZVxuXG5jb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS5GYXVsdDogSW1tdXRhYmxlRXJyb3JEZWZpbml0aW9ue2Jhc2U9UkVRVUlSRUQsIGNhdGVnb3J5PVVTRVJfRVJST1IsIGNhdXNlPW51bGwsIGRlYnVnSW5mbz1jb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6VVNFUl9QUk9KRUNUX01JU1NJTkc6IEJ1Y2tldCBpcyBSZXF1ZXN0ZXIgUGF5cyBidWNrZXQgYnV0IG5vIGJpbGxpbmcgcHJvamVjdCBpZCBwcm92aWRlZCBmb3Igbm9uLW93bmVyLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5BY2Nlc3NDb250cm9sc0hlbHBlci5sb2FkQnVja2V0KEFjY2Vzc0NvbnRyb2xzSGVscGVyLmphdmE6MzAyKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuQWNjZXNzQ29udHJvbHNIZWxwZXIuZ2V0QWNsUmVzb3VyY2VGb3JSZXF1ZXN0KEFjY2Vzc0NvbnRyb2xzSGVscGVyLmphdmE6NzMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5EZWxldGVBY2xzLmhhbmRsZVJlcXVlc3RSZWNlaXZlZChEZWxldGVBY2xzLmphdmE6NzEpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5EZWxldGVBY2xzLmhhbmRsZVJlcXVlc3RSZWNlaXZlZChEZWxldGVBY2xzLmphdmE6MjApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5BY2Nlc3NDb250cm9sc0RlbGVnYXRvci5kZWxldGUoQWNjZXNzQ29udHJvbHNEZWxlZ2F0b3IuamF2YToxMDkpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBCdWNrZXQgaXMgUmVxdWVzdGVyIFBheXMgYnVja2V0IGJ1dCBubyBiaWxsaW5nIHByb2plY3QgaWQgcHJvdmlkZWQgZm9yIG5vbi1vd25lci5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MjkwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAxKVxuXHQuLi4gMTkgbW9yZVxuLCBkb21haW49Z2xvYmFsLCBleHRlbmRlZEhlbHA9bnVsbCwgaHR0cEhlYWRlcnM9e30sIGh0dHBTdGF0dXM9YmFkUmVxdWVzdCwgaW50ZXJuYWxSZWFzb249UmVhc29ue2FyZ3VtZW50cz17fSwgY2F1c2U9bnVsbCwgY29kZT1nZGF0YS5Db3JlRXJyb3JEb21haW4uUkVRVUlSRUQsIGNyZWF0ZWRCeUJhY2tlbmQ9dHJ1ZSwgZGVidWdNZXNzYWdlPWNvbS5nb29nbGUubmV0LnJwYzMuUnBjRXhjZXB0aW9uOiBjbG91ZC5iaWdzdG9yZS5SZXNwb25zZUNvZGUuRXJyb3JDb2RlOjpVU0VSX1BST0pFQ1RfTUlTU0lORzogQnVja2V0IGlzIFJlcXVlc3RlciBQYXlzIGJ1Y2tldCBidXQgbm8gYmlsbGluZyBwcm9qZWN0IGlkIHByb3ZpZGVkIGZvciBub24tb3duZXIuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRvUnBjM0V4Y2VwdGlvbihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjEzNSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLkFjY2Vzc0NvbnRyb2xzSGVscGVyLmxvYWRCdWNrZXQoQWNjZXNzQ29udHJvbHNIZWxwZXIuamF2YTozMDIpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5BY2Nlc3NDb250cm9sc0hlbHBlci5nZXRBY2xSZXNvdXJjZUZvclJlcXVlc3QoQWNjZXNzQ29udHJvbHNIZWxwZXIuamF2YTo3Mylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLkRlbGV0ZUFjbHMuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKERlbGV0ZUFjbHMuamF2YTo3MSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLkRlbGV0ZUFjbHMuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKERlbGV0ZUFjbHMuamF2YToyMClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLkFjY2Vzc0NvbnRyb2xzRGVsZWdhdG9yLmRlbGV0ZShBY2Nlc3NDb250cm9sc0RlbGVnYXRvci5qYXZhOjEwOSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uUnBjUmVjZWl2ZXIubGFtYmRhJHByb2Nlc3NSZXF1ZXN0QXN5bmMkNChScGNSZWNlaXZlci5qYXZhOjIwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uQXN5bmNFeGVjdXRvci5sYW1iZGEkc3VibWl0JDAoQXN5bmNFeGVjdXRvci5qYXZhOjI3Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KENvbnRleHRSdW5uYWJsZS5qYXZhOjUwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZSQxLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozOSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NzIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozNilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRXhlY3V0b3JzJFJ1bm5hYmxlQWRhcHRlci5jYWxsKEV4ZWN1dG9ycy5qYXZhOjUxMSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRnV0dXJlVGFzay5ydW4oRnV0dXJlVGFzay5qYXZhOjI2Nilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yLnJ1bldvcmtlcihUaHJlYWRQb29sRXhlY3V0b3IuamF2YToxMTQ5KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IkV29ya2VyLnJ1bihUaHJlYWRQb29sRXhlY3V0b3IuamF2YTo2MjQpXG5cdGF0IGphdmEubGFuZy5UaHJlYWQucnVuKFRocmVhZC5qYXZhOjc0OClcbkNhdXNlZCBieTogY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb246IEJ1Y2tldCBpcyBSZXF1ZXN0ZXIgUGF5cyBidWNrZXQgYnV0IG5vIGJpbGxpbmcgcHJvamVjdCBpZCBwcm92aWRlZCBmb3Igbm9uLW93bmVyLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxOSBtb3JlXG4sIGVycm9yUHJvdG9Db2RlPVJFUVVJUkVELCBlcnJvclByb3RvRG9tYWluPWdkYXRhLkNvcmVFcnJvckRvbWFpbiwgZmlsdGVyZWRNZXNzYWdlPW51bGwsIGxvY2F0aW9uPW51bGwsIG1lc3NhZ2U9QnVja2V0IGlzIHJlcXVlc3RlciBwYXlzIGJ1Y2tldCBidXQgbm8gdXNlciBwcm9qZWN0IHByb3ZpZGVkLiwgdW5uYW1lZEFyZ3VtZW50cz1bXX0sIGxvY2F0aW9uPW51bGwsIG1lc3NhZ2U9QnVja2V0IGlzIHJlcXVlc3RlciBwYXlzIGJ1Y2tldCBidXQgbm8gdXNlciBwcm9qZWN0IHByb3ZpZGVkLiwgcmVhc29uPXJlcXVpcmVkLCBycGNDb2RlPTQwMH0gQnVja2V0IGlzIHJlcXVlc3RlciBwYXlzIGJ1Y2tldCBidXQgbm8gdXNlciBwcm9qZWN0IHByb3ZpZGVkLjogY29tLmdvb2dsZS5uZXQucnBjMy5ScGNFeGNlcHRpb246IGNsb3VkLmJpZ3N0b3JlLlJlc3BvbnNlQ29kZS5FcnJvckNvZGU6OlVTRVJfUFJPSkVDVF9NSVNTSU5HOiBCdWNrZXQgaXMgUmVxdWVzdGVyIFBheXMgYnVja2V0IGJ1dCBubyBiaWxsaW5nIHByb2plY3QgaWQgcHJvdmlkZWQgZm9yIG5vbi1vd25lci5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udG9ScGMzRXhjZXB0aW9uKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MTM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuQWNjZXNzQ29udHJvbHNIZWxwZXIubG9hZEJ1Y2tldChBY2Nlc3NDb250cm9sc0hlbHBlci5qYXZhOjMwMilcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLkFjY2Vzc0NvbnRyb2xzSGVscGVyLmdldEFjbFJlc291cmNlRm9yUmVxdWVzdChBY2Nlc3NDb250cm9sc0hlbHBlci5qYXZhOjczKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuRGVsZXRlQWNscy5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoRGVsZXRlQWNscy5qYXZhOjcxKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuRGVsZXRlQWNscy5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoRGVsZXRlQWNscy5qYXZhOjIwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmZyYW1ld29yay5SZXF1ZXN0SGFuZGxlci5oYW5kbGUoUmVxdWVzdEhhbmRsZXIuamF2YToyOTQpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uQWNjZXNzQ29udHJvbHNEZWxlZ2F0b3IuZGVsZXRlKEFjY2Vzc0NvbnRyb2xzRGVsZWdhdG9yLmphdmE6MTA5KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5ScGNSZWNlaXZlci5sYW1iZGEkcHJvY2Vzc1JlcXVlc3RBc3luYyQ0KFJwY1JlY2VpdmVyLmphdmE6MjAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5Bc3luY0V4ZWN1dG9yLmxhbWJkYSRzdWJtaXQkMChBc3luY0V4ZWN1dG9yLmphdmE6MjcyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoQ29udGV4dFJ1bm5hYmxlLmphdmE6NTApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlJDEucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM5KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo3Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5FeGVjdXRvcnMkUnVubmFibGVBZGFwdGVyLmNhbGwoRXhlY3V0b3JzLmphdmE6NTExKVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5GdXR1cmVUYXNrLnJ1bihGdXR1cmVUYXNrLmphdmE6MjY2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IucnVuV29ya2VyKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjExNDkpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvciRXb3JrZXIucnVuKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjYyNClcblx0YXQgamF2YS5sYW5nLlRocmVhZC5ydW4oVGhyZWFkLmphdmE6NzQ4KVxuQ2F1c2VkIGJ5OiBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbjogQnVja2V0IGlzIFJlcXVlc3RlciBQYXlzIGJ1Y2tldCBidXQgbm8gYmlsbGluZyBwcm9qZWN0IGlkIHByb3ZpZGVkIGZvciBub24tb3duZXIuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93T25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjI5MClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMSlcblx0Li4uIDE5IG1vcmVcblxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS5FcnJvckNvbGxlY3Rvci50b0ZhdWx0KEVycm9yQ29sbGVjdG9yLmphdmE6NTQpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5yZXN0LmFkYXB0ZXIucm9zeS5Sb3N5RXJyb3JDb252ZXJ0ZXIudG9GYXVsdChSb3N5RXJyb3JDb252ZXJ0ZXIuamF2YTo2Nylcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnJlc3QuYWRhcHRlci5yb3N5LlJvc3lIYW5kbGVyJDIuY2FsbChSb3N5SGFuZGxlci5qYXZhOjI1OClcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnJlc3QuYWRhcHRlci5yb3N5LlJvc3lIYW5kbGVyJDIuY2FsbChSb3N5SGFuZGxlci5qYXZhOjIzOClcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkRpcmVjdEV4ZWN1dG9yLmV4ZWN1dGUoRGlyZWN0RXhlY3V0b3IuamF2YTozMClcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmV4ZWN1dGVMaXN0ZW5lcihBYnN0cmFjdEZ1dHVyZS5qYXZhOjExNDMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5jb21wbGV0ZShBYnN0cmFjdEZ1dHVyZS5qYXZhOjk2Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLnNldChBYnN0cmFjdEZ1dHVyZS5qYXZhOjczMSlcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkRpcmVjdEV4ZWN1dG9yLmV4ZWN1dGUoRGlyZWN0RXhlY3V0b3IuamF2YTozMClcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmV4ZWN1dGVMaXN0ZW5lcihBYnN0cmFjdEZ1dHVyZS5qYXZhOjExNDMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5jb21wbGV0ZShBYnN0cmFjdEZ1dHVyZS5qYXZhOjk2Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLnNldChBYnN0cmFjdEZ1dHVyZS5qYXZhOjczMSlcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnRocmVhZC5UaHJlYWRUcmFja2VycyRUaHJlYWRUcmFja2luZ1J1bm5hYmxlLnJ1bihUaHJlYWRUcmFja2Vycy5qYXZhOjEyNilcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRUcmFjZUNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoVHJhY2VDb250ZXh0LmphdmE6NDU1KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuc2VydmVyLkNvbW1vbk1vZHVsZSRDb250ZXh0Q2FycnlpbmdFeGVjdXRvclNlcnZpY2UkMS5ydW5JbkNvbnRleHQoQ29tbW9uTW9kdWxlLmphdmE6ODQ2KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JFRyYWNlQ29udGV4dFJ1bm5hYmxlJDEucnVuKFRyYWNlQ29udGV4dC5qYXZhOjQ2Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRBYnN0cmFjdFRyYWNlQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoVHJhY2VDb250ZXh0LmphdmE6MzIxKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JEFic3RyYWN0VHJhY2VDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KFRyYWNlQ29udGV4dC5qYXZhOjMxMylcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRUcmFjZUNvbnRleHRSdW5uYWJsZS5ydW4oVHJhY2VDb250ZXh0LmphdmE6NDU5KVxuXHRhdCBjb20uZ29vZ2xlLmdzZS5pbnRlcm5hbC5EaXNwYXRjaFF1ZXVlSW1wbCRXb3JrZXJUaHJlYWQucnVuKERpc3BhdGNoUXVldWVJbXBsLmphdmE6NDAzKVxuIn1dLCJjb2RlIjo0MDAsIm1lc3NhZ2UiOiJCdWNrZXQgaXMgcmVxdWVzdGVyIHBheXMgYnVja2V0IGJ1dCBubyB1c2VyIHByb2plY3QgcHJvdmlkZWQuIn19"
+ }
+ },
+ {
+ "ID": "69453ac394695e48",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/defaultObjectAcl/domain-google.com?alt=json\u0026prettyPrint=false\u0026userProject=gcloud-golang-firestore-tests",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "40295f9b87f0f18ad0e9ff0e6fb99330/5866970472102070507;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/defaultObjectAcl/domain-google.com?alt=json\u0026prettyPrint=false\u0026userProject=gcloud-golang-firestore-tests"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 404,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0"
+ ],
+ "Content-Length": [
+ "2911"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:08 GMT"
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:25:08 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051395000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "471383502717"
+ ],
+ "X-Google-Backends": [
+ "vrbh67:4361,/bns/yv/borg/yv/bns/blobstore2/bitpusher/259.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=JMysW-aOIMmngASFkp7wAw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/259.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/259:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CP3elYXcDRoCGAYoATo_ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGM6ropHgHCIVMTE3MjM4MDU4ODYxOTM3NTE5MTQ0MOArSp8BEoIBeWEyOS5jLkVsb2xCcldWbUZlX1AxVDdUOHVpTXdFMHBZUjdTc2NVMDBFdEZkc2tSenBQY0NLWkhUeEZaYXI0Q25tZmR6bXFRLTNVV0kzOF9wdEx5VTZ2Z1Q3dlRBeW42Z3g4dUcyd0szSHIzaTZrV1JBZkozc1pNMGQ1allkNHpWQTAEOhZOT1RfQV9QRVJTSVNURU5UX1RPS0VO"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Upload-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UoAIy7VG2gOhNoHOLq09jywLkL6GqJBFh12dcwNvIYHlc2RjT6csXgnyyOlgOpUEd0DmFu84oEVta-tKvkj4fhR_E255A"
+ ]
+ },
+ "Body": "eyJlcnJvciI6eyJlcnJvcnMiOlt7ImRvbWFpbiI6Imdsb2JhbCIsInJlYXNvbiI6Im5vdEZvdW5kIiwibWVzc2FnZSI6Ik5vdCBGb3VuZCIsImRlYnVnSW5mbyI6ImNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLkZhdWx0OiBJbW11dGFibGVFcnJvckRlZmluaXRpb257YmFzZT1OT1RfRk9VTkQsIGNhdGVnb3J5PVVTRVJfRVJST1IsIGNhdXNlPW51bGwsIGRlYnVnSW5mbz1udWxsLCBkb21haW49Z2xvYmFsLCBleHRlbmRlZEhlbHA9bnVsbCwgaHR0cEhlYWRlcnM9e30sIGh0dHBTdGF0dXM9bm90Rm91bmQsIGludGVybmFsUmVhc29uPVJlYXNvbnthcmd1bWVudHM9e30sIGNhdXNlPW51bGwsIGNvZGU9Z2RhdGEuQ29yZUVycm9yRG9tYWluLk5PVF9GT1VORCwgY3JlYXRlZEJ5QmFja2VuZD10cnVlLCBkZWJ1Z01lc3NhZ2U9bnVsbCwgZXJyb3JQcm90b0NvZGU9Tk9UX0ZPVU5ELCBlcnJvclByb3RvRG9tYWluPWdkYXRhLkNvcmVFcnJvckRvbWFpbiwgZmlsdGVyZWRNZXNzYWdlPW51bGwsIGxvY2F0aW9uPWVudGl0eS5yZXNvdXJjZV9pZC5zY29wZSwgbWVzc2FnZT1udWxsLCB1bm5hbWVkQXJndW1lbnRzPVtdfSwgbG9jYXRpb249ZW50aXR5LnJlc291cmNlX2lkLnNjb3BlLCBtZXNzYWdlPU5vdCBGb3VuZCwgcmVhc29uPW5vdEZvdW5kLCBycGNDb2RlPTQwNH0gTm90IEZvdW5kXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLkVycm9yQ29sbGVjdG9yLnRvRmF1bHQoRXJyb3JDb2xsZWN0b3IuamF2YTo1NClcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnJlc3QuYWRhcHRlci5yb3N5LlJvc3lFcnJvckNvbnZlcnRlci50b0ZhdWx0KFJvc3lFcnJvckNvbnZlcnRlci5qYXZhOjY3KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIucmVzdC5hZGFwdGVyLnJvc3kuUm9zeUhhbmRsZXIkMi5jYWxsKFJvc3lIYW5kbGVyLmphdmE6MjU4KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIucmVzdC5hZGFwdGVyLnJvc3kuUm9zeUhhbmRsZXIkMi5jYWxsKFJvc3lIYW5kbGVyLmphdmE6MjM4KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS51dGlsLkNhbGxhYmxlRnV0dXJlLnJ1bihDYWxsYWJsZUZ1dHVyZS5qYXZhOjYyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuRGlyZWN0RXhlY3V0b3IuZXhlY3V0ZShEaXJlY3RFeGVjdXRvci5qYXZhOjMwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuZXhlY3V0ZUxpc3RlbmVyKEFic3RyYWN0RnV0dXJlLmphdmE6MTE0Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmNvbXBsZXRlKEFic3RyYWN0RnV0dXJlLmphdmE6OTYzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuc2V0KEFic3RyYWN0RnV0dXJlLmphdmE6NzMxKVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS51dGlsLkNhbGxhYmxlRnV0dXJlLnJ1bihDYWxsYWJsZUZ1dHVyZS5qYXZhOjYyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuRGlyZWN0RXhlY3V0b3IuZXhlY3V0ZShEaXJlY3RFeGVjdXRvci5qYXZhOjMwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuZXhlY3V0ZUxpc3RlbmVyKEFic3RyYWN0RnV0dXJlLmphdmE6MTE0Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmNvbXBsZXRlKEFic3RyYWN0RnV0dXJlLmphdmE6OTYzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuc2V0KEFic3RyYWN0RnV0dXJlLmphdmE6NzMxKVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS51dGlsLkNhbGxhYmxlRnV0dXJlLnJ1bihDYWxsYWJsZUZ1dHVyZS5qYXZhOjYyKVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIudGhyZWFkLlRocmVhZFRyYWNrZXJzJFRocmVhZFRyYWNraW5nUnVubmFibGUucnVuKFRocmVhZFRyYWNrZXJzLmphdmE6MTI2KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JFRyYWNlQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChUcmFjZUNvbnRleHQuamF2YTo0NTUpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5zZXJ2ZXIuQ29tbW9uTW9kdWxlJENvbnRleHRDYXJyeWluZ0V4ZWN1dG9yU2VydmljZSQxLnJ1bkluQ29udGV4dChDb21tb25Nb2R1bGUuamF2YTo4NDYpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkVHJhY2VDb250ZXh0UnVubmFibGUkMS5ydW4oVHJhY2VDb250ZXh0LmphdmE6NDYyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JEFic3RyYWN0VHJhY2VDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihUcmFjZUNvbnRleHQuamF2YTozMjEpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkQWJzdHJhY3RUcmFjZUNvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoVHJhY2VDb250ZXh0LmphdmE6MzEzKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JFRyYWNlQ29udGV4dFJ1bm5hYmxlLnJ1bihUcmFjZUNvbnRleHQuamF2YTo0NTkpXG5cdGF0IGNvbS5nb29nbGUuZ3NlLmludGVybmFsLkRpc3BhdGNoUXVldWVJbXBsJFdvcmtlclRocmVhZC5ydW4oRGlzcGF0Y2hRdWV1ZUltcGwuamF2YTo0MDMpXG4ifV0sImNvZGUiOjQwNCwibWVzc2FnZSI6Ik5vdCBGb3VuZCJ9fQ=="
+ }
+ },
+ {
+ "ID": "4e81fa1d549dd7d1",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/defaultObjectAcl/domain-google.com?alt=json\u0026prettyPrint=false\u0026userProject=veener-jba",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "e7961ff53ec44511ed91686f7343d103/7457382376169221514;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/defaultObjectAcl/domain-google.com?alt=json\u0026prettyPrint=false\u0026userProject=veener-jba"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 403,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0"
+ ],
+ "Content-Length": [
+ "13987"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:08 GMT"
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:25:08 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051395000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "471383502717"
+ ],
+ "X-Google-Backends": [
+ "vrng11:4017,/bns/yr/borg/yr/bns/blobstore2/bitpusher/34.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=JMysW_6AJ8GlkATKoZr4CA"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/34.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/34:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CP3elYXcDRoCGAYoATo_ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGM6ropHgHCIVMTE3MjM4MDU4ODYxOTM3NTE5MTQ0MOArSp8BEoIBeWEyOS5jLkVsb2xCcldWbUZlX1AxVDdUOHVpTXdFMHBZUjdTc2NVMDBFdEZkc2tSenBQY0NLWkhUeEZaYXI0Q25tZmR6bXFRLTNVV0kzOF9wdEx5VTZ2Z1Q3dlRBeW42Z3g4dUcyd0szSHIzaTZrV1JBZkozc1pNMGQ1allkNHpWQTAEOhZOT1RfQV9QRVJTSVNURU5UX1RPS0VO"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Upload-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UqqFd_29T2_H_95CurwBBNSdJkTcPsStuCJ-y30twVICigUMCZDDGuZQzqiDSF_N8EH0diT0_WkrCovZ_LDkaDH_YKmQg"
+ ]
+ },
+ "Body": "eyJlcnJvciI6eyJlcnJvcnMiOlt7ImRvbWFpbiI6Imdsb2JhbCIsInJlYXNvbiI6ImZvcmJpZGRlbiIsIm1lc3NhZ2UiOiJpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLiIsImRlYnVnSW5mbyI6ImNvbS5nb29nbGUubmV0LnJwYzMuUnBjRXhjZXB0aW9uOiBjbG91ZC5iaWdzdG9yZS5SZXNwb25zZUNvZGUuRXJyb3JDb2RlOjpVU0VSX1BST0pFQ1RfQUNDRVNTX0RFTklFRDogaW50ZWdyYXRpb25AZ2Nsb3VkLWdvbGFuZy1maXJlc3RvcmUtdGVzdHMuaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20gZG9lcyBub3QgaGF2ZSBzZXJ2aWNldXNhZ2Uuc2VydmljZXMudXNlIGFjY2VzcyB0byBwcm9qZWN0IDY0MjA4MDkxODEwMS5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udG9ScGMzRXhjZXB0aW9uKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MTM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuQWNjZXNzQ29udHJvbHNIZWxwZXIubG9hZEJ1Y2tldChBY2Nlc3NDb250cm9sc0hlbHBlci5qYXZhOjMwMilcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLkFjY2Vzc0NvbnRyb2xzSGVscGVyLmdldEFjbFJlc291cmNlRm9yUmVxdWVzdChBY2Nlc3NDb250cm9sc0hlbHBlci5qYXZhOjczKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuRGVsZXRlQWNscy5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoRGVsZXRlQWNscy5qYXZhOjcxKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuRGVsZXRlQWNscy5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoRGVsZXRlQWNscy5qYXZhOjIwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmZyYW1ld29yay5SZXF1ZXN0SGFuZGxlci5oYW5kbGUoUmVxdWVzdEhhbmRsZXIuamF2YToyOTQpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uQWNjZXNzQ29udHJvbHNEZWxlZ2F0b3IuZGVsZXRlKEFjY2Vzc0NvbnRyb2xzRGVsZWdhdG9yLmphdmE6MTA5KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5ScGNSZWNlaXZlci5sYW1iZGEkcHJvY2Vzc1JlcXVlc3RBc3luYyQ0KFJwY1JlY2VpdmVyLmphdmE6MjAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5Bc3luY0V4ZWN1dG9yLmxhbWJkYSRzdWJtaXQkMChBc3luY0V4ZWN1dG9yLmphdmE6MjcyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoQ29udGV4dFJ1bm5hYmxlLmphdmE6NTApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlJDEucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM5KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo3Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5FeGVjdXRvcnMkUnVubmFibGVBZGFwdGVyLmNhbGwoRXhlY3V0b3JzLmphdmE6NTExKVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5GdXR1cmVUYXNrLnJ1bihGdXR1cmVUYXNrLmphdmE6MjY2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IucnVuV29ya2VyKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjExNDkpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvciRXb3JrZXIucnVuKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjYyNClcblx0YXQgamF2YS5sYW5nLlRocmVhZC5ydW4oVGhyZWFkLmphdmE6NzQ4KVxuQ2F1c2VkIGJ5OiBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbjogaW50ZWdyYXRpb25AZ2Nsb3VkLWdvbGFuZy1maXJlc3RvcmUtdGVzdHMuaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20gZG9lcyBub3QgaGF2ZSBzZXJ2aWNldXNhZ2Uuc2VydmljZXMudXNlIGFjY2VzcyB0byBwcm9qZWN0IDY0MjA4MDkxODEwMS5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MjkwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAxKVxuXHQuLi4gMTkgbW9yZVxuXG5jb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS5GYXVsdDogSW1tdXRhYmxlRXJyb3JEZWZpbml0aW9ue2Jhc2U9Rk9SQklEREVOLCBjYXRlZ29yeT1VU0VSX0VSUk9SLCBjYXVzZT1udWxsLCBkZWJ1Z0luZm89Y29tLmdvb2dsZS5uZXQucnBjMy5ScGNFeGNlcHRpb246IGNsb3VkLmJpZ3N0b3JlLlJlc3BvbnNlQ29kZS5FcnJvckNvZGU6OlVTRVJfUFJPSkVDVF9BQ0NFU1NfREVOSUVEOiBpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5BY2Nlc3NDb250cm9sc0hlbHBlci5sb2FkQnVja2V0KEFjY2Vzc0NvbnRyb2xzSGVscGVyLmphdmE6MzAyKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuQWNjZXNzQ29udHJvbHNIZWxwZXIuZ2V0QWNsUmVzb3VyY2VGb3JSZXF1ZXN0KEFjY2Vzc0NvbnRyb2xzSGVscGVyLmphdmE6NzMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5EZWxldGVBY2xzLmhhbmRsZVJlcXVlc3RSZWNlaXZlZChEZWxldGVBY2xzLmphdmE6NzEpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5EZWxldGVBY2xzLmhhbmRsZVJlcXVlc3RSZWNlaXZlZChEZWxldGVBY2xzLmphdmE6MjApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5BY2Nlc3NDb250cm9sc0RlbGVnYXRvci5kZWxldGUoQWNjZXNzQ29udHJvbHNEZWxlZ2F0b3IuamF2YToxMDkpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxOSBtb3JlXG4sIGRvbWFpbj1nbG9iYWwsIGV4dGVuZGVkSGVscD1udWxsLCBodHRwSGVhZGVycz17fSwgaHR0cFN0YXR1cz1mb3JiaWRkZW4sIGludGVybmFsUmVhc29uPVJlYXNvbnthcmd1bWVudHM9e30sIGNhdXNlPW51bGwsIGNvZGU9Z2RhdGEuQ29yZUVycm9yRG9tYWluLkZPUkJJRERFTiwgY3JlYXRlZEJ5QmFja2VuZD10cnVlLCBkZWJ1Z01lc3NhZ2U9Y29tLmdvb2dsZS5uZXQucnBjMy5ScGNFeGNlcHRpb246IGNsb3VkLmJpZ3N0b3JlLlJlc3BvbnNlQ29kZS5FcnJvckNvZGU6OlVTRVJfUFJPSkVDVF9BQ0NFU1NfREVOSUVEOiBpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5BY2Nlc3NDb250cm9sc0hlbHBlci5sb2FkQnVja2V0KEFjY2Vzc0NvbnRyb2xzSGVscGVyLmphdmE6MzAyKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuQWNjZXNzQ29udHJvbHNIZWxwZXIuZ2V0QWNsUmVzb3VyY2VGb3JSZXF1ZXN0KEFjY2Vzc0NvbnRyb2xzSGVscGVyLmphdmE6NzMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5EZWxldGVBY2xzLmhhbmRsZVJlcXVlc3RSZWNlaXZlZChEZWxldGVBY2xzLmphdmE6NzEpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5EZWxldGVBY2xzLmhhbmRsZVJlcXVlc3RSZWNlaXZlZChEZWxldGVBY2xzLmphdmE6MjApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5BY2Nlc3NDb250cm9sc0RlbGVnYXRvci5kZWxldGUoQWNjZXNzQ29udHJvbHNEZWxlZ2F0b3IuamF2YToxMDkpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxOSBtb3JlXG4sIGVycm9yUHJvdG9Db2RlPUZPUkJJRERFTiwgZXJyb3JQcm90b0RvbWFpbj1nZGF0YS5Db3JlRXJyb3JEb21haW4sIGZpbHRlcmVkTWVzc2FnZT1udWxsLCBsb2NhdGlvbj1udWxsLCBtZXNzYWdlPWludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIGRvZXMgbm90IGhhdmUgc2VydmljZXVzYWdlLnNlcnZpY2VzLnVzZSBhY2Nlc3MgdG8gcHJvamVjdCA2NDIwODA5MTgxMDEuLCB1bm5hbWVkQXJndW1lbnRzPVtdfSwgbG9jYXRpb249bnVsbCwgbWVzc2FnZT1pbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLiwgcmVhc29uPWZvcmJpZGRlbiwgcnBjQ29kZT00MDN9IGludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIGRvZXMgbm90IGhhdmUgc2VydmljZXVzYWdlLnNlcnZpY2VzLnVzZSBhY2Nlc3MgdG8gcHJvamVjdCA2NDIwODA5MTgxMDEuOiBjb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6VVNFUl9QUk9KRUNUX0FDQ0VTU19ERU5JRUQ6IGludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIGRvZXMgbm90IGhhdmUgc2VydmljZXVzYWdlLnNlcnZpY2VzLnVzZSBhY2Nlc3MgdG8gcHJvamVjdCA2NDIwODA5MTgxMDEuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRvUnBjM0V4Y2VwdGlvbihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjEzNSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLkFjY2Vzc0NvbnRyb2xzSGVscGVyLmxvYWRCdWNrZXQoQWNjZXNzQ29udHJvbHNIZWxwZXIuamF2YTozMDIpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5BY2Nlc3NDb250cm9sc0hlbHBlci5nZXRBY2xSZXNvdXJjZUZvclJlcXVlc3QoQWNjZXNzQ29udHJvbHNIZWxwZXIuamF2YTo3Mylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLkRlbGV0ZUFjbHMuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKERlbGV0ZUFjbHMuamF2YTo3MSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLkRlbGV0ZUFjbHMuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKERlbGV0ZUFjbHMuamF2YToyMClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLkFjY2Vzc0NvbnRyb2xzRGVsZWdhdG9yLmRlbGV0ZShBY2Nlc3NDb250cm9sc0RlbGVnYXRvci5qYXZhOjEwOSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uUnBjUmVjZWl2ZXIubGFtYmRhJHByb2Nlc3NSZXF1ZXN0QXN5bmMkNChScGNSZWNlaXZlci5qYXZhOjIwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uQXN5bmNFeGVjdXRvci5sYW1iZGEkc3VibWl0JDAoQXN5bmNFeGVjdXRvci5qYXZhOjI3Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KENvbnRleHRSdW5uYWJsZS5qYXZhOjUwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZSQxLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozOSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NzIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozNilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRXhlY3V0b3JzJFJ1bm5hYmxlQWRhcHRlci5jYWxsKEV4ZWN1dG9ycy5qYXZhOjUxMSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRnV0dXJlVGFzay5ydW4oRnV0dXJlVGFzay5qYXZhOjI2Nilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yLnJ1bldvcmtlcihUaHJlYWRQb29sRXhlY3V0b3IuamF2YToxMTQ5KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IkV29ya2VyLnJ1bihUaHJlYWRQb29sRXhlY3V0b3IuamF2YTo2MjQpXG5cdGF0IGphdmEubGFuZy5UaHJlYWQucnVuKFRocmVhZC5qYXZhOjc0OClcbkNhdXNlZCBieTogY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb246IGludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIGRvZXMgbm90IGhhdmUgc2VydmljZXVzYWdlLnNlcnZpY2VzLnVzZSBhY2Nlc3MgdG8gcHJvamVjdCA2NDIwODA5MTgxMDEuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93T25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjI5MClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMSlcblx0Li4uIDE5IG1vcmVcblxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS5FcnJvckNvbGxlY3Rvci50b0ZhdWx0KEVycm9yQ29sbGVjdG9yLmphdmE6NTQpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5yZXN0LmFkYXB0ZXIucm9zeS5Sb3N5RXJyb3JDb252ZXJ0ZXIudG9GYXVsdChSb3N5RXJyb3JDb252ZXJ0ZXIuamF2YTo2Nylcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnJlc3QuYWRhcHRlci5yb3N5LlJvc3lIYW5kbGVyJDIuY2FsbChSb3N5SGFuZGxlci5qYXZhOjI1OClcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnJlc3QuYWRhcHRlci5yb3N5LlJvc3lIYW5kbGVyJDIuY2FsbChSb3N5SGFuZGxlci5qYXZhOjIzOClcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkRpcmVjdEV4ZWN1dG9yLmV4ZWN1dGUoRGlyZWN0RXhlY3V0b3IuamF2YTozMClcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmV4ZWN1dGVMaXN0ZW5lcihBYnN0cmFjdEZ1dHVyZS5qYXZhOjExNDMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5jb21wbGV0ZShBYnN0cmFjdEZ1dHVyZS5qYXZhOjk2Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLnNldChBYnN0cmFjdEZ1dHVyZS5qYXZhOjczMSlcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkRpcmVjdEV4ZWN1dG9yLmV4ZWN1dGUoRGlyZWN0RXhlY3V0b3IuamF2YTozMClcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmV4ZWN1dGVMaXN0ZW5lcihBYnN0cmFjdEZ1dHVyZS5qYXZhOjExNDMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5jb21wbGV0ZShBYnN0cmFjdEZ1dHVyZS5qYXZhOjk2Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLnNldChBYnN0cmFjdEZ1dHVyZS5qYXZhOjczMSlcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnRocmVhZC5UaHJlYWRUcmFja2VycyRUaHJlYWRUcmFja2luZ1J1bm5hYmxlLnJ1bihUaHJlYWRUcmFja2Vycy5qYXZhOjEyNilcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRUcmFjZUNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoVHJhY2VDb250ZXh0LmphdmE6NDU1KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuc2VydmVyLkNvbW1vbk1vZHVsZSRDb250ZXh0Q2FycnlpbmdFeGVjdXRvclNlcnZpY2UkMS5ydW5JbkNvbnRleHQoQ29tbW9uTW9kdWxlLmphdmE6ODQ2KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JFRyYWNlQ29udGV4dFJ1bm5hYmxlJDEucnVuKFRyYWNlQ29udGV4dC5qYXZhOjQ2Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRBYnN0cmFjdFRyYWNlQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoVHJhY2VDb250ZXh0LmphdmE6MzIxKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JEFic3RyYWN0VHJhY2VDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KFRyYWNlQ29udGV4dC5qYXZhOjMxMylcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRUcmFjZUNvbnRleHRSdW5uYWJsZS5ydW4oVHJhY2VDb250ZXh0LmphdmE6NDU5KVxuXHRhdCBjb20uZ29vZ2xlLmdzZS5pbnRlcm5hbC5EaXNwYXRjaFF1ZXVlSW1wbCRXb3JrZXJUaHJlYWQucnVuKERpc3BhdGNoUXVldWVJbXBsLmphdmE6NDAzKVxuIn1dLCJjb2RlIjo0MDMsIm1lc3NhZ2UiOiJpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLiJ9fQ=="
+ }
+ },
+ {
+ "ID": "7df91939b16a2c81",
+ "Request": {
+ "Method": "PUT",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/foo/acl/domain-google.com?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "107"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "b2716cf9b5aa6106b6d3d84e155dd3a6/9047512809537917736;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/foo/acl/domain-google.com?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJlbnRpdHkiOiJkb21haW4tZ29vZ2xlLmNvbSIsInJvbGUiOiJSRUFERVIifQo="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "463"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:09 GMT"
+ ],
+ "Etag": [
+ "CISC0OiW290CEAU="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051395000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrbr88:4353,/bns/yv/borg/yv/bns/blobstore2/bitpusher/193.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=JMysW5r_ONOSgwS845_ACg"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/193.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/193:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATpxChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4CtK4wESxgF5YTI5LmMuRW93QkpRWVNNdC1OVDFNYTJvWXBrbG1qcDlJMlZaUFZ5bFl5Z2Q3Nk5tQXlXbWR3WVBoMm00dGI3ZmZjOUlzcTU4MmVFcFBhNzhNWGpNZmIzaE9WTE9xRHpNTUFfTG9NQXVJZkdkMGgzSWowZ1dxdW5DS1g3Qk1mQlJxM001TUtMMXBHOWNyU0ZBT29lVkZpTDhpWlBsUDI0VjE5THdzZ0d1ZnVrQTFtVzVJcTJUUkVXeWQyNjRKZC1lS2UxdTAwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Ur9ztnAX_J_zFeQE4_hRnQ7btIzyA7VxKK0HAhiVm2EEWBKqUlImVx8tuF0RV3DtIeQ1c3_TZsw25NUDRWcGqPLxRIw4Q"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMvZm9vLzE1MzgwNTEwOTM1NjE2MDQvZG9tYWluLWdvb2dsZS5jb20iLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMvby9mb28vYWNsL2RvbWFpbi1nb29nbGUuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzIiwib2JqZWN0IjoiZm9vIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwOTM1NjE2MDQiLCJlbnRpdHkiOiJkb21haW4tZ29vZ2xlLmNvbSIsInJvbGUiOiJSRUFERVIiLCJkb21haW4iOiJnb29nbGUuY29tIiwiZXRhZyI6IkNJU0MwT2lXMjkwQ0VBVT0ifQ=="
+ }
+ },
+ {
+ "ID": "7d4b183a11bce139",
+ "Request": {
+ "Method": "PUT",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/foo/acl/domain-google.com?alt=json\u0026prettyPrint=false\u0026userProject=dulcet-port-762",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "107"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "ed4c07520b33a6edeccca7e43cbd2b59/10637923609815316679;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/foo/acl/domain-google.com?alt=json\u0026prettyPrint=false\u0026userProject=dulcet-port-762"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJlbnRpdHkiOiJkb21haW4tZ29vZ2xlLmNvbSIsInJvbGUiOiJSRUFERVIifQo="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "463"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:09 GMT"
+ ],
+ "Etag": [
+ "CISC0OiW290CEAU="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051395000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrta22:4161,/bns/yv/borg/yv/bns/blobstore2/bitpusher/372.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=JcysW6yZDcflgQSplIvgBw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/372.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/372:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATpxChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4CtK4wESxgF5YTI5LmMuRW93QkpRWVNNdC1OVDFNYTJvWXBrbG1qcDlJMlZaUFZ5bFl5Z2Q3Nk5tQXlXbWR3WVBoMm00dGI3ZmZjOUlzcTU4MmVFcFBhNzhNWGpNZmIzaE9WTE9xRHpNTUFfTG9NQXVJZkdkMGgzSWowZ1dxdW5DS1g3Qk1mQlJxM001TUtMMXBHOWNyU0ZBT29lVkZpTDhpWlBsUDI0VjE5THdzZ0d1ZnVrQTFtVzVJcTJUUkVXeWQyNjRKZC1lS2UxdTAwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UpJrq84lbv5EUPgf6THcIVagDI8PK2rgrYCRntGvroWRZvZ3SfUfd2sHPmkck7SuQlCffNYbH0k97QCysZK0do7CzwK8A"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMvZm9vLzE1MzgwNTEwOTM1NjE2MDQvZG9tYWluLWdvb2dsZS5jb20iLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMvby9mb28vYWNsL2RvbWFpbi1nb29nbGUuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzIiwib2JqZWN0IjoiZm9vIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwOTM1NjE2MDQiLCJlbnRpdHkiOiJkb21haW4tZ29vZ2xlLmNvbSIsInJvbGUiOiJSRUFERVIiLCJkb21haW4iOiJnb29nbGUuY29tIiwiZXRhZyI6IkNJU0MwT2lXMjkwQ0VBVT0ifQ=="
+ }
+ },
+ {
+ "ID": "830be57d8d5b034e",
+ "Request": {
+ "Method": "PUT",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/foo/acl/domain-google.com?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "107"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "47beea259ddd2b4ce2f3abd8d7dc99bc/12228335513865690726;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/foo/acl/domain-google.com?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJlbnRpdHkiOiJkb21haW4tZ29vZ2xlLmNvbSIsInJvbGUiOiJSRUFERVIifQo="
+ },
+ "Response": {
+ "StatusCode": 400,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Content-Length": [
+ "13131"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:09 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051395000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "471383502717"
+ ],
+ "X-Google-Backends": [
+ "vrti20:4165,/bns/yw/borg/yw/bns/blobstore2/bitpusher/44.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=JcysW_mJEte8hgSCg6LoCA"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yw/borg/yw/bns/blobstore2/bitpusher/44.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yw/borg/yw/bns/blobstore2/bitpusher/44:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CP3elYXcDRoCGAYoATo_ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGM6ropHgHCIVMTE3MjM4MDU4ODYxOTM3NTE5MTQ0MOArSp8BEoIBeWEyOS5jLkVsb2xCcldWbUZlX1AxVDdUOHVpTXdFMHBZUjdTc2NVMDBFdEZkc2tSenBQY0NLWkhUeEZaYXI0Q25tZmR6bXFRLTNVV0kzOF9wdEx5VTZ2Z1Q3dlRBeW42Z3g4dUcyd0szSHIzaTZrV1JBZkozc1pNMGQ1allkNHpWQTAEOhZOT1RfQV9QRVJTSVNURU5UX1RPS0VO"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Upload-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UpdIdGeWvzEPEhxanvKVaOS9s30-Ks08qtwPfKpcUgEvujPfnyww57z0FCERZ2_qwzT68OwihUV926Vyq4Kb4frc6nuCA"
+ ]
+ },
+ "Body": "eyJlcnJvciI6eyJlcnJvcnMiOlt7ImRvbWFpbiI6Imdsb2JhbCIsInJlYXNvbiI6InJlcXVpcmVkIiwibWVzc2FnZSI6IkJ1Y2tldCBpcyByZXF1ZXN0ZXIgcGF5cyBidWNrZXQgYnV0IG5vIHVzZXIgcHJvamVjdCBwcm92aWRlZC4iLCJkZWJ1Z0luZm8iOiJjb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6VVNFUl9QUk9KRUNUX01JU1NJTkc6IEJ1Y2tldCBpcyBSZXF1ZXN0ZXIgUGF5cyBidWNrZXQgYnV0IG5vIGJpbGxpbmcgcHJvamVjdCBpZCBwcm92aWRlZCBmb3Igbm9uLW93bmVyLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5BY2Nlc3NDb250cm9sc0hlbHBlci5sb2FkT2JqZWN0KEFjY2Vzc0NvbnRyb2xzSGVscGVyLmphdmE6MzMxKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuQWNjZXNzQ29udHJvbHNIZWxwZXIuZ2V0QWNsUmVzb3VyY2VGb3JSZXF1ZXN0KEFjY2Vzc0NvbnRyb2xzSGVscGVyLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5VcGRhdGVBY2xzLmhhbmRsZVJlcXVlc3RSZWNlaXZlZChVcGRhdGVBY2xzLmphdmE6NjIpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5VcGRhdGVBY2xzLmhhbmRsZVJlcXVlc3RSZWNlaXZlZChVcGRhdGVBY2xzLmphdmE6MTYpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5BY2Nlc3NDb250cm9sc0RlbGVnYXRvci51cGRhdGUoQWNjZXNzQ29udHJvbHNEZWxlZ2F0b3IuamF2YToxMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBCdWNrZXQgaXMgUmVxdWVzdGVyIFBheXMgYnVja2V0IGJ1dCBubyBiaWxsaW5nIHByb2plY3QgaWQgcHJvdmlkZWQgZm9yIG5vbi1vd25lci5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MjkwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAxKVxuXHQuLi4gMTkgbW9yZVxuXG5jb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS5GYXVsdDogSW1tdXRhYmxlRXJyb3JEZWZpbml0aW9ue2Jhc2U9UkVRVUlSRUQsIGNhdGVnb3J5PVVTRVJfRVJST1IsIGNhdXNlPW51bGwsIGRlYnVnSW5mbz1jb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6VVNFUl9QUk9KRUNUX01JU1NJTkc6IEJ1Y2tldCBpcyBSZXF1ZXN0ZXIgUGF5cyBidWNrZXQgYnV0IG5vIGJpbGxpbmcgcHJvamVjdCBpZCBwcm92aWRlZCBmb3Igbm9uLW93bmVyLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5BY2Nlc3NDb250cm9sc0hlbHBlci5sb2FkT2JqZWN0KEFjY2Vzc0NvbnRyb2xzSGVscGVyLmphdmE6MzMxKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuQWNjZXNzQ29udHJvbHNIZWxwZXIuZ2V0QWNsUmVzb3VyY2VGb3JSZXF1ZXN0KEFjY2Vzc0NvbnRyb2xzSGVscGVyLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5VcGRhdGVBY2xzLmhhbmRsZVJlcXVlc3RSZWNlaXZlZChVcGRhdGVBY2xzLmphdmE6NjIpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5VcGRhdGVBY2xzLmhhbmRsZVJlcXVlc3RSZWNlaXZlZChVcGRhdGVBY2xzLmphdmE6MTYpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5BY2Nlc3NDb250cm9sc0RlbGVnYXRvci51cGRhdGUoQWNjZXNzQ29udHJvbHNEZWxlZ2F0b3IuamF2YToxMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBCdWNrZXQgaXMgUmVxdWVzdGVyIFBheXMgYnVja2V0IGJ1dCBubyBiaWxsaW5nIHByb2plY3QgaWQgcHJvdmlkZWQgZm9yIG5vbi1vd25lci5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MjkwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAxKVxuXHQuLi4gMTkgbW9yZVxuLCBkb21haW49Z2xvYmFsLCBleHRlbmRlZEhlbHA9bnVsbCwgaHR0cEhlYWRlcnM9e30sIGh0dHBTdGF0dXM9YmFkUmVxdWVzdCwgaW50ZXJuYWxSZWFzb249UmVhc29ue2FyZ3VtZW50cz17fSwgY2F1c2U9bnVsbCwgY29kZT1nZGF0YS5Db3JlRXJyb3JEb21haW4uUkVRVUlSRUQsIGNyZWF0ZWRCeUJhY2tlbmQ9dHJ1ZSwgZGVidWdNZXNzYWdlPWNvbS5nb29nbGUubmV0LnJwYzMuUnBjRXhjZXB0aW9uOiBjbG91ZC5iaWdzdG9yZS5SZXNwb25zZUNvZGUuRXJyb3JDb2RlOjpVU0VSX1BST0pFQ1RfTUlTU0lORzogQnVja2V0IGlzIFJlcXVlc3RlciBQYXlzIGJ1Y2tldCBidXQgbm8gYmlsbGluZyBwcm9qZWN0IGlkIHByb3ZpZGVkIGZvciBub24tb3duZXIuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRvUnBjM0V4Y2VwdGlvbihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjEzNSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLkFjY2Vzc0NvbnRyb2xzSGVscGVyLmxvYWRPYmplY3QoQWNjZXNzQ29udHJvbHNIZWxwZXIuamF2YTozMzEpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5BY2Nlc3NDb250cm9sc0hlbHBlci5nZXRBY2xSZXNvdXJjZUZvclJlcXVlc3QoQWNjZXNzQ29udHJvbHNIZWxwZXIuamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLlVwZGF0ZUFjbHMuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKFVwZGF0ZUFjbHMuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLlVwZGF0ZUFjbHMuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKFVwZGF0ZUFjbHMuamF2YToxNilcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLkFjY2Vzc0NvbnRyb2xzRGVsZWdhdG9yLnVwZGF0ZShBY2Nlc3NDb250cm9sc0RlbGVnYXRvci5qYXZhOjEwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uUnBjUmVjZWl2ZXIubGFtYmRhJHByb2Nlc3NSZXF1ZXN0QXN5bmMkNChScGNSZWNlaXZlci5qYXZhOjIwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uQXN5bmNFeGVjdXRvci5sYW1iZGEkc3VibWl0JDAoQXN5bmNFeGVjdXRvci5qYXZhOjI3Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KENvbnRleHRSdW5uYWJsZS5qYXZhOjUwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZSQxLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozOSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NzIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozNilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRXhlY3V0b3JzJFJ1bm5hYmxlQWRhcHRlci5jYWxsKEV4ZWN1dG9ycy5qYXZhOjUxMSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRnV0dXJlVGFzay5ydW4oRnV0dXJlVGFzay5qYXZhOjI2Nilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yLnJ1bldvcmtlcihUaHJlYWRQb29sRXhlY3V0b3IuamF2YToxMTQ5KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IkV29ya2VyLnJ1bihUaHJlYWRQb29sRXhlY3V0b3IuamF2YTo2MjQpXG5cdGF0IGphdmEubGFuZy5UaHJlYWQucnVuKFRocmVhZC5qYXZhOjc0OClcbkNhdXNlZCBieTogY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb246IEJ1Y2tldCBpcyBSZXF1ZXN0ZXIgUGF5cyBidWNrZXQgYnV0IG5vIGJpbGxpbmcgcHJvamVjdCBpZCBwcm92aWRlZCBmb3Igbm9uLW93bmVyLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxOSBtb3JlXG4sIGVycm9yUHJvdG9Db2RlPVJFUVVJUkVELCBlcnJvclByb3RvRG9tYWluPWdkYXRhLkNvcmVFcnJvckRvbWFpbiwgZmlsdGVyZWRNZXNzYWdlPW51bGwsIGxvY2F0aW9uPW51bGwsIG1lc3NhZ2U9QnVja2V0IGlzIHJlcXVlc3RlciBwYXlzIGJ1Y2tldCBidXQgbm8gdXNlciBwcm9qZWN0IHByb3ZpZGVkLiwgdW5uYW1lZEFyZ3VtZW50cz1bXX0sIGxvY2F0aW9uPW51bGwsIG1lc3NhZ2U9QnVja2V0IGlzIHJlcXVlc3RlciBwYXlzIGJ1Y2tldCBidXQgbm8gdXNlciBwcm9qZWN0IHByb3ZpZGVkLiwgcmVhc29uPXJlcXVpcmVkLCBycGNDb2RlPTQwMH0gQnVja2V0IGlzIHJlcXVlc3RlciBwYXlzIGJ1Y2tldCBidXQgbm8gdXNlciBwcm9qZWN0IHByb3ZpZGVkLjogY29tLmdvb2dsZS5uZXQucnBjMy5ScGNFeGNlcHRpb246IGNsb3VkLmJpZ3N0b3JlLlJlc3BvbnNlQ29kZS5FcnJvckNvZGU6OlVTRVJfUFJPSkVDVF9NSVNTSU5HOiBCdWNrZXQgaXMgUmVxdWVzdGVyIFBheXMgYnVja2V0IGJ1dCBubyBiaWxsaW5nIHByb2plY3QgaWQgcHJvdmlkZWQgZm9yIG5vbi1vd25lci5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udG9ScGMzRXhjZXB0aW9uKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MTM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuQWNjZXNzQ29udHJvbHNIZWxwZXIubG9hZE9iamVjdChBY2Nlc3NDb250cm9sc0hlbHBlci5qYXZhOjMzMSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLkFjY2Vzc0NvbnRyb2xzSGVscGVyLmdldEFjbFJlc291cmNlRm9yUmVxdWVzdChBY2Nlc3NDb250cm9sc0hlbHBlci5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuVXBkYXRlQWNscy5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoVXBkYXRlQWNscy5qYXZhOjYyKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuVXBkYXRlQWNscy5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoVXBkYXRlQWNscy5qYXZhOjE2KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmZyYW1ld29yay5SZXF1ZXN0SGFuZGxlci5oYW5kbGUoUmVxdWVzdEhhbmRsZXIuamF2YToyOTQpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uQWNjZXNzQ29udHJvbHNEZWxlZ2F0b3IudXBkYXRlKEFjY2Vzc0NvbnRyb2xzRGVsZWdhdG9yLmphdmE6MTAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5ScGNSZWNlaXZlci5sYW1iZGEkcHJvY2Vzc1JlcXVlc3RBc3luYyQ0KFJwY1JlY2VpdmVyLmphdmE6MjAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5Bc3luY0V4ZWN1dG9yLmxhbWJkYSRzdWJtaXQkMChBc3luY0V4ZWN1dG9yLmphdmE6MjcyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoQ29udGV4dFJ1bm5hYmxlLmphdmE6NTApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlJDEucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM5KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo3Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5FeGVjdXRvcnMkUnVubmFibGVBZGFwdGVyLmNhbGwoRXhlY3V0b3JzLmphdmE6NTExKVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5GdXR1cmVUYXNrLnJ1bihGdXR1cmVUYXNrLmphdmE6MjY2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IucnVuV29ya2VyKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjExNDkpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvciRXb3JrZXIucnVuKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjYyNClcblx0YXQgamF2YS5sYW5nLlRocmVhZC5ydW4oVGhyZWFkLmphdmE6NzQ4KVxuQ2F1c2VkIGJ5OiBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbjogQnVja2V0IGlzIFJlcXVlc3RlciBQYXlzIGJ1Y2tldCBidXQgbm8gYmlsbGluZyBwcm9qZWN0IGlkIHByb3ZpZGVkIGZvciBub24tb3duZXIuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93T25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjI5MClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMSlcblx0Li4uIDE5IG1vcmVcblxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS5FcnJvckNvbGxlY3Rvci50b0ZhdWx0KEVycm9yQ29sbGVjdG9yLmphdmE6NTQpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5yZXN0LmFkYXB0ZXIucm9zeS5Sb3N5RXJyb3JDb252ZXJ0ZXIudG9GYXVsdChSb3N5RXJyb3JDb252ZXJ0ZXIuamF2YTo2Nylcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnJlc3QuYWRhcHRlci5yb3N5LlJvc3lIYW5kbGVyJDIuY2FsbChSb3N5SGFuZGxlci5qYXZhOjI1OClcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnJlc3QuYWRhcHRlci5yb3N5LlJvc3lIYW5kbGVyJDIuY2FsbChSb3N5SGFuZGxlci5qYXZhOjIzOClcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkRpcmVjdEV4ZWN1dG9yLmV4ZWN1dGUoRGlyZWN0RXhlY3V0b3IuamF2YTozMClcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmV4ZWN1dGVMaXN0ZW5lcihBYnN0cmFjdEZ1dHVyZS5qYXZhOjExNDMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5jb21wbGV0ZShBYnN0cmFjdEZ1dHVyZS5qYXZhOjk2Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLnNldChBYnN0cmFjdEZ1dHVyZS5qYXZhOjczMSlcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkRpcmVjdEV4ZWN1dG9yLmV4ZWN1dGUoRGlyZWN0RXhlY3V0b3IuamF2YTozMClcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmV4ZWN1dGVMaXN0ZW5lcihBYnN0cmFjdEZ1dHVyZS5qYXZhOjExNDMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5jb21wbGV0ZShBYnN0cmFjdEZ1dHVyZS5qYXZhOjk2Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLnNldChBYnN0cmFjdEZ1dHVyZS5qYXZhOjczMSlcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnRocmVhZC5UaHJlYWRUcmFja2VycyRUaHJlYWRUcmFja2luZ1J1bm5hYmxlLnJ1bihUaHJlYWRUcmFja2Vycy5qYXZhOjEyNilcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRUcmFjZUNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoVHJhY2VDb250ZXh0LmphdmE6NDU1KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuc2VydmVyLkNvbW1vbk1vZHVsZSRDb250ZXh0Q2FycnlpbmdFeGVjdXRvclNlcnZpY2UkMS5ydW5JbkNvbnRleHQoQ29tbW9uTW9kdWxlLmphdmE6ODQ2KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JFRyYWNlQ29udGV4dFJ1bm5hYmxlJDEucnVuKFRyYWNlQ29udGV4dC5qYXZhOjQ2Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRBYnN0cmFjdFRyYWNlQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoVHJhY2VDb250ZXh0LmphdmE6MzIxKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JEFic3RyYWN0VHJhY2VDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KFRyYWNlQ29udGV4dC5qYXZhOjMxMylcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRUcmFjZUNvbnRleHRSdW5uYWJsZS5ydW4oVHJhY2VDb250ZXh0LmphdmE6NDU5KVxuXHRhdCBjb20uZ29vZ2xlLmdzZS5pbnRlcm5hbC5EaXNwYXRjaFF1ZXVlSW1wbCRXb3JrZXJUaHJlYWQucnVuKERpc3BhdGNoUXVldWVJbXBsLmphdmE6NDAzKVxuIn1dLCJjb2RlIjo0MDAsIm1lc3NhZ2UiOiJCdWNrZXQgaXMgcmVxdWVzdGVyIHBheXMgYnVja2V0IGJ1dCBubyB1c2VyIHByb2plY3QgcHJvdmlkZWQuIn19"
+ }
+ },
+ {
+ "ID": "a813a7a74b51212b",
+ "Request": {
+ "Method": "PUT",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/foo/acl/domain-google.com?alt=json\u0026prettyPrint=false\u0026userProject=gcloud-golang-firestore-tests",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "107"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "e31f23b0bbd0536807020a4116896372/13818465947251163908;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/foo/acl/domain-google.com?alt=json\u0026prettyPrint=false\u0026userProject=gcloud-golang-firestore-tests"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJlbnRpdHkiOiJkb21haW4tZ29vZ2xlLmNvbSIsInJvbGUiOiJSRUFERVIifQo="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "463"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:09 GMT"
+ ],
+ "Etag": [
+ "CISC0OiW290CEAU="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051395000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "471383502717"
+ ],
+ "X-Google-Backends": [
+ "vrkx5:4004,/bns/yv/borg/yv/bns/blobstore2/bitpusher/210.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=JcysW9OaIJLWgwSI4rWoBg"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/210.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/210:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CP3elYXcDRoCGAYoATo_ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGM6ropHgHCIVMTE3MjM4MDU4ODYxOTM3NTE5MTQ0MOArSp8BEoIBeWEyOS5jLkVsb2xCcldWbUZlX1AxVDdUOHVpTXdFMHBZUjdTc2NVMDBFdEZkc2tSenBQY0NLWkhUeEZaYXI0Q25tZmR6bXFRLTNVV0kzOF9wdEx5VTZ2Z1Q3dlRBeW42Z3g4dUcyd0szSHIzaTZrV1JBZkozc1pNMGQ1allkNHpWQTAEOhZOT1RfQV9QRVJTSVNURU5UX1RPS0VO"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UparWf6waxsZzPSiInxkNT-tYiY9T7YcRChH9lHB29YNw_LvBYyQN5RVNVa0PA3tEd31Har-YzV8SG9c216FVNesZYb7Q"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMvZm9vLzE1MzgwNTEwOTM1NjE2MDQvZG9tYWluLWdvb2dsZS5jb20iLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMvby9mb28vYWNsL2RvbWFpbi1nb29nbGUuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzIiwib2JqZWN0IjoiZm9vIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwOTM1NjE2MDQiLCJlbnRpdHkiOiJkb21haW4tZ29vZ2xlLmNvbSIsInJvbGUiOiJSRUFERVIiLCJkb21haW4iOiJnb29nbGUuY29tIiwiZXRhZyI6IkNJU0MwT2lXMjkwQ0VBVT0ifQ=="
+ }
+ },
+ {
+ "ID": "876de65442e97d90",
+ "Request": {
+ "Method": "PUT",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/foo/acl/domain-google.com?alt=json\u0026prettyPrint=false\u0026userProject=veener-jba",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "107"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "92b1d8b4d4646c948ae20f5d76daeddc/15408877847006636451;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/foo/acl/domain-google.com?alt=json\u0026prettyPrint=false\u0026userProject=veener-jba"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJlbnRpdHkiOiJkb21haW4tZ29vZ2xlLmNvbSIsInJvbGUiOiJSRUFERVIifQo="
+ },
+ "Response": {
+ "StatusCode": 403,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Content-Length": [
+ "13987"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:09 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051395000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "471383502717"
+ ],
+ "X-Google-Backends": [
+ "vrga66:4480,/bns/yw/borg/yw/bns/blobstore2/bitpusher/129.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=JcysW7yZJcLYN-_yv-gJ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yw/borg/yw/bns/blobstore2/bitpusher/129.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yw/borg/yw/bns/blobstore2/bitpusher/129:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CP3elYXcDRoCGAYoATo_ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGM6ropHgHCIVMTE3MjM4MDU4ODYxOTM3NTE5MTQ0MOArSp8BEoIBeWEyOS5jLkVsb2xCcldWbUZlX1AxVDdUOHVpTXdFMHBZUjdTc2NVMDBFdEZkc2tSenBQY0NLWkhUeEZaYXI0Q25tZmR6bXFRLTNVV0kzOF9wdEx5VTZ2Z1Q3dlRBeW42Z3g4dUcyd0szSHIzaTZrV1JBZkozc1pNMGQ1allkNHpWQTAEOhZOT1RfQV9QRVJTSVNURU5UX1RPS0VO"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Upload-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UpzYeinxYvUcF89GNgxzHiwRGzRSiOPh8lXsF8Ui7yYuzaYzTYa1sdbSYFYW0mg6VMgQO1a8jcG50JRjKPSkwXB5S1zPg"
+ ]
+ },
+ "Body": "eyJlcnJvciI6eyJlcnJvcnMiOlt7ImRvbWFpbiI6Imdsb2JhbCIsInJlYXNvbiI6ImZvcmJpZGRlbiIsIm1lc3NhZ2UiOiJpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLiIsImRlYnVnSW5mbyI6ImNvbS5nb29nbGUubmV0LnJwYzMuUnBjRXhjZXB0aW9uOiBjbG91ZC5iaWdzdG9yZS5SZXNwb25zZUNvZGUuRXJyb3JDb2RlOjpVU0VSX1BST0pFQ1RfQUNDRVNTX0RFTklFRDogaW50ZWdyYXRpb25AZ2Nsb3VkLWdvbGFuZy1maXJlc3RvcmUtdGVzdHMuaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20gZG9lcyBub3QgaGF2ZSBzZXJ2aWNldXNhZ2Uuc2VydmljZXMudXNlIGFjY2VzcyB0byBwcm9qZWN0IDY0MjA4MDkxODEwMS5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udG9ScGMzRXhjZXB0aW9uKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MTM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuQWNjZXNzQ29udHJvbHNIZWxwZXIubG9hZE9iamVjdChBY2Nlc3NDb250cm9sc0hlbHBlci5qYXZhOjMzMSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLkFjY2Vzc0NvbnRyb2xzSGVscGVyLmdldEFjbFJlc291cmNlRm9yUmVxdWVzdChBY2Nlc3NDb250cm9sc0hlbHBlci5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuVXBkYXRlQWNscy5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoVXBkYXRlQWNscy5qYXZhOjYyKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuVXBkYXRlQWNscy5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoVXBkYXRlQWNscy5qYXZhOjE2KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmZyYW1ld29yay5SZXF1ZXN0SGFuZGxlci5oYW5kbGUoUmVxdWVzdEhhbmRsZXIuamF2YToyOTQpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uQWNjZXNzQ29udHJvbHNEZWxlZ2F0b3IudXBkYXRlKEFjY2Vzc0NvbnRyb2xzRGVsZWdhdG9yLmphdmE6MTAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5ScGNSZWNlaXZlci5sYW1iZGEkcHJvY2Vzc1JlcXVlc3RBc3luYyQ0KFJwY1JlY2VpdmVyLmphdmE6MjAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5Bc3luY0V4ZWN1dG9yLmxhbWJkYSRzdWJtaXQkMChBc3luY0V4ZWN1dG9yLmphdmE6MjcyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoQ29udGV4dFJ1bm5hYmxlLmphdmE6NTApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlJDEucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM5KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo3Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5FeGVjdXRvcnMkUnVubmFibGVBZGFwdGVyLmNhbGwoRXhlY3V0b3JzLmphdmE6NTExKVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5GdXR1cmVUYXNrLnJ1bihGdXR1cmVUYXNrLmphdmE6MjY2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IucnVuV29ya2VyKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjExNDkpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvciRXb3JrZXIucnVuKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjYyNClcblx0YXQgamF2YS5sYW5nLlRocmVhZC5ydW4oVGhyZWFkLmphdmE6NzQ4KVxuQ2F1c2VkIGJ5OiBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbjogaW50ZWdyYXRpb25AZ2Nsb3VkLWdvbGFuZy1maXJlc3RvcmUtdGVzdHMuaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20gZG9lcyBub3QgaGF2ZSBzZXJ2aWNldXNhZ2Uuc2VydmljZXMudXNlIGFjY2VzcyB0byBwcm9qZWN0IDY0MjA4MDkxODEwMS5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MjkwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAxKVxuXHQuLi4gMTkgbW9yZVxuXG5jb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS5GYXVsdDogSW1tdXRhYmxlRXJyb3JEZWZpbml0aW9ue2Jhc2U9Rk9SQklEREVOLCBjYXRlZ29yeT1VU0VSX0VSUk9SLCBjYXVzZT1udWxsLCBkZWJ1Z0luZm89Y29tLmdvb2dsZS5uZXQucnBjMy5ScGNFeGNlcHRpb246IGNsb3VkLmJpZ3N0b3JlLlJlc3BvbnNlQ29kZS5FcnJvckNvZGU6OlVTRVJfUFJPSkVDVF9BQ0NFU1NfREVOSUVEOiBpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5BY2Nlc3NDb250cm9sc0hlbHBlci5sb2FkT2JqZWN0KEFjY2Vzc0NvbnRyb2xzSGVscGVyLmphdmE6MzMxKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuQWNjZXNzQ29udHJvbHNIZWxwZXIuZ2V0QWNsUmVzb3VyY2VGb3JSZXF1ZXN0KEFjY2Vzc0NvbnRyb2xzSGVscGVyLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5VcGRhdGVBY2xzLmhhbmRsZVJlcXVlc3RSZWNlaXZlZChVcGRhdGVBY2xzLmphdmE6NjIpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5VcGRhdGVBY2xzLmhhbmRsZVJlcXVlc3RSZWNlaXZlZChVcGRhdGVBY2xzLmphdmE6MTYpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5BY2Nlc3NDb250cm9sc0RlbGVnYXRvci51cGRhdGUoQWNjZXNzQ29udHJvbHNEZWxlZ2F0b3IuamF2YToxMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxOSBtb3JlXG4sIGRvbWFpbj1nbG9iYWwsIGV4dGVuZGVkSGVscD1udWxsLCBodHRwSGVhZGVycz17fSwgaHR0cFN0YXR1cz1mb3JiaWRkZW4sIGludGVybmFsUmVhc29uPVJlYXNvbnthcmd1bWVudHM9e30sIGNhdXNlPW51bGwsIGNvZGU9Z2RhdGEuQ29yZUVycm9yRG9tYWluLkZPUkJJRERFTiwgY3JlYXRlZEJ5QmFja2VuZD10cnVlLCBkZWJ1Z01lc3NhZ2U9Y29tLmdvb2dsZS5uZXQucnBjMy5ScGNFeGNlcHRpb246IGNsb3VkLmJpZ3N0b3JlLlJlc3BvbnNlQ29kZS5FcnJvckNvZGU6OlVTRVJfUFJPSkVDVF9BQ0NFU1NfREVOSUVEOiBpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5BY2Nlc3NDb250cm9sc0hlbHBlci5sb2FkT2JqZWN0KEFjY2Vzc0NvbnRyb2xzSGVscGVyLmphdmE6MzMxKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuQWNjZXNzQ29udHJvbHNIZWxwZXIuZ2V0QWNsUmVzb3VyY2VGb3JSZXF1ZXN0KEFjY2Vzc0NvbnRyb2xzSGVscGVyLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5VcGRhdGVBY2xzLmhhbmRsZVJlcXVlc3RSZWNlaXZlZChVcGRhdGVBY2xzLmphdmE6NjIpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5VcGRhdGVBY2xzLmhhbmRsZVJlcXVlc3RSZWNlaXZlZChVcGRhdGVBY2xzLmphdmE6MTYpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5BY2Nlc3NDb250cm9sc0RlbGVnYXRvci51cGRhdGUoQWNjZXNzQ29udHJvbHNEZWxlZ2F0b3IuamF2YToxMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxOSBtb3JlXG4sIGVycm9yUHJvdG9Db2RlPUZPUkJJRERFTiwgZXJyb3JQcm90b0RvbWFpbj1nZGF0YS5Db3JlRXJyb3JEb21haW4sIGZpbHRlcmVkTWVzc2FnZT1udWxsLCBsb2NhdGlvbj1udWxsLCBtZXNzYWdlPWludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIGRvZXMgbm90IGhhdmUgc2VydmljZXVzYWdlLnNlcnZpY2VzLnVzZSBhY2Nlc3MgdG8gcHJvamVjdCA2NDIwODA5MTgxMDEuLCB1bm5hbWVkQXJndW1lbnRzPVtdfSwgbG9jYXRpb249bnVsbCwgbWVzc2FnZT1pbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLiwgcmVhc29uPWZvcmJpZGRlbiwgcnBjQ29kZT00MDN9IGludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIGRvZXMgbm90IGhhdmUgc2VydmljZXVzYWdlLnNlcnZpY2VzLnVzZSBhY2Nlc3MgdG8gcHJvamVjdCA2NDIwODA5MTgxMDEuOiBjb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6VVNFUl9QUk9KRUNUX0FDQ0VTU19ERU5JRUQ6IGludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIGRvZXMgbm90IGhhdmUgc2VydmljZXVzYWdlLnNlcnZpY2VzLnVzZSBhY2Nlc3MgdG8gcHJvamVjdCA2NDIwODA5MTgxMDEuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRvUnBjM0V4Y2VwdGlvbihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjEzNSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLkFjY2Vzc0NvbnRyb2xzSGVscGVyLmxvYWRPYmplY3QoQWNjZXNzQ29udHJvbHNIZWxwZXIuamF2YTozMzEpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5BY2Nlc3NDb250cm9sc0hlbHBlci5nZXRBY2xSZXNvdXJjZUZvclJlcXVlc3QoQWNjZXNzQ29udHJvbHNIZWxwZXIuamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLlVwZGF0ZUFjbHMuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKFVwZGF0ZUFjbHMuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLlVwZGF0ZUFjbHMuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKFVwZGF0ZUFjbHMuamF2YToxNilcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLkFjY2Vzc0NvbnRyb2xzRGVsZWdhdG9yLnVwZGF0ZShBY2Nlc3NDb250cm9sc0RlbGVnYXRvci5qYXZhOjEwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uUnBjUmVjZWl2ZXIubGFtYmRhJHByb2Nlc3NSZXF1ZXN0QXN5bmMkNChScGNSZWNlaXZlci5qYXZhOjIwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uQXN5bmNFeGVjdXRvci5sYW1iZGEkc3VibWl0JDAoQXN5bmNFeGVjdXRvci5qYXZhOjI3Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KENvbnRleHRSdW5uYWJsZS5qYXZhOjUwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZSQxLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozOSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NzIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozNilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRXhlY3V0b3JzJFJ1bm5hYmxlQWRhcHRlci5jYWxsKEV4ZWN1dG9ycy5qYXZhOjUxMSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRnV0dXJlVGFzay5ydW4oRnV0dXJlVGFzay5qYXZhOjI2Nilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yLnJ1bldvcmtlcihUaHJlYWRQb29sRXhlY3V0b3IuamF2YToxMTQ5KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IkV29ya2VyLnJ1bihUaHJlYWRQb29sRXhlY3V0b3IuamF2YTo2MjQpXG5cdGF0IGphdmEubGFuZy5UaHJlYWQucnVuKFRocmVhZC5qYXZhOjc0OClcbkNhdXNlZCBieTogY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb246IGludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIGRvZXMgbm90IGhhdmUgc2VydmljZXVzYWdlLnNlcnZpY2VzLnVzZSBhY2Nlc3MgdG8gcHJvamVjdCA2NDIwODA5MTgxMDEuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93T25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjI5MClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMSlcblx0Li4uIDE5IG1vcmVcblxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS5FcnJvckNvbGxlY3Rvci50b0ZhdWx0KEVycm9yQ29sbGVjdG9yLmphdmE6NTQpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5yZXN0LmFkYXB0ZXIucm9zeS5Sb3N5RXJyb3JDb252ZXJ0ZXIudG9GYXVsdChSb3N5RXJyb3JDb252ZXJ0ZXIuamF2YTo2Nylcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnJlc3QuYWRhcHRlci5yb3N5LlJvc3lIYW5kbGVyJDIuY2FsbChSb3N5SGFuZGxlci5qYXZhOjI1OClcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnJlc3QuYWRhcHRlci5yb3N5LlJvc3lIYW5kbGVyJDIuY2FsbChSb3N5SGFuZGxlci5qYXZhOjIzOClcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkRpcmVjdEV4ZWN1dG9yLmV4ZWN1dGUoRGlyZWN0RXhlY3V0b3IuamF2YTozMClcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmV4ZWN1dGVMaXN0ZW5lcihBYnN0cmFjdEZ1dHVyZS5qYXZhOjExNDMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5jb21wbGV0ZShBYnN0cmFjdEZ1dHVyZS5qYXZhOjk2Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLnNldChBYnN0cmFjdEZ1dHVyZS5qYXZhOjczMSlcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkRpcmVjdEV4ZWN1dG9yLmV4ZWN1dGUoRGlyZWN0RXhlY3V0b3IuamF2YTozMClcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmV4ZWN1dGVMaXN0ZW5lcihBYnN0cmFjdEZ1dHVyZS5qYXZhOjExNDMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5jb21wbGV0ZShBYnN0cmFjdEZ1dHVyZS5qYXZhOjk2Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLnNldChBYnN0cmFjdEZ1dHVyZS5qYXZhOjczMSlcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnRocmVhZC5UaHJlYWRUcmFja2VycyRUaHJlYWRUcmFja2luZ1J1bm5hYmxlLnJ1bihUaHJlYWRUcmFja2Vycy5qYXZhOjEyNilcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRUcmFjZUNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoVHJhY2VDb250ZXh0LmphdmE6NDU1KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuc2VydmVyLkNvbW1vbk1vZHVsZSRDb250ZXh0Q2FycnlpbmdFeGVjdXRvclNlcnZpY2UkMS5ydW5JbkNvbnRleHQoQ29tbW9uTW9kdWxlLmphdmE6ODQ2KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JFRyYWNlQ29udGV4dFJ1bm5hYmxlJDEucnVuKFRyYWNlQ29udGV4dC5qYXZhOjQ2Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRBYnN0cmFjdFRyYWNlQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoVHJhY2VDb250ZXh0LmphdmE6MzIxKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JEFic3RyYWN0VHJhY2VDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KFRyYWNlQ29udGV4dC5qYXZhOjMxMylcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRUcmFjZUNvbnRleHRSdW5uYWJsZS5ydW4oVHJhY2VDb250ZXh0LmphdmE6NDU5KVxuXHRhdCBjb20uZ29vZ2xlLmdzZS5pbnRlcm5hbC5EaXNwYXRjaFF1ZXVlSW1wbCRXb3JrZXJUaHJlYWQucnVuKERpc3BhdGNoUXVldWVJbXBsLmphdmE6NDAzKVxuIn1dLCJjb2RlIjo0MDMsIm1lc3NhZ2UiOiJpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLiJ9fQ=="
+ }
+ },
+ {
+ "ID": "e99d5454df27e734",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/foo/acl?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "7f483e09cc86f574831ee0421c35e5fa/16999289751073787458;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/foo/acl?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0, must-revalidate, no-transform"
+ ],
+ "Content-Length": [
+ "2788"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:09 GMT"
+ ],
+ "Etag": [
+ "CISC0OiW290CEAU="
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:25:09 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051389000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vnfw23:4201,/bns/yx/borg/yx/bns/blobstore2/bitpusher/9.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=JcysW4XqM4aHzgLkspKIAw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yx/borg/yx/bns/blobstore2/bitpusher/9.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yx/borg/yx/bns/blobstore2/bitpusher/9:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATpxChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4CtK4wESxgF5YTI5LmMuRW93QkpRWVNNdC1OVDFNYTJvWXBrbG1qcDlJMlZaUFZ5bFl5Z2Q3Nk5tQXlXbWR3WVBoMm00dGI3ZmZjOUlzcTU4MmVFcFBhNzhNWGpNZmIzaE9WTE9xRHpNTUFfTG9NQXVJZkdkMGgzSWowZ1dxdW5DS1g3Qk1mQlJxM001TUtMMXBHOWNyU0ZBT29lVkZpTDhpWlBsUDI0VjE5THdzZ0d1ZnVrQTFtVzVJcTJUUkVXeWQyNjRKZC1lS2UxdTAwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UqFw4JZAQYCIoQGiC7YzARGdUVRclLSastcA-IAYPl1bPk7zoXPFij4lSO9h4-TbRz8X60Ra30Z25QAmogMkZrnIrI_3Q"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9scyIsIml0ZW1zIjpbeyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMvZm9vLzE1MzgwNTEwOTM1NjE2MDQvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMvby9mb28vYWNsL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzIiwib2JqZWN0IjoiZm9vIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwOTM1NjE2MDQiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNJU0MwT2lXMjkwQ0VBVT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9mb28vMTUzODA1MTA5MzU2MTYwNC9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMvby9mb28vYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMyIsIm9iamVjdCI6ImZvbyIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDkzNTYxNjA0IiwiZW50aXR5IjoicHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6ImVkaXRvcnMifSwiZXRhZyI6IkNJU0MwT2lXMjkwQ0VBVT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9mb28vMTUzODA1MTA5MzU2MTYwNC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMvby9mb28vYWNsL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMyIsIm9iamVjdCI6ImZvbyIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDkzNTYxNjA0IiwiZW50aXR5IjoicHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6IlJFQURFUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJ2aWV3ZXJzIn0sImV0YWciOiJDSVNDME9pVzI5MENFQVU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMvZm9vLzE1MzgwNTEwOTM1NjE2MDQvdXNlci1pbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9vL2Zvby9hY2wvdXNlci1pbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMyIsIm9iamVjdCI6ImZvbyIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDkzNTYxNjA0IiwiZW50aXR5IjoidXNlci1pbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSIsInJvbGUiOiJPV05FUiIsImVtYWlsIjoiaW50ZWdyYXRpb25AZ2Nsb3VkLWdvbGFuZy1maXJlc3RvcmUtdGVzdHMuaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJldGFnIjoiQ0lTQzBPaVcyOTBDRUFVPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL2Zvby8xNTM4MDUxMDkzNTYxNjA0L2RvbWFpbi1nb29nbGUuY29tIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL28vZm9vL2FjbC9kb21haW4tZ29vZ2xlLmNvbSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMyIsIm9iamVjdCI6ImZvbyIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDkzNTYxNjA0IiwiZW50aXR5IjoiZG9tYWluLWdvb2dsZS5jb20iLCJyb2xlIjoiUkVBREVSIiwiZG9tYWluIjoiZ29vZ2xlLmNvbSIsImV0YWciOiJDSVNDME9pVzI5MENFQVU9In1dfQ=="
+ }
+ },
+ {
+ "ID": "bbbff1cdd72a26e1",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/foo/acl?alt=json\u0026prettyPrint=false\u0026userProject=dulcet-port-762",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "bd9b2393642462b5c8bdce455c561af9/143237956896535776;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/foo/acl?alt=json\u0026prettyPrint=false\u0026userProject=dulcet-port-762"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0, must-revalidate, no-transform"
+ ],
+ "Content-Length": [
+ "2788"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:10 GMT"
+ ],
+ "Etag": [
+ "CISC0OiW290CEAU="
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:25:10 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051395000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrnn4:4418,/bns/yr/borg/yr/bns/blobstore2/bitpusher/46.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=JcysW9fdOcnF4QTguLLQCg"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/46.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/46:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATpxChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4CtK4wESxgF5YTI5LmMuRW93QkpRWVNNdC1OVDFNYTJvWXBrbG1qcDlJMlZaUFZ5bFl5Z2Q3Nk5tQXlXbWR3WVBoMm00dGI3ZmZjOUlzcTU4MmVFcFBhNzhNWGpNZmIzaE9WTE9xRHpNTUFfTG9NQXVJZkdkMGgzSWowZ1dxdW5DS1g3Qk1mQlJxM001TUtMMXBHOWNyU0ZBT29lVkZpTDhpWlBsUDI0VjE5THdzZ0d1ZnVrQTFtVzVJcTJUUkVXeWQyNjRKZC1lS2UxdTAwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Up-qKjKEvLs8mhoIBZjn644PJsEbock0wyZqP8NEPka0nZsHh6rwl__6LRjjPXz7RjZQvSOgYhfyoOpQfeCDnqWNMLS5hFmmPaEnzetwARYdsDJSsM"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9scyIsIml0ZW1zIjpbeyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMvZm9vLzE1MzgwNTEwOTM1NjE2MDQvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMvby9mb28vYWNsL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzIiwib2JqZWN0IjoiZm9vIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwOTM1NjE2MDQiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNJU0MwT2lXMjkwQ0VBVT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9mb28vMTUzODA1MTA5MzU2MTYwNC9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMvby9mb28vYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMyIsIm9iamVjdCI6ImZvbyIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDkzNTYxNjA0IiwiZW50aXR5IjoicHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6ImVkaXRvcnMifSwiZXRhZyI6IkNJU0MwT2lXMjkwQ0VBVT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9mb28vMTUzODA1MTA5MzU2MTYwNC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMvby9mb28vYWNsL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMyIsIm9iamVjdCI6ImZvbyIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDkzNTYxNjA0IiwiZW50aXR5IjoicHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6IlJFQURFUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJ2aWV3ZXJzIn0sImV0YWciOiJDSVNDME9pVzI5MENFQVU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMvZm9vLzE1MzgwNTEwOTM1NjE2MDQvdXNlci1pbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9vL2Zvby9hY2wvdXNlci1pbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMyIsIm9iamVjdCI6ImZvbyIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDkzNTYxNjA0IiwiZW50aXR5IjoidXNlci1pbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSIsInJvbGUiOiJPV05FUiIsImVtYWlsIjoiaW50ZWdyYXRpb25AZ2Nsb3VkLWdvbGFuZy1maXJlc3RvcmUtdGVzdHMuaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJldGFnIjoiQ0lTQzBPaVcyOTBDRUFVPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL2Zvby8xNTM4MDUxMDkzNTYxNjA0L2RvbWFpbi1nb29nbGUuY29tIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL28vZm9vL2FjbC9kb21haW4tZ29vZ2xlLmNvbSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMyIsIm9iamVjdCI6ImZvbyIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDkzNTYxNjA0IiwiZW50aXR5IjoiZG9tYWluLWdvb2dsZS5jb20iLCJyb2xlIjoiUkVBREVSIiwiZG9tYWluIjoiZ29vZ2xlLmNvbSIsImV0YWciOiJDSVNDME9pVzI5MENFQVU9In1dfQ=="
+ }
+ },
+ {
+ "ID": "fb158f6c638e4fd6",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/foo/acl?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "178ed4ffd76e625ae8bdeebf4cdf500c/1661311895755643263;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/foo/acl?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 400,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0"
+ ],
+ "Content-Length": [
+ "13087"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:10 GMT"
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:25:10 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051395000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "471383502717"
+ ],
+ "X-Google-Backends": [
+ "vrsq4:4180,/bns/yr/borg/yr/bns/blobstore2/bitpusher/109.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=JsysW4fJAc2TkATewpPoBg"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/109.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/109:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CP3elYXcDRoCGAYoATo_ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGM6ropHgHCIVMTE3MjM4MDU4ODYxOTM3NTE5MTQ0MOArSp8BEoIBeWEyOS5jLkVsb2xCcldWbUZlX1AxVDdUOHVpTXdFMHBZUjdTc2NVMDBFdEZkc2tSenBQY0NLWkhUeEZaYXI0Q25tZmR6bXFRLTNVV0kzOF9wdEx5VTZ2Z1Q3dlRBeW42Z3g4dUcyd0szSHIzaTZrV1JBZkozc1pNMGQ1allkNHpWQTAEOhZOT1RfQV9QRVJTSVNURU5UX1RPS0VO"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Upload-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UrLqMkF52b9YI5CWStirR3Vx8PSHOZLqsWPvlYejebN9HGI6BlPhip2U0WLxvWfEETUtnYyqKPjq5X8CxS83-22QWB9LA"
+ ]
+ },
+ "Body": "eyJlcnJvciI6eyJlcnJvcnMiOlt7ImRvbWFpbiI6Imdsb2JhbCIsInJlYXNvbiI6InJlcXVpcmVkIiwibWVzc2FnZSI6IkJ1Y2tldCBpcyByZXF1ZXN0ZXIgcGF5cyBidWNrZXQgYnV0IG5vIHVzZXIgcHJvamVjdCBwcm92aWRlZC4iLCJkZWJ1Z0luZm8iOiJjb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6VVNFUl9QUk9KRUNUX01JU1NJTkc6IEJ1Y2tldCBpcyBSZXF1ZXN0ZXIgUGF5cyBidWNrZXQgYnV0IG5vIGJpbGxpbmcgcHJvamVjdCBpZCBwcm92aWRlZCBmb3Igbm9uLW93bmVyLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5BY2Nlc3NDb250cm9sc0hlbHBlci5sb2FkT2JqZWN0KEFjY2Vzc0NvbnRyb2xzSGVscGVyLmphdmE6MzMxKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuQWNjZXNzQ29udHJvbHNIZWxwZXIuZ2V0QWNsUmVzb3VyY2VGb3JSZXF1ZXN0KEFjY2Vzc0NvbnRyb2xzSGVscGVyLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5MaXN0QWNscy5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoTGlzdEFjbHMuamF2YTo4NSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLkxpc3RBY2xzLmhhbmRsZVJlcXVlc3RSZWNlaXZlZChMaXN0QWNscy5qYXZhOjIwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmZyYW1ld29yay5SZXF1ZXN0SGFuZGxlci5oYW5kbGUoUmVxdWVzdEhhbmRsZXIuamF2YToyOTQpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uQWNjZXNzQ29udHJvbHNEZWxlZ2F0b3IubGlzdChBY2Nlc3NDb250cm9sc0RlbGVnYXRvci5qYXZhOjg5KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5ScGNSZWNlaXZlci5sYW1iZGEkcHJvY2Vzc1JlcXVlc3RBc3luYyQ0KFJwY1JlY2VpdmVyLmphdmE6MjAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5Bc3luY0V4ZWN1dG9yLmxhbWJkYSRzdWJtaXQkMChBc3luY0V4ZWN1dG9yLmphdmE6MjcyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoQ29udGV4dFJ1bm5hYmxlLmphdmE6NTApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlJDEucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM5KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo3Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5FeGVjdXRvcnMkUnVubmFibGVBZGFwdGVyLmNhbGwoRXhlY3V0b3JzLmphdmE6NTExKVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5GdXR1cmVUYXNrLnJ1bihGdXR1cmVUYXNrLmphdmE6MjY2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IucnVuV29ya2VyKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjExNDkpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvciRXb3JrZXIucnVuKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjYyNClcblx0YXQgamF2YS5sYW5nLlRocmVhZC5ydW4oVGhyZWFkLmphdmE6NzQ4KVxuQ2F1c2VkIGJ5OiBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbjogQnVja2V0IGlzIFJlcXVlc3RlciBQYXlzIGJ1Y2tldCBidXQgbm8gYmlsbGluZyBwcm9qZWN0IGlkIHByb3ZpZGVkIGZvciBub24tb3duZXIuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93T25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjI5MClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMSlcblx0Li4uIDE5IG1vcmVcblxuY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUuRmF1bHQ6IEltbXV0YWJsZUVycm9yRGVmaW5pdGlvbntiYXNlPVJFUVVJUkVELCBjYXRlZ29yeT1VU0VSX0VSUk9SLCBjYXVzZT1udWxsLCBkZWJ1Z0luZm89Y29tLmdvb2dsZS5uZXQucnBjMy5ScGNFeGNlcHRpb246IGNsb3VkLmJpZ3N0b3JlLlJlc3BvbnNlQ29kZS5FcnJvckNvZGU6OlVTRVJfUFJPSkVDVF9NSVNTSU5HOiBCdWNrZXQgaXMgUmVxdWVzdGVyIFBheXMgYnVja2V0IGJ1dCBubyBiaWxsaW5nIHByb2plY3QgaWQgcHJvdmlkZWQgZm9yIG5vbi1vd25lci5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udG9ScGMzRXhjZXB0aW9uKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MTM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuQWNjZXNzQ29udHJvbHNIZWxwZXIubG9hZE9iamVjdChBY2Nlc3NDb250cm9sc0hlbHBlci5qYXZhOjMzMSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLkFjY2Vzc0NvbnRyb2xzSGVscGVyLmdldEFjbFJlc291cmNlRm9yUmVxdWVzdChBY2Nlc3NDb250cm9sc0hlbHBlci5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuTGlzdEFjbHMuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKExpc3RBY2xzLmphdmE6ODUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5MaXN0QWNscy5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoTGlzdEFjbHMuamF2YToyMClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLkFjY2Vzc0NvbnRyb2xzRGVsZWdhdG9yLmxpc3QoQWNjZXNzQ29udHJvbHNEZWxlZ2F0b3IuamF2YTo4OSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uUnBjUmVjZWl2ZXIubGFtYmRhJHByb2Nlc3NSZXF1ZXN0QXN5bmMkNChScGNSZWNlaXZlci5qYXZhOjIwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uQXN5bmNFeGVjdXRvci5sYW1iZGEkc3VibWl0JDAoQXN5bmNFeGVjdXRvci5qYXZhOjI3Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KENvbnRleHRSdW5uYWJsZS5qYXZhOjUwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZSQxLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozOSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NzIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozNilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRXhlY3V0b3JzJFJ1bm5hYmxlQWRhcHRlci5jYWxsKEV4ZWN1dG9ycy5qYXZhOjUxMSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRnV0dXJlVGFzay5ydW4oRnV0dXJlVGFzay5qYXZhOjI2Nilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yLnJ1bldvcmtlcihUaHJlYWRQb29sRXhlY3V0b3IuamF2YToxMTQ5KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IkV29ya2VyLnJ1bihUaHJlYWRQb29sRXhlY3V0b3IuamF2YTo2MjQpXG5cdGF0IGphdmEubGFuZy5UaHJlYWQucnVuKFRocmVhZC5qYXZhOjc0OClcbkNhdXNlZCBieTogY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb246IEJ1Y2tldCBpcyBSZXF1ZXN0ZXIgUGF5cyBidWNrZXQgYnV0IG5vIGJpbGxpbmcgcHJvamVjdCBpZCBwcm92aWRlZCBmb3Igbm9uLW93bmVyLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxOSBtb3JlXG4sIGRvbWFpbj1nbG9iYWwsIGV4dGVuZGVkSGVscD1udWxsLCBodHRwSGVhZGVycz17fSwgaHR0cFN0YXR1cz1iYWRSZXF1ZXN0LCBpbnRlcm5hbFJlYXNvbj1SZWFzb257YXJndW1lbnRzPXt9LCBjYXVzZT1udWxsLCBjb2RlPWdkYXRhLkNvcmVFcnJvckRvbWFpbi5SRVFVSVJFRCwgY3JlYXRlZEJ5QmFja2VuZD10cnVlLCBkZWJ1Z01lc3NhZ2U9Y29tLmdvb2dsZS5uZXQucnBjMy5ScGNFeGNlcHRpb246IGNsb3VkLmJpZ3N0b3JlLlJlc3BvbnNlQ29kZS5FcnJvckNvZGU6OlVTRVJfUFJPSkVDVF9NSVNTSU5HOiBCdWNrZXQgaXMgUmVxdWVzdGVyIFBheXMgYnVja2V0IGJ1dCBubyBiaWxsaW5nIHByb2plY3QgaWQgcHJvdmlkZWQgZm9yIG5vbi1vd25lci5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udG9ScGMzRXhjZXB0aW9uKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MTM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuQWNjZXNzQ29udHJvbHNIZWxwZXIubG9hZE9iamVjdChBY2Nlc3NDb250cm9sc0hlbHBlci5qYXZhOjMzMSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLkFjY2Vzc0NvbnRyb2xzSGVscGVyLmdldEFjbFJlc291cmNlRm9yUmVxdWVzdChBY2Nlc3NDb250cm9sc0hlbHBlci5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuTGlzdEFjbHMuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKExpc3RBY2xzLmphdmE6ODUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5MaXN0QWNscy5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoTGlzdEFjbHMuamF2YToyMClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLkFjY2Vzc0NvbnRyb2xzRGVsZWdhdG9yLmxpc3QoQWNjZXNzQ29udHJvbHNEZWxlZ2F0b3IuamF2YTo4OSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uUnBjUmVjZWl2ZXIubGFtYmRhJHByb2Nlc3NSZXF1ZXN0QXN5bmMkNChScGNSZWNlaXZlci5qYXZhOjIwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uQXN5bmNFeGVjdXRvci5sYW1iZGEkc3VibWl0JDAoQXN5bmNFeGVjdXRvci5qYXZhOjI3Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KENvbnRleHRSdW5uYWJsZS5qYXZhOjUwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZSQxLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozOSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NzIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozNilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRXhlY3V0b3JzJFJ1bm5hYmxlQWRhcHRlci5jYWxsKEV4ZWN1dG9ycy5qYXZhOjUxMSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRnV0dXJlVGFzay5ydW4oRnV0dXJlVGFzay5qYXZhOjI2Nilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yLnJ1bldvcmtlcihUaHJlYWRQb29sRXhlY3V0b3IuamF2YToxMTQ5KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IkV29ya2VyLnJ1bihUaHJlYWRQb29sRXhlY3V0b3IuamF2YTo2MjQpXG5cdGF0IGphdmEubGFuZy5UaHJlYWQucnVuKFRocmVhZC5qYXZhOjc0OClcbkNhdXNlZCBieTogY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb246IEJ1Y2tldCBpcyBSZXF1ZXN0ZXIgUGF5cyBidWNrZXQgYnV0IG5vIGJpbGxpbmcgcHJvamVjdCBpZCBwcm92aWRlZCBmb3Igbm9uLW93bmVyLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxOSBtb3JlXG4sIGVycm9yUHJvdG9Db2RlPVJFUVVJUkVELCBlcnJvclByb3RvRG9tYWluPWdkYXRhLkNvcmVFcnJvckRvbWFpbiwgZmlsdGVyZWRNZXNzYWdlPW51bGwsIGxvY2F0aW9uPW51bGwsIG1lc3NhZ2U9QnVja2V0IGlzIHJlcXVlc3RlciBwYXlzIGJ1Y2tldCBidXQgbm8gdXNlciBwcm9qZWN0IHByb3ZpZGVkLiwgdW5uYW1lZEFyZ3VtZW50cz1bXX0sIGxvY2F0aW9uPW51bGwsIG1lc3NhZ2U9QnVja2V0IGlzIHJlcXVlc3RlciBwYXlzIGJ1Y2tldCBidXQgbm8gdXNlciBwcm9qZWN0IHByb3ZpZGVkLiwgcmVhc29uPXJlcXVpcmVkLCBycGNDb2RlPTQwMH0gQnVja2V0IGlzIHJlcXVlc3RlciBwYXlzIGJ1Y2tldCBidXQgbm8gdXNlciBwcm9qZWN0IHByb3ZpZGVkLjogY29tLmdvb2dsZS5uZXQucnBjMy5ScGNFeGNlcHRpb246IGNsb3VkLmJpZ3N0b3JlLlJlc3BvbnNlQ29kZS5FcnJvckNvZGU6OlVTRVJfUFJPSkVDVF9NSVNTSU5HOiBCdWNrZXQgaXMgUmVxdWVzdGVyIFBheXMgYnVja2V0IGJ1dCBubyBiaWxsaW5nIHByb2plY3QgaWQgcHJvdmlkZWQgZm9yIG5vbi1vd25lci5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udG9ScGMzRXhjZXB0aW9uKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MTM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuQWNjZXNzQ29udHJvbHNIZWxwZXIubG9hZE9iamVjdChBY2Nlc3NDb250cm9sc0hlbHBlci5qYXZhOjMzMSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLkFjY2Vzc0NvbnRyb2xzSGVscGVyLmdldEFjbFJlc291cmNlRm9yUmVxdWVzdChBY2Nlc3NDb250cm9sc0hlbHBlci5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuTGlzdEFjbHMuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKExpc3RBY2xzLmphdmE6ODUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5MaXN0QWNscy5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoTGlzdEFjbHMuamF2YToyMClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLkFjY2Vzc0NvbnRyb2xzRGVsZWdhdG9yLmxpc3QoQWNjZXNzQ29udHJvbHNEZWxlZ2F0b3IuamF2YTo4OSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uUnBjUmVjZWl2ZXIubGFtYmRhJHByb2Nlc3NSZXF1ZXN0QXN5bmMkNChScGNSZWNlaXZlci5qYXZhOjIwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uQXN5bmNFeGVjdXRvci5sYW1iZGEkc3VibWl0JDAoQXN5bmNFeGVjdXRvci5qYXZhOjI3Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KENvbnRleHRSdW5uYWJsZS5qYXZhOjUwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZSQxLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozOSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NzIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozNilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRXhlY3V0b3JzJFJ1bm5hYmxlQWRhcHRlci5jYWxsKEV4ZWN1dG9ycy5qYXZhOjUxMSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRnV0dXJlVGFzay5ydW4oRnV0dXJlVGFzay5qYXZhOjI2Nilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yLnJ1bldvcmtlcihUaHJlYWRQb29sRXhlY3V0b3IuamF2YToxMTQ5KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IkV29ya2VyLnJ1bihUaHJlYWRQb29sRXhlY3V0b3IuamF2YTo2MjQpXG5cdGF0IGphdmEubGFuZy5UaHJlYWQucnVuKFRocmVhZC5qYXZhOjc0OClcbkNhdXNlZCBieTogY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb246IEJ1Y2tldCBpcyBSZXF1ZXN0ZXIgUGF5cyBidWNrZXQgYnV0IG5vIGJpbGxpbmcgcHJvamVjdCBpZCBwcm92aWRlZCBmb3Igbm9uLW93bmVyLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxOSBtb3JlXG5cblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUuRXJyb3JDb2xsZWN0b3IudG9GYXVsdChFcnJvckNvbGxlY3Rvci5qYXZhOjU0KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIucmVzdC5hZGFwdGVyLnJvc3kuUm9zeUVycm9yQ29udmVydGVyLnRvRmF1bHQoUm9zeUVycm9yQ29udmVydGVyLmphdmE6NjcpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5yZXN0LmFkYXB0ZXIucm9zeS5Sb3N5SGFuZGxlciQyLmNhbGwoUm9zeUhhbmRsZXIuamF2YToyNTgpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5yZXN0LmFkYXB0ZXIucm9zeS5Sb3N5SGFuZGxlciQyLmNhbGwoUm9zeUhhbmRsZXIuamF2YToyMzgpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLnV0aWwuQ2FsbGFibGVGdXR1cmUucnVuKENhbGxhYmxlRnV0dXJlLmphdmE6NjIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5EaXJlY3RFeGVjdXRvci5leGVjdXRlKERpcmVjdEV4ZWN1dG9yLmphdmE6MzApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5leGVjdXRlTGlzdGVuZXIoQWJzdHJhY3RGdXR1cmUuamF2YToxMTQzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuY29tcGxldGUoQWJzdHJhY3RGdXR1cmUuamF2YTo5NjMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5zZXQoQWJzdHJhY3RGdXR1cmUuamF2YTo3MzEpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLnV0aWwuQ2FsbGFibGVGdXR1cmUucnVuKENhbGxhYmxlRnV0dXJlLmphdmE6NjIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5EaXJlY3RFeGVjdXRvci5leGVjdXRlKERpcmVjdEV4ZWN1dG9yLmphdmE6MzApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5leGVjdXRlTGlzdGVuZXIoQWJzdHJhY3RGdXR1cmUuamF2YToxMTQzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuY29tcGxldGUoQWJzdHJhY3RGdXR1cmUuamF2YTo5NjMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5zZXQoQWJzdHJhY3RGdXR1cmUuamF2YTo3MzEpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLnV0aWwuQ2FsbGFibGVGdXR1cmUucnVuKENhbGxhYmxlRnV0dXJlLmphdmE6NjIpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci50aHJlYWQuVGhyZWFkVHJhY2tlcnMkVGhyZWFkVHJhY2tpbmdSdW5uYWJsZS5ydW4oVGhyZWFkVHJhY2tlcnMuamF2YToxMjYpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkVHJhY2VDb250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KFRyYWNlQ29udGV4dC5qYXZhOjQ1NSlcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnNlcnZlci5Db21tb25Nb2R1bGUkQ29udGV4dENhcnJ5aW5nRXhlY3V0b3JTZXJ2aWNlJDEucnVuSW5Db250ZXh0KENvbW1vbk1vZHVsZS5qYXZhOjg0Nilcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRUcmFjZUNvbnRleHRSdW5uYWJsZSQxLnJ1bihUcmFjZUNvbnRleHQuamF2YTo0NjIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkQWJzdHJhY3RUcmFjZUNvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKFRyYWNlQ29udGV4dC5qYXZhOjMyMSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRBYnN0cmFjdFRyYWNlQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChUcmFjZUNvbnRleHQuamF2YTozMTMpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkVHJhY2VDb250ZXh0UnVubmFibGUucnVuKFRyYWNlQ29udGV4dC5qYXZhOjQ1OSlcblx0YXQgY29tLmdvb2dsZS5nc2UuaW50ZXJuYWwuRGlzcGF0Y2hRdWV1ZUltcGwkV29ya2VyVGhyZWFkLnJ1bihEaXNwYXRjaFF1ZXVlSW1wbC5qYXZhOjQwMylcbiJ9XSwiY29kZSI6NDAwLCJtZXNzYWdlIjoiQnVja2V0IGlzIHJlcXVlc3RlciBwYXlzIGJ1Y2tldCBidXQgbm8gdXNlciBwcm9qZWN0IHByb3ZpZGVkLiJ9fQ=="
+ }
+ },
+ {
+ "ID": "693609fc63a880a4",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/foo/acl?alt=json\u0026prettyPrint=false\u0026userProject=gcloud-golang-firestore-tests",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "8b22dec014f63a2e09a65e7c874c6748/3251723795511181085;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/foo/acl?alt=json\u0026prettyPrint=false\u0026userProject=gcloud-golang-firestore-tests"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0, must-revalidate, no-transform"
+ ],
+ "Content-Length": [
+ "2788"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:10 GMT"
+ ],
+ "Etag": [
+ "CISC0OiW290CEAU="
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:25:10 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051402000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "471383502717"
+ ],
+ "X-Google-Backends": [
+ "vndz193:4319,/bns/yx/borg/yx/bns/blobstore2/bitpusher/140.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=JsysW_aKD4aPzgLKg4SoDw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yx/borg/yx/bns/blobstore2/bitpusher/140.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yx/borg/yx/bns/blobstore2/bitpusher/140:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CP3elYXcDRoCGAYoATo_ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGM6ropHgHCIVMTE3MjM4MDU4ODYxOTM3NTE5MTQ0MOArSp8BEoIBeWEyOS5jLkVsb2xCcldWbUZlX1AxVDdUOHVpTXdFMHBZUjdTc2NVMDBFdEZkc2tSenBQY0NLWkhUeEZaYXI0Q25tZmR6bXFRLTNVV0kzOF9wdEx5VTZ2Z1Q3dlRBeW42Z3g4dUcyd0szSHIzaTZrV1JBZkozc1pNMGQ1allkNHpWQTAEOhZOT1RfQV9QRVJTSVNURU5UX1RPS0VO"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UrCrxz4Y9yMZaxH9kPNeKc4g8xHIDxwP8VRABr_owQG37mhGZmX6zaxL6F7NumpXRxx1PcDxTqpZOs883WeJaV6OOphiQ"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9scyIsIml0ZW1zIjpbeyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMvZm9vLzE1MzgwNTEwOTM1NjE2MDQvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMvby9mb28vYWNsL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzIiwib2JqZWN0IjoiZm9vIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwOTM1NjE2MDQiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNJU0MwT2lXMjkwQ0VBVT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9mb28vMTUzODA1MTA5MzU2MTYwNC9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMvby9mb28vYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMyIsIm9iamVjdCI6ImZvbyIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDkzNTYxNjA0IiwiZW50aXR5IjoicHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6ImVkaXRvcnMifSwiZXRhZyI6IkNJU0MwT2lXMjkwQ0VBVT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9mb28vMTUzODA1MTA5MzU2MTYwNC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMvby9mb28vYWNsL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMyIsIm9iamVjdCI6ImZvbyIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDkzNTYxNjA0IiwiZW50aXR5IjoicHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6IlJFQURFUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJ2aWV3ZXJzIn0sImV0YWciOiJDSVNDME9pVzI5MENFQVU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMvZm9vLzE1MzgwNTEwOTM1NjE2MDQvdXNlci1pbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9vL2Zvby9hY2wvdXNlci1pbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMyIsIm9iamVjdCI6ImZvbyIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDkzNTYxNjA0IiwiZW50aXR5IjoidXNlci1pbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSIsInJvbGUiOiJPV05FUiIsImVtYWlsIjoiaW50ZWdyYXRpb25AZ2Nsb3VkLWdvbGFuZy1maXJlc3RvcmUtdGVzdHMuaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJldGFnIjoiQ0lTQzBPaVcyOTBDRUFVPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL2Zvby8xNTM4MDUxMDkzNTYxNjA0L2RvbWFpbi1nb29nbGUuY29tIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL28vZm9vL2FjbC9kb21haW4tZ29vZ2xlLmNvbSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMyIsIm9iamVjdCI6ImZvbyIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDkzNTYxNjA0IiwiZW50aXR5IjoiZG9tYWluLWdvb2dsZS5jb20iLCJyb2xlIjoiUkVBREVSIiwiZG9tYWluIjoiZ29vZ2xlLmNvbSIsImV0YWciOiJDSVNDME9pVzI5MENFQVU9In1dfQ=="
+ }
+ },
+ {
+ "ID": "49029dea88229164",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/foo/acl?alt=json\u0026prettyPrint=false\u0026userProject=veener-jba",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "3c62f541a3ae01cd6be129967cac3585/4842135699578332348;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/foo/acl?alt=json\u0026prettyPrint=false\u0026userProject=veener-jba"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 403,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0"
+ ],
+ "Content-Length": [
+ "13943"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:10 GMT"
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:25:10 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051395000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "471383502717"
+ ],
+ "X-Google-Backends": [
+ "vrlj28:4249,/bns/yr/borg/yr/bns/blobstore2/bitpusher/9.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=JsysW4HPE7Lm4QS0iZ9I"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/9.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/9:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CP3elYXcDRoCGAYoATo_ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGM6ropHgHCIVMTE3MjM4MDU4ODYxOTM3NTE5MTQ0MOArSp8BEoIBeWEyOS5jLkVsb2xCcldWbUZlX1AxVDdUOHVpTXdFMHBZUjdTc2NVMDBFdEZkc2tSenBQY0NLWkhUeEZaYXI0Q25tZmR6bXFRLTNVV0kzOF9wdEx5VTZ2Z1Q3dlRBeW42Z3g4dUcyd0szSHIzaTZrV1JBZkozc1pNMGQ1allkNHpWQTAEOhZOT1RfQV9QRVJTSVNURU5UX1RPS0VO"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Upload-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UpZ4wlQKc6jj-9k6xSk9TQKMTHvk4TESMFYPNCoKiuH4Al89gLex9FpSev5P7meDHYF63-FRR9ZZMcy1rSFyfh9JtVEEw"
+ ]
+ },
+ "Body": "eyJlcnJvciI6eyJlcnJvcnMiOlt7ImRvbWFpbiI6Imdsb2JhbCIsInJlYXNvbiI6ImZvcmJpZGRlbiIsIm1lc3NhZ2UiOiJpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLiIsImRlYnVnSW5mbyI6ImNvbS5nb29nbGUubmV0LnJwYzMuUnBjRXhjZXB0aW9uOiBjbG91ZC5iaWdzdG9yZS5SZXNwb25zZUNvZGUuRXJyb3JDb2RlOjpVU0VSX1BST0pFQ1RfQUNDRVNTX0RFTklFRDogaW50ZWdyYXRpb25AZ2Nsb3VkLWdvbGFuZy1maXJlc3RvcmUtdGVzdHMuaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20gZG9lcyBub3QgaGF2ZSBzZXJ2aWNldXNhZ2Uuc2VydmljZXMudXNlIGFjY2VzcyB0byBwcm9qZWN0IDY0MjA4MDkxODEwMS5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udG9ScGMzRXhjZXB0aW9uKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MTM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuQWNjZXNzQ29udHJvbHNIZWxwZXIubG9hZE9iamVjdChBY2Nlc3NDb250cm9sc0hlbHBlci5qYXZhOjMzMSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLkFjY2Vzc0NvbnRyb2xzSGVscGVyLmdldEFjbFJlc291cmNlRm9yUmVxdWVzdChBY2Nlc3NDb250cm9sc0hlbHBlci5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuTGlzdEFjbHMuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKExpc3RBY2xzLmphdmE6ODUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5MaXN0QWNscy5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoTGlzdEFjbHMuamF2YToyMClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLkFjY2Vzc0NvbnRyb2xzRGVsZWdhdG9yLmxpc3QoQWNjZXNzQ29udHJvbHNEZWxlZ2F0b3IuamF2YTo4OSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uUnBjUmVjZWl2ZXIubGFtYmRhJHByb2Nlc3NSZXF1ZXN0QXN5bmMkNChScGNSZWNlaXZlci5qYXZhOjIwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uQXN5bmNFeGVjdXRvci5sYW1iZGEkc3VibWl0JDAoQXN5bmNFeGVjdXRvci5qYXZhOjI3Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KENvbnRleHRSdW5uYWJsZS5qYXZhOjUwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZSQxLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozOSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NzIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozNilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRXhlY3V0b3JzJFJ1bm5hYmxlQWRhcHRlci5jYWxsKEV4ZWN1dG9ycy5qYXZhOjUxMSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRnV0dXJlVGFzay5ydW4oRnV0dXJlVGFzay5qYXZhOjI2Nilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yLnJ1bldvcmtlcihUaHJlYWRQb29sRXhlY3V0b3IuamF2YToxMTQ5KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IkV29ya2VyLnJ1bihUaHJlYWRQb29sRXhlY3V0b3IuamF2YTo2MjQpXG5cdGF0IGphdmEubGFuZy5UaHJlYWQucnVuKFRocmVhZC5qYXZhOjc0OClcbkNhdXNlZCBieTogY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb246IGludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIGRvZXMgbm90IGhhdmUgc2VydmljZXVzYWdlLnNlcnZpY2VzLnVzZSBhY2Nlc3MgdG8gcHJvamVjdCA2NDIwODA5MTgxMDEuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93T25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjI5MClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMSlcblx0Li4uIDE5IG1vcmVcblxuY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUuRmF1bHQ6IEltbXV0YWJsZUVycm9yRGVmaW5pdGlvbntiYXNlPUZPUkJJRERFTiwgY2F0ZWdvcnk9VVNFUl9FUlJPUiwgY2F1c2U9bnVsbCwgZGVidWdJbmZvPWNvbS5nb29nbGUubmV0LnJwYzMuUnBjRXhjZXB0aW9uOiBjbG91ZC5iaWdzdG9yZS5SZXNwb25zZUNvZGUuRXJyb3JDb2RlOjpVU0VSX1BST0pFQ1RfQUNDRVNTX0RFTklFRDogaW50ZWdyYXRpb25AZ2Nsb3VkLWdvbGFuZy1maXJlc3RvcmUtdGVzdHMuaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20gZG9lcyBub3QgaGF2ZSBzZXJ2aWNldXNhZ2Uuc2VydmljZXMudXNlIGFjY2VzcyB0byBwcm9qZWN0IDY0MjA4MDkxODEwMS5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udG9ScGMzRXhjZXB0aW9uKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MTM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuQWNjZXNzQ29udHJvbHNIZWxwZXIubG9hZE9iamVjdChBY2Nlc3NDb250cm9sc0hlbHBlci5qYXZhOjMzMSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLkFjY2Vzc0NvbnRyb2xzSGVscGVyLmdldEFjbFJlc291cmNlRm9yUmVxdWVzdChBY2Nlc3NDb250cm9sc0hlbHBlci5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuTGlzdEFjbHMuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKExpc3RBY2xzLmphdmE6ODUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5MaXN0QWNscy5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoTGlzdEFjbHMuamF2YToyMClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLkFjY2Vzc0NvbnRyb2xzRGVsZWdhdG9yLmxpc3QoQWNjZXNzQ29udHJvbHNEZWxlZ2F0b3IuamF2YTo4OSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uUnBjUmVjZWl2ZXIubGFtYmRhJHByb2Nlc3NSZXF1ZXN0QXN5bmMkNChScGNSZWNlaXZlci5qYXZhOjIwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uQXN5bmNFeGVjdXRvci5sYW1iZGEkc3VibWl0JDAoQXN5bmNFeGVjdXRvci5qYXZhOjI3Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KENvbnRleHRSdW5uYWJsZS5qYXZhOjUwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZSQxLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozOSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NzIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozNilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRXhlY3V0b3JzJFJ1bm5hYmxlQWRhcHRlci5jYWxsKEV4ZWN1dG9ycy5qYXZhOjUxMSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRnV0dXJlVGFzay5ydW4oRnV0dXJlVGFzay5qYXZhOjI2Nilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yLnJ1bldvcmtlcihUaHJlYWRQb29sRXhlY3V0b3IuamF2YToxMTQ5KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IkV29ya2VyLnJ1bihUaHJlYWRQb29sRXhlY3V0b3IuamF2YTo2MjQpXG5cdGF0IGphdmEubGFuZy5UaHJlYWQucnVuKFRocmVhZC5qYXZhOjc0OClcbkNhdXNlZCBieTogY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb246IGludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIGRvZXMgbm90IGhhdmUgc2VydmljZXVzYWdlLnNlcnZpY2VzLnVzZSBhY2Nlc3MgdG8gcHJvamVjdCA2NDIwODA5MTgxMDEuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93T25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjI5MClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMSlcblx0Li4uIDE5IG1vcmVcbiwgZG9tYWluPWdsb2JhbCwgZXh0ZW5kZWRIZWxwPW51bGwsIGh0dHBIZWFkZXJzPXt9LCBodHRwU3RhdHVzPWZvcmJpZGRlbiwgaW50ZXJuYWxSZWFzb249UmVhc29ue2FyZ3VtZW50cz17fSwgY2F1c2U9bnVsbCwgY29kZT1nZGF0YS5Db3JlRXJyb3JEb21haW4uRk9SQklEREVOLCBjcmVhdGVkQnlCYWNrZW5kPXRydWUsIGRlYnVnTWVzc2FnZT1jb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6VVNFUl9QUk9KRUNUX0FDQ0VTU19ERU5JRUQ6IGludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIGRvZXMgbm90IGhhdmUgc2VydmljZXVzYWdlLnNlcnZpY2VzLnVzZSBhY2Nlc3MgdG8gcHJvamVjdCA2NDIwODA5MTgxMDEuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRvUnBjM0V4Y2VwdGlvbihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjEzNSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLkFjY2Vzc0NvbnRyb2xzSGVscGVyLmxvYWRPYmplY3QoQWNjZXNzQ29udHJvbHNIZWxwZXIuamF2YTozMzEpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5BY2Nlc3NDb250cm9sc0hlbHBlci5nZXRBY2xSZXNvdXJjZUZvclJlcXVlc3QoQWNjZXNzQ29udHJvbHNIZWxwZXIuamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLkxpc3RBY2xzLmhhbmRsZVJlcXVlc3RSZWNlaXZlZChMaXN0QWNscy5qYXZhOjg1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuTGlzdEFjbHMuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKExpc3RBY2xzLmphdmE6MjApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5BY2Nlc3NDb250cm9sc0RlbGVnYXRvci5saXN0KEFjY2Vzc0NvbnRyb2xzRGVsZWdhdG9yLmphdmE6ODkpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxOSBtb3JlXG4sIGVycm9yUHJvdG9Db2RlPUZPUkJJRERFTiwgZXJyb3JQcm90b0RvbWFpbj1nZGF0YS5Db3JlRXJyb3JEb21haW4sIGZpbHRlcmVkTWVzc2FnZT1udWxsLCBsb2NhdGlvbj1udWxsLCBtZXNzYWdlPWludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIGRvZXMgbm90IGhhdmUgc2VydmljZXVzYWdlLnNlcnZpY2VzLnVzZSBhY2Nlc3MgdG8gcHJvamVjdCA2NDIwODA5MTgxMDEuLCB1bm5hbWVkQXJndW1lbnRzPVtdfSwgbG9jYXRpb249bnVsbCwgbWVzc2FnZT1pbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLiwgcmVhc29uPWZvcmJpZGRlbiwgcnBjQ29kZT00MDN9IGludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIGRvZXMgbm90IGhhdmUgc2VydmljZXVzYWdlLnNlcnZpY2VzLnVzZSBhY2Nlc3MgdG8gcHJvamVjdCA2NDIwODA5MTgxMDEuOiBjb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6VVNFUl9QUk9KRUNUX0FDQ0VTU19ERU5JRUQ6IGludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIGRvZXMgbm90IGhhdmUgc2VydmljZXVzYWdlLnNlcnZpY2VzLnVzZSBhY2Nlc3MgdG8gcHJvamVjdCA2NDIwODA5MTgxMDEuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRvUnBjM0V4Y2VwdGlvbihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjEzNSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLkFjY2Vzc0NvbnRyb2xzSGVscGVyLmxvYWRPYmplY3QoQWNjZXNzQ29udHJvbHNIZWxwZXIuamF2YTozMzEpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5BY2Nlc3NDb250cm9sc0hlbHBlci5nZXRBY2xSZXNvdXJjZUZvclJlcXVlc3QoQWNjZXNzQ29udHJvbHNIZWxwZXIuamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLkxpc3RBY2xzLmhhbmRsZVJlcXVlc3RSZWNlaXZlZChMaXN0QWNscy5qYXZhOjg1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuTGlzdEFjbHMuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKExpc3RBY2xzLmphdmE6MjApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5BY2Nlc3NDb250cm9sc0RlbGVnYXRvci5saXN0KEFjY2Vzc0NvbnRyb2xzRGVsZWdhdG9yLmphdmE6ODkpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxOSBtb3JlXG5cblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUuRXJyb3JDb2xsZWN0b3IudG9GYXVsdChFcnJvckNvbGxlY3Rvci5qYXZhOjU0KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIucmVzdC5hZGFwdGVyLnJvc3kuUm9zeUVycm9yQ29udmVydGVyLnRvRmF1bHQoUm9zeUVycm9yQ29udmVydGVyLmphdmE6NjcpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5yZXN0LmFkYXB0ZXIucm9zeS5Sb3N5SGFuZGxlciQyLmNhbGwoUm9zeUhhbmRsZXIuamF2YToyNTgpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5yZXN0LmFkYXB0ZXIucm9zeS5Sb3N5SGFuZGxlciQyLmNhbGwoUm9zeUhhbmRsZXIuamF2YToyMzgpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLnV0aWwuQ2FsbGFibGVGdXR1cmUucnVuKENhbGxhYmxlRnV0dXJlLmphdmE6NjIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5EaXJlY3RFeGVjdXRvci5leGVjdXRlKERpcmVjdEV4ZWN1dG9yLmphdmE6MzApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5leGVjdXRlTGlzdGVuZXIoQWJzdHJhY3RGdXR1cmUuamF2YToxMTQzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuY29tcGxldGUoQWJzdHJhY3RGdXR1cmUuamF2YTo5NjMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5zZXQoQWJzdHJhY3RGdXR1cmUuamF2YTo3MzEpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLnV0aWwuQ2FsbGFibGVGdXR1cmUucnVuKENhbGxhYmxlRnV0dXJlLmphdmE6NjIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5EaXJlY3RFeGVjdXRvci5leGVjdXRlKERpcmVjdEV4ZWN1dG9yLmphdmE6MzApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5leGVjdXRlTGlzdGVuZXIoQWJzdHJhY3RGdXR1cmUuamF2YToxMTQzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuY29tcGxldGUoQWJzdHJhY3RGdXR1cmUuamF2YTo5NjMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5zZXQoQWJzdHJhY3RGdXR1cmUuamF2YTo3MzEpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLnV0aWwuQ2FsbGFibGVGdXR1cmUucnVuKENhbGxhYmxlRnV0dXJlLmphdmE6NjIpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci50aHJlYWQuVGhyZWFkVHJhY2tlcnMkVGhyZWFkVHJhY2tpbmdSdW5uYWJsZS5ydW4oVGhyZWFkVHJhY2tlcnMuamF2YToxMjYpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkVHJhY2VDb250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KFRyYWNlQ29udGV4dC5qYXZhOjQ1NSlcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnNlcnZlci5Db21tb25Nb2R1bGUkQ29udGV4dENhcnJ5aW5nRXhlY3V0b3JTZXJ2aWNlJDEucnVuSW5Db250ZXh0KENvbW1vbk1vZHVsZS5qYXZhOjg0Nilcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRUcmFjZUNvbnRleHRSdW5uYWJsZSQxLnJ1bihUcmFjZUNvbnRleHQuamF2YTo0NjIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkQWJzdHJhY3RUcmFjZUNvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKFRyYWNlQ29udGV4dC5qYXZhOjMyMSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRBYnN0cmFjdFRyYWNlQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChUcmFjZUNvbnRleHQuamF2YTozMTMpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkVHJhY2VDb250ZXh0UnVubmFibGUucnVuKFRyYWNlQ29udGV4dC5qYXZhOjQ1OSlcblx0YXQgY29tLmdvb2dsZS5nc2UuaW50ZXJuYWwuRGlzcGF0Y2hRdWV1ZUltcGwkV29ya2VyVGhyZWFkLnJ1bihEaXNwYXRjaFF1ZXVlSW1wbC5qYXZhOjQwMylcbiJ9XSwiY29kZSI6NDAzLCJtZXNzYWdlIjoiaW50ZWdyYXRpb25AZ2Nsb3VkLWdvbGFuZy1maXJlc3RvcmUtdGVzdHMuaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20gZG9lcyBub3QgaGF2ZSBzZXJ2aWNldXNhZ2Uuc2VydmljZXMudXNlIGFjY2VzcyB0byBwcm9qZWN0IDY0MjA4MDkxODEwMS4ifX0="
+ }
+ },
+ {
+ "ID": "0bbffc509aa58e86",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/foo/acl/domain-google.com?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "9d5b4009a62181db92bb7fa0d649ded2/6432547603628706395;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/foo/acl/domain-google.com?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 204,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "0"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:10 GMT"
+ ],
+ "Etag": [
+ "CISC0OiW290CEAY="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051395000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrmt5:4328,/bns/yr/borg/yr/bns/blobstore2/bitpusher/18.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=JsysW8_mH86x4QTpi5mYDw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/18.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/18:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATpxChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4CtK4wESxgF5YTI5LmMuRW93QkpRWVNNdC1OVDFNYTJvWXBrbG1qcDlJMlZaUFZ5bFl5Z2Q3Nk5tQXlXbWR3WVBoMm00dGI3ZmZjOUlzcTU4MmVFcFBhNzhNWGpNZmIzaE9WTE9xRHpNTUFfTG9NQXVJZkdkMGgzSWowZ1dxdW5DS1g3Qk1mQlJxM001TUtMMXBHOWNyU0ZBT29lVkZpTDhpWlBsUDI0VjE5THdzZ0d1ZnVrQTFtVzVJcTJUUkVXeWQyNjRKZC1lS2UxdTAwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UrkIesSXHaDQvjErkm-acBua1UtOmcpvV-fYBGu2-zEFeRu3-06b0Edan4rTIQdT4ALc5dtMnMvRz-wsO5y-DT2jHEHjQ"
+ ]
+ },
+ "Body": ""
+ }
+ },
+ {
+ "ID": "288d5c2ae22a0cf0",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/foo/acl/domain-google.com?alt=json\u0026prettyPrint=false\u0026userProject=dulcet-port-762",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "942e217b3d85e1854cbd33d54d01cda3/8022676933224427513;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/foo/acl/domain-google.com?alt=json\u0026prettyPrint=false\u0026userProject=dulcet-port-762"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 404,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0"
+ ],
+ "Content-Length": [
+ "2911"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:10 GMT"
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:25:10 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051395000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrjy17:4329,/bns/yw/borg/yw/bns/blobstore2/bitpusher/67.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=JsysW9mwM9jdhATbvJjQBA"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yw/borg/yw/bns/blobstore2/bitpusher/67.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yw/borg/yw/bns/blobstore2/bitpusher/67:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATpxChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4CtK4wESxgF5YTI5LmMuRW93QkpRWVNNdC1OVDFNYTJvWXBrbG1qcDlJMlZaUFZ5bFl5Z2Q3Nk5tQXlXbWR3WVBoMm00dGI3ZmZjOUlzcTU4MmVFcFBhNzhNWGpNZmIzaE9WTE9xRHpNTUFfTG9NQXVJZkdkMGgzSWowZ1dxdW5DS1g3Qk1mQlJxM001TUtMMXBHOWNyU0ZBT29lVkZpTDhpWlBsUDI0VjE5THdzZ0d1ZnVrQTFtVzVJcTJUUkVXeWQyNjRKZC1lS2UxdTAwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Upload-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UpwCfg1tfuHO6z9s2bgjLvSiNnbc_vMT2qmOOj1c4I0DhiJ46RI6sySBd8gte-AwJBFOhANbtvKXuz1Bq6S18z47aPrFA"
+ ]
+ },
+ "Body": "eyJlcnJvciI6eyJlcnJvcnMiOlt7ImRvbWFpbiI6Imdsb2JhbCIsInJlYXNvbiI6Im5vdEZvdW5kIiwibWVzc2FnZSI6Ik5vdCBGb3VuZCIsImRlYnVnSW5mbyI6ImNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLkZhdWx0OiBJbW11dGFibGVFcnJvckRlZmluaXRpb257YmFzZT1OT1RfRk9VTkQsIGNhdGVnb3J5PVVTRVJfRVJST1IsIGNhdXNlPW51bGwsIGRlYnVnSW5mbz1udWxsLCBkb21haW49Z2xvYmFsLCBleHRlbmRlZEhlbHA9bnVsbCwgaHR0cEhlYWRlcnM9e30sIGh0dHBTdGF0dXM9bm90Rm91bmQsIGludGVybmFsUmVhc29uPVJlYXNvbnthcmd1bWVudHM9e30sIGNhdXNlPW51bGwsIGNvZGU9Z2RhdGEuQ29yZUVycm9yRG9tYWluLk5PVF9GT1VORCwgY3JlYXRlZEJ5QmFja2VuZD10cnVlLCBkZWJ1Z01lc3NhZ2U9bnVsbCwgZXJyb3JQcm90b0NvZGU9Tk9UX0ZPVU5ELCBlcnJvclByb3RvRG9tYWluPWdkYXRhLkNvcmVFcnJvckRvbWFpbiwgZmlsdGVyZWRNZXNzYWdlPW51bGwsIGxvY2F0aW9uPWVudGl0eS5yZXNvdXJjZV9pZC5zY29wZSwgbWVzc2FnZT1udWxsLCB1bm5hbWVkQXJndW1lbnRzPVtdfSwgbG9jYXRpb249ZW50aXR5LnJlc291cmNlX2lkLnNjb3BlLCBtZXNzYWdlPU5vdCBGb3VuZCwgcmVhc29uPW5vdEZvdW5kLCBycGNDb2RlPTQwNH0gTm90IEZvdW5kXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLkVycm9yQ29sbGVjdG9yLnRvRmF1bHQoRXJyb3JDb2xsZWN0b3IuamF2YTo1NClcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnJlc3QuYWRhcHRlci5yb3N5LlJvc3lFcnJvckNvbnZlcnRlci50b0ZhdWx0KFJvc3lFcnJvckNvbnZlcnRlci5qYXZhOjY3KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIucmVzdC5hZGFwdGVyLnJvc3kuUm9zeUhhbmRsZXIkMi5jYWxsKFJvc3lIYW5kbGVyLmphdmE6MjU4KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIucmVzdC5hZGFwdGVyLnJvc3kuUm9zeUhhbmRsZXIkMi5jYWxsKFJvc3lIYW5kbGVyLmphdmE6MjM4KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS51dGlsLkNhbGxhYmxlRnV0dXJlLnJ1bihDYWxsYWJsZUZ1dHVyZS5qYXZhOjYyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuRGlyZWN0RXhlY3V0b3IuZXhlY3V0ZShEaXJlY3RFeGVjdXRvci5qYXZhOjMwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuZXhlY3V0ZUxpc3RlbmVyKEFic3RyYWN0RnV0dXJlLmphdmE6MTE0Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmNvbXBsZXRlKEFic3RyYWN0RnV0dXJlLmphdmE6OTYzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuc2V0KEFic3RyYWN0RnV0dXJlLmphdmE6NzMxKVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS51dGlsLkNhbGxhYmxlRnV0dXJlLnJ1bihDYWxsYWJsZUZ1dHVyZS5qYXZhOjYyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuRGlyZWN0RXhlY3V0b3IuZXhlY3V0ZShEaXJlY3RFeGVjdXRvci5qYXZhOjMwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuZXhlY3V0ZUxpc3RlbmVyKEFic3RyYWN0RnV0dXJlLmphdmE6MTE0Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmNvbXBsZXRlKEFic3RyYWN0RnV0dXJlLmphdmE6OTYzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuc2V0KEFic3RyYWN0RnV0dXJlLmphdmE6NzMxKVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS51dGlsLkNhbGxhYmxlRnV0dXJlLnJ1bihDYWxsYWJsZUZ1dHVyZS5qYXZhOjYyKVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIudGhyZWFkLlRocmVhZFRyYWNrZXJzJFRocmVhZFRyYWNraW5nUnVubmFibGUucnVuKFRocmVhZFRyYWNrZXJzLmphdmE6MTI2KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JFRyYWNlQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChUcmFjZUNvbnRleHQuamF2YTo0NTUpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5zZXJ2ZXIuQ29tbW9uTW9kdWxlJENvbnRleHRDYXJyeWluZ0V4ZWN1dG9yU2VydmljZSQxLnJ1bkluQ29udGV4dChDb21tb25Nb2R1bGUuamF2YTo4NDYpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkVHJhY2VDb250ZXh0UnVubmFibGUkMS5ydW4oVHJhY2VDb250ZXh0LmphdmE6NDYyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JEFic3RyYWN0VHJhY2VDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihUcmFjZUNvbnRleHQuamF2YTozMjEpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkQWJzdHJhY3RUcmFjZUNvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoVHJhY2VDb250ZXh0LmphdmE6MzEzKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JFRyYWNlQ29udGV4dFJ1bm5hYmxlLnJ1bihUcmFjZUNvbnRleHQuamF2YTo0NTkpXG5cdGF0IGNvbS5nb29nbGUuZ3NlLmludGVybmFsLkRpc3BhdGNoUXVldWVJbXBsJFdvcmtlclRocmVhZC5ydW4oRGlzcGF0Y2hRdWV1ZUltcGwuamF2YTo0MDMpXG4ifV0sImNvZGUiOjQwNCwibWVzc2FnZSI6Ik5vdCBGb3VuZCJ9fQ=="
+ }
+ },
+ {
+ "ID": "096f174db397deb0",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/foo/acl/domain-google.com?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "1a6d483de945e889227f26e82c9b2130/9613088837274801560;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/foo/acl/domain-google.com?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 400,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0"
+ ],
+ "Content-Length": [
+ "13131"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:11 GMT"
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:25:11 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051395000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "471383502717"
+ ],
+ "X-Google-Backends": [
+ "vrjo80:4463,/bns/yv/borg/yv/bns/blobstore2/bitpusher/165.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=JsysW6auOo2MNtHGrBA"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/165.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/165:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CP3elYXcDRoCGAYoATo_ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGM6ropHgHCIVMTE3MjM4MDU4ODYxOTM3NTE5MTQ0MOArSp8BEoIBeWEyOS5jLkVsb2xCcldWbUZlX1AxVDdUOHVpTXdFMHBZUjdTc2NVMDBFdEZkc2tSenBQY0NLWkhUeEZaYXI0Q25tZmR6bXFRLTNVV0kzOF9wdEx5VTZ2Z1Q3dlRBeW42Z3g4dUcyd0szSHIzaTZrV1JBZkozc1pNMGQ1allkNHpWQTAEOhZOT1RfQV9QRVJTSVNURU5UX1RPS0VO"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Upload-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UqoWzqmrIL9nx-7PA1ttiQoj5BezEBJr40Xc0d0FypqBUUG9UeaFFFGk4g_mlpFryQTNJZBHRgLlrVJuvQzW9cb-AMBxA"
+ ]
+ },
+ "Body": "eyJlcnJvciI6eyJlcnJvcnMiOlt7ImRvbWFpbiI6Imdsb2JhbCIsInJlYXNvbiI6InJlcXVpcmVkIiwibWVzc2FnZSI6IkJ1Y2tldCBpcyByZXF1ZXN0ZXIgcGF5cyBidWNrZXQgYnV0IG5vIHVzZXIgcHJvamVjdCBwcm92aWRlZC4iLCJkZWJ1Z0luZm8iOiJjb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6VVNFUl9QUk9KRUNUX01JU1NJTkc6IEJ1Y2tldCBpcyBSZXF1ZXN0ZXIgUGF5cyBidWNrZXQgYnV0IG5vIGJpbGxpbmcgcHJvamVjdCBpZCBwcm92aWRlZCBmb3Igbm9uLW93bmVyLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5BY2Nlc3NDb250cm9sc0hlbHBlci5sb2FkT2JqZWN0KEFjY2Vzc0NvbnRyb2xzSGVscGVyLmphdmE6MzMxKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuQWNjZXNzQ29udHJvbHNIZWxwZXIuZ2V0QWNsUmVzb3VyY2VGb3JSZXF1ZXN0KEFjY2Vzc0NvbnRyb2xzSGVscGVyLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5EZWxldGVBY2xzLmhhbmRsZVJlcXVlc3RSZWNlaXZlZChEZWxldGVBY2xzLmphdmE6NzEpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5EZWxldGVBY2xzLmhhbmRsZVJlcXVlc3RSZWNlaXZlZChEZWxldGVBY2xzLmphdmE6MjApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5BY2Nlc3NDb250cm9sc0RlbGVnYXRvci5kZWxldGUoQWNjZXNzQ29udHJvbHNEZWxlZ2F0b3IuamF2YToxMDkpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBCdWNrZXQgaXMgUmVxdWVzdGVyIFBheXMgYnVja2V0IGJ1dCBubyBiaWxsaW5nIHByb2plY3QgaWQgcHJvdmlkZWQgZm9yIG5vbi1vd25lci5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MjkwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAxKVxuXHQuLi4gMTkgbW9yZVxuXG5jb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS5GYXVsdDogSW1tdXRhYmxlRXJyb3JEZWZpbml0aW9ue2Jhc2U9UkVRVUlSRUQsIGNhdGVnb3J5PVVTRVJfRVJST1IsIGNhdXNlPW51bGwsIGRlYnVnSW5mbz1jb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6VVNFUl9QUk9KRUNUX01JU1NJTkc6IEJ1Y2tldCBpcyBSZXF1ZXN0ZXIgUGF5cyBidWNrZXQgYnV0IG5vIGJpbGxpbmcgcHJvamVjdCBpZCBwcm92aWRlZCBmb3Igbm9uLW93bmVyLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5BY2Nlc3NDb250cm9sc0hlbHBlci5sb2FkT2JqZWN0KEFjY2Vzc0NvbnRyb2xzSGVscGVyLmphdmE6MzMxKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuQWNjZXNzQ29udHJvbHNIZWxwZXIuZ2V0QWNsUmVzb3VyY2VGb3JSZXF1ZXN0KEFjY2Vzc0NvbnRyb2xzSGVscGVyLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5EZWxldGVBY2xzLmhhbmRsZVJlcXVlc3RSZWNlaXZlZChEZWxldGVBY2xzLmphdmE6NzEpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5EZWxldGVBY2xzLmhhbmRsZVJlcXVlc3RSZWNlaXZlZChEZWxldGVBY2xzLmphdmE6MjApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5BY2Nlc3NDb250cm9sc0RlbGVnYXRvci5kZWxldGUoQWNjZXNzQ29udHJvbHNEZWxlZ2F0b3IuamF2YToxMDkpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBCdWNrZXQgaXMgUmVxdWVzdGVyIFBheXMgYnVja2V0IGJ1dCBubyBiaWxsaW5nIHByb2plY3QgaWQgcHJvdmlkZWQgZm9yIG5vbi1vd25lci5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MjkwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAxKVxuXHQuLi4gMTkgbW9yZVxuLCBkb21haW49Z2xvYmFsLCBleHRlbmRlZEhlbHA9bnVsbCwgaHR0cEhlYWRlcnM9e30sIGh0dHBTdGF0dXM9YmFkUmVxdWVzdCwgaW50ZXJuYWxSZWFzb249UmVhc29ue2FyZ3VtZW50cz17fSwgY2F1c2U9bnVsbCwgY29kZT1nZGF0YS5Db3JlRXJyb3JEb21haW4uUkVRVUlSRUQsIGNyZWF0ZWRCeUJhY2tlbmQ9dHJ1ZSwgZGVidWdNZXNzYWdlPWNvbS5nb29nbGUubmV0LnJwYzMuUnBjRXhjZXB0aW9uOiBjbG91ZC5iaWdzdG9yZS5SZXNwb25zZUNvZGUuRXJyb3JDb2RlOjpVU0VSX1BST0pFQ1RfTUlTU0lORzogQnVja2V0IGlzIFJlcXVlc3RlciBQYXlzIGJ1Y2tldCBidXQgbm8gYmlsbGluZyBwcm9qZWN0IGlkIHByb3ZpZGVkIGZvciBub24tb3duZXIuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRvUnBjM0V4Y2VwdGlvbihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjEzNSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLkFjY2Vzc0NvbnRyb2xzSGVscGVyLmxvYWRPYmplY3QoQWNjZXNzQ29udHJvbHNIZWxwZXIuamF2YTozMzEpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5BY2Nlc3NDb250cm9sc0hlbHBlci5nZXRBY2xSZXNvdXJjZUZvclJlcXVlc3QoQWNjZXNzQ29udHJvbHNIZWxwZXIuamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLkRlbGV0ZUFjbHMuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKERlbGV0ZUFjbHMuamF2YTo3MSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLkRlbGV0ZUFjbHMuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKERlbGV0ZUFjbHMuamF2YToyMClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLkFjY2Vzc0NvbnRyb2xzRGVsZWdhdG9yLmRlbGV0ZShBY2Nlc3NDb250cm9sc0RlbGVnYXRvci5qYXZhOjEwOSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uUnBjUmVjZWl2ZXIubGFtYmRhJHByb2Nlc3NSZXF1ZXN0QXN5bmMkNChScGNSZWNlaXZlci5qYXZhOjIwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uQXN5bmNFeGVjdXRvci5sYW1iZGEkc3VibWl0JDAoQXN5bmNFeGVjdXRvci5qYXZhOjI3Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KENvbnRleHRSdW5uYWJsZS5qYXZhOjUwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZSQxLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozOSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NzIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozNilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRXhlY3V0b3JzJFJ1bm5hYmxlQWRhcHRlci5jYWxsKEV4ZWN1dG9ycy5qYXZhOjUxMSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRnV0dXJlVGFzay5ydW4oRnV0dXJlVGFzay5qYXZhOjI2Nilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yLnJ1bldvcmtlcihUaHJlYWRQb29sRXhlY3V0b3IuamF2YToxMTQ5KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IkV29ya2VyLnJ1bihUaHJlYWRQb29sRXhlY3V0b3IuamF2YTo2MjQpXG5cdGF0IGphdmEubGFuZy5UaHJlYWQucnVuKFRocmVhZC5qYXZhOjc0OClcbkNhdXNlZCBieTogY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb246IEJ1Y2tldCBpcyBSZXF1ZXN0ZXIgUGF5cyBidWNrZXQgYnV0IG5vIGJpbGxpbmcgcHJvamVjdCBpZCBwcm92aWRlZCBmb3Igbm9uLW93bmVyLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxOSBtb3JlXG4sIGVycm9yUHJvdG9Db2RlPVJFUVVJUkVELCBlcnJvclByb3RvRG9tYWluPWdkYXRhLkNvcmVFcnJvckRvbWFpbiwgZmlsdGVyZWRNZXNzYWdlPW51bGwsIGxvY2F0aW9uPW51bGwsIG1lc3NhZ2U9QnVja2V0IGlzIHJlcXVlc3RlciBwYXlzIGJ1Y2tldCBidXQgbm8gdXNlciBwcm9qZWN0IHByb3ZpZGVkLiwgdW5uYW1lZEFyZ3VtZW50cz1bXX0sIGxvY2F0aW9uPW51bGwsIG1lc3NhZ2U9QnVja2V0IGlzIHJlcXVlc3RlciBwYXlzIGJ1Y2tldCBidXQgbm8gdXNlciBwcm9qZWN0IHByb3ZpZGVkLiwgcmVhc29uPXJlcXVpcmVkLCBycGNDb2RlPTQwMH0gQnVja2V0IGlzIHJlcXVlc3RlciBwYXlzIGJ1Y2tldCBidXQgbm8gdXNlciBwcm9qZWN0IHByb3ZpZGVkLjogY29tLmdvb2dsZS5uZXQucnBjMy5ScGNFeGNlcHRpb246IGNsb3VkLmJpZ3N0b3JlLlJlc3BvbnNlQ29kZS5FcnJvckNvZGU6OlVTRVJfUFJPSkVDVF9NSVNTSU5HOiBCdWNrZXQgaXMgUmVxdWVzdGVyIFBheXMgYnVja2V0IGJ1dCBubyBiaWxsaW5nIHByb2plY3QgaWQgcHJvdmlkZWQgZm9yIG5vbi1vd25lci5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udG9ScGMzRXhjZXB0aW9uKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MTM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuQWNjZXNzQ29udHJvbHNIZWxwZXIubG9hZE9iamVjdChBY2Nlc3NDb250cm9sc0hlbHBlci5qYXZhOjMzMSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLkFjY2Vzc0NvbnRyb2xzSGVscGVyLmdldEFjbFJlc291cmNlRm9yUmVxdWVzdChBY2Nlc3NDb250cm9sc0hlbHBlci5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuRGVsZXRlQWNscy5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoRGVsZXRlQWNscy5qYXZhOjcxKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuRGVsZXRlQWNscy5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoRGVsZXRlQWNscy5qYXZhOjIwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmZyYW1ld29yay5SZXF1ZXN0SGFuZGxlci5oYW5kbGUoUmVxdWVzdEhhbmRsZXIuamF2YToyOTQpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uQWNjZXNzQ29udHJvbHNEZWxlZ2F0b3IuZGVsZXRlKEFjY2Vzc0NvbnRyb2xzRGVsZWdhdG9yLmphdmE6MTA5KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5ScGNSZWNlaXZlci5sYW1iZGEkcHJvY2Vzc1JlcXVlc3RBc3luYyQ0KFJwY1JlY2VpdmVyLmphdmE6MjAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5Bc3luY0V4ZWN1dG9yLmxhbWJkYSRzdWJtaXQkMChBc3luY0V4ZWN1dG9yLmphdmE6MjcyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoQ29udGV4dFJ1bm5hYmxlLmphdmE6NTApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlJDEucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM5KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo3Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5FeGVjdXRvcnMkUnVubmFibGVBZGFwdGVyLmNhbGwoRXhlY3V0b3JzLmphdmE6NTExKVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5GdXR1cmVUYXNrLnJ1bihGdXR1cmVUYXNrLmphdmE6MjY2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IucnVuV29ya2VyKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjExNDkpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvciRXb3JrZXIucnVuKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjYyNClcblx0YXQgamF2YS5sYW5nLlRocmVhZC5ydW4oVGhyZWFkLmphdmE6NzQ4KVxuQ2F1c2VkIGJ5OiBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbjogQnVja2V0IGlzIFJlcXVlc3RlciBQYXlzIGJ1Y2tldCBidXQgbm8gYmlsbGluZyBwcm9qZWN0IGlkIHByb3ZpZGVkIGZvciBub24tb3duZXIuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93T25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjI5MClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMSlcblx0Li4uIDE5IG1vcmVcblxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS5FcnJvckNvbGxlY3Rvci50b0ZhdWx0KEVycm9yQ29sbGVjdG9yLmphdmE6NTQpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5yZXN0LmFkYXB0ZXIucm9zeS5Sb3N5RXJyb3JDb252ZXJ0ZXIudG9GYXVsdChSb3N5RXJyb3JDb252ZXJ0ZXIuamF2YTo2Nylcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnJlc3QuYWRhcHRlci5yb3N5LlJvc3lIYW5kbGVyJDIuY2FsbChSb3N5SGFuZGxlci5qYXZhOjI1OClcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnJlc3QuYWRhcHRlci5yb3N5LlJvc3lIYW5kbGVyJDIuY2FsbChSb3N5SGFuZGxlci5qYXZhOjIzOClcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkRpcmVjdEV4ZWN1dG9yLmV4ZWN1dGUoRGlyZWN0RXhlY3V0b3IuamF2YTozMClcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmV4ZWN1dGVMaXN0ZW5lcihBYnN0cmFjdEZ1dHVyZS5qYXZhOjExNDMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5jb21wbGV0ZShBYnN0cmFjdEZ1dHVyZS5qYXZhOjk2Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLnNldChBYnN0cmFjdEZ1dHVyZS5qYXZhOjczMSlcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkRpcmVjdEV4ZWN1dG9yLmV4ZWN1dGUoRGlyZWN0RXhlY3V0b3IuamF2YTozMClcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmV4ZWN1dGVMaXN0ZW5lcihBYnN0cmFjdEZ1dHVyZS5qYXZhOjExNDMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5jb21wbGV0ZShBYnN0cmFjdEZ1dHVyZS5qYXZhOjk2Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLnNldChBYnN0cmFjdEZ1dHVyZS5qYXZhOjczMSlcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnRocmVhZC5UaHJlYWRUcmFja2VycyRUaHJlYWRUcmFja2luZ1J1bm5hYmxlLnJ1bihUaHJlYWRUcmFja2Vycy5qYXZhOjEyNilcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRUcmFjZUNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoVHJhY2VDb250ZXh0LmphdmE6NDU1KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuc2VydmVyLkNvbW1vbk1vZHVsZSRDb250ZXh0Q2FycnlpbmdFeGVjdXRvclNlcnZpY2UkMS5ydW5JbkNvbnRleHQoQ29tbW9uTW9kdWxlLmphdmE6ODQ2KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JFRyYWNlQ29udGV4dFJ1bm5hYmxlJDEucnVuKFRyYWNlQ29udGV4dC5qYXZhOjQ2Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRBYnN0cmFjdFRyYWNlQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoVHJhY2VDb250ZXh0LmphdmE6MzIxKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JEFic3RyYWN0VHJhY2VDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KFRyYWNlQ29udGV4dC5qYXZhOjMxMylcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRUcmFjZUNvbnRleHRSdW5uYWJsZS5ydW4oVHJhY2VDb250ZXh0LmphdmE6NDU5KVxuXHRhdCBjb20uZ29vZ2xlLmdzZS5pbnRlcm5hbC5EaXNwYXRjaFF1ZXVlSW1wbCRXb3JrZXJUaHJlYWQucnVuKERpc3BhdGNoUXVldWVJbXBsLmphdmE6NDAzKVxuIn1dLCJjb2RlIjo0MDAsIm1lc3NhZ2UiOiJCdWNrZXQgaXMgcmVxdWVzdGVyIHBheXMgYnVja2V0IGJ1dCBubyB1c2VyIHByb2plY3QgcHJvdmlkZWQuIn19"
+ }
+ },
+ {
+ "ID": "9a6144618da834c7",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/foo/acl/domain-google.com?alt=json\u0026prettyPrint=false\u0026userProject=gcloud-golang-firestore-tests",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "9b4ccb516b0ed7601e591296cf1453ba/11203500741341952567;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/foo/acl/domain-google.com?alt=json\u0026prettyPrint=false\u0026userProject=gcloud-golang-firestore-tests"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 404,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0"
+ ],
+ "Content-Length": [
+ "2911"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:11 GMT"
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:25:11 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051395000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "471383502717"
+ ],
+ "X-Google-Backends": [
+ "vrhq4:4312,/bns/yv/borg/yv/bns/blobstore2/bitpusher/111.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=J8ysW6HbB8-cgQS1rZiIAQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/111.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/111:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CP3elYXcDRoCGAYoATo_ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGM6ropHgHCIVMTE3MjM4MDU4ODYxOTM3NTE5MTQ0MOArSp8BEoIBeWEyOS5jLkVsb2xCcldWbUZlX1AxVDdUOHVpTXdFMHBZUjdTc2NVMDBFdEZkc2tSenBQY0NLWkhUeEZaYXI0Q25tZmR6bXFRLTNVV0kzOF9wdEx5VTZ2Z1Q3dlRBeW42Z3g4dUcyd0szSHIzaTZrV1JBZkozc1pNMGQ1allkNHpWQTAEOhZOT1RfQV9QRVJTSVNURU5UX1RPS0VO"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Upload-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UpLOFQ92MklcwxjQqPryjDyxnQlsUd23ini1iIR7nX2UvjxF_jcqx_zsF7NG8QzDitrsVr_W2-wuJsTeHCRk6ZDMjBaDQ"
+ ]
+ },
+ "Body": "eyJlcnJvciI6eyJlcnJvcnMiOlt7ImRvbWFpbiI6Imdsb2JhbCIsInJlYXNvbiI6Im5vdEZvdW5kIiwibWVzc2FnZSI6Ik5vdCBGb3VuZCIsImRlYnVnSW5mbyI6ImNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLkZhdWx0OiBJbW11dGFibGVFcnJvckRlZmluaXRpb257YmFzZT1OT1RfRk9VTkQsIGNhdGVnb3J5PVVTRVJfRVJST1IsIGNhdXNlPW51bGwsIGRlYnVnSW5mbz1udWxsLCBkb21haW49Z2xvYmFsLCBleHRlbmRlZEhlbHA9bnVsbCwgaHR0cEhlYWRlcnM9e30sIGh0dHBTdGF0dXM9bm90Rm91bmQsIGludGVybmFsUmVhc29uPVJlYXNvbnthcmd1bWVudHM9e30sIGNhdXNlPW51bGwsIGNvZGU9Z2RhdGEuQ29yZUVycm9yRG9tYWluLk5PVF9GT1VORCwgY3JlYXRlZEJ5QmFja2VuZD10cnVlLCBkZWJ1Z01lc3NhZ2U9bnVsbCwgZXJyb3JQcm90b0NvZGU9Tk9UX0ZPVU5ELCBlcnJvclByb3RvRG9tYWluPWdkYXRhLkNvcmVFcnJvckRvbWFpbiwgZmlsdGVyZWRNZXNzYWdlPW51bGwsIGxvY2F0aW9uPWVudGl0eS5yZXNvdXJjZV9pZC5zY29wZSwgbWVzc2FnZT1udWxsLCB1bm5hbWVkQXJndW1lbnRzPVtdfSwgbG9jYXRpb249ZW50aXR5LnJlc291cmNlX2lkLnNjb3BlLCBtZXNzYWdlPU5vdCBGb3VuZCwgcmVhc29uPW5vdEZvdW5kLCBycGNDb2RlPTQwNH0gTm90IEZvdW5kXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLkVycm9yQ29sbGVjdG9yLnRvRmF1bHQoRXJyb3JDb2xsZWN0b3IuamF2YTo1NClcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnJlc3QuYWRhcHRlci5yb3N5LlJvc3lFcnJvckNvbnZlcnRlci50b0ZhdWx0KFJvc3lFcnJvckNvbnZlcnRlci5qYXZhOjY3KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIucmVzdC5hZGFwdGVyLnJvc3kuUm9zeUhhbmRsZXIkMi5jYWxsKFJvc3lIYW5kbGVyLmphdmE6MjU4KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIucmVzdC5hZGFwdGVyLnJvc3kuUm9zeUhhbmRsZXIkMi5jYWxsKFJvc3lIYW5kbGVyLmphdmE6MjM4KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS51dGlsLkNhbGxhYmxlRnV0dXJlLnJ1bihDYWxsYWJsZUZ1dHVyZS5qYXZhOjYyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuRGlyZWN0RXhlY3V0b3IuZXhlY3V0ZShEaXJlY3RFeGVjdXRvci5qYXZhOjMwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuZXhlY3V0ZUxpc3RlbmVyKEFic3RyYWN0RnV0dXJlLmphdmE6MTE0Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmNvbXBsZXRlKEFic3RyYWN0RnV0dXJlLmphdmE6OTYzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuc2V0KEFic3RyYWN0RnV0dXJlLmphdmE6NzMxKVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS51dGlsLkNhbGxhYmxlRnV0dXJlLnJ1bihDYWxsYWJsZUZ1dHVyZS5qYXZhOjYyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuRGlyZWN0RXhlY3V0b3IuZXhlY3V0ZShEaXJlY3RFeGVjdXRvci5qYXZhOjMwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuZXhlY3V0ZUxpc3RlbmVyKEFic3RyYWN0RnV0dXJlLmphdmE6MTE0Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmNvbXBsZXRlKEFic3RyYWN0RnV0dXJlLmphdmE6OTYzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuc2V0KEFic3RyYWN0RnV0dXJlLmphdmE6NzMxKVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS51dGlsLkNhbGxhYmxlRnV0dXJlLnJ1bihDYWxsYWJsZUZ1dHVyZS5qYXZhOjYyKVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIudGhyZWFkLlRocmVhZFRyYWNrZXJzJFRocmVhZFRyYWNraW5nUnVubmFibGUucnVuKFRocmVhZFRyYWNrZXJzLmphdmE6MTI2KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JFRyYWNlQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChUcmFjZUNvbnRleHQuamF2YTo0NTUpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5zZXJ2ZXIuQ29tbW9uTW9kdWxlJENvbnRleHRDYXJyeWluZ0V4ZWN1dG9yU2VydmljZSQxLnJ1bkluQ29udGV4dChDb21tb25Nb2R1bGUuamF2YTo4NDYpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkVHJhY2VDb250ZXh0UnVubmFibGUkMS5ydW4oVHJhY2VDb250ZXh0LmphdmE6NDYyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JEFic3RyYWN0VHJhY2VDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihUcmFjZUNvbnRleHQuamF2YTozMjEpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkQWJzdHJhY3RUcmFjZUNvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoVHJhY2VDb250ZXh0LmphdmE6MzEzKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JFRyYWNlQ29udGV4dFJ1bm5hYmxlLnJ1bihUcmFjZUNvbnRleHQuamF2YTo0NTkpXG5cdGF0IGNvbS5nb29nbGUuZ3NlLmludGVybmFsLkRpc3BhdGNoUXVldWVJbXBsJFdvcmtlclRocmVhZC5ydW4oRGlzcGF0Y2hRdWV1ZUltcGwuamF2YTo0MDMpXG4ifV0sImNvZGUiOjQwNCwibWVzc2FnZSI6Ik5vdCBGb3VuZCJ9fQ=="
+ }
+ },
+ {
+ "ID": "c52b7f33ca3920d5",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/foo/acl/domain-google.com?alt=json\u0026prettyPrint=false\u0026userProject=veener-jba",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "f0700b25c7e12a6b9dec52fbd6091dee/12793631170432524245;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/foo/acl/domain-google.com?alt=json\u0026prettyPrint=false\u0026userProject=veener-jba"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 403,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0"
+ ],
+ "Content-Length": [
+ "13987"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:11 GMT"
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:25:11 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051402000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "471383502717"
+ ],
+ "X-Google-Backends": [
+ "vnlu1:4025,/bns/yx/borg/yx/bns/blobstore2/bitpusher/90.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=J8ysW97FDMTnzAKpnrCABg"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yx/borg/yx/bns/blobstore2/bitpusher/90.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yx/borg/yx/bns/blobstore2/bitpusher/90:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CP3elYXcDRoCGAYoATo_ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGM6ropHgHCIVMTE3MjM4MDU4ODYxOTM3NTE5MTQ0MOArSp8BEoIBeWEyOS5jLkVsb2xCcldWbUZlX1AxVDdUOHVpTXdFMHBZUjdTc2NVMDBFdEZkc2tSenBQY0NLWkhUeEZaYXI0Q25tZmR6bXFRLTNVV0kzOF9wdEx5VTZ2Z1Q3dlRBeW42Z3g4dUcyd0szSHIzaTZrV1JBZkozc1pNMGQ1allkNHpWQTAEOhZOT1RfQV9QRVJTSVNURU5UX1RPS0VO"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Upload-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UrmFjyyAPppeAl4NIJZEu0UFkt54qMbRjRWm_O014wmEJVzEZVPqDwfNrVFaKI6Xx_ULf38vu9EUup85Ce8EcuZeMkDIQ"
+ ]
+ },
+ "Body": "eyJlcnJvciI6eyJlcnJvcnMiOlt7ImRvbWFpbiI6Imdsb2JhbCIsInJlYXNvbiI6ImZvcmJpZGRlbiIsIm1lc3NhZ2UiOiJpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLiIsImRlYnVnSW5mbyI6ImNvbS5nb29nbGUubmV0LnJwYzMuUnBjRXhjZXB0aW9uOiBjbG91ZC5iaWdzdG9yZS5SZXNwb25zZUNvZGUuRXJyb3JDb2RlOjpVU0VSX1BST0pFQ1RfQUNDRVNTX0RFTklFRDogaW50ZWdyYXRpb25AZ2Nsb3VkLWdvbGFuZy1maXJlc3RvcmUtdGVzdHMuaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20gZG9lcyBub3QgaGF2ZSBzZXJ2aWNldXNhZ2Uuc2VydmljZXMudXNlIGFjY2VzcyB0byBwcm9qZWN0IDY0MjA4MDkxODEwMS5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udG9ScGMzRXhjZXB0aW9uKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MTM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuQWNjZXNzQ29udHJvbHNIZWxwZXIubG9hZE9iamVjdChBY2Nlc3NDb250cm9sc0hlbHBlci5qYXZhOjMzMSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLkFjY2Vzc0NvbnRyb2xzSGVscGVyLmdldEFjbFJlc291cmNlRm9yUmVxdWVzdChBY2Nlc3NDb250cm9sc0hlbHBlci5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuRGVsZXRlQWNscy5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoRGVsZXRlQWNscy5qYXZhOjcxKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuRGVsZXRlQWNscy5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoRGVsZXRlQWNscy5qYXZhOjIwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmZyYW1ld29yay5SZXF1ZXN0SGFuZGxlci5oYW5kbGUoUmVxdWVzdEhhbmRsZXIuamF2YToyOTQpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uQWNjZXNzQ29udHJvbHNEZWxlZ2F0b3IuZGVsZXRlKEFjY2Vzc0NvbnRyb2xzRGVsZWdhdG9yLmphdmE6MTA5KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5ScGNSZWNlaXZlci5sYW1iZGEkcHJvY2Vzc1JlcXVlc3RBc3luYyQ0KFJwY1JlY2VpdmVyLmphdmE6MjAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5Bc3luY0V4ZWN1dG9yLmxhbWJkYSRzdWJtaXQkMChBc3luY0V4ZWN1dG9yLmphdmE6MjcyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoQ29udGV4dFJ1bm5hYmxlLmphdmE6NTApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlJDEucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM5KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo3Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5FeGVjdXRvcnMkUnVubmFibGVBZGFwdGVyLmNhbGwoRXhlY3V0b3JzLmphdmE6NTExKVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5GdXR1cmVUYXNrLnJ1bihGdXR1cmVUYXNrLmphdmE6MjY2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IucnVuV29ya2VyKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjExNDkpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvciRXb3JrZXIucnVuKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjYyNClcblx0YXQgamF2YS5sYW5nLlRocmVhZC5ydW4oVGhyZWFkLmphdmE6NzQ4KVxuQ2F1c2VkIGJ5OiBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbjogaW50ZWdyYXRpb25AZ2Nsb3VkLWdvbGFuZy1maXJlc3RvcmUtdGVzdHMuaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20gZG9lcyBub3QgaGF2ZSBzZXJ2aWNldXNhZ2Uuc2VydmljZXMudXNlIGFjY2VzcyB0byBwcm9qZWN0IDY0MjA4MDkxODEwMS5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MjkwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAxKVxuXHQuLi4gMTkgbW9yZVxuXG5jb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS5GYXVsdDogSW1tdXRhYmxlRXJyb3JEZWZpbml0aW9ue2Jhc2U9Rk9SQklEREVOLCBjYXRlZ29yeT1VU0VSX0VSUk9SLCBjYXVzZT1udWxsLCBkZWJ1Z0luZm89Y29tLmdvb2dsZS5uZXQucnBjMy5ScGNFeGNlcHRpb246IGNsb3VkLmJpZ3N0b3JlLlJlc3BvbnNlQ29kZS5FcnJvckNvZGU6OlVTRVJfUFJPSkVDVF9BQ0NFU1NfREVOSUVEOiBpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5BY2Nlc3NDb250cm9sc0hlbHBlci5sb2FkT2JqZWN0KEFjY2Vzc0NvbnRyb2xzSGVscGVyLmphdmE6MzMxKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuQWNjZXNzQ29udHJvbHNIZWxwZXIuZ2V0QWNsUmVzb3VyY2VGb3JSZXF1ZXN0KEFjY2Vzc0NvbnRyb2xzSGVscGVyLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5EZWxldGVBY2xzLmhhbmRsZVJlcXVlc3RSZWNlaXZlZChEZWxldGVBY2xzLmphdmE6NzEpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5EZWxldGVBY2xzLmhhbmRsZVJlcXVlc3RSZWNlaXZlZChEZWxldGVBY2xzLmphdmE6MjApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5BY2Nlc3NDb250cm9sc0RlbGVnYXRvci5kZWxldGUoQWNjZXNzQ29udHJvbHNEZWxlZ2F0b3IuamF2YToxMDkpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxOSBtb3JlXG4sIGRvbWFpbj1nbG9iYWwsIGV4dGVuZGVkSGVscD1udWxsLCBodHRwSGVhZGVycz17fSwgaHR0cFN0YXR1cz1mb3JiaWRkZW4sIGludGVybmFsUmVhc29uPVJlYXNvbnthcmd1bWVudHM9e30sIGNhdXNlPW51bGwsIGNvZGU9Z2RhdGEuQ29yZUVycm9yRG9tYWluLkZPUkJJRERFTiwgY3JlYXRlZEJ5QmFja2VuZD10cnVlLCBkZWJ1Z01lc3NhZ2U9Y29tLmdvb2dsZS5uZXQucnBjMy5ScGNFeGNlcHRpb246IGNsb3VkLmJpZ3N0b3JlLlJlc3BvbnNlQ29kZS5FcnJvckNvZGU6OlVTRVJfUFJPSkVDVF9BQ0NFU1NfREVOSUVEOiBpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5BY2Nlc3NDb250cm9sc0hlbHBlci5sb2FkT2JqZWN0KEFjY2Vzc0NvbnRyb2xzSGVscGVyLmphdmE6MzMxKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmFjbHMuQWNjZXNzQ29udHJvbHNIZWxwZXIuZ2V0QWNsUmVzb3VyY2VGb3JSZXF1ZXN0KEFjY2Vzc0NvbnRyb2xzSGVscGVyLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5EZWxldGVBY2xzLmhhbmRsZVJlcXVlc3RSZWNlaXZlZChEZWxldGVBY2xzLmphdmE6NzEpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5EZWxldGVBY2xzLmhhbmRsZVJlcXVlc3RSZWNlaXZlZChEZWxldGVBY2xzLmphdmE6MjApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5BY2Nlc3NDb250cm9sc0RlbGVnYXRvci5kZWxldGUoQWNjZXNzQ29udHJvbHNEZWxlZ2F0b3IuamF2YToxMDkpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxOSBtb3JlXG4sIGVycm9yUHJvdG9Db2RlPUZPUkJJRERFTiwgZXJyb3JQcm90b0RvbWFpbj1nZGF0YS5Db3JlRXJyb3JEb21haW4sIGZpbHRlcmVkTWVzc2FnZT1udWxsLCBsb2NhdGlvbj1udWxsLCBtZXNzYWdlPWludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIGRvZXMgbm90IGhhdmUgc2VydmljZXVzYWdlLnNlcnZpY2VzLnVzZSBhY2Nlc3MgdG8gcHJvamVjdCA2NDIwODA5MTgxMDEuLCB1bm5hbWVkQXJndW1lbnRzPVtdfSwgbG9jYXRpb249bnVsbCwgbWVzc2FnZT1pbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLiwgcmVhc29uPWZvcmJpZGRlbiwgcnBjQ29kZT00MDN9IGludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIGRvZXMgbm90IGhhdmUgc2VydmljZXVzYWdlLnNlcnZpY2VzLnVzZSBhY2Nlc3MgdG8gcHJvamVjdCA2NDIwODA5MTgxMDEuOiBjb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6VVNFUl9QUk9KRUNUX0FDQ0VTU19ERU5JRUQ6IGludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIGRvZXMgbm90IGhhdmUgc2VydmljZXVzYWdlLnNlcnZpY2VzLnVzZSBhY2Nlc3MgdG8gcHJvamVjdCA2NDIwODA5MTgxMDEuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRvUnBjM0V4Y2VwdGlvbihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjEzNSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLkFjY2Vzc0NvbnRyb2xzSGVscGVyLmxvYWRPYmplY3QoQWNjZXNzQ29udHJvbHNIZWxwZXIuamF2YTozMzEpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYWNscy5BY2Nlc3NDb250cm9sc0hlbHBlci5nZXRBY2xSZXNvdXJjZUZvclJlcXVlc3QoQWNjZXNzQ29udHJvbHNIZWxwZXIuamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLkRlbGV0ZUFjbHMuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKERlbGV0ZUFjbHMuamF2YTo3MSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5hY2xzLkRlbGV0ZUFjbHMuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKERlbGV0ZUFjbHMuamF2YToyMClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLkFjY2Vzc0NvbnRyb2xzRGVsZWdhdG9yLmRlbGV0ZShBY2Nlc3NDb250cm9sc0RlbGVnYXRvci5qYXZhOjEwOSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uUnBjUmVjZWl2ZXIubGFtYmRhJHByb2Nlc3NSZXF1ZXN0QXN5bmMkNChScGNSZWNlaXZlci5qYXZhOjIwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uQXN5bmNFeGVjdXRvci5sYW1iZGEkc3VibWl0JDAoQXN5bmNFeGVjdXRvci5qYXZhOjI3Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KENvbnRleHRSdW5uYWJsZS5qYXZhOjUwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZSQxLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozOSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NzIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozNilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRXhlY3V0b3JzJFJ1bm5hYmxlQWRhcHRlci5jYWxsKEV4ZWN1dG9ycy5qYXZhOjUxMSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRnV0dXJlVGFzay5ydW4oRnV0dXJlVGFzay5qYXZhOjI2Nilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yLnJ1bldvcmtlcihUaHJlYWRQb29sRXhlY3V0b3IuamF2YToxMTQ5KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IkV29ya2VyLnJ1bihUaHJlYWRQb29sRXhlY3V0b3IuamF2YTo2MjQpXG5cdGF0IGphdmEubGFuZy5UaHJlYWQucnVuKFRocmVhZC5qYXZhOjc0OClcbkNhdXNlZCBieTogY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb246IGludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIGRvZXMgbm90IGhhdmUgc2VydmljZXVzYWdlLnNlcnZpY2VzLnVzZSBhY2Nlc3MgdG8gcHJvamVjdCA2NDIwODA5MTgxMDEuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93T25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjI5MClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMSlcblx0Li4uIDE5IG1vcmVcblxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS5FcnJvckNvbGxlY3Rvci50b0ZhdWx0KEVycm9yQ29sbGVjdG9yLmphdmE6NTQpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5yZXN0LmFkYXB0ZXIucm9zeS5Sb3N5RXJyb3JDb252ZXJ0ZXIudG9GYXVsdChSb3N5RXJyb3JDb252ZXJ0ZXIuamF2YTo2Nylcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnJlc3QuYWRhcHRlci5yb3N5LlJvc3lIYW5kbGVyJDIuY2FsbChSb3N5SGFuZGxlci5qYXZhOjI1OClcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnJlc3QuYWRhcHRlci5yb3N5LlJvc3lIYW5kbGVyJDIuY2FsbChSb3N5SGFuZGxlci5qYXZhOjIzOClcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkRpcmVjdEV4ZWN1dG9yLmV4ZWN1dGUoRGlyZWN0RXhlY3V0b3IuamF2YTozMClcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmV4ZWN1dGVMaXN0ZW5lcihBYnN0cmFjdEZ1dHVyZS5qYXZhOjExNDMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5jb21wbGV0ZShBYnN0cmFjdEZ1dHVyZS5qYXZhOjk2Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLnNldChBYnN0cmFjdEZ1dHVyZS5qYXZhOjczMSlcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkRpcmVjdEV4ZWN1dG9yLmV4ZWN1dGUoRGlyZWN0RXhlY3V0b3IuamF2YTozMClcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmV4ZWN1dGVMaXN0ZW5lcihBYnN0cmFjdEZ1dHVyZS5qYXZhOjExNDMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5jb21wbGV0ZShBYnN0cmFjdEZ1dHVyZS5qYXZhOjk2Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLnNldChBYnN0cmFjdEZ1dHVyZS5qYXZhOjczMSlcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnRocmVhZC5UaHJlYWRUcmFja2VycyRUaHJlYWRUcmFja2luZ1J1bm5hYmxlLnJ1bihUaHJlYWRUcmFja2Vycy5qYXZhOjEyNilcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRUcmFjZUNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoVHJhY2VDb250ZXh0LmphdmE6NDU1KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuc2VydmVyLkNvbW1vbk1vZHVsZSRDb250ZXh0Q2FycnlpbmdFeGVjdXRvclNlcnZpY2UkMS5ydW5JbkNvbnRleHQoQ29tbW9uTW9kdWxlLmphdmE6ODQ2KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JFRyYWNlQ29udGV4dFJ1bm5hYmxlJDEucnVuKFRyYWNlQ29udGV4dC5qYXZhOjQ2Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRBYnN0cmFjdFRyYWNlQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoVHJhY2VDb250ZXh0LmphdmE6MzIxKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JEFic3RyYWN0VHJhY2VDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KFRyYWNlQ29udGV4dC5qYXZhOjMxMylcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRUcmFjZUNvbnRleHRSdW5uYWJsZS5ydW4oVHJhY2VDb250ZXh0LmphdmE6NDU5KVxuXHRhdCBjb20uZ29vZ2xlLmdzZS5pbnRlcm5hbC5EaXNwYXRjaFF1ZXVlSW1wbCRXb3JrZXJUaHJlYWQucnVuKERpc3BhdGNoUXVldWVJbXBsLmphdmE6NDAzKVxuIn1dLCJjb2RlIjo0MDMsIm1lc3NhZ2UiOiJpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLiJ9fQ=="
+ }
+ },
+ {
+ "ID": "35caaa1961758473",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/foo/rewriteTo/b/go-integration-test-20180927-44630911863640-0003/o/copy?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "3"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "9d039fe48c3d6d31e978c142d65f7278/14384043074482898292;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/foo/rewriteTo/b/go-integration-test-20180927-44630911863640-0003/o/copy?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "e30K"
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3366"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:12 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051411000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vnaz77:4273,/bns/yx/borg/yx/bns/blobstore2/bitpusher/128.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=J8ysW9jcGoGKzQKK-Yv4CQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yx/borg/yx/bns/blobstore2/bitpusher/128.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yx/borg/yx/bns/blobstore2/bitpusher/128:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp0ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4StK4wESxgF5YTI5LmMuRW93QkpRWVNNdC1OVDFNYTJvWXBrbG1qcDlJMlZaUFZ5bFl5Z2Q3Nk5tQXlXbWR3WVBoMm00dGI3ZmZjOUlzcTU4MmVFcFBhNzhNWGpNZmIzaE9WTE9xRHpNTUFfTG9NQXVJZkdkMGgzSWowZ1dxdW5DS1g3Qk1mQlJxM001TUtMMXBHOWNyU0ZBT29lVkZpTDhpWlBsUDI0VjE5THdzZ0d1ZnVrQTFtVzVJcTJUUkVXeWQyNjRKZC1lS2UxdTAwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UoLVz1xVnB7DeGhm_uQ-fvJJcGqAvxf9eVPqr9nZ6F2T2v7hQViOoF6MMD9KhOv1w9uev9CbEiD5z80sBjc1OEbaTgsQA"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNyZXdyaXRlUmVzcG9uc2UiLCJ0b3RhbEJ5dGVzUmV3cml0dGVuIjoiNSIsIm9iamVjdFNpemUiOiI1IiwiZG9uZSI6dHJ1ZSwicmVzb3VyY2UiOnsia2luZCI6InN0b3JhZ2Ujb2JqZWN0IiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMvY29weS8xNTM4MDUxMTExOTM1MzgxIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL28vY29weSIsIm5hbWUiOiJjb3B5IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTExMTE5MzUzODEiLCJtZXRhZ2VuZXJhdGlvbiI6IjEiLCJjb250ZW50VHlwZSI6InRleHQvcGxhaW4iLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjU6MTEuOTM0WiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI1OjExLjkzNFoiLCJzdG9yYWdlQ2xhc3MiOiJTVEFOREFSRCIsInRpbWVTdG9yYWdlQ2xhc3NVcGRhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNToxMS45MzRaIiwic2l6ZSI6IjUiLCJtZDVIYXNoIjoiWFVGQUtyeExLbmE1Y1oyUkVCZkZrZz09IiwibWVkaWFMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vZG93bmxvYWQvc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9vL2NvcHk/Z2VuZXJhdGlvbj0xNTM4MDUxMTExOTM1MzgxJmFsdD1tZWRpYSIsImNvbnRlbnRMYW5ndWFnZSI6ImVuIiwiY2FjaGVDb250cm9sIjoicHVibGljLCBtYXgtYWdlPTYwIiwiYWNsIjpbeyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMvY29weS8xNTM4MDUxMTExOTM1MzgxL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL28vY29weS9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJvYmplY3QiOiJjb3B5IiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTExMTE5MzUzODEiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNKVzdzZkdXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9jb3B5LzE1MzgwNTExMTE5MzUzODEvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL28vY29weS9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzIiwib2JqZWN0IjoiY29weSIsImdlbmVyYXRpb24iOiIxNTM4MDUxMTExOTM1MzgxIiwiZW50aXR5IjoicHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6ImVkaXRvcnMifSwiZXRhZyI6IkNKVzdzZkdXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9jb3B5LzE1MzgwNTExMTE5MzUzODEvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL28vY29weS9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzIiwib2JqZWN0IjoiY29weSIsImdlbmVyYXRpb24iOiIxNTM4MDUxMTExOTM1MzgxIiwiZW50aXR5IjoicHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6IlJFQURFUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJ2aWV3ZXJzIn0sImV0YWciOiJDSlc3c2ZHVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMvY29weS8xNTM4MDUxMTExOTM1MzgxL3VzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMvby9jb3B5L2FjbC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzIiwib2JqZWN0IjoiY29weSIsImdlbmVyYXRpb24iOiIxNTM4MDUxMTExOTM1MzgxIiwiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInJvbGUiOiJPV05FUiIsImVtYWlsIjoiMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJldGFnIjoiQ0pXN3NmR1cyOTBDRUFFPSJ9XSwib3duZXIiOnsiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSJ9LCJjcmMzMmMiOiJtbkc3VEE9PSIsImV0YWciOiJDSlc3c2ZHVzI5MENFQUU9In19"
+ }
+ },
+ {
+ "ID": "0fd88baa3033f493",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/foo/rewriteTo/b/go-integration-test-20180927-44630911863640-0003/o/copy?alt=json\u0026prettyPrint=false\u0026projection=full\u0026userProject=dulcet-port-762",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "3"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "09f1f12c42b7c8149240acb13b43935d/15974453879055198739;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/foo/rewriteTo/b/go-integration-test-20180927-44630911863640-0003/o/copy?alt=json\u0026prettyPrint=false\u0026projection=full\u0026userProject=dulcet-port-762"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "e30K"
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3366"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:12 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051412000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vro189:4159,/bns/yr/borg/yr/bns/blobstore2/bitpusher/3.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=KMysW7WoBIPTkAOc94W4BQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/3.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/3:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp0ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4StK4wESxgF5YTI5LmMuRW93QkpRWVNNdC1OVDFNYTJvWXBrbG1qcDlJMlZaUFZ5bFl5Z2Q3Nk5tQXlXbWR3WVBoMm00dGI3ZmZjOUlzcTU4MmVFcFBhNzhNWGpNZmIzaE9WTE9xRHpNTUFfTG9NQXVJZkdkMGgzSWowZ1dxdW5DS1g3Qk1mQlJxM001TUtMMXBHOWNyU0ZBT29lVkZpTDhpWlBsUDI0VjE5THdzZ0d1ZnVrQTFtVzVJcTJUUkVXeWQyNjRKZC1lS2UxdTAwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Uq0ghIYIN0eHwuJHKVrDV7rhoHUiSGfwYvCq0Tbab-5NbHWPI_zlvjPKSpYTTnU2-LwWmJCJQdTXOYEEVFoNsjHCHLdTQ"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNyZXdyaXRlUmVzcG9uc2UiLCJ0b3RhbEJ5dGVzUmV3cml0dGVuIjoiNSIsIm9iamVjdFNpemUiOiI1IiwiZG9uZSI6dHJ1ZSwicmVzb3VyY2UiOnsia2luZCI6InN0b3JhZ2Ujb2JqZWN0IiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMvY29weS8xNTM4MDUxMTEyNTM1MTQyIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL28vY29weSIsIm5hbWUiOiJjb3B5IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTExMTI1MzUxNDIiLCJtZXRhZ2VuZXJhdGlvbiI6IjEiLCJjb250ZW50VHlwZSI6InRleHQvcGxhaW4iLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjU6MTIuNTMzWiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI1OjEyLjUzM1oiLCJzdG9yYWdlQ2xhc3MiOiJTVEFOREFSRCIsInRpbWVTdG9yYWdlQ2xhc3NVcGRhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNToxMi41MzNaIiwic2l6ZSI6IjUiLCJtZDVIYXNoIjoiWFVGQUtyeExLbmE1Y1oyUkVCZkZrZz09IiwibWVkaWFMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vZG93bmxvYWQvc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9vL2NvcHk/Z2VuZXJhdGlvbj0xNTM4MDUxMTEyNTM1MTQyJmFsdD1tZWRpYSIsImNvbnRlbnRMYW5ndWFnZSI6ImVuIiwiY2FjaGVDb250cm9sIjoicHVibGljLCBtYXgtYWdlPTYwIiwiYWNsIjpbeyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMvY29weS8xNTM4MDUxMTEyNTM1MTQyL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL28vY29weS9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJvYmplY3QiOiJjb3B5IiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTExMTI1MzUxNDIiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNPYUkxdkdXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9jb3B5LzE1MzgwNTExMTI1MzUxNDIvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL28vY29weS9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzIiwib2JqZWN0IjoiY29weSIsImdlbmVyYXRpb24iOiIxNTM4MDUxMTEyNTM1MTQyIiwiZW50aXR5IjoicHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6ImVkaXRvcnMifSwiZXRhZyI6IkNPYUkxdkdXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9jb3B5LzE1MzgwNTExMTI1MzUxNDIvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL28vY29weS9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzIiwib2JqZWN0IjoiY29weSIsImdlbmVyYXRpb24iOiIxNTM4MDUxMTEyNTM1MTQyIiwiZW50aXR5IjoicHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6IlJFQURFUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJ2aWV3ZXJzIn0sImV0YWciOiJDT2FJMXZHVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMvY29weS8xNTM4MDUxMTEyNTM1MTQyL3VzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMvby9jb3B5L2FjbC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzIiwib2JqZWN0IjoiY29weSIsImdlbmVyYXRpb24iOiIxNTM4MDUxMTEyNTM1MTQyIiwiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInJvbGUiOiJPV05FUiIsImVtYWlsIjoiMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJldGFnIjoiQ09hSTF2R1cyOTBDRUFFPSJ9XSwib3duZXIiOnsiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSJ9LCJjcmMzMmMiOiJtbkc3VEE9PSIsImV0YWciOiJDT2FJMXZHVzI5MENFQUU9In19"
+ }
+ },
+ {
+ "ID": "53fbb33131b2c479",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/foo/rewriteTo/b/go-integration-test-20180927-44630911863640-0003/o/copy?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "3"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "82868f26ec5b6e299b4474b2cfae6959/17564865783105638577;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/foo/rewriteTo/b/go-integration-test-20180927-44630911863640-0003/o/copy?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "e30K"
+ },
+ "Response": {
+ "StatusCode": 400,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Content-Length": [
+ "13391"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:12 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051412000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "471383502717"
+ ],
+ "X-Google-Backends": [
+ "vrbd126:4463,/bns/yr/borg/yr/bns/blobstore2/bitpusher/6.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=KMysW8GPKITi4QTTsIOoBA"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/6.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/6:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CP3elYXcDRoCGAYoATpCChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGM6ropHgHCIVMTE3MjM4MDU4ODYxOTM3NTE5MTQ0MOArMOErSp8BEoIBeWEyOS5jLkVsb2xCcldWbUZlX1AxVDdUOHVpTXdFMHBZUjdTc2NVMDBFdEZkc2tSenBQY0NLWkhUeEZaYXI0Q25tZmR6bXFRLTNVV0kzOF9wdEx5VTZ2Z1Q3dlRBeW42Z3g4dUcyd0szSHIzaTZrV1JBZkozc1pNMGQ1allkNHpWQTAEOhZOT1RfQV9QRVJTSVNURU5UX1RPS0VO"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Upload-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Ur-3PRMrpJH_qpKJfXYAc9NIi9qSUo9fN7ClGHRFbFLuUxvgBIf6Igeo-jEzfIDVBbyTmScU7Q_P1pMxZCt9DvTQlxFng"
+ ]
+ },
+ "Body": "eyJlcnJvciI6eyJlcnJvcnMiOlt7ImRvbWFpbiI6Imdsb2JhbCIsInJlYXNvbiI6InJlcXVpcmVkIiwibWVzc2FnZSI6IkJ1Y2tldCBpcyByZXF1ZXN0ZXIgcGF5cyBidWNrZXQgYnV0IG5vIHVzZXIgcHJvamVjdCBwcm92aWRlZC4iLCJkZWJ1Z0luZm8iOiJjb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6VVNFUl9QUk9KRUNUX01JU1NJTkc6IEJ1Y2tldCBpcyBSZXF1ZXN0ZXIgUGF5cyBidWNrZXQgYnV0IG5vIGJpbGxpbmcgcHJvamVjdCBpZCBwcm92aWRlZCBmb3Igbm9uLW93bmVyLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjMwMilcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5PYmplY3RzRGVsZWdhdG9yLnJld3JpdGUoT2JqZWN0c0RlbGVnYXRvci5qYXZhOjEyNClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uUnBjUmVjZWl2ZXIubGFtYmRhJHByb2Nlc3NSZXF1ZXN0QXN5bmMkNChScGNSZWNlaXZlci5qYXZhOjIwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uQXN5bmNFeGVjdXRvci5sYW1iZGEkc3VibWl0JDAoQXN5bmNFeGVjdXRvci5qYXZhOjI3Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KENvbnRleHRSdW5uYWJsZS5qYXZhOjUwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZSQxLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozOSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NzIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozNilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRXhlY3V0b3JzJFJ1bm5hYmxlQWRhcHRlci5jYWxsKEV4ZWN1dG9ycy5qYXZhOjUxMSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRnV0dXJlVGFzay5ydW4oRnV0dXJlVGFzay5qYXZhOjI2Nilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yLnJ1bldvcmtlcihUaHJlYWRQb29sRXhlY3V0b3IuamF2YToxMTQ5KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IkV29ya2VyLnJ1bihUaHJlYWRQb29sRXhlY3V0b3IuamF2YTo2MjQpXG5cdGF0IGphdmEubGFuZy5UaHJlYWQucnVuKFRocmVhZC5qYXZhOjc0OClcbkNhdXNlZCBieTogY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb246IEJ1Y2tldCBpcyBSZXF1ZXN0ZXIgUGF5cyBidWNrZXQgYnV0IG5vIGJpbGxpbmcgcHJvamVjdCBpZCBwcm92aWRlZCBmb3Igbm9uLW93bmVyLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLnJld3JpdGVyLkZyb250ZW5kUmV3cml0ZUFjdGlvbnMuZ2V0U291cmNlT2JqZWN0KEZyb250ZW5kUmV3cml0ZUFjdGlvbnMuamF2YToxODYpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLnJld3JpdGVyLlJld3JpdGVyLnJld3JpdGVPYmplY3QoUmV3cml0ZXIuamF2YTozNjIpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLnJld3JpdGVyLlJld3JpdGVyLnJld3JpdGVPYmplY3QoUmV3cml0ZXIuamF2YTozMzMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5SZXdyaXRlT2JqZWN0LnJld3JpdGVJbkZyb250ZW5kKFJld3JpdGVPYmplY3QuamF2YTozNDcpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5SZXdyaXRlT2JqZWN0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChSZXdyaXRlT2JqZWN0LmphdmE6MjQwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuUmV3cml0ZU9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoUmV3cml0ZU9iamVjdC5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmZyYW1ld29yay5SZXF1ZXN0SGFuZGxlci5oYW5kbGUoUmVxdWVzdEhhbmRsZXIuamF2YToyOTQpXG5cdC4uLiAxNCBtb3JlXG5cbmNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLkZhdWx0OiBJbW11dGFibGVFcnJvckRlZmluaXRpb257YmFzZT1SRVFVSVJFRCwgY2F0ZWdvcnk9VVNFUl9FUlJPUiwgY2F1c2U9bnVsbCwgZGVidWdJbmZvPWNvbS5nb29nbGUubmV0LnJwYzMuUnBjRXhjZXB0aW9uOiBjbG91ZC5iaWdzdG9yZS5SZXNwb25zZUNvZGUuRXJyb3JDb2RlOjpVU0VSX1BST0pFQ1RfTUlTU0lORzogQnVja2V0IGlzIFJlcXVlc3RlciBQYXlzIGJ1Y2tldCBidXQgbm8gYmlsbGluZyBwcm9qZWN0IGlkIHByb3ZpZGVkIGZvciBub24tb3duZXIuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRvUnBjM0V4Y2VwdGlvbihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjEzNSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6MzAyKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLk9iamVjdHNEZWxlZ2F0b3IucmV3cml0ZShPYmplY3RzRGVsZWdhdG9yLmphdmE6MTI0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5ScGNSZWNlaXZlci5sYW1iZGEkcHJvY2Vzc1JlcXVlc3RBc3luYyQ0KFJwY1JlY2VpdmVyLmphdmE6MjAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5Bc3luY0V4ZWN1dG9yLmxhbWJkYSRzdWJtaXQkMChBc3luY0V4ZWN1dG9yLmphdmE6MjcyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoQ29udGV4dFJ1bm5hYmxlLmphdmE6NTApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlJDEucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM5KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo3Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5FeGVjdXRvcnMkUnVubmFibGVBZGFwdGVyLmNhbGwoRXhlY3V0b3JzLmphdmE6NTExKVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5GdXR1cmVUYXNrLnJ1bihGdXR1cmVUYXNrLmphdmE6MjY2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IucnVuV29ya2VyKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjExNDkpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvciRXb3JrZXIucnVuKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjYyNClcblx0YXQgamF2YS5sYW5nLlRocmVhZC5ydW4oVGhyZWFkLmphdmE6NzQ4KVxuQ2F1c2VkIGJ5OiBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbjogQnVja2V0IGlzIFJlcXVlc3RlciBQYXlzIGJ1Y2tldCBidXQgbm8gYmlsbGluZyBwcm9qZWN0IGlkIHByb3ZpZGVkIGZvciBub24tb3duZXIuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93T25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjI5MClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24ucmV3cml0ZXIuRnJvbnRlbmRSZXdyaXRlQWN0aW9ucy5nZXRTb3VyY2VPYmplY3QoRnJvbnRlbmRSZXdyaXRlQWN0aW9ucy5qYXZhOjE4Nilcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24ucmV3cml0ZXIuUmV3cml0ZXIucmV3cml0ZU9iamVjdChSZXdyaXRlci5qYXZhOjM2Milcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24ucmV3cml0ZXIuUmV3cml0ZXIucmV3cml0ZU9iamVjdChSZXdyaXRlci5qYXZhOjMzMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5vYmplY3RzLlJld3JpdGVPYmplY3QucmV3cml0ZUluRnJvbnRlbmQoUmV3cml0ZU9iamVjdC5qYXZhOjM0Nylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5vYmplY3RzLlJld3JpdGVPYmplY3QuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKFJld3JpdGVPYmplY3QuamF2YToyNDApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5SZXdyaXRlT2JqZWN0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChSZXdyaXRlT2JqZWN0LmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0Li4uIDE0IG1vcmVcbiwgZG9tYWluPWdsb2JhbCwgZXh0ZW5kZWRIZWxwPW51bGwsIGh0dHBIZWFkZXJzPXt9LCBodHRwU3RhdHVzPWJhZFJlcXVlc3QsIGludGVybmFsUmVhc29uPVJlYXNvbnthcmd1bWVudHM9e30sIGNhdXNlPW51bGwsIGNvZGU9Z2RhdGEuQ29yZUVycm9yRG9tYWluLlJFUVVJUkVELCBjcmVhdGVkQnlCYWNrZW5kPXRydWUsIGRlYnVnTWVzc2FnZT1jb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6VVNFUl9QUk9KRUNUX01JU1NJTkc6IEJ1Y2tldCBpcyBSZXF1ZXN0ZXIgUGF5cyBidWNrZXQgYnV0IG5vIGJpbGxpbmcgcHJvamVjdCBpZCBwcm92aWRlZCBmb3Igbm9uLW93bmVyLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjMwMilcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5PYmplY3RzRGVsZWdhdG9yLnJld3JpdGUoT2JqZWN0c0RlbGVnYXRvci5qYXZhOjEyNClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uUnBjUmVjZWl2ZXIubGFtYmRhJHByb2Nlc3NSZXF1ZXN0QXN5bmMkNChScGNSZWNlaXZlci5qYXZhOjIwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uQXN5bmNFeGVjdXRvci5sYW1iZGEkc3VibWl0JDAoQXN5bmNFeGVjdXRvci5qYXZhOjI3Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KENvbnRleHRSdW5uYWJsZS5qYXZhOjUwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZSQxLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozOSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NzIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozNilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRXhlY3V0b3JzJFJ1bm5hYmxlQWRhcHRlci5jYWxsKEV4ZWN1dG9ycy5qYXZhOjUxMSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRnV0dXJlVGFzay5ydW4oRnV0dXJlVGFzay5qYXZhOjI2Nilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yLnJ1bldvcmtlcihUaHJlYWRQb29sRXhlY3V0b3IuamF2YToxMTQ5KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IkV29ya2VyLnJ1bihUaHJlYWRQb29sRXhlY3V0b3IuamF2YTo2MjQpXG5cdGF0IGphdmEubGFuZy5UaHJlYWQucnVuKFRocmVhZC5qYXZhOjc0OClcbkNhdXNlZCBieTogY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb246IEJ1Y2tldCBpcyBSZXF1ZXN0ZXIgUGF5cyBidWNrZXQgYnV0IG5vIGJpbGxpbmcgcHJvamVjdCBpZCBwcm92aWRlZCBmb3Igbm9uLW93bmVyLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLnJld3JpdGVyLkZyb250ZW5kUmV3cml0ZUFjdGlvbnMuZ2V0U291cmNlT2JqZWN0KEZyb250ZW5kUmV3cml0ZUFjdGlvbnMuamF2YToxODYpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLnJld3JpdGVyLlJld3JpdGVyLnJld3JpdGVPYmplY3QoUmV3cml0ZXIuamF2YTozNjIpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLnJld3JpdGVyLlJld3JpdGVyLnJld3JpdGVPYmplY3QoUmV3cml0ZXIuamF2YTozMzMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5SZXdyaXRlT2JqZWN0LnJld3JpdGVJbkZyb250ZW5kKFJld3JpdGVPYmplY3QuamF2YTozNDcpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5SZXdyaXRlT2JqZWN0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChSZXdyaXRlT2JqZWN0LmphdmE6MjQwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuUmV3cml0ZU9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoUmV3cml0ZU9iamVjdC5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmZyYW1ld29yay5SZXF1ZXN0SGFuZGxlci5oYW5kbGUoUmVxdWVzdEhhbmRsZXIuamF2YToyOTQpXG5cdC4uLiAxNCBtb3JlXG4sIGVycm9yUHJvdG9Db2RlPVJFUVVJUkVELCBlcnJvclByb3RvRG9tYWluPWdkYXRhLkNvcmVFcnJvckRvbWFpbiwgZmlsdGVyZWRNZXNzYWdlPW51bGwsIGxvY2F0aW9uPW51bGwsIG1lc3NhZ2U9QnVja2V0IGlzIHJlcXVlc3RlciBwYXlzIGJ1Y2tldCBidXQgbm8gdXNlciBwcm9qZWN0IHByb3ZpZGVkLiwgdW5uYW1lZEFyZ3VtZW50cz1bXX0sIGxvY2F0aW9uPW51bGwsIG1lc3NhZ2U9QnVja2V0IGlzIHJlcXVlc3RlciBwYXlzIGJ1Y2tldCBidXQgbm8gdXNlciBwcm9qZWN0IHByb3ZpZGVkLiwgcmVhc29uPXJlcXVpcmVkLCBycGNDb2RlPTQwMH0gQnVja2V0IGlzIHJlcXVlc3RlciBwYXlzIGJ1Y2tldCBidXQgbm8gdXNlciBwcm9qZWN0IHByb3ZpZGVkLjogY29tLmdvb2dsZS5uZXQucnBjMy5ScGNFeGNlcHRpb246IGNsb3VkLmJpZ3N0b3JlLlJlc3BvbnNlQ29kZS5FcnJvckNvZGU6OlVTRVJfUFJPSkVDVF9NSVNTSU5HOiBCdWNrZXQgaXMgUmVxdWVzdGVyIFBheXMgYnVja2V0IGJ1dCBubyBiaWxsaW5nIHByb2plY3QgaWQgcHJvdmlkZWQgZm9yIG5vbi1vd25lci5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udG9ScGMzRXhjZXB0aW9uKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MTM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmZyYW1ld29yay5SZXF1ZXN0SGFuZGxlci5oYW5kbGUoUmVxdWVzdEhhbmRsZXIuamF2YTozMDIpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uT2JqZWN0c0RlbGVnYXRvci5yZXdyaXRlKE9iamVjdHNEZWxlZ2F0b3IuamF2YToxMjQpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBCdWNrZXQgaXMgUmVxdWVzdGVyIFBheXMgYnVja2V0IGJ1dCBubyBiaWxsaW5nIHByb2plY3QgaWQgcHJvdmlkZWQgZm9yIG5vbi1vd25lci5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MjkwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5yZXdyaXRlci5Gcm9udGVuZFJld3JpdGVBY3Rpb25zLmdldFNvdXJjZU9iamVjdChGcm9udGVuZFJld3JpdGVBY3Rpb25zLmphdmE6MTg2KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5yZXdyaXRlci5SZXdyaXRlci5yZXdyaXRlT2JqZWN0KFJld3JpdGVyLmphdmE6MzYyKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5yZXdyaXRlci5SZXdyaXRlci5yZXdyaXRlT2JqZWN0KFJld3JpdGVyLmphdmE6MzMzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuUmV3cml0ZU9iamVjdC5yZXdyaXRlSW5Gcm9udGVuZChSZXdyaXRlT2JqZWN0LmphdmE6MzQ3KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuUmV3cml0ZU9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoUmV3cml0ZU9iamVjdC5qYXZhOjI0MClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5vYmplY3RzLlJld3JpdGVPYmplY3QuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKFJld3JpdGVPYmplY3QuamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHQuLi4gMTQgbW9yZVxuXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLkVycm9yQ29sbGVjdG9yLnRvRmF1bHQoRXJyb3JDb2xsZWN0b3IuamF2YTo1NClcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnJlc3QuYWRhcHRlci5yb3N5LlJvc3lFcnJvckNvbnZlcnRlci50b0ZhdWx0KFJvc3lFcnJvckNvbnZlcnRlci5qYXZhOjY3KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIucmVzdC5hZGFwdGVyLnJvc3kuUm9zeUhhbmRsZXIkMi5jYWxsKFJvc3lIYW5kbGVyLmphdmE6MjU4KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIucmVzdC5hZGFwdGVyLnJvc3kuUm9zeUhhbmRsZXIkMi5jYWxsKFJvc3lIYW5kbGVyLmphdmE6MjM4KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS51dGlsLkNhbGxhYmxlRnV0dXJlLnJ1bihDYWxsYWJsZUZ1dHVyZS5qYXZhOjYyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuRGlyZWN0RXhlY3V0b3IuZXhlY3V0ZShEaXJlY3RFeGVjdXRvci5qYXZhOjMwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuZXhlY3V0ZUxpc3RlbmVyKEFic3RyYWN0RnV0dXJlLmphdmE6MTE0Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmNvbXBsZXRlKEFic3RyYWN0RnV0dXJlLmphdmE6OTYzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuc2V0KEFic3RyYWN0RnV0dXJlLmphdmE6NzMxKVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS51dGlsLkNhbGxhYmxlRnV0dXJlLnJ1bihDYWxsYWJsZUZ1dHVyZS5qYXZhOjYyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuRGlyZWN0RXhlY3V0b3IuZXhlY3V0ZShEaXJlY3RFeGVjdXRvci5qYXZhOjMwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuZXhlY3V0ZUxpc3RlbmVyKEFic3RyYWN0RnV0dXJlLmphdmE6MTE0Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmNvbXBsZXRlKEFic3RyYWN0RnV0dXJlLmphdmE6OTYzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuc2V0KEFic3RyYWN0RnV0dXJlLmphdmE6NzMxKVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS51dGlsLkNhbGxhYmxlRnV0dXJlLnJ1bihDYWxsYWJsZUZ1dHVyZS5qYXZhOjYyKVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIudGhyZWFkLlRocmVhZFRyYWNrZXJzJFRocmVhZFRyYWNraW5nUnVubmFibGUucnVuKFRocmVhZFRyYWNrZXJzLmphdmE6MTI2KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JFRyYWNlQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChUcmFjZUNvbnRleHQuamF2YTo0NTUpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5zZXJ2ZXIuQ29tbW9uTW9kdWxlJENvbnRleHRDYXJyeWluZ0V4ZWN1dG9yU2VydmljZSQxLnJ1bkluQ29udGV4dChDb21tb25Nb2R1bGUuamF2YTo4NDYpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkVHJhY2VDb250ZXh0UnVubmFibGUkMS5ydW4oVHJhY2VDb250ZXh0LmphdmE6NDYyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JEFic3RyYWN0VHJhY2VDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihUcmFjZUNvbnRleHQuamF2YTozMjEpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkQWJzdHJhY3RUcmFjZUNvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoVHJhY2VDb250ZXh0LmphdmE6MzEzKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JFRyYWNlQ29udGV4dFJ1bm5hYmxlLnJ1bihUcmFjZUNvbnRleHQuamF2YTo0NTkpXG5cdGF0IGNvbS5nb29nbGUuZ3NlLmludGVybmFsLkRpc3BhdGNoUXVldWVJbXBsJFdvcmtlclRocmVhZC5ydW4oRGlzcGF0Y2hRdWV1ZUltcGwuamF2YTo0MDMpXG4ifV0sImNvZGUiOjQwMCwibWVzc2FnZSI6IkJ1Y2tldCBpcyByZXF1ZXN0ZXIgcGF5cyBidWNrZXQgYnV0IG5vIHVzZXIgcHJvamVjdCBwcm92aWRlZC4ifX0="
+ }
+ },
+ {
+ "ID": "f86365df7b93f43c",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/foo/rewriteTo/b/go-integration-test-20180927-44630911863640-0003/o/copy?alt=json\u0026prettyPrint=false\u0026projection=full\u0026userProject=gcloud-golang-firestore-tests",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "3"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "9ddfb31e3f881c845551040d149daa03/708533613463303504;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/foo/rewriteTo/b/go-integration-test-20180927-44630911863640-0003/o/copy?alt=json\u0026prettyPrint=false\u0026projection=full\u0026userProject=gcloud-golang-firestore-tests"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "e30K"
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3321"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:13 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051412000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "471383502717"
+ ],
+ "X-Google-Backends": [
+ "vrlw11:4360,/bns/yv/borg/yv/bns/blobstore2/bitpusher/67.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=KMysW5WjMoqOgwTBuI7wDA"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/67.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/67:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CP3elYXcDRoCGAYoATpCChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGM6ropHgHCIVMTE3MjM4MDU4ODYxOTM3NTE5MTQ0MOArMOErSp8BEoIBeWEyOS5jLkVsb2xCcldWbUZlX1AxVDdUOHVpTXdFMHBZUjdTc2NVMDBFdEZkc2tSenBQY0NLWkhUeEZaYXI0Q25tZmR6bXFRLTNVV0kzOF9wdEx5VTZ2Z1Q3dlRBeW42Z3g4dUcyd0szSHIzaTZrV1JBZkozc1pNMGQ1allkNHpWQTAEOhZOT1RfQV9QRVJTSVNURU5UX1RPS0VO"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UrovVDo882mWpoavyshb6LknBxbQkL6Ya9AnN5uoVuTl1lfogtISVulQ2qAStL-GJMjMMnY3YCHK4yUm5jOG7JBH8Ub4A"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNyZXdyaXRlUmVzcG9uc2UiLCJ0b3RhbEJ5dGVzUmV3cml0dGVuIjoiNSIsIm9iamVjdFNpemUiOiI1IiwiZG9uZSI6dHJ1ZSwicmVzb3VyY2UiOnsia2luZCI6InN0b3JhZ2Ujb2JqZWN0IiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMvY29weS8xNTM4MDUxMTEyOTQxMjM1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL28vY29weSIsIm5hbWUiOiJjb3B5IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTExMTI5NDEyMzUiLCJtZXRhZ2VuZXJhdGlvbiI6IjEiLCJjb250ZW50VHlwZSI6InRleHQvcGxhaW4iLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjU6MTIuOTQxWiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI1OjEyLjk0MVoiLCJzdG9yYWdlQ2xhc3MiOiJTVEFOREFSRCIsInRpbWVTdG9yYWdlQ2xhc3NVcGRhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNToxMi45NDFaIiwic2l6ZSI6IjUiLCJtZDVIYXNoIjoiWFVGQUtyeExLbmE1Y1oyUkVCZkZrZz09IiwibWVkaWFMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vZG93bmxvYWQvc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9vL2NvcHk/Z2VuZXJhdGlvbj0xNTM4MDUxMTEyOTQxMjM1JmFsdD1tZWRpYSIsImNvbnRlbnRMYW5ndWFnZSI6ImVuIiwiY2FjaGVDb250cm9sIjoicHVibGljLCBtYXgtYWdlPTYwIiwiYWNsIjpbeyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMvY29weS8xNTM4MDUxMTEyOTQxMjM1L3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL28vY29weS9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJvYmplY3QiOiJjb3B5IiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTExMTI5NDEyMzUiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNMUHQ3dkdXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9jb3B5LzE1MzgwNTExMTI5NDEyMzUvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL28vY29weS9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzIiwib2JqZWN0IjoiY29weSIsImdlbmVyYXRpb24iOiIxNTM4MDUxMTEyOTQxMjM1IiwiZW50aXR5IjoicHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6ImVkaXRvcnMifSwiZXRhZyI6IkNMUHQ3dkdXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9jb3B5LzE1MzgwNTExMTI5NDEyMzUvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL28vY29weS9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzIiwib2JqZWN0IjoiY29weSIsImdlbmVyYXRpb24iOiIxNTM4MDUxMTEyOTQxMjM1IiwiZW50aXR5IjoicHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6IlJFQURFUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJ2aWV3ZXJzIn0sImV0YWciOiJDTFB0N3ZHVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMvY29weS8xNTM4MDUxMTEyOTQxMjM1L3VzZXItaW50ZWdyYXRpb25AZ2Nsb3VkLWdvbGFuZy1maXJlc3RvcmUtdGVzdHMuaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMvby9jb3B5L2FjbC91c2VyLWludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzIiwib2JqZWN0IjoiY29weSIsImdlbmVyYXRpb24iOiIxNTM4MDUxMTEyOTQxMjM1IiwiZW50aXR5IjoidXNlci1pbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSIsInJvbGUiOiJPV05FUiIsImVtYWlsIjoiaW50ZWdyYXRpb25AZ2Nsb3VkLWdvbGFuZy1maXJlc3RvcmUtdGVzdHMuaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJldGFnIjoiQ0xQdDd2R1cyOTBDRUFFPSJ9XSwib3duZXIiOnsiZW50aXR5IjoidXNlci1pbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSJ9LCJjcmMzMmMiOiJtbkc3VEE9PSIsImV0YWciOiJDTFB0N3ZHVzI5MENFQUU9In19"
+ }
+ },
+ {
+ "ID": "5879616fb9645b35",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/foo/rewriteTo/b/go-integration-test-20180927-44630911863640-0003/o/copy?alt=json\u0026prettyPrint=false\u0026projection=full\u0026userProject=veener-jba",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "3"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "b83e165b179c0491707d79c900744d04/2298945517513677807;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/foo/rewriteTo/b/go-integration-test-20180927-44630911863640-0003/o/copy?alt=json\u0026prettyPrint=false\u0026projection=full\u0026userProject=veener-jba"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "e30K"
+ },
+ "Response": {
+ "StatusCode": 403,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Content-Length": [
+ "14247"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:13 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051412000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "471383502717"
+ ],
+ "X-Google-Backends": [
+ "vrua10:4104,/bns/yv/borg/yv/bns/blobstore2/bitpusher/268.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=KcysW_rQA9KeggS9oqBY"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/268.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/268:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CP3elYXcDRoCGAYoATpCChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGM6ropHgHCIVMTE3MjM4MDU4ODYxOTM3NTE5MTQ0MOArMOErSp8BEoIBeWEyOS5jLkVsb2xCcldWbUZlX1AxVDdUOHVpTXdFMHBZUjdTc2NVMDBFdEZkc2tSenBQY0NLWkhUeEZaYXI0Q25tZmR6bXFRLTNVV0kzOF9wdEx5VTZ2Z1Q3dlRBeW42Z3g4dUcyd0szSHIzaTZrV1JBZkozc1pNMGQ1allkNHpWQTAEOhZOT1RfQV9QRVJTSVNURU5UX1RPS0VO"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Upload-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UrFsS7uheKWICgicbUs1cp26n1d1UfjI-Zyvhd_j3EOO7rhY-n1p44ri63jTHbJcoBVsPrvnFxkdQ7M9nfEkgyBNH3lyw"
+ ]
+ },
+ "Body": "eyJlcnJvciI6eyJlcnJvcnMiOlt7ImRvbWFpbiI6Imdsb2JhbCIsInJlYXNvbiI6ImZvcmJpZGRlbiIsIm1lc3NhZ2UiOiJpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLiIsImRlYnVnSW5mbyI6ImNvbS5nb29nbGUubmV0LnJwYzMuUnBjRXhjZXB0aW9uOiBjbG91ZC5iaWdzdG9yZS5SZXNwb25zZUNvZGUuRXJyb3JDb2RlOjpVU0VSX1BST0pFQ1RfQUNDRVNTX0RFTklFRDogaW50ZWdyYXRpb25AZ2Nsb3VkLWdvbGFuZy1maXJlc3RvcmUtdGVzdHMuaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20gZG9lcyBub3QgaGF2ZSBzZXJ2aWNldXNhZ2Uuc2VydmljZXMudXNlIGFjY2VzcyB0byBwcm9qZWN0IDY0MjA4MDkxODEwMS5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udG9ScGMzRXhjZXB0aW9uKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MTM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmZyYW1ld29yay5SZXF1ZXN0SGFuZGxlci5oYW5kbGUoUmVxdWVzdEhhbmRsZXIuamF2YTozMDIpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uT2JqZWN0c0RlbGVnYXRvci5yZXdyaXRlKE9iamVjdHNEZWxlZ2F0b3IuamF2YToxMjQpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLnJld3JpdGVyLkZyb250ZW5kUmV3cml0ZUFjdGlvbnMuZ2V0U291cmNlT2JqZWN0KEZyb250ZW5kUmV3cml0ZUFjdGlvbnMuamF2YToxODYpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLnJld3JpdGVyLlJld3JpdGVyLnJld3JpdGVPYmplY3QoUmV3cml0ZXIuamF2YTozNjIpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLnJld3JpdGVyLlJld3JpdGVyLnJld3JpdGVPYmplY3QoUmV3cml0ZXIuamF2YTozMzMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5SZXdyaXRlT2JqZWN0LnJld3JpdGVJbkZyb250ZW5kKFJld3JpdGVPYmplY3QuamF2YTozNDcpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5SZXdyaXRlT2JqZWN0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChSZXdyaXRlT2JqZWN0LmphdmE6MjQwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuUmV3cml0ZU9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoUmV3cml0ZU9iamVjdC5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmZyYW1ld29yay5SZXF1ZXN0SGFuZGxlci5oYW5kbGUoUmVxdWVzdEhhbmRsZXIuamF2YToyOTQpXG5cdC4uLiAxNCBtb3JlXG5cbmNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLkZhdWx0OiBJbW11dGFibGVFcnJvckRlZmluaXRpb257YmFzZT1GT1JCSURERU4sIGNhdGVnb3J5PVVTRVJfRVJST1IsIGNhdXNlPW51bGwsIGRlYnVnSW5mbz1jb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6VVNFUl9QUk9KRUNUX0FDQ0VTU19ERU5JRUQ6IGludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIGRvZXMgbm90IGhhdmUgc2VydmljZXVzYWdlLnNlcnZpY2VzLnVzZSBhY2Nlc3MgdG8gcHJvamVjdCA2NDIwODA5MTgxMDEuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRvUnBjM0V4Y2VwdGlvbihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjEzNSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6MzAyKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLk9iamVjdHNEZWxlZ2F0b3IucmV3cml0ZShPYmplY3RzRGVsZWdhdG9yLmphdmE6MTI0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5ScGNSZWNlaXZlci5sYW1iZGEkcHJvY2Vzc1JlcXVlc3RBc3luYyQ0KFJwY1JlY2VpdmVyLmphdmE6MjAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5Bc3luY0V4ZWN1dG9yLmxhbWJkYSRzdWJtaXQkMChBc3luY0V4ZWN1dG9yLmphdmE6MjcyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoQ29udGV4dFJ1bm5hYmxlLmphdmE6NTApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlJDEucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM5KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo3Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5FeGVjdXRvcnMkUnVubmFibGVBZGFwdGVyLmNhbGwoRXhlY3V0b3JzLmphdmE6NTExKVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5GdXR1cmVUYXNrLnJ1bihGdXR1cmVUYXNrLmphdmE6MjY2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IucnVuV29ya2VyKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjExNDkpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvciRXb3JrZXIucnVuKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjYyNClcblx0YXQgamF2YS5sYW5nLlRocmVhZC5ydW4oVGhyZWFkLmphdmE6NzQ4KVxuQ2F1c2VkIGJ5OiBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbjogaW50ZWdyYXRpb25AZ2Nsb3VkLWdvbGFuZy1maXJlc3RvcmUtdGVzdHMuaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20gZG9lcyBub3QgaGF2ZSBzZXJ2aWNldXNhZ2Uuc2VydmljZXMudXNlIGFjY2VzcyB0byBwcm9qZWN0IDY0MjA4MDkxODEwMS5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MjkwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5yZXdyaXRlci5Gcm9udGVuZFJld3JpdGVBY3Rpb25zLmdldFNvdXJjZU9iamVjdChGcm9udGVuZFJld3JpdGVBY3Rpb25zLmphdmE6MTg2KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5yZXdyaXRlci5SZXdyaXRlci5yZXdyaXRlT2JqZWN0KFJld3JpdGVyLmphdmE6MzYyKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5yZXdyaXRlci5SZXdyaXRlci5yZXdyaXRlT2JqZWN0KFJld3JpdGVyLmphdmE6MzMzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuUmV3cml0ZU9iamVjdC5yZXdyaXRlSW5Gcm9udGVuZChSZXdyaXRlT2JqZWN0LmphdmE6MzQ3KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuUmV3cml0ZU9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoUmV3cml0ZU9iamVjdC5qYXZhOjI0MClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5vYmplY3RzLlJld3JpdGVPYmplY3QuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKFJld3JpdGVPYmplY3QuamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHQuLi4gMTQgbW9yZVxuLCBkb21haW49Z2xvYmFsLCBleHRlbmRlZEhlbHA9bnVsbCwgaHR0cEhlYWRlcnM9e30sIGh0dHBTdGF0dXM9Zm9yYmlkZGVuLCBpbnRlcm5hbFJlYXNvbj1SZWFzb257YXJndW1lbnRzPXt9LCBjYXVzZT1udWxsLCBjb2RlPWdkYXRhLkNvcmVFcnJvckRvbWFpbi5GT1JCSURERU4sIGNyZWF0ZWRCeUJhY2tlbmQ9dHJ1ZSwgZGVidWdNZXNzYWdlPWNvbS5nb29nbGUubmV0LnJwYzMuUnBjRXhjZXB0aW9uOiBjbG91ZC5iaWdzdG9yZS5SZXNwb25zZUNvZGUuRXJyb3JDb2RlOjpVU0VSX1BST0pFQ1RfQUNDRVNTX0RFTklFRDogaW50ZWdyYXRpb25AZ2Nsb3VkLWdvbGFuZy1maXJlc3RvcmUtdGVzdHMuaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20gZG9lcyBub3QgaGF2ZSBzZXJ2aWNldXNhZ2Uuc2VydmljZXMudXNlIGFjY2VzcyB0byBwcm9qZWN0IDY0MjA4MDkxODEwMS5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udG9ScGMzRXhjZXB0aW9uKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MTM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmZyYW1ld29yay5SZXF1ZXN0SGFuZGxlci5oYW5kbGUoUmVxdWVzdEhhbmRsZXIuamF2YTozMDIpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uT2JqZWN0c0RlbGVnYXRvci5yZXdyaXRlKE9iamVjdHNEZWxlZ2F0b3IuamF2YToxMjQpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLnJld3JpdGVyLkZyb250ZW5kUmV3cml0ZUFjdGlvbnMuZ2V0U291cmNlT2JqZWN0KEZyb250ZW5kUmV3cml0ZUFjdGlvbnMuamF2YToxODYpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLnJld3JpdGVyLlJld3JpdGVyLnJld3JpdGVPYmplY3QoUmV3cml0ZXIuamF2YTozNjIpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLnJld3JpdGVyLlJld3JpdGVyLnJld3JpdGVPYmplY3QoUmV3cml0ZXIuamF2YTozMzMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5SZXdyaXRlT2JqZWN0LnJld3JpdGVJbkZyb250ZW5kKFJld3JpdGVPYmplY3QuamF2YTozNDcpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5SZXdyaXRlT2JqZWN0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChSZXdyaXRlT2JqZWN0LmphdmE6MjQwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuUmV3cml0ZU9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoUmV3cml0ZU9iamVjdC5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmZyYW1ld29yay5SZXF1ZXN0SGFuZGxlci5oYW5kbGUoUmVxdWVzdEhhbmRsZXIuamF2YToyOTQpXG5cdC4uLiAxNCBtb3JlXG4sIGVycm9yUHJvdG9Db2RlPUZPUkJJRERFTiwgZXJyb3JQcm90b0RvbWFpbj1nZGF0YS5Db3JlRXJyb3JEb21haW4sIGZpbHRlcmVkTWVzc2FnZT1udWxsLCBsb2NhdGlvbj1udWxsLCBtZXNzYWdlPWludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIGRvZXMgbm90IGhhdmUgc2VydmljZXVzYWdlLnNlcnZpY2VzLnVzZSBhY2Nlc3MgdG8gcHJvamVjdCA2NDIwODA5MTgxMDEuLCB1bm5hbWVkQXJndW1lbnRzPVtdfSwgbG9jYXRpb249bnVsbCwgbWVzc2FnZT1pbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLiwgcmVhc29uPWZvcmJpZGRlbiwgcnBjQ29kZT00MDN9IGludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIGRvZXMgbm90IGhhdmUgc2VydmljZXVzYWdlLnNlcnZpY2VzLnVzZSBhY2Nlc3MgdG8gcHJvamVjdCA2NDIwODA5MTgxMDEuOiBjb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6VVNFUl9QUk9KRUNUX0FDQ0VTU19ERU5JRUQ6IGludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIGRvZXMgbm90IGhhdmUgc2VydmljZXVzYWdlLnNlcnZpY2VzLnVzZSBhY2Nlc3MgdG8gcHJvamVjdCA2NDIwODA5MTgxMDEuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRvUnBjM0V4Y2VwdGlvbihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjEzNSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6MzAyKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLk9iamVjdHNEZWxlZ2F0b3IucmV3cml0ZShPYmplY3RzRGVsZWdhdG9yLmphdmE6MTI0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5ScGNSZWNlaXZlci5sYW1iZGEkcHJvY2Vzc1JlcXVlc3RBc3luYyQ0KFJwY1JlY2VpdmVyLmphdmE6MjAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5Bc3luY0V4ZWN1dG9yLmxhbWJkYSRzdWJtaXQkMChBc3luY0V4ZWN1dG9yLmphdmE6MjcyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoQ29udGV4dFJ1bm5hYmxlLmphdmE6NTApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlJDEucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM5KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo3Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5FeGVjdXRvcnMkUnVubmFibGVBZGFwdGVyLmNhbGwoRXhlY3V0b3JzLmphdmE6NTExKVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5GdXR1cmVUYXNrLnJ1bihGdXR1cmVUYXNrLmphdmE6MjY2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IucnVuV29ya2VyKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjExNDkpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvciRXb3JrZXIucnVuKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjYyNClcblx0YXQgamF2YS5sYW5nLlRocmVhZC5ydW4oVGhyZWFkLmphdmE6NzQ4KVxuQ2F1c2VkIGJ5OiBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbjogaW50ZWdyYXRpb25AZ2Nsb3VkLWdvbGFuZy1maXJlc3RvcmUtdGVzdHMuaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20gZG9lcyBub3QgaGF2ZSBzZXJ2aWNldXNhZ2Uuc2VydmljZXMudXNlIGFjY2VzcyB0byBwcm9qZWN0IDY0MjA4MDkxODEwMS5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MjkwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5yZXdyaXRlci5Gcm9udGVuZFJld3JpdGVBY3Rpb25zLmdldFNvdXJjZU9iamVjdChGcm9udGVuZFJld3JpdGVBY3Rpb25zLmphdmE6MTg2KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5yZXdyaXRlci5SZXdyaXRlci5yZXdyaXRlT2JqZWN0KFJld3JpdGVyLmphdmE6MzYyKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5yZXdyaXRlci5SZXdyaXRlci5yZXdyaXRlT2JqZWN0KFJld3JpdGVyLmphdmE6MzMzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuUmV3cml0ZU9iamVjdC5yZXdyaXRlSW5Gcm9udGVuZChSZXdyaXRlT2JqZWN0LmphdmE6MzQ3KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuUmV3cml0ZU9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoUmV3cml0ZU9iamVjdC5qYXZhOjI0MClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5vYmplY3RzLlJld3JpdGVPYmplY3QuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKFJld3JpdGVPYmplY3QuamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHQuLi4gMTQgbW9yZVxuXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLkVycm9yQ29sbGVjdG9yLnRvRmF1bHQoRXJyb3JDb2xsZWN0b3IuamF2YTo1NClcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnJlc3QuYWRhcHRlci5yb3N5LlJvc3lFcnJvckNvbnZlcnRlci50b0ZhdWx0KFJvc3lFcnJvckNvbnZlcnRlci5qYXZhOjY3KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIucmVzdC5hZGFwdGVyLnJvc3kuUm9zeUhhbmRsZXIkMi5jYWxsKFJvc3lIYW5kbGVyLmphdmE6MjU4KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIucmVzdC5hZGFwdGVyLnJvc3kuUm9zeUhhbmRsZXIkMi5jYWxsKFJvc3lIYW5kbGVyLmphdmE6MjM4KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS51dGlsLkNhbGxhYmxlRnV0dXJlLnJ1bihDYWxsYWJsZUZ1dHVyZS5qYXZhOjYyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuRGlyZWN0RXhlY3V0b3IuZXhlY3V0ZShEaXJlY3RFeGVjdXRvci5qYXZhOjMwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuZXhlY3V0ZUxpc3RlbmVyKEFic3RyYWN0RnV0dXJlLmphdmE6MTE0Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmNvbXBsZXRlKEFic3RyYWN0RnV0dXJlLmphdmE6OTYzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuc2V0KEFic3RyYWN0RnV0dXJlLmphdmE6NzMxKVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS51dGlsLkNhbGxhYmxlRnV0dXJlLnJ1bihDYWxsYWJsZUZ1dHVyZS5qYXZhOjYyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuRGlyZWN0RXhlY3V0b3IuZXhlY3V0ZShEaXJlY3RFeGVjdXRvci5qYXZhOjMwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuZXhlY3V0ZUxpc3RlbmVyKEFic3RyYWN0RnV0dXJlLmphdmE6MTE0Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmNvbXBsZXRlKEFic3RyYWN0RnV0dXJlLmphdmE6OTYzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuc2V0KEFic3RyYWN0RnV0dXJlLmphdmE6NzMxKVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS51dGlsLkNhbGxhYmxlRnV0dXJlLnJ1bihDYWxsYWJsZUZ1dHVyZS5qYXZhOjYyKVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIudGhyZWFkLlRocmVhZFRyYWNrZXJzJFRocmVhZFRyYWNraW5nUnVubmFibGUucnVuKFRocmVhZFRyYWNrZXJzLmphdmE6MTI2KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JFRyYWNlQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChUcmFjZUNvbnRleHQuamF2YTo0NTUpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5zZXJ2ZXIuQ29tbW9uTW9kdWxlJENvbnRleHRDYXJyeWluZ0V4ZWN1dG9yU2VydmljZSQxLnJ1bkluQ29udGV4dChDb21tb25Nb2R1bGUuamF2YTo4NDYpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkVHJhY2VDb250ZXh0UnVubmFibGUkMS5ydW4oVHJhY2VDb250ZXh0LmphdmE6NDYyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JEFic3RyYWN0VHJhY2VDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihUcmFjZUNvbnRleHQuamF2YTozMjEpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkQWJzdHJhY3RUcmFjZUNvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoVHJhY2VDb250ZXh0LmphdmE6MzEzKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JFRyYWNlQ29udGV4dFJ1bm5hYmxlLnJ1bihUcmFjZUNvbnRleHQuamF2YTo0NTkpXG5cdGF0IGNvbS5nb29nbGUuZ3NlLmludGVybmFsLkRpc3BhdGNoUXVldWVJbXBsJFdvcmtlclRocmVhZC5ydW4oRGlzcGF0Y2hRdWV1ZUltcGwuamF2YTo0MDMpXG4ifV0sImNvZGUiOjQwMywibWVzc2FnZSI6ImludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIGRvZXMgbm90IGhhdmUgc2VydmljZXVzYWdlLnNlcnZpY2VzLnVzZSBhY2Nlc3MgdG8gcHJvamVjdCA2NDIwODA5MTgxMDEuIn19"
+ }
+ },
+ {
+ "ID": "d58b6d243a768de2",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/compose/compose?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "127"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "af35fdd27845b2cb356c7bc7026838b3/3889357421580894349;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/compose/compose?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJkZXN0aW5hdGlvbiI6eyJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMifSwic291cmNlT2JqZWN0cyI6W3sibmFtZSI6ImZvbyJ9LHsibmFtZSI6ImNvcHkifV19Cg=="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "742"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:13 GMT"
+ ],
+ "Etag": [
+ "CJeim/KW290CEAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051412000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrbf23:4359,/bns/yv/borg/yv/bns/blobstore2/bitpusher/164.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=KcysW5CYEJCAgwTX26HYCw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/164.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/164:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp0ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4StK4wESxgF5YTI5LmMuRW93QkpRWVNNdC1OVDFNYTJvWXBrbG1qcDlJMlZaUFZ5bFl5Z2Q3Nk5tQXlXbWR3WVBoMm00dGI3ZmZjOUlzcTU4MmVFcFBhNzhNWGpNZmIzaE9WTE9xRHpNTUFfTG9NQXVJZkdkMGgzSWowZ1dxdW5DS1g3Qk1mQlJxM001TUtMMXBHOWNyU0ZBT29lVkZpTDhpWlBsUDI0VjE5THdzZ0d1ZnVrQTFtVzVJcTJUUkVXeWQyNjRKZC1lS2UxdTAwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Uq0XH95_bvjP8WCkrA3pEAug5FEKD-6kMcOQN8UBPYQvggU93eZabBmIcjCp0AcvnZyHYRIt8a_d6oH8Y_Cdp1nTKhPvg"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9jb21wb3NlLzE1MzgwNTExMTM2Njg4ODciLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMvby9jb21wb3NlIiwibmFtZSI6ImNvbXBvc2UiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTExMzY2ODg4NyIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNToxMy42NjdaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjU6MTMuNjY3WiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI1OjEzLjY2N1oiLCJzaXplIjoiMTAiLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL28vY29tcG9zZT9nZW5lcmF0aW9uPTE1MzgwNTExMTM2Njg4ODcmYWx0PW1lZGlhIiwiY3JjMzJjIjoiL1JDT2dnPT0iLCJjb21wb25lbnRDb3VudCI6MiwiZXRhZyI6IkNKZWltL0tXMjkwQ0VBRT0ifQ=="
+ }
+ },
+ {
+ "ID": "82f9c7e73e26169f",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/compose/compose?alt=json\u0026prettyPrint=false\u0026userProject=dulcet-port-762",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "127"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "88656daa72f3a44c8d1036302cce6ab8/5407430256633472556;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/compose/compose?alt=json\u0026prettyPrint=false\u0026userProject=dulcet-port-762"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJkZXN0aW5hdGlvbiI6eyJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMifSwic291cmNlT2JqZWN0cyI6W3sibmFtZSI6ImZvbyJ9LHsibmFtZSI6ImNvcHkifV19Cg=="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "742"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:14 GMT"
+ ],
+ "Etag": [
+ "CLjYwPKW290CEAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051412000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrt187:4251,/bns/yv/borg/yv/bns/blobstore2/bitpusher/82.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=KcysW9CAN4OlgASf-Jco"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/82.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/82:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp0ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4StK4wESxgF5YTI5LmMuRW93QkpRWVNNdC1OVDFNYTJvWXBrbG1qcDlJMlZaUFZ5bFl5Z2Q3Nk5tQXlXbWR3WVBoMm00dGI3ZmZjOUlzcTU4MmVFcFBhNzhNWGpNZmIzaE9WTE9xRHpNTUFfTG9NQXVJZkdkMGgzSWowZ1dxdW5DS1g3Qk1mQlJxM001TUtMMXBHOWNyU0ZBT29lVkZpTDhpWlBsUDI0VjE5THdzZ0d1ZnVrQTFtVzVJcTJUUkVXeWQyNjRKZC1lS2UxdTAwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UoaT4viYqVfzBgidvfngr5I3dfnvBo_Q97aJ53xZZHVShVI9-ajQVC6y5nJ7D6UaetBaaqvIMuyyPtISMa-XjlL4Fk3qg"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9jb21wb3NlLzE1MzgwNTExMTQyODIwNDAiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMvby9jb21wb3NlIiwibmFtZSI6ImNvbXBvc2UiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTExNDI4MjA0MCIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNToxNC4yODFaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjU6MTQuMjgxWiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI1OjE0LjI4MVoiLCJzaXplIjoiMTAiLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL28vY29tcG9zZT9nZW5lcmF0aW9uPTE1MzgwNTExMTQyODIwNDAmYWx0PW1lZGlhIiwiY3JjMzJjIjoiL1JDT2dnPT0iLCJjb21wb25lbnRDb3VudCI6MiwiZXRhZyI6IkNMall3UEtXMjkwQ0VBRT0ifQ=="
+ }
+ },
+ {
+ "ID": "e6671b4e33cec5f9",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/compose/compose?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "127"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "57be10b174302620db439bb9e5bd529e/6997842160700623819;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/compose/compose?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJkZXN0aW5hdGlvbiI6eyJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMifSwic291cmNlT2JqZWN0cyI6W3sibmFtZSI6ImZvbyJ9LHsibmFtZSI6ImNvcHkifV19Cg=="
+ },
+ "Response": {
+ "StatusCode": 400,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Content-Length": [
+ "12159"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:14 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051412000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "471383502717"
+ ],
+ "X-Google-Backends": [
+ "vrch124:4064,/bns/yv/borg/yv/bns/blobstore2/bitpusher/203.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=KsysW9-vGJC0ggSujK6wDw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/203.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/203:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CP3elYXcDRoCGAYoATpCChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGM6ropHgHCIVMTE3MjM4MDU4ODYxOTM3NTE5MTQ0MOArMOErSp8BEoIBeWEyOS5jLkVsb2xCcldWbUZlX1AxVDdUOHVpTXdFMHBZUjdTc2NVMDBFdEZkc2tSenBQY0NLWkhUeEZaYXI0Q25tZmR6bXFRLTNVV0kzOF9wdEx5VTZ2Z1Q3dlRBeW42Z3g4dUcyd0szSHIzaTZrV1JBZkozc1pNMGQ1allkNHpWQTAEOhZOT1RfQV9QRVJTSVNURU5UX1RPS0VO"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Upload-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UqACTq5n8sFNIiVA2h8aH3Vj_ZswPTuWjjESekvJFvdlKomAhXobltpqY4fsj2szRDB9frX-PjOv9hytKgpgnK0_P6CZg"
+ ]
+ },
+ "Body": "eyJlcnJvciI6eyJlcnJvcnMiOlt7ImRvbWFpbiI6Imdsb2JhbCIsInJlYXNvbiI6InJlcXVpcmVkIiwibWVzc2FnZSI6IkJ1Y2tldCBpcyByZXF1ZXN0ZXIgcGF5cyBidWNrZXQgYnV0IG5vIHVzZXIgcHJvamVjdCBwcm92aWRlZC4iLCJkZWJ1Z0luZm8iOiJjb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6VVNFUl9QUk9KRUNUX01JU1NJTkc6IEJ1Y2tldCBpcyBSZXF1ZXN0ZXIgUGF5cyBidWNrZXQgYnV0IG5vIGJpbGxpbmcgcHJvamVjdCBpZCBwcm92aWRlZCBmb3Igbm9uLW93bmVyLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5Db21wb3NlT2JqZWN0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChDb21wb3NlT2JqZWN0LmphdmE6MTk1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuQ29tcG9zZU9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoQ29tcG9zZU9iamVjdC5qYXZhOjQ1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmZyYW1ld29yay5SZXF1ZXN0SGFuZGxlci5oYW5kbGUoUmVxdWVzdEhhbmRsZXIuamF2YToyOTQpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uT2JqZWN0c0RlbGVnYXRvci5jb21wb3NlKE9iamVjdHNEZWxlZ2F0b3IuamF2YToxMjkpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBCdWNrZXQgaXMgUmVxdWVzdGVyIFBheXMgYnVja2V0IGJ1dCBubyBiaWxsaW5nIHByb2plY3QgaWQgcHJvdmlkZWQgZm9yIG5vbi1vd25lci5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MjkwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAxKVxuXHQuLi4gMTcgbW9yZVxuXG5jb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS5GYXVsdDogSW1tdXRhYmxlRXJyb3JEZWZpbml0aW9ue2Jhc2U9UkVRVUlSRUQsIGNhdGVnb3J5PVVTRVJfRVJST1IsIGNhdXNlPW51bGwsIGRlYnVnSW5mbz1jb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6VVNFUl9QUk9KRUNUX01JU1NJTkc6IEJ1Y2tldCBpcyBSZXF1ZXN0ZXIgUGF5cyBidWNrZXQgYnV0IG5vIGJpbGxpbmcgcHJvamVjdCBpZCBwcm92aWRlZCBmb3Igbm9uLW93bmVyLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5Db21wb3NlT2JqZWN0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChDb21wb3NlT2JqZWN0LmphdmE6MTk1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuQ29tcG9zZU9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoQ29tcG9zZU9iamVjdC5qYXZhOjQ1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmZyYW1ld29yay5SZXF1ZXN0SGFuZGxlci5oYW5kbGUoUmVxdWVzdEhhbmRsZXIuamF2YToyOTQpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uT2JqZWN0c0RlbGVnYXRvci5jb21wb3NlKE9iamVjdHNEZWxlZ2F0b3IuamF2YToxMjkpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBCdWNrZXQgaXMgUmVxdWVzdGVyIFBheXMgYnVja2V0IGJ1dCBubyBiaWxsaW5nIHByb2plY3QgaWQgcHJvdmlkZWQgZm9yIG5vbi1vd25lci5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MjkwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAxKVxuXHQuLi4gMTcgbW9yZVxuLCBkb21haW49Z2xvYmFsLCBleHRlbmRlZEhlbHA9bnVsbCwgaHR0cEhlYWRlcnM9e30sIGh0dHBTdGF0dXM9YmFkUmVxdWVzdCwgaW50ZXJuYWxSZWFzb249UmVhc29ue2FyZ3VtZW50cz17fSwgY2F1c2U9bnVsbCwgY29kZT1nZGF0YS5Db3JlRXJyb3JEb21haW4uUkVRVUlSRUQsIGNyZWF0ZWRCeUJhY2tlbmQ9dHJ1ZSwgZGVidWdNZXNzYWdlPWNvbS5nb29nbGUubmV0LnJwYzMuUnBjRXhjZXB0aW9uOiBjbG91ZC5iaWdzdG9yZS5SZXNwb25zZUNvZGUuRXJyb3JDb2RlOjpVU0VSX1BST0pFQ1RfTUlTU0lORzogQnVja2V0IGlzIFJlcXVlc3RlciBQYXlzIGJ1Y2tldCBidXQgbm8gYmlsbGluZyBwcm9qZWN0IGlkIHByb3ZpZGVkIGZvciBub24tb3duZXIuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRvUnBjM0V4Y2VwdGlvbihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjEzNSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5vYmplY3RzLkNvbXBvc2VPYmplY3QuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKENvbXBvc2VPYmplY3QuamF2YToxOTUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5Db21wb3NlT2JqZWN0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChDb21wb3NlT2JqZWN0LmphdmE6NDUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5PYmplY3RzRGVsZWdhdG9yLmNvbXBvc2UoT2JqZWN0c0RlbGVnYXRvci5qYXZhOjEyOSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uUnBjUmVjZWl2ZXIubGFtYmRhJHByb2Nlc3NSZXF1ZXN0QXN5bmMkNChScGNSZWNlaXZlci5qYXZhOjIwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uQXN5bmNFeGVjdXRvci5sYW1iZGEkc3VibWl0JDAoQXN5bmNFeGVjdXRvci5qYXZhOjI3Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KENvbnRleHRSdW5uYWJsZS5qYXZhOjUwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZSQxLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozOSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NzIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozNilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRXhlY3V0b3JzJFJ1bm5hYmxlQWRhcHRlci5jYWxsKEV4ZWN1dG9ycy5qYXZhOjUxMSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRnV0dXJlVGFzay5ydW4oRnV0dXJlVGFzay5qYXZhOjI2Nilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yLnJ1bldvcmtlcihUaHJlYWRQb29sRXhlY3V0b3IuamF2YToxMTQ5KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IkV29ya2VyLnJ1bihUaHJlYWRQb29sRXhlY3V0b3IuamF2YTo2MjQpXG5cdGF0IGphdmEubGFuZy5UaHJlYWQucnVuKFRocmVhZC5qYXZhOjc0OClcbkNhdXNlZCBieTogY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb246IEJ1Y2tldCBpcyBSZXF1ZXN0ZXIgUGF5cyBidWNrZXQgYnV0IG5vIGJpbGxpbmcgcHJvamVjdCBpZCBwcm92aWRlZCBmb3Igbm9uLW93bmVyLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxNyBtb3JlXG4sIGVycm9yUHJvdG9Db2RlPVJFUVVJUkVELCBlcnJvclByb3RvRG9tYWluPWdkYXRhLkNvcmVFcnJvckRvbWFpbiwgZmlsdGVyZWRNZXNzYWdlPW51bGwsIGxvY2F0aW9uPW51bGwsIG1lc3NhZ2U9QnVja2V0IGlzIHJlcXVlc3RlciBwYXlzIGJ1Y2tldCBidXQgbm8gdXNlciBwcm9qZWN0IHByb3ZpZGVkLiwgdW5uYW1lZEFyZ3VtZW50cz1bXX0sIGxvY2F0aW9uPW51bGwsIG1lc3NhZ2U9QnVja2V0IGlzIHJlcXVlc3RlciBwYXlzIGJ1Y2tldCBidXQgbm8gdXNlciBwcm9qZWN0IHByb3ZpZGVkLiwgcmVhc29uPXJlcXVpcmVkLCBycGNDb2RlPTQwMH0gQnVja2V0IGlzIHJlcXVlc3RlciBwYXlzIGJ1Y2tldCBidXQgbm8gdXNlciBwcm9qZWN0IHByb3ZpZGVkLjogY29tLmdvb2dsZS5uZXQucnBjMy5ScGNFeGNlcHRpb246IGNsb3VkLmJpZ3N0b3JlLlJlc3BvbnNlQ29kZS5FcnJvckNvZGU6OlVTRVJfUFJPSkVDVF9NSVNTSU5HOiBCdWNrZXQgaXMgUmVxdWVzdGVyIFBheXMgYnVja2V0IGJ1dCBubyBiaWxsaW5nIHByb2plY3QgaWQgcHJvdmlkZWQgZm9yIG5vbi1vd25lci5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udG9ScGMzRXhjZXB0aW9uKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MTM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuQ29tcG9zZU9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoQ29tcG9zZU9iamVjdC5qYXZhOjE5NSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5vYmplY3RzLkNvbXBvc2VPYmplY3QuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKENvbXBvc2VPYmplY3QuamF2YTo0NSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLk9iamVjdHNEZWxlZ2F0b3IuY29tcG9zZShPYmplY3RzRGVsZWdhdG9yLmphdmE6MTI5KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5ScGNSZWNlaXZlci5sYW1iZGEkcHJvY2Vzc1JlcXVlc3RBc3luYyQ0KFJwY1JlY2VpdmVyLmphdmE6MjAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5Bc3luY0V4ZWN1dG9yLmxhbWJkYSRzdWJtaXQkMChBc3luY0V4ZWN1dG9yLmphdmE6MjcyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoQ29udGV4dFJ1bm5hYmxlLmphdmE6NTApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlJDEucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM5KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo3Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5FeGVjdXRvcnMkUnVubmFibGVBZGFwdGVyLmNhbGwoRXhlY3V0b3JzLmphdmE6NTExKVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5GdXR1cmVUYXNrLnJ1bihGdXR1cmVUYXNrLmphdmE6MjY2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IucnVuV29ya2VyKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjExNDkpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvciRXb3JrZXIucnVuKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjYyNClcblx0YXQgamF2YS5sYW5nLlRocmVhZC5ydW4oVGhyZWFkLmphdmE6NzQ4KVxuQ2F1c2VkIGJ5OiBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbjogQnVja2V0IGlzIFJlcXVlc3RlciBQYXlzIGJ1Y2tldCBidXQgbm8gYmlsbGluZyBwcm9qZWN0IGlkIHByb3ZpZGVkIGZvciBub24tb3duZXIuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93T25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjI5MClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMSlcblx0Li4uIDE3IG1vcmVcblxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS5FcnJvckNvbGxlY3Rvci50b0ZhdWx0KEVycm9yQ29sbGVjdG9yLmphdmE6NTQpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5yZXN0LmFkYXB0ZXIucm9zeS5Sb3N5RXJyb3JDb252ZXJ0ZXIudG9GYXVsdChSb3N5RXJyb3JDb252ZXJ0ZXIuamF2YTo2Nylcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnJlc3QuYWRhcHRlci5yb3N5LlJvc3lIYW5kbGVyJDIuY2FsbChSb3N5SGFuZGxlci5qYXZhOjI1OClcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnJlc3QuYWRhcHRlci5yb3N5LlJvc3lIYW5kbGVyJDIuY2FsbChSb3N5SGFuZGxlci5qYXZhOjIzOClcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkRpcmVjdEV4ZWN1dG9yLmV4ZWN1dGUoRGlyZWN0RXhlY3V0b3IuamF2YTozMClcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmV4ZWN1dGVMaXN0ZW5lcihBYnN0cmFjdEZ1dHVyZS5qYXZhOjExNDMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5jb21wbGV0ZShBYnN0cmFjdEZ1dHVyZS5qYXZhOjk2Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLnNldChBYnN0cmFjdEZ1dHVyZS5qYXZhOjczMSlcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkRpcmVjdEV4ZWN1dG9yLmV4ZWN1dGUoRGlyZWN0RXhlY3V0b3IuamF2YTozMClcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmV4ZWN1dGVMaXN0ZW5lcihBYnN0cmFjdEZ1dHVyZS5qYXZhOjExNDMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5jb21wbGV0ZShBYnN0cmFjdEZ1dHVyZS5qYXZhOjk2Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLnNldChBYnN0cmFjdEZ1dHVyZS5qYXZhOjczMSlcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnRocmVhZC5UaHJlYWRUcmFja2VycyRUaHJlYWRUcmFja2luZ1J1bm5hYmxlLnJ1bihUaHJlYWRUcmFja2Vycy5qYXZhOjEyNilcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRUcmFjZUNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoVHJhY2VDb250ZXh0LmphdmE6NDU1KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuc2VydmVyLkNvbW1vbk1vZHVsZSRDb250ZXh0Q2FycnlpbmdFeGVjdXRvclNlcnZpY2UkMS5ydW5JbkNvbnRleHQoQ29tbW9uTW9kdWxlLmphdmE6ODQ2KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JFRyYWNlQ29udGV4dFJ1bm5hYmxlJDEucnVuKFRyYWNlQ29udGV4dC5qYXZhOjQ2Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRBYnN0cmFjdFRyYWNlQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoVHJhY2VDb250ZXh0LmphdmE6MzIxKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JEFic3RyYWN0VHJhY2VDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KFRyYWNlQ29udGV4dC5qYXZhOjMxMylcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRUcmFjZUNvbnRleHRSdW5uYWJsZS5ydW4oVHJhY2VDb250ZXh0LmphdmE6NDU5KVxuXHRhdCBjb20uZ29vZ2xlLmdzZS5pbnRlcm5hbC5EaXNwYXRjaFF1ZXVlSW1wbCRXb3JrZXJUaHJlYWQucnVuKERpc3BhdGNoUXVldWVJbXBsLmphdmE6NDAzKVxuIn1dLCJjb2RlIjo0MDAsIm1lc3NhZ2UiOiJCdWNrZXQgaXMgcmVxdWVzdGVyIHBheXMgYnVja2V0IGJ1dCBubyB1c2VyIHByb2plY3QgcHJvdmlkZWQuIn19"
+ }
+ },
+ {
+ "ID": "d5dec65b14d1e564",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/compose/compose?alt=json\u0026prettyPrint=false\u0026userProject=gcloud-golang-firestore-tests",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "127"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "e3b2ca3ee9799fdbcd67edea72cb2b13/8588254064751063401;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/compose/compose?alt=json\u0026prettyPrint=false\u0026userProject=gcloud-golang-firestore-tests"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJkZXN0aW5hdGlvbiI6eyJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMifSwic291cmNlT2JqZWN0cyI6W3sibmFtZSI6ImZvbyJ9LHsibmFtZSI6ImNvcHkifV19Cg=="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "742"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:14 GMT"
+ ],
+ "Etag": [
+ "CPPa3fKW290CEAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051412000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "471383502717"
+ ],
+ "X-Google-Backends": [
+ "vray3:4145,/bns/yr/borg/yr/bns/blobstore2/bitpusher/1.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=KsysW-D8JYeTkATnw5OYAQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/1.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/1:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CP3elYXcDRoCGAYoATpCChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGM6ropHgHCIVMTE3MjM4MDU4ODYxOTM3NTE5MTQ0MOArMOErSp8BEoIBeWEyOS5jLkVsb2xCcldWbUZlX1AxVDdUOHVpTXdFMHBZUjdTc2NVMDBFdEZkc2tSenBQY0NLWkhUeEZaYXI0Q25tZmR6bXFRLTNVV0kzOF9wdEx5VTZ2Z1Q3dlRBeW42Z3g4dUcyd0szSHIzaTZrV1JBZkozc1pNMGQ1allkNHpWQTAEOhZOT1RfQV9QRVJTSVNURU5UX1RPS0VO"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Uqw7poK3DL_KB2b-NGyg3S_etaxdZOQT8tM1CB3Njtjp5I5cTq4IkFxXrlPXslCK4wfycAl4MApkddYSmiVeRaX2IXCvQ"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9jb21wb3NlLzE1MzgwNTExMTQ3NTc0OTEiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMvby9jb21wb3NlIiwibmFtZSI6ImNvbXBvc2UiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTExNDc1NzQ5MSIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNToxNC43NTdaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjU6MTQuNzU3WiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI1OjE0Ljc1N1oiLCJzaXplIjoiMTAiLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL28vY29tcG9zZT9nZW5lcmF0aW9uPTE1MzgwNTExMTQ3NTc0OTEmYWx0PW1lZGlhIiwiY3JjMzJjIjoiL1JDT2dnPT0iLCJjb21wb25lbnRDb3VudCI6MiwiZXRhZyI6IkNQUGEzZktXMjkwQ0VBRT0ifQ=="
+ }
+ },
+ {
+ "ID": "24c660b93668472d",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/compose/compose?alt=json\u0026prettyPrint=false\u0026userProject=veener-jba",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "127"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "be05ebeb28473769bdebf0265c356dd1/10178665964523312648;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/compose/compose?alt=json\u0026prettyPrint=false\u0026userProject=veener-jba"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJkZXN0aW5hdGlvbiI6eyJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMifSwic291cmNlT2JqZWN0cyI6W3sibmFtZSI6ImZvbyJ9LHsibmFtZSI6ImNvcHkifV19Cg=="
+ },
+ "Response": {
+ "StatusCode": 403,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Content-Length": [
+ "13015"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:15 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051412000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "471383502717"
+ ],
+ "X-Google-Backends": [
+ "vrmm26:4177,/bns/yv/borg/yv/bns/blobstore2/bitpusher/113.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=KsysW8vBNsLygwT0jIrYCA"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/113.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/113:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CP3elYXcDRoCGAYoATpCChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGM6ropHgHCIVMTE3MjM4MDU4ODYxOTM3NTE5MTQ0MOArMOErSp8BEoIBeWEyOS5jLkVsb2xCcldWbUZlX1AxVDdUOHVpTXdFMHBZUjdTc2NVMDBFdEZkc2tSenBQY0NLWkhUeEZaYXI0Q25tZmR6bXFRLTNVV0kzOF9wdEx5VTZ2Z1Q3dlRBeW42Z3g4dUcyd0szSHIzaTZrV1JBZkozc1pNMGQ1allkNHpWQTAEOhZOT1RfQV9QRVJTSVNURU5UX1RPS0VO"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Upload-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UoEj3IamdTcELhnX6VeqX7ghzI3eYDEPV8bpculXR797zpQlEOtsuXWVEwCdLTnbT5jN26sovoxVnQ3kVIP4zvetR60xg"
+ ]
+ },
+ "Body": "eyJlcnJvciI6eyJlcnJvcnMiOlt7ImRvbWFpbiI6Imdsb2JhbCIsInJlYXNvbiI6ImZvcmJpZGRlbiIsIm1lc3NhZ2UiOiJpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLiIsImRlYnVnSW5mbyI6ImNvbS5nb29nbGUubmV0LnJwYzMuUnBjRXhjZXB0aW9uOiBjbG91ZC5iaWdzdG9yZS5SZXNwb25zZUNvZGUuRXJyb3JDb2RlOjpVU0VSX1BST0pFQ1RfQUNDRVNTX0RFTklFRDogaW50ZWdyYXRpb25AZ2Nsb3VkLWdvbGFuZy1maXJlc3RvcmUtdGVzdHMuaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20gZG9lcyBub3QgaGF2ZSBzZXJ2aWNldXNhZ2Uuc2VydmljZXMudXNlIGFjY2VzcyB0byBwcm9qZWN0IDY0MjA4MDkxODEwMS5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udG9ScGMzRXhjZXB0aW9uKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MTM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuQ29tcG9zZU9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoQ29tcG9zZU9iamVjdC5qYXZhOjE5NSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5vYmplY3RzLkNvbXBvc2VPYmplY3QuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKENvbXBvc2VPYmplY3QuamF2YTo0NSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLk9iamVjdHNEZWxlZ2F0b3IuY29tcG9zZShPYmplY3RzRGVsZWdhdG9yLmphdmE6MTI5KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5ScGNSZWNlaXZlci5sYW1iZGEkcHJvY2Vzc1JlcXVlc3RBc3luYyQ0KFJwY1JlY2VpdmVyLmphdmE6MjAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5Bc3luY0V4ZWN1dG9yLmxhbWJkYSRzdWJtaXQkMChBc3luY0V4ZWN1dG9yLmphdmE6MjcyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoQ29udGV4dFJ1bm5hYmxlLmphdmE6NTApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlJDEucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM5KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo3Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5FeGVjdXRvcnMkUnVubmFibGVBZGFwdGVyLmNhbGwoRXhlY3V0b3JzLmphdmE6NTExKVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5GdXR1cmVUYXNrLnJ1bihGdXR1cmVUYXNrLmphdmE6MjY2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IucnVuV29ya2VyKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjExNDkpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvciRXb3JrZXIucnVuKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjYyNClcblx0YXQgamF2YS5sYW5nLlRocmVhZC5ydW4oVGhyZWFkLmphdmE6NzQ4KVxuQ2F1c2VkIGJ5OiBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbjogaW50ZWdyYXRpb25AZ2Nsb3VkLWdvbGFuZy1maXJlc3RvcmUtdGVzdHMuaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20gZG9lcyBub3QgaGF2ZSBzZXJ2aWNldXNhZ2Uuc2VydmljZXMudXNlIGFjY2VzcyB0byBwcm9qZWN0IDY0MjA4MDkxODEwMS5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MjkwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAxKVxuXHQuLi4gMTcgbW9yZVxuXG5jb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS5GYXVsdDogSW1tdXRhYmxlRXJyb3JEZWZpbml0aW9ue2Jhc2U9Rk9SQklEREVOLCBjYXRlZ29yeT1VU0VSX0VSUk9SLCBjYXVzZT1udWxsLCBkZWJ1Z0luZm89Y29tLmdvb2dsZS5uZXQucnBjMy5ScGNFeGNlcHRpb246IGNsb3VkLmJpZ3N0b3JlLlJlc3BvbnNlQ29kZS5FcnJvckNvZGU6OlVTRVJfUFJPSkVDVF9BQ0NFU1NfREVOSUVEOiBpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5Db21wb3NlT2JqZWN0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChDb21wb3NlT2JqZWN0LmphdmE6MTk1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuQ29tcG9zZU9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoQ29tcG9zZU9iamVjdC5qYXZhOjQ1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmZyYW1ld29yay5SZXF1ZXN0SGFuZGxlci5oYW5kbGUoUmVxdWVzdEhhbmRsZXIuamF2YToyOTQpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uT2JqZWN0c0RlbGVnYXRvci5jb21wb3NlKE9iamVjdHNEZWxlZ2F0b3IuamF2YToxMjkpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxNyBtb3JlXG4sIGRvbWFpbj1nbG9iYWwsIGV4dGVuZGVkSGVscD1udWxsLCBodHRwSGVhZGVycz17fSwgaHR0cFN0YXR1cz1mb3JiaWRkZW4sIGludGVybmFsUmVhc29uPVJlYXNvbnthcmd1bWVudHM9e30sIGNhdXNlPW51bGwsIGNvZGU9Z2RhdGEuQ29yZUVycm9yRG9tYWluLkZPUkJJRERFTiwgY3JlYXRlZEJ5QmFja2VuZD10cnVlLCBkZWJ1Z01lc3NhZ2U9Y29tLmdvb2dsZS5uZXQucnBjMy5ScGNFeGNlcHRpb246IGNsb3VkLmJpZ3N0b3JlLlJlc3BvbnNlQ29kZS5FcnJvckNvZGU6OlVTRVJfUFJPSkVDVF9BQ0NFU1NfREVOSUVEOiBpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5Db21wb3NlT2JqZWN0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChDb21wb3NlT2JqZWN0LmphdmE6MTk1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuQ29tcG9zZU9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoQ29tcG9zZU9iamVjdC5qYXZhOjQ1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmZyYW1ld29yay5SZXF1ZXN0SGFuZGxlci5oYW5kbGUoUmVxdWVzdEhhbmRsZXIuamF2YToyOTQpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uT2JqZWN0c0RlbGVnYXRvci5jb21wb3NlKE9iamVjdHNEZWxlZ2F0b3IuamF2YToxMjkpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxNyBtb3JlXG4sIGVycm9yUHJvdG9Db2RlPUZPUkJJRERFTiwgZXJyb3JQcm90b0RvbWFpbj1nZGF0YS5Db3JlRXJyb3JEb21haW4sIGZpbHRlcmVkTWVzc2FnZT1udWxsLCBsb2NhdGlvbj1udWxsLCBtZXNzYWdlPWludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIGRvZXMgbm90IGhhdmUgc2VydmljZXVzYWdlLnNlcnZpY2VzLnVzZSBhY2Nlc3MgdG8gcHJvamVjdCA2NDIwODA5MTgxMDEuLCB1bm5hbWVkQXJndW1lbnRzPVtdfSwgbG9jYXRpb249bnVsbCwgbWVzc2FnZT1pbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLiwgcmVhc29uPWZvcmJpZGRlbiwgcnBjQ29kZT00MDN9IGludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIGRvZXMgbm90IGhhdmUgc2VydmljZXVzYWdlLnNlcnZpY2VzLnVzZSBhY2Nlc3MgdG8gcHJvamVjdCA2NDIwODA5MTgxMDEuOiBjb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6VVNFUl9QUk9KRUNUX0FDQ0VTU19ERU5JRUQ6IGludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIGRvZXMgbm90IGhhdmUgc2VydmljZXVzYWdlLnNlcnZpY2VzLnVzZSBhY2Nlc3MgdG8gcHJvamVjdCA2NDIwODA5MTgxMDEuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRvUnBjM0V4Y2VwdGlvbihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjEzNSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5vYmplY3RzLkNvbXBvc2VPYmplY3QuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKENvbXBvc2VPYmplY3QuamF2YToxOTUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5Db21wb3NlT2JqZWN0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChDb21wb3NlT2JqZWN0LmphdmE6NDUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5PYmplY3RzRGVsZWdhdG9yLmNvbXBvc2UoT2JqZWN0c0RlbGVnYXRvci5qYXZhOjEyOSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uUnBjUmVjZWl2ZXIubGFtYmRhJHByb2Nlc3NSZXF1ZXN0QXN5bmMkNChScGNSZWNlaXZlci5qYXZhOjIwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uQXN5bmNFeGVjdXRvci5sYW1iZGEkc3VibWl0JDAoQXN5bmNFeGVjdXRvci5qYXZhOjI3Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KENvbnRleHRSdW5uYWJsZS5qYXZhOjUwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZSQxLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozOSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NzIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozNilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRXhlY3V0b3JzJFJ1bm5hYmxlQWRhcHRlci5jYWxsKEV4ZWN1dG9ycy5qYXZhOjUxMSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRnV0dXJlVGFzay5ydW4oRnV0dXJlVGFzay5qYXZhOjI2Nilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yLnJ1bldvcmtlcihUaHJlYWRQb29sRXhlY3V0b3IuamF2YToxMTQ5KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IkV29ya2VyLnJ1bihUaHJlYWRQb29sRXhlY3V0b3IuamF2YTo2MjQpXG5cdGF0IGphdmEubGFuZy5UaHJlYWQucnVuKFRocmVhZC5qYXZhOjc0OClcbkNhdXNlZCBieTogY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb246IGludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIGRvZXMgbm90IGhhdmUgc2VydmljZXVzYWdlLnNlcnZpY2VzLnVzZSBhY2Nlc3MgdG8gcHJvamVjdCA2NDIwODA5MTgxMDEuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93T25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjI5MClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMSlcblx0Li4uIDE3IG1vcmVcblxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS5FcnJvckNvbGxlY3Rvci50b0ZhdWx0KEVycm9yQ29sbGVjdG9yLmphdmE6NTQpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5yZXN0LmFkYXB0ZXIucm9zeS5Sb3N5RXJyb3JDb252ZXJ0ZXIudG9GYXVsdChSb3N5RXJyb3JDb252ZXJ0ZXIuamF2YTo2Nylcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnJlc3QuYWRhcHRlci5yb3N5LlJvc3lIYW5kbGVyJDIuY2FsbChSb3N5SGFuZGxlci5qYXZhOjI1OClcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnJlc3QuYWRhcHRlci5yb3N5LlJvc3lIYW5kbGVyJDIuY2FsbChSb3N5SGFuZGxlci5qYXZhOjIzOClcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkRpcmVjdEV4ZWN1dG9yLmV4ZWN1dGUoRGlyZWN0RXhlY3V0b3IuamF2YTozMClcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmV4ZWN1dGVMaXN0ZW5lcihBYnN0cmFjdEZ1dHVyZS5qYXZhOjExNDMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5jb21wbGV0ZShBYnN0cmFjdEZ1dHVyZS5qYXZhOjk2Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLnNldChBYnN0cmFjdEZ1dHVyZS5qYXZhOjczMSlcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkRpcmVjdEV4ZWN1dG9yLmV4ZWN1dGUoRGlyZWN0RXhlY3V0b3IuamF2YTozMClcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmV4ZWN1dGVMaXN0ZW5lcihBYnN0cmFjdEZ1dHVyZS5qYXZhOjExNDMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5jb21wbGV0ZShBYnN0cmFjdEZ1dHVyZS5qYXZhOjk2Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLnNldChBYnN0cmFjdEZ1dHVyZS5qYXZhOjczMSlcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnRocmVhZC5UaHJlYWRUcmFja2VycyRUaHJlYWRUcmFja2luZ1J1bm5hYmxlLnJ1bihUaHJlYWRUcmFja2Vycy5qYXZhOjEyNilcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRUcmFjZUNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoVHJhY2VDb250ZXh0LmphdmE6NDU1KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuc2VydmVyLkNvbW1vbk1vZHVsZSRDb250ZXh0Q2FycnlpbmdFeGVjdXRvclNlcnZpY2UkMS5ydW5JbkNvbnRleHQoQ29tbW9uTW9kdWxlLmphdmE6ODQ2KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JFRyYWNlQ29udGV4dFJ1bm5hYmxlJDEucnVuKFRyYWNlQ29udGV4dC5qYXZhOjQ2Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRBYnN0cmFjdFRyYWNlQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoVHJhY2VDb250ZXh0LmphdmE6MzIxKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JEFic3RyYWN0VHJhY2VDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KFRyYWNlQ29udGV4dC5qYXZhOjMxMylcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRUcmFjZUNvbnRleHRSdW5uYWJsZS5ydW4oVHJhY2VDb250ZXh0LmphdmE6NDU5KVxuXHRhdCBjb20uZ29vZ2xlLmdzZS5pbnRlcm5hbC5EaXNwYXRjaFF1ZXVlSW1wbCRXb3JrZXJUaHJlYWQucnVuKERpc3BhdGNoUXVldWVJbXBsLmphdmE6NDAzKVxuIn1dLCJjb2RlIjo0MDMsIm1lc3NhZ2UiOiJpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLiJ9fQ=="
+ }
+ },
+ {
+ "ID": "8258f8e2dc12967c",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Type": [
+ "multipart/related; boundary=a689dc23618e3f3e66aa43d96c5419cf130f3b626c9fa0e4d4c51e49c721"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "0df3a8a5e79adbc213ad94e8657ffc2f/11009759428470810967;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "LS1hNjg5ZGMyMzYxOGUzZjNlNjZhYTQzZDk2YzU0MTljZjEzMGYzYjYyNmM5ZmEwZTRkNGM1MWU0OWM3MjENCkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vanNvbg0KDQp7ImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMyIsIm5hbWUiOiJmb28ifQoNCi0tYTY4OWRjMjM2MThlM2YzZTY2YWE0M2Q5NmM1NDE5Y2YxMzBmM2I2MjZjOWZhMGU0ZDRjNTFlNDljNzIxDQpDb250ZW50LVR5cGU6IHRleHQvcGxhaW47IGNoYXJzZXQ9dXRmLTgNCg0KaGVsbG8NCi0tYTY4OWRjMjM2MThlM2YzZTY2YWE0M2Q5NmM1NDE5Y2YxMzBmM2I2MjZjOWZhMGU0ZDRjNTFlNDljNzIxLS0NCg=="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3205"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:15 GMT"
+ ],
+ "Etag": [
+ "CKeVh/OW290CEAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051388000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrnk23:4310,/bns/yr/borg/yr/bns/blobstore2/bitpusher/0.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=K8ysW_iHCMSxkATZ74bIAQ"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/0.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/0:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWVNNdC1OVDFNYTJvWXBrbG1qcDlJMlZaUFZ5bFl5Z2Q3Nk5tQXlXbWR3WVBoMm00dGI3ZmZjOUlzcTU4MmVFcFBhNzhNWGpNZmIzaE9WTE9xRHpNTUFfTG9NQXVJZkdkMGgzSWowZ1dxdW5DS1g3Qk1mQlJxM001TUtMMXBHOWNyU0ZBT29lVkZpTDhpWlBsUDI0VjE5THdzZ0d1ZnVrQTFtVzVJcTJUUkVXeWQyNjRKZC1lS2UxdTAwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_single_post_uploads"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UrK68i4wgUfs8FAKX_CTgQ_yQHjxuVG81WoqFKLDV_C_STun4Y3x3F7rBPIWnouByRLYZyIwwnJPGmZe5PDKq0vps65DA"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9mb28vMTUzODA1MTExNTQzNjcxMSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9vL2ZvbyIsIm5hbWUiOiJmb28iLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTExNTQzNjcxMSIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOCIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNToxNS40MzZaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjU6MTUuNDM2WiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI1OjE1LjQzNloiLCJzaXplIjoiNSIsIm1kNUhhc2giOiJYVUZBS3J4TEtuYTVjWjJSRUJmRmtnPT0iLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL28vZm9vP2dlbmVyYXRpb249MTUzODA1MTExNTQzNjcxMSZhbHQ9bWVkaWEiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9mb28vMTUzODA1MTExNTQzNjcxMS9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9vL2Zvby9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJvYmplY3QiOiJmb28iLCJnZW5lcmF0aW9uIjoiMTUzODA1MTExNTQzNjcxMSIsImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6Im93bmVycyJ9LCJldGFnIjoiQ0tlVmgvT1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL2Zvby8xNTM4MDUxMTE1NDM2NzExL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9vL2Zvby9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzIiwib2JqZWN0IjoiZm9vIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTExMTU0MzY3MTEiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0tlVmgvT1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL2Zvby8xNTM4MDUxMTE1NDM2NzExL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9vL2Zvby9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzIiwib2JqZWN0IjoiZm9vIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTExMTU0MzY3MTEiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNLZVZoL09XMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9mb28vMTUzODA1MTExNTQzNjcxMS91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL28vZm9vL2FjbC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzIiwib2JqZWN0IjoiZm9vIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTExMTU0MzY3MTEiLCJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwicm9sZSI6Ik9XTkVSIiwiZW1haWwiOiIzNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImV0YWciOiJDS2VWaC9PVzI5MENFQUU9In1dLCJvd25lciI6eyJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIn0sImNyYzMyYyI6Im1uRzdUQT09IiwiZXRhZyI6IkNLZVZoL09XMjkwQ0VBRT0ifQ=="
+ }
+ },
+ {
+ "ID": "3610413c1a01c96c",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/foo?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "51d5a9571886ff76af7257bedf96bf1b/11768796397892009126;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/foo?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 204,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "0"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:15 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051388000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrhr16:4228,/bns/yv/borg/yv/bns/blobstore2/bitpusher/58.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=K8ysW-zxIZOOgQTGxbr4Cg"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/58.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/58:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWVNNdC1OVDFNYTJvWXBrbG1qcDlJMlZaUFZ5bFl5Z2Q3Nk5tQXlXbWR3WVBoMm00dGI3ZmZjOUlzcTU4MmVFcFBhNzhNWGpNZmIzaE9WTE9xRHpNTUFfTG9NQXVJZkdkMGgzSWowZ1dxdW5DS1g3Qk1mQlJxM001TUtMMXBHOWNyU0ZBT29lVkZpTDhpWlBsUDI0VjE5THdzZ0d1ZnVrQTFtVzVJcTJUUkVXeWQyNjRKZC1lS2UxdTAwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UqE55aemrYjdFA8FkDCwW812jfM5D0wZd7golIxJUOE-xP3suwjn4V7dwR978-yKqkJ5Fjz2xxYKRTVPTq9qS8yfeB02OKDwOjsuNxmtVMKA-0A8KI"
+ ]
+ },
+ "Body": ""
+ }
+ },
+ {
+ "ID": "49aa8c8fefb3577a",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Type": [
+ "multipart/related; boundary=ab6dfb15520815f8119effd1b1d5f7dec91a7e7b8477b1ac4492c7f9a037"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "5662dde3618e05ad28aa32d8645d4e42/12600170233043111670;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "LS1hYjZkZmIxNTUyMDgxNWY4MTE5ZWZmZDFiMWQ1ZjdkZWM5MWE3ZTdiODQ3N2IxYWM0NDkyYzdmOWEwMzcNCkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vanNvbg0KDQp7ImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMyIsIm5hbWUiOiJmb28ifQoNCi0tYWI2ZGZiMTU1MjA4MTVmODExOWVmZmQxYjFkNWY3ZGVjOTFhN2U3Yjg0NzdiMWFjNDQ5MmM3ZjlhMDM3DQpDb250ZW50LVR5cGU6IHRleHQvcGxhaW47IGNoYXJzZXQ9dXRmLTgNCg0KaGVsbG8NCi0tYWI2ZGZiMTU1MjA4MTVmODExOWVmZmQxYjFkNWY3ZGVjOTFhN2U3Yjg0NzdiMWFjNDQ5MmM3ZjlhMDM3LS0NCg=="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3205"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:16 GMT"
+ ],
+ "Etag": [
+ "CJa+sfOW290CEAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051388000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vraz3:4225,/bns/yr/borg/yr/bns/blobstore2/bitpusher/37.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=K8ysW87ENNHD4QTY_bTQDA"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/37.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/37:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWVNNdC1OVDFNYTJvWXBrbG1qcDlJMlZaUFZ5bFl5Z2Q3Nk5tQXlXbWR3WVBoMm00dGI3ZmZjOUlzcTU4MmVFcFBhNzhNWGpNZmIzaE9WTE9xRHpNTUFfTG9NQXVJZkdkMGgzSWowZ1dxdW5DS1g3Qk1mQlJxM001TUtMMXBHOWNyU0ZBT29lVkZpTDhpWlBsUDI0VjE5THdzZ0d1ZnVrQTFtVzVJcTJUUkVXeWQyNjRKZC1lS2UxdTAwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_single_post_uploads"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Uqs6PH1tPVOygCthX3HcFpiXsTBPsOE0XUzHj3uRrIEmDTAKhT8TiGBcBSVXXv6lgRWAkfRmYxErnNfB7r5P_Rnx84vhQ"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9mb28vMTUzODA1MTExNjEzMDA3MCIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9vL2ZvbyIsIm5hbWUiOiJmb28iLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTExNjEzMDA3MCIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOCIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNToxNi4xMjlaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjU6MTYuMTI5WiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI1OjE2LjEyOVoiLCJzaXplIjoiNSIsIm1kNUhhc2giOiJYVUZBS3J4TEtuYTVjWjJSRUJmRmtnPT0iLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL28vZm9vP2dlbmVyYXRpb249MTUzODA1MTExNjEzMDA3MCZhbHQ9bWVkaWEiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9mb28vMTUzODA1MTExNjEzMDA3MC9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9vL2Zvby9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJvYmplY3QiOiJmb28iLCJnZW5lcmF0aW9uIjoiMTUzODA1MTExNjEzMDA3MCIsImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6Im93bmVycyJ9LCJldGFnIjoiQ0phK3NmT1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL2Zvby8xNTM4MDUxMTE2MTMwMDcwL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9vL2Zvby9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzIiwib2JqZWN0IjoiZm9vIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTExMTYxMzAwNzAiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0phK3NmT1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL2Zvby8xNTM4MDUxMTE2MTMwMDcwL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9vL2Zvby9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzIiwib2JqZWN0IjoiZm9vIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTExMTYxMzAwNzAiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNKYStzZk9XMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9mb28vMTUzODA1MTExNjEzMDA3MC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL28vZm9vL2FjbC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzIiwib2JqZWN0IjoiZm9vIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTExMTYxMzAwNzAiLCJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwicm9sZSI6Ik9XTkVSIiwiZW1haWwiOiIzNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImV0YWciOiJDSmErc2ZPVzI5MENFQUU9In1dLCJvd25lciI6eyJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIn0sImNyYzMyYyI6Im1uRzdUQT09IiwiZXRhZyI6IkNKYStzZk9XMjkwQ0VBRT0ifQ=="
+ }
+ },
+ {
+ "ID": "07c8a1555393f910",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/foo?alt=json\u0026prettyPrint=false\u0026userProject=dulcet-port-762",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "d007af7835e7bbb949a25b07284eca47/13359207202464309573;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/foo?alt=json\u0026prettyPrint=false\u0026userProject=dulcet-port-762"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 204,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "0"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:16 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051388000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vra74:4154,/bns/yv/borg/yv/bns/blobstore2/bitpusher/129.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=LMysW_T0DtP-gASw_pngAw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/129.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/129:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWVNNdC1OVDFNYTJvWXBrbG1qcDlJMlZaUFZ5bFl5Z2Q3Nk5tQXlXbWR3WVBoMm00dGI3ZmZjOUlzcTU4MmVFcFBhNzhNWGpNZmIzaE9WTE9xRHpNTUFfTG9NQXVJZkdkMGgzSWowZ1dxdW5DS1g3Qk1mQlJxM001TUtMMXBHOWNyU0ZBT29lVkZpTDhpWlBsUDI0VjE5THdzZ0d1ZnVrQTFtVzVJcTJUUkVXeWQyNjRKZC1lS2UxdTAwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Ur-j16n2uzB3mZoBZM424vIBmsK2vOIC3mwutsAMtqFqwEa2_PgKKWN_ZBQzGq-8Yd6wNWnTQtGMgvom3GAi-BBhY1Q2w"
+ ]
+ },
+ "Body": ""
+ }
+ },
+ {
+ "ID": "2defffbcd8976267",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Type": [
+ "multipart/related; boundary=75a80d9841f4290d47e65be40815577244a41e66a9a9cf3df47372ffb308"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "f3b9c63bf79fa11cdaabdbb76d9a0bd2/14190300666411807892;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "LS03NWE4MGQ5ODQxZjQyOTBkNDdlNjViZTQwODE1NTc3MjQ0YTQxZTY2YTlhOWNmM2RmNDczNzJmZmIzMDgNCkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vanNvbg0KDQp7ImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMyIsIm5hbWUiOiJmb28ifQoNCi0tNzVhODBkOTg0MWY0MjkwZDQ3ZTY1YmU0MDgxNTU3NzI0NGE0MWU2NmE5YTljZjNkZjQ3MzcyZmZiMzA4DQpDb250ZW50LVR5cGU6IHRleHQvcGxhaW47IGNoYXJzZXQ9dXRmLTgNCg0KaGVsbG8NCi0tNzVhODBkOTg0MWY0MjkwZDQ3ZTY1YmU0MDgxNTU3NzI0NGE0MWU2NmE5YTljZjNkZjQ3MzcyZmZiMzA4LS0NCg=="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3205"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:16 GMT"
+ ],
+ "Etag": [
+ "CPqF3POW290CEAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051388000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrud24:4012,/bns/yr/borg/yr/bns/blobstore2/bitpusher/90.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=LMysW_6rItCBkATK14bwDg"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/90.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/90:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWVNNdC1OVDFNYTJvWXBrbG1qcDlJMlZaUFZ5bFl5Z2Q3Nk5tQXlXbWR3WVBoMm00dGI3ZmZjOUlzcTU4MmVFcFBhNzhNWGpNZmIzaE9WTE9xRHpNTUFfTG9NQXVJZkdkMGgzSWowZ1dxdW5DS1g3Qk1mQlJxM001TUtMMXBHOWNyU0ZBT29lVkZpTDhpWlBsUDI0VjE5THdzZ0d1ZnVrQTFtVzVJcTJUUkVXeWQyNjRKZC1lS2UxdTAwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_single_post_uploads"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UoIxj06L4-s3I6oVItW3TiAANXDlYSURjREeXxJ2GhVRJSrZsuU5X4YSySqZ-BrklVUdF0QIgUxqu4ng18fcrEHYKgsoA"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9mb28vMTUzODA1MTExNjgyNzM4NiIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9vL2ZvbyIsIm5hbWUiOiJmb28iLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTExNjgyNzM4NiIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOCIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNToxNi44MjdaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjU6MTYuODI3WiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI1OjE2LjgyN1oiLCJzaXplIjoiNSIsIm1kNUhhc2giOiJYVUZBS3J4TEtuYTVjWjJSRUJmRmtnPT0iLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL28vZm9vP2dlbmVyYXRpb249MTUzODA1MTExNjgyNzM4NiZhbHQ9bWVkaWEiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9mb28vMTUzODA1MTExNjgyNzM4Ni9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9vL2Zvby9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJvYmplY3QiOiJmb28iLCJnZW5lcmF0aW9uIjoiMTUzODA1MTExNjgyNzM4NiIsImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6Im93bmVycyJ9LCJldGFnIjoiQ1BxRjNQT1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL2Zvby8xNTM4MDUxMTE2ODI3Mzg2L3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9vL2Zvby9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzIiwib2JqZWN0IjoiZm9vIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTExMTY4MjczODYiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ1BxRjNQT1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL2Zvby8xNTM4MDUxMTE2ODI3Mzg2L3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9vL2Zvby9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzIiwib2JqZWN0IjoiZm9vIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTExMTY4MjczODYiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNQcUYzUE9XMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9mb28vMTUzODA1MTExNjgyNzM4Ni91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL28vZm9vL2FjbC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzIiwib2JqZWN0IjoiZm9vIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTExMTY4MjczODYiLCJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwicm9sZSI6Ik9XTkVSIiwiZW1haWwiOiIzNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImV0YWciOiJDUHFGM1BPVzI5MENFQUU9In1dLCJvd25lciI6eyJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIn0sImNyYzMyYyI6Im1uRzdUQT09IiwiZXRhZyI6IkNQcUYzUE9XMjkwQ0VBRT0ifQ=="
+ }
+ },
+ {
+ "ID": "a778a38a339a93e4",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/foo?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "71d26a27642e73b3cd6be125433435a2/14949619106514683876;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/foo?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 400,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0"
+ ],
+ "Content-Length": [
+ "12135"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:17 GMT"
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:25:17 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051393000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "471383502717"
+ ],
+ "X-Google-Backends": [
+ "vrud24:4012,/bns/yv/borg/yv/bns/blobstore2/bitpusher/59.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=LMysW5vuOcjAggTmnbjABA"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/59.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/59:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CP3elYXcDRoCGAYoATpFChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGM6ropHgHCIVMTE3MjM4MDU4ODYxOTM3NTE5MTQ0MOArMOErMOMrSp8BEoIBeWEyOS5jLkVsb2xCcldWbUZlX1AxVDdUOHVpTXdFMHBZUjdTc2NVMDBFdEZkc2tSenBQY0NLWkhUeEZaYXI0Q25tZmR6bXFRLTNVV0kzOF9wdEx5VTZ2Z1Q3dlRBeW42Z3g4dUcyd0szSHIzaTZrV1JBZkozc1pNMGQ1allkNHpWQTAEOhZOT1RfQV9QRVJTSVNURU5UX1RPS0VO"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Upload-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UoVnK5NfmwNaxGyeQ_rxmtw2pIfr-rNJNSvRUsZHttcvwhswcNcgXCauYsMiUo3GB2K8ydgQ0-KHfu05d22wU_DGlJTaQ"
+ ]
+ },
+ "Body": "eyJlcnJvciI6eyJlcnJvcnMiOlt7ImRvbWFpbiI6Imdsb2JhbCIsInJlYXNvbiI6InJlcXVpcmVkIiwibWVzc2FnZSI6IkJ1Y2tldCBpcyByZXF1ZXN0ZXIgcGF5cyBidWNrZXQgYnV0IG5vIHVzZXIgcHJvamVjdCBwcm92aWRlZC4iLCJkZWJ1Z0luZm8iOiJjb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6VVNFUl9QUk9KRUNUX01JU1NJTkc6IEJ1Y2tldCBpcyBSZXF1ZXN0ZXIgUGF5cyBidWNrZXQgYnV0IG5vIGJpbGxpbmcgcHJvamVjdCBpZCBwcm92aWRlZCBmb3Igbm9uLW93bmVyLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5EZWxldGVPYmplY3QuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKERlbGV0ZU9iamVjdC5qYXZhOjc3KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuRGVsZXRlT2JqZWN0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChEZWxldGVPYmplY3QuamF2YToyMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLk9iamVjdHNEZWxlZ2F0b3IuZGVsZXRlKE9iamVjdHNEZWxlZ2F0b3IuamF2YToxMTMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBCdWNrZXQgaXMgUmVxdWVzdGVyIFBheXMgYnVja2V0IGJ1dCBubyBiaWxsaW5nIHByb2plY3QgaWQgcHJvdmlkZWQgZm9yIG5vbi1vd25lci5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MjkwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAxKVxuXHQuLi4gMTcgbW9yZVxuXG5jb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS5GYXVsdDogSW1tdXRhYmxlRXJyb3JEZWZpbml0aW9ue2Jhc2U9UkVRVUlSRUQsIGNhdGVnb3J5PVVTRVJfRVJST1IsIGNhdXNlPW51bGwsIGRlYnVnSW5mbz1jb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6VVNFUl9QUk9KRUNUX01JU1NJTkc6IEJ1Y2tldCBpcyBSZXF1ZXN0ZXIgUGF5cyBidWNrZXQgYnV0IG5vIGJpbGxpbmcgcHJvamVjdCBpZCBwcm92aWRlZCBmb3Igbm9uLW93bmVyLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5EZWxldGVPYmplY3QuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKERlbGV0ZU9iamVjdC5qYXZhOjc3KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuRGVsZXRlT2JqZWN0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChEZWxldGVPYmplY3QuamF2YToyMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLk9iamVjdHNEZWxlZ2F0b3IuZGVsZXRlKE9iamVjdHNEZWxlZ2F0b3IuamF2YToxMTMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBCdWNrZXQgaXMgUmVxdWVzdGVyIFBheXMgYnVja2V0IGJ1dCBubyBiaWxsaW5nIHByb2plY3QgaWQgcHJvdmlkZWQgZm9yIG5vbi1vd25lci5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MjkwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAxKVxuXHQuLi4gMTcgbW9yZVxuLCBkb21haW49Z2xvYmFsLCBleHRlbmRlZEhlbHA9bnVsbCwgaHR0cEhlYWRlcnM9e30sIGh0dHBTdGF0dXM9YmFkUmVxdWVzdCwgaW50ZXJuYWxSZWFzb249UmVhc29ue2FyZ3VtZW50cz17fSwgY2F1c2U9bnVsbCwgY29kZT1nZGF0YS5Db3JlRXJyb3JEb21haW4uUkVRVUlSRUQsIGNyZWF0ZWRCeUJhY2tlbmQ9dHJ1ZSwgZGVidWdNZXNzYWdlPWNvbS5nb29nbGUubmV0LnJwYzMuUnBjRXhjZXB0aW9uOiBjbG91ZC5iaWdzdG9yZS5SZXNwb25zZUNvZGUuRXJyb3JDb2RlOjpVU0VSX1BST0pFQ1RfTUlTU0lORzogQnVja2V0IGlzIFJlcXVlc3RlciBQYXlzIGJ1Y2tldCBidXQgbm8gYmlsbGluZyBwcm9qZWN0IGlkIHByb3ZpZGVkIGZvciBub24tb3duZXIuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRvUnBjM0V4Y2VwdGlvbihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjEzNSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5vYmplY3RzLkRlbGV0ZU9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoRGVsZXRlT2JqZWN0LmphdmE6NzcpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5EZWxldGVPYmplY3QuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKERlbGV0ZU9iamVjdC5qYXZhOjIzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmZyYW1ld29yay5SZXF1ZXN0SGFuZGxlci5oYW5kbGUoUmVxdWVzdEhhbmRsZXIuamF2YToyOTQpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uT2JqZWN0c0RlbGVnYXRvci5kZWxldGUoT2JqZWN0c0RlbGVnYXRvci5qYXZhOjExMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uUnBjUmVjZWl2ZXIubGFtYmRhJHByb2Nlc3NSZXF1ZXN0QXN5bmMkNChScGNSZWNlaXZlci5qYXZhOjIwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uQXN5bmNFeGVjdXRvci5sYW1iZGEkc3VibWl0JDAoQXN5bmNFeGVjdXRvci5qYXZhOjI3Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KENvbnRleHRSdW5uYWJsZS5qYXZhOjUwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZSQxLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozOSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NzIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozNilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRXhlY3V0b3JzJFJ1bm5hYmxlQWRhcHRlci5jYWxsKEV4ZWN1dG9ycy5qYXZhOjUxMSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRnV0dXJlVGFzay5ydW4oRnV0dXJlVGFzay5qYXZhOjI2Nilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yLnJ1bldvcmtlcihUaHJlYWRQb29sRXhlY3V0b3IuamF2YToxMTQ5KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IkV29ya2VyLnJ1bihUaHJlYWRQb29sRXhlY3V0b3IuamF2YTo2MjQpXG5cdGF0IGphdmEubGFuZy5UaHJlYWQucnVuKFRocmVhZC5qYXZhOjc0OClcbkNhdXNlZCBieTogY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb246IEJ1Y2tldCBpcyBSZXF1ZXN0ZXIgUGF5cyBidWNrZXQgYnV0IG5vIGJpbGxpbmcgcHJvamVjdCBpZCBwcm92aWRlZCBmb3Igbm9uLW93bmVyLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxNyBtb3JlXG4sIGVycm9yUHJvdG9Db2RlPVJFUVVJUkVELCBlcnJvclByb3RvRG9tYWluPWdkYXRhLkNvcmVFcnJvckRvbWFpbiwgZmlsdGVyZWRNZXNzYWdlPW51bGwsIGxvY2F0aW9uPW51bGwsIG1lc3NhZ2U9QnVja2V0IGlzIHJlcXVlc3RlciBwYXlzIGJ1Y2tldCBidXQgbm8gdXNlciBwcm9qZWN0IHByb3ZpZGVkLiwgdW5uYW1lZEFyZ3VtZW50cz1bXX0sIGxvY2F0aW9uPW51bGwsIG1lc3NhZ2U9QnVja2V0IGlzIHJlcXVlc3RlciBwYXlzIGJ1Y2tldCBidXQgbm8gdXNlciBwcm9qZWN0IHByb3ZpZGVkLiwgcmVhc29uPXJlcXVpcmVkLCBycGNDb2RlPTQwMH0gQnVja2V0IGlzIHJlcXVlc3RlciBwYXlzIGJ1Y2tldCBidXQgbm8gdXNlciBwcm9qZWN0IHByb3ZpZGVkLjogY29tLmdvb2dsZS5uZXQucnBjMy5ScGNFeGNlcHRpb246IGNsb3VkLmJpZ3N0b3JlLlJlc3BvbnNlQ29kZS5FcnJvckNvZGU6OlVTRVJfUFJPSkVDVF9NSVNTSU5HOiBCdWNrZXQgaXMgUmVxdWVzdGVyIFBheXMgYnVja2V0IGJ1dCBubyBiaWxsaW5nIHByb2plY3QgaWQgcHJvdmlkZWQgZm9yIG5vbi1vd25lci5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udG9ScGMzRXhjZXB0aW9uKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MTM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuRGVsZXRlT2JqZWN0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChEZWxldGVPYmplY3QuamF2YTo3Nylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5vYmplY3RzLkRlbGV0ZU9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoRGVsZXRlT2JqZWN0LmphdmE6MjMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5PYmplY3RzRGVsZWdhdG9yLmRlbGV0ZShPYmplY3RzRGVsZWdhdG9yLmphdmE6MTEzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5ScGNSZWNlaXZlci5sYW1iZGEkcHJvY2Vzc1JlcXVlc3RBc3luYyQ0KFJwY1JlY2VpdmVyLmphdmE6MjAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5Bc3luY0V4ZWN1dG9yLmxhbWJkYSRzdWJtaXQkMChBc3luY0V4ZWN1dG9yLmphdmE6MjcyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoQ29udGV4dFJ1bm5hYmxlLmphdmE6NTApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlJDEucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM5KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo3Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5FeGVjdXRvcnMkUnVubmFibGVBZGFwdGVyLmNhbGwoRXhlY3V0b3JzLmphdmE6NTExKVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5GdXR1cmVUYXNrLnJ1bihGdXR1cmVUYXNrLmphdmE6MjY2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IucnVuV29ya2VyKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjExNDkpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvciRXb3JrZXIucnVuKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjYyNClcblx0YXQgamF2YS5sYW5nLlRocmVhZC5ydW4oVGhyZWFkLmphdmE6NzQ4KVxuQ2F1c2VkIGJ5OiBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbjogQnVja2V0IGlzIFJlcXVlc3RlciBQYXlzIGJ1Y2tldCBidXQgbm8gYmlsbGluZyBwcm9qZWN0IGlkIHByb3ZpZGVkIGZvciBub24tb3duZXIuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93T25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjI5MClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMSlcblx0Li4uIDE3IG1vcmVcblxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS5FcnJvckNvbGxlY3Rvci50b0ZhdWx0KEVycm9yQ29sbGVjdG9yLmphdmE6NTQpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5yZXN0LmFkYXB0ZXIucm9zeS5Sb3N5RXJyb3JDb252ZXJ0ZXIudG9GYXVsdChSb3N5RXJyb3JDb252ZXJ0ZXIuamF2YTo2Nylcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnJlc3QuYWRhcHRlci5yb3N5LlJvc3lIYW5kbGVyJDIuY2FsbChSb3N5SGFuZGxlci5qYXZhOjI1OClcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnJlc3QuYWRhcHRlci5yb3N5LlJvc3lIYW5kbGVyJDIuY2FsbChSb3N5SGFuZGxlci5qYXZhOjIzOClcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkRpcmVjdEV4ZWN1dG9yLmV4ZWN1dGUoRGlyZWN0RXhlY3V0b3IuamF2YTozMClcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmV4ZWN1dGVMaXN0ZW5lcihBYnN0cmFjdEZ1dHVyZS5qYXZhOjExNDMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5jb21wbGV0ZShBYnN0cmFjdEZ1dHVyZS5qYXZhOjk2Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLnNldChBYnN0cmFjdEZ1dHVyZS5qYXZhOjczMSlcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkRpcmVjdEV4ZWN1dG9yLmV4ZWN1dGUoRGlyZWN0RXhlY3V0b3IuamF2YTozMClcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmV4ZWN1dGVMaXN0ZW5lcihBYnN0cmFjdEZ1dHVyZS5qYXZhOjExNDMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5jb21wbGV0ZShBYnN0cmFjdEZ1dHVyZS5qYXZhOjk2Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLnNldChBYnN0cmFjdEZ1dHVyZS5qYXZhOjczMSlcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnRocmVhZC5UaHJlYWRUcmFja2VycyRUaHJlYWRUcmFja2luZ1J1bm5hYmxlLnJ1bihUaHJlYWRUcmFja2Vycy5qYXZhOjEyNilcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRUcmFjZUNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoVHJhY2VDb250ZXh0LmphdmE6NDU1KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuc2VydmVyLkNvbW1vbk1vZHVsZSRDb250ZXh0Q2FycnlpbmdFeGVjdXRvclNlcnZpY2UkMS5ydW5JbkNvbnRleHQoQ29tbW9uTW9kdWxlLmphdmE6ODQ2KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JFRyYWNlQ29udGV4dFJ1bm5hYmxlJDEucnVuKFRyYWNlQ29udGV4dC5qYXZhOjQ2Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRBYnN0cmFjdFRyYWNlQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoVHJhY2VDb250ZXh0LmphdmE6MzIxKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JEFic3RyYWN0VHJhY2VDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KFRyYWNlQ29udGV4dC5qYXZhOjMxMylcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRUcmFjZUNvbnRleHRSdW5uYWJsZS5ydW4oVHJhY2VDb250ZXh0LmphdmE6NDU5KVxuXHRhdCBjb20uZ29vZ2xlLmdzZS5pbnRlcm5hbC5EaXNwYXRjaFF1ZXVlSW1wbCRXb3JrZXJUaHJlYWQucnVuKERpc3BhdGNoUXVldWVJbXBsLmphdmE6NDAzKVxuIn1dLCJjb2RlIjo0MDAsIm1lc3NhZ2UiOiJCdWNrZXQgaXMgcmVxdWVzdGVyIHBheXMgYnVja2V0IGJ1dCBubyB1c2VyIHByb2plY3QgcHJvdmlkZWQuIn19"
+ }
+ },
+ {
+ "ID": "2a8fd68359cb1958",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Type": [
+ "multipart/related; boundary=4f6e9b78f5a8b7e850386764f72a73c816d0f8dc26327ea4d10da74cc35d"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "b7aa87d2a9c5480b8c28fa68dd906821/15708656071657756979;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "LS00ZjZlOWI3OGY1YThiN2U4NTAzODY3NjRmNzJhNzNjODE2ZDBmOGRjMjYzMjdlYTRkMTBkYTc0Y2MzNWQNCkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vanNvbg0KDQp7ImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMyIsIm5hbWUiOiJmb28ifQoNCi0tNGY2ZTliNzhmNWE4YjdlODUwMzg2NzY0ZjcyYTczYzgxNmQwZjhkYzI2MzI3ZWE0ZDEwZGE3NGNjMzVkDQpDb250ZW50LVR5cGU6IHRleHQvcGxhaW47IGNoYXJzZXQ9dXRmLTgNCg0KaGVsbG8NCi0tNGY2ZTliNzhmNWE4YjdlODUwMzg2NzY0ZjcyYTczYzgxNmQwZjhkYzI2MzI3ZWE0ZDEwZGE3NGNjMzVkLS0NCg=="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3205"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:17 GMT"
+ ],
+ "Etag": [
+ "CNGxgfSW290CEAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051388000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vreu27:4180,/bns/yv/borg/yv/bns/blobstore2/bitpusher/296.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=LcysW5DkB8u0gASSk5bYAQ"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/296.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/296:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWVNNdC1OVDFNYTJvWXBrbG1qcDlJMlZaUFZ5bFl5Z2Q3Nk5tQXlXbWR3WVBoMm00dGI3ZmZjOUlzcTU4MmVFcFBhNzhNWGpNZmIzaE9WTE9xRHpNTUFfTG9NQXVJZkdkMGgzSWowZ1dxdW5DS1g3Qk1mQlJxM001TUtMMXBHOWNyU0ZBT29lVkZpTDhpWlBsUDI0VjE5THdzZ0d1ZnVrQTFtVzVJcTJUUkVXeWQyNjRKZC1lS2UxdTAwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_single_post_uploads"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UqupdeNHxKM38dADbCeH8nI7nmyi0vHoWSYlJ0PAgo11y3jQ1rPgq5MBoKWmfN2F_34QBdaOSTTs3SlTrlTGozCPBuYVA"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9mb28vMTUzODA1MTExNzQzOTE4NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9vL2ZvbyIsIm5hbWUiOiJmb28iLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTExNzQzOTE4NSIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOCIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNToxNy40MzhaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjU6MTcuNDM4WiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI1OjE3LjQzOFoiLCJzaXplIjoiNSIsIm1kNUhhc2giOiJYVUZBS3J4TEtuYTVjWjJSRUJmRmtnPT0iLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL28vZm9vP2dlbmVyYXRpb249MTUzODA1MTExNzQzOTE4NSZhbHQ9bWVkaWEiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9mb28vMTUzODA1MTExNzQzOTE4NS9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9vL2Zvby9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJvYmplY3QiOiJmb28iLCJnZW5lcmF0aW9uIjoiMTUzODA1MTExNzQzOTE4NSIsImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6Im93bmVycyJ9LCJldGFnIjoiQ05HeGdmU1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL2Zvby8xNTM4MDUxMTE3NDM5MTg1L3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9vL2Zvby9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzIiwib2JqZWN0IjoiZm9vIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTExMTc0MzkxODUiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ05HeGdmU1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL2Zvby8xNTM4MDUxMTE3NDM5MTg1L3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9vL2Zvby9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzIiwib2JqZWN0IjoiZm9vIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTExMTc0MzkxODUiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNOR3hnZlNXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9mb28vMTUzODA1MTExNzQzOTE4NS91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL28vZm9vL2FjbC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzIiwib2JqZWN0IjoiZm9vIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTExMTc0MzkxODUiLCJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwicm9sZSI6Ik9XTkVSIiwiZW1haWwiOiIzNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImV0YWciOiJDTkd4Z2ZTVzI5MENFQUU9In1dLCJvd25lciI6eyJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIn0sImNyYzMyYyI6Im1uRzdUQT09IiwiZXRhZyI6IkNOR3hnZlNXMjkwQ0VBRT0ifQ=="
+ }
+ },
+ {
+ "ID": "9c087f5dea9ff46c",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/foo?alt=json\u0026prettyPrint=false\u0026userProject=gcloud-golang-firestore-tests",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "fe3cb9d98b5c4a69974af372d060dcd6/16540031006286998658;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/foo?alt=json\u0026prettyPrint=false\u0026userProject=gcloud-golang-firestore-tests"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 204,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "0"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:17 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051393000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "471383502717"
+ ],
+ "X-Google-Backends": [
+ "vrvp14:4177,/bns/yr/borg/yr/bns/blobstore2/bitpusher/47.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=LcysW7eCIpGBkAS56Iz4BQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/47.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/47:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CP3elYXcDRoCGAYoATpFChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGM6ropHgHCIVMTE3MjM4MDU4ODYxOTM3NTE5MTQ0MOArMOErMOMrSp8BEoIBeWEyOS5jLkVsb2xCcldWbUZlX1AxVDdUOHVpTXdFMHBZUjdTc2NVMDBFdEZkc2tSenBQY0NLWkhUeEZaYXI0Q25tZmR6bXFRLTNVV0kzOF9wdEx5VTZ2Z1Q3dlRBeW42Z3g4dUcyd0szSHIzaTZrV1JBZkozc1pNMGQ1allkNHpWQTAEOhZOT1RfQV9QRVJTSVNURU5UX1RPS0VO"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UpKOP9rXNco4uzsEObaLaIwSS_pvKPoR_hIfr8ARW6YDpAg5SvCHTDLc9x0bBHmSQOdoBISIPL2ExjWg_f7idxUZICJAw"
+ ]
+ },
+ "Body": ""
+ }
+ },
+ {
+ "ID": "3939dd32424044e0",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Type": [
+ "multipart/related; boundary=85973a0d1061499ceaef6ac4ba7dca168f9fea012e335225842463125991"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "0b26e241919815ac6310bc678ab9ee93/17299067975708131282;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "LS04NTk3M2EwZDEwNjE0OTljZWFlZjZhYzRiYTdkY2ExNjhmOWZlYTAxMmUzMzUyMjU4NDI0NjMxMjU5OTENCkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vanNvbg0KDQp7ImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMyIsIm5hbWUiOiJmb28ifQoNCi0tODU5NzNhMGQxMDYxNDk5Y2VhZWY2YWM0YmE3ZGNhMTY4ZjlmZWEwMTJlMzM1MjI1ODQyNDYzMTI1OTkxDQpDb250ZW50LVR5cGU6IHRleHQvcGxhaW47IGNoYXJzZXQ9dXRmLTgNCg0KaGVsbG8NCi0tODU5NzNhMGQxMDYxNDk5Y2VhZWY2YWM0YmE3ZGNhMTY4ZjlmZWEwMTJlMzM1MjI1ODQyNDYzMTI1OTkxLS0NCg=="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3205"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:18 GMT"
+ ],
+ "Etag": [
+ "CPDLpvSW290CEAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051388000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrde80:4389,/bns/yv/borg/yv/bns/blobstore2/bitpusher/334.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=LcysW7ShLpLsgQT85IbADw"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/334.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/334:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWVNNdC1OVDFNYTJvWXBrbG1qcDlJMlZaUFZ5bFl5Z2Q3Nk5tQXlXbWR3WVBoMm00dGI3ZmZjOUlzcTU4MmVFcFBhNzhNWGpNZmIzaE9WTE9xRHpNTUFfTG9NQXVJZkdkMGgzSWowZ1dxdW5DS1g3Qk1mQlJxM001TUtMMXBHOWNyU0ZBT29lVkZpTDhpWlBsUDI0VjE5THdzZ0d1ZnVrQTFtVzVJcTJUUkVXeWQyNjRKZC1lS2UxdTAwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_single_post_uploads"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UqDXeA-_PCymYgmewqvC4l3Gbco2LCE5-vGB4Kb1wbr-7oBYEHShdOTDNW8t1PhNwvA0Z-Y1rO1b-A5vDAXffu1UKLqHg"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9mb28vMTUzODA1MTExODA0ODc1MiIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9vL2ZvbyIsIm5hbWUiOiJmb28iLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTExODA0ODc1MiIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOCIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNToxOC4wNDhaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjU6MTguMDQ4WiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI1OjE4LjA0OFoiLCJzaXplIjoiNSIsIm1kNUhhc2giOiJYVUZBS3J4TEtuYTVjWjJSRUJmRmtnPT0iLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL28vZm9vP2dlbmVyYXRpb249MTUzODA1MTExODA0ODc1MiZhbHQ9bWVkaWEiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9mb28vMTUzODA1MTExODA0ODc1Mi9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9vL2Zvby9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDMiLCJvYmplY3QiOiJmb28iLCJnZW5lcmF0aW9uIjoiMTUzODA1MTExODA0ODc1MiIsImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6Im93bmVycyJ9LCJldGFnIjoiQ1BETHB2U1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL2Zvby8xNTM4MDUxMTE4MDQ4NzUyL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9vL2Zvby9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzIiwib2JqZWN0IjoiZm9vIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTExMTgwNDg3NTIiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ1BETHB2U1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL2Zvby8xNTM4MDUxMTE4MDQ4NzUyL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9vL2Zvby9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzIiwib2JqZWN0IjoiZm9vIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTExMTgwNDg3NTIiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNQRExwdlNXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMy9mb28vMTUzODA1MTExODA0ODc1Mi91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzL28vZm9vL2FjbC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAzIiwib2JqZWN0IjoiZm9vIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTExMTgwNDg3NTIiLCJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwicm9sZSI6Ik9XTkVSIiwiZW1haWwiOiIzNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImV0YWciOiJDUERMcHZTVzI5MENFQUU9In1dLCJvd25lciI6eyJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIn0sImNyYzMyYyI6Im1uRzdUQT09IiwiZXRhZyI6IkNQRExwdlNXMjkwQ0VBRT0ifQ=="
+ }
+ },
+ {
+ "ID": "74c09e371d29ac29",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/foo?alt=json\u0026prettyPrint=false\u0026userProject=veener-jba",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "a676d7c79d62a934a91a442e50088d50/18130161439655629345;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/foo?alt=json\u0026prettyPrint=false\u0026userProject=veener-jba"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 403,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0"
+ ],
+ "Content-Length": [
+ "12991"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:18 GMT"
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:25:18 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051393000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "471383502717"
+ ],
+ "X-Google-Backends": [
+ "vrny26:4047,/bns/yr/borg/yr/bns/blobstore2/bitpusher/40.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=LsysW7WDCo_s4QS_yY3QBA"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/40.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/40:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CP3elYXcDRoCGAYoATpFChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGM6ropHgHCIVMTE3MjM4MDU4ODYxOTM3NTE5MTQ0MOArMOErMOMrSp8BEoIBeWEyOS5jLkVsb2xCcldWbUZlX1AxVDdUOHVpTXdFMHBZUjdTc2NVMDBFdEZkc2tSenBQY0NLWkhUeEZaYXI0Q25tZmR6bXFRLTNVV0kzOF9wdEx5VTZ2Z1Q3dlRBeW42Z3g4dUcyd0szSHIzaTZrV1JBZkozc1pNMGQ1allkNHpWQTAEOhZOT1RfQV9QRVJTSVNURU5UX1RPS0VO"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Upload-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UrpZwGPce9nNsZPGsv95kJIkHK0LTBKS0xq9-VuVNdTJGloUo7xESD3m8qGC5o_TwJ73P4MLGzp2V-K8W2dO7pqIQkQyA"
+ ]
+ },
+ "Body": "eyJlcnJvciI6eyJlcnJvcnMiOlt7ImRvbWFpbiI6Imdsb2JhbCIsInJlYXNvbiI6ImZvcmJpZGRlbiIsIm1lc3NhZ2UiOiJpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLiIsImRlYnVnSW5mbyI6ImNvbS5nb29nbGUubmV0LnJwYzMuUnBjRXhjZXB0aW9uOiBjbG91ZC5iaWdzdG9yZS5SZXNwb25zZUNvZGUuRXJyb3JDb2RlOjpVU0VSX1BST0pFQ1RfQUNDRVNTX0RFTklFRDogaW50ZWdyYXRpb25AZ2Nsb3VkLWdvbGFuZy1maXJlc3RvcmUtdGVzdHMuaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20gZG9lcyBub3QgaGF2ZSBzZXJ2aWNldXNhZ2Uuc2VydmljZXMudXNlIGFjY2VzcyB0byBwcm9qZWN0IDY0MjA4MDkxODEwMS5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udG9ScGMzRXhjZXB0aW9uKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MTM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuRGVsZXRlT2JqZWN0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChEZWxldGVPYmplY3QuamF2YTo3Nylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5vYmplY3RzLkRlbGV0ZU9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoRGVsZXRlT2JqZWN0LmphdmE6MjMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5PYmplY3RzRGVsZWdhdG9yLmRlbGV0ZShPYmplY3RzRGVsZWdhdG9yLmphdmE6MTEzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5ScGNSZWNlaXZlci5sYW1iZGEkcHJvY2Vzc1JlcXVlc3RBc3luYyQ0KFJwY1JlY2VpdmVyLmphdmE6MjAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5Bc3luY0V4ZWN1dG9yLmxhbWJkYSRzdWJtaXQkMChBc3luY0V4ZWN1dG9yLmphdmE6MjcyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoQ29udGV4dFJ1bm5hYmxlLmphdmE6NTApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlJDEucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM5KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo3Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5FeGVjdXRvcnMkUnVubmFibGVBZGFwdGVyLmNhbGwoRXhlY3V0b3JzLmphdmE6NTExKVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5GdXR1cmVUYXNrLnJ1bihGdXR1cmVUYXNrLmphdmE6MjY2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IucnVuV29ya2VyKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjExNDkpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvciRXb3JrZXIucnVuKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjYyNClcblx0YXQgamF2YS5sYW5nLlRocmVhZC5ydW4oVGhyZWFkLmphdmE6NzQ4KVxuQ2F1c2VkIGJ5OiBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbjogaW50ZWdyYXRpb25AZ2Nsb3VkLWdvbGFuZy1maXJlc3RvcmUtdGVzdHMuaWFtLmdzZXJ2aWNlYWNjb3VudC5jb20gZG9lcyBub3QgaGF2ZSBzZXJ2aWNldXNhZ2Uuc2VydmljZXMudXNlIGFjY2VzcyB0byBwcm9qZWN0IDY0MjA4MDkxODEwMS5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MjkwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAxKVxuXHQuLi4gMTcgbW9yZVxuXG5jb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS5GYXVsdDogSW1tdXRhYmxlRXJyb3JEZWZpbml0aW9ue2Jhc2U9Rk9SQklEREVOLCBjYXRlZ29yeT1VU0VSX0VSUk9SLCBjYXVzZT1udWxsLCBkZWJ1Z0luZm89Y29tLmdvb2dsZS5uZXQucnBjMy5ScGNFeGNlcHRpb246IGNsb3VkLmJpZ3N0b3JlLlJlc3BvbnNlQ29kZS5FcnJvckNvZGU6OlVTRVJfUFJPSkVDVF9BQ0NFU1NfREVOSUVEOiBpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5EZWxldGVPYmplY3QuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKERlbGV0ZU9iamVjdC5qYXZhOjc3KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuRGVsZXRlT2JqZWN0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChEZWxldGVPYmplY3QuamF2YToyMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLk9iamVjdHNEZWxlZ2F0b3IuZGVsZXRlKE9iamVjdHNEZWxlZ2F0b3IuamF2YToxMTMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxNyBtb3JlXG4sIGRvbWFpbj1nbG9iYWwsIGV4dGVuZGVkSGVscD1udWxsLCBodHRwSGVhZGVycz17fSwgaHR0cFN0YXR1cz1mb3JiaWRkZW4sIGludGVybmFsUmVhc29uPVJlYXNvbnthcmd1bWVudHM9e30sIGNhdXNlPW51bGwsIGNvZGU9Z2RhdGEuQ29yZUVycm9yRG9tYWluLkZPUkJJRERFTiwgY3JlYXRlZEJ5QmFja2VuZD10cnVlLCBkZWJ1Z01lc3NhZ2U9Y29tLmdvb2dsZS5uZXQucnBjMy5ScGNFeGNlcHRpb246IGNsb3VkLmJpZ3N0b3JlLlJlc3BvbnNlQ29kZS5FcnJvckNvZGU6OlVTRVJfUFJPSkVDVF9BQ0NFU1NfREVOSUVEOiBpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5EZWxldGVPYmplY3QuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKERlbGV0ZU9iamVjdC5qYXZhOjc3KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuRGVsZXRlT2JqZWN0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChEZWxldGVPYmplY3QuamF2YToyMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLk9iamVjdHNEZWxlZ2F0b3IuZGVsZXRlKE9iamVjdHNEZWxlZ2F0b3IuamF2YToxMTMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxNyBtb3JlXG4sIGVycm9yUHJvdG9Db2RlPUZPUkJJRERFTiwgZXJyb3JQcm90b0RvbWFpbj1nZGF0YS5Db3JlRXJyb3JEb21haW4sIGZpbHRlcmVkTWVzc2FnZT1udWxsLCBsb2NhdGlvbj1udWxsLCBtZXNzYWdlPWludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIGRvZXMgbm90IGhhdmUgc2VydmljZXVzYWdlLnNlcnZpY2VzLnVzZSBhY2Nlc3MgdG8gcHJvamVjdCA2NDIwODA5MTgxMDEuLCB1bm5hbWVkQXJndW1lbnRzPVtdfSwgbG9jYXRpb249bnVsbCwgbWVzc2FnZT1pbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLiwgcmVhc29uPWZvcmJpZGRlbiwgcnBjQ29kZT00MDN9IGludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIGRvZXMgbm90IGhhdmUgc2VydmljZXVzYWdlLnNlcnZpY2VzLnVzZSBhY2Nlc3MgdG8gcHJvamVjdCA2NDIwODA5MTgxMDEuOiBjb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6VVNFUl9QUk9KRUNUX0FDQ0VTU19ERU5JRUQ6IGludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIGRvZXMgbm90IGhhdmUgc2VydmljZXVzYWdlLnNlcnZpY2VzLnVzZSBhY2Nlc3MgdG8gcHJvamVjdCA2NDIwODA5MTgxMDEuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRvUnBjM0V4Y2VwdGlvbihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjEzNSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5vYmplY3RzLkRlbGV0ZU9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoRGVsZXRlT2JqZWN0LmphdmE6NzcpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5EZWxldGVPYmplY3QuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKERlbGV0ZU9iamVjdC5qYXZhOjIzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmZyYW1ld29yay5SZXF1ZXN0SGFuZGxlci5oYW5kbGUoUmVxdWVzdEhhbmRsZXIuamF2YToyOTQpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uT2JqZWN0c0RlbGVnYXRvci5kZWxldGUoT2JqZWN0c0RlbGVnYXRvci5qYXZhOjExMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uUnBjUmVjZWl2ZXIubGFtYmRhJHByb2Nlc3NSZXF1ZXN0QXN5bmMkNChScGNSZWNlaXZlci5qYXZhOjIwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uQXN5bmNFeGVjdXRvci5sYW1iZGEkc3VibWl0JDAoQXN5bmNFeGVjdXRvci5qYXZhOjI3Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KENvbnRleHRSdW5uYWJsZS5qYXZhOjUwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZSQxLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozOSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NzIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozNilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRXhlY3V0b3JzJFJ1bm5hYmxlQWRhcHRlci5jYWxsKEV4ZWN1dG9ycy5qYXZhOjUxMSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRnV0dXJlVGFzay5ydW4oRnV0dXJlVGFzay5qYXZhOjI2Nilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yLnJ1bldvcmtlcihUaHJlYWRQb29sRXhlY3V0b3IuamF2YToxMTQ5KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IkV29ya2VyLnJ1bihUaHJlYWRQb29sRXhlY3V0b3IuamF2YTo2MjQpXG5cdGF0IGphdmEubGFuZy5UaHJlYWQucnVuKFRocmVhZC5qYXZhOjc0OClcbkNhdXNlZCBieTogY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb246IGludGVncmF0aW9uQGdjbG91ZC1nb2xhbmctZmlyZXN0b3JlLXRlc3RzLmlhbS5nc2VydmljZWFjY291bnQuY29tIGRvZXMgbm90IGhhdmUgc2VydmljZXVzYWdlLnNlcnZpY2VzLnVzZSBhY2Nlc3MgdG8gcHJvamVjdCA2NDIwODA5MTgxMDEuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93T25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjI5MClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMSlcblx0Li4uIDE3IG1vcmVcblxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS5FcnJvckNvbGxlY3Rvci50b0ZhdWx0KEVycm9yQ29sbGVjdG9yLmphdmE6NTQpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5yZXN0LmFkYXB0ZXIucm9zeS5Sb3N5RXJyb3JDb252ZXJ0ZXIudG9GYXVsdChSb3N5RXJyb3JDb252ZXJ0ZXIuamF2YTo2Nylcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnJlc3QuYWRhcHRlci5yb3N5LlJvc3lIYW5kbGVyJDIuY2FsbChSb3N5SGFuZGxlci5qYXZhOjI1OClcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnJlc3QuYWRhcHRlci5yb3N5LlJvc3lIYW5kbGVyJDIuY2FsbChSb3N5SGFuZGxlci5qYXZhOjIzOClcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkRpcmVjdEV4ZWN1dG9yLmV4ZWN1dGUoRGlyZWN0RXhlY3V0b3IuamF2YTozMClcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmV4ZWN1dGVMaXN0ZW5lcihBYnN0cmFjdEZ1dHVyZS5qYXZhOjExNDMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5jb21wbGV0ZShBYnN0cmFjdEZ1dHVyZS5qYXZhOjk2Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLnNldChBYnN0cmFjdEZ1dHVyZS5qYXZhOjczMSlcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkRpcmVjdEV4ZWN1dG9yLmV4ZWN1dGUoRGlyZWN0RXhlY3V0b3IuamF2YTozMClcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmV4ZWN1dGVMaXN0ZW5lcihBYnN0cmFjdEZ1dHVyZS5qYXZhOjExNDMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5jb21wbGV0ZShBYnN0cmFjdEZ1dHVyZS5qYXZhOjk2Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLnNldChBYnN0cmFjdEZ1dHVyZS5qYXZhOjczMSlcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnRocmVhZC5UaHJlYWRUcmFja2VycyRUaHJlYWRUcmFja2luZ1J1bm5hYmxlLnJ1bihUaHJlYWRUcmFja2Vycy5qYXZhOjEyNilcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRUcmFjZUNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoVHJhY2VDb250ZXh0LmphdmE6NDU1KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuc2VydmVyLkNvbW1vbk1vZHVsZSRDb250ZXh0Q2FycnlpbmdFeGVjdXRvclNlcnZpY2UkMS5ydW5JbkNvbnRleHQoQ29tbW9uTW9kdWxlLmphdmE6ODQ2KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JFRyYWNlQ29udGV4dFJ1bm5hYmxlJDEucnVuKFRyYWNlQ29udGV4dC5qYXZhOjQ2Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRBYnN0cmFjdFRyYWNlQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoVHJhY2VDb250ZXh0LmphdmE6MzIxKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JEFic3RyYWN0VHJhY2VDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KFRyYWNlQ29udGV4dC5qYXZhOjMxMylcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRUcmFjZUNvbnRleHRSdW5uYWJsZS5ydW4oVHJhY2VDb250ZXh0LmphdmE6NDU5KVxuXHRhdCBjb20uZ29vZ2xlLmdzZS5pbnRlcm5hbC5EaXNwYXRjaFF1ZXVlSW1wbCRXb3JrZXJUaHJlYWQucnVuKERpc3BhdGNoUXVldWVJbXBsLmphdmE6NDAzKVxuIn1dLCJjb2RlIjo0MDMsIm1lc3NhZ2UiOiJpbnRlZ3JhdGlvbkBnY2xvdWQtZ29sYW5nLWZpcmVzdG9yZS10ZXN0cy5pYW0uZ3NlcnZpY2VhY2NvdW50LmNvbSBkb2VzIG5vdCBoYXZlIHNlcnZpY2V1c2FnZS5zZXJ2aWNlcy51c2UgYWNjZXNzIHRvIHByb2plY3QgNjQyMDgwOTE4MTAxLiJ9fQ=="
+ }
+ },
+ {
+ "ID": "a0e8258aaf3c4072",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/foo?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "68b50c9729fbc325a856f265c14e1399/443017281042506864;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/foo?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 204,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "0"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:18 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051418000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vnme26:4110,/bns/yx/borg/yx/bns/blobstore2/bitpusher/111.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=LsysW9-NFNXGzALmmI6YCg"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yx/borg/yx/bns/blobstore2/bitpusher/111.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yx/borg/yx/bns/blobstore2/bitpusher/111:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWVNNdC1OVDFNYTJvWXBrbG1qcDlJMlZaUFZ5bFl5Z2Q3Nk5tQXlXbWR3WVBoMm00dGI3ZmZjOUlzcTU4MmVFcFBhNzhNWGpNZmIzaE9WTE9xRHpNTUFfTG9NQXVJZkdkMGgzSWowZ1dxdW5DS1g3Qk1mQlJxM001TUtMMXBHOWNyU0ZBT29lVkZpTDhpWlBsUDI0VjE5THdzZ0d1ZnVrQTFtVzVJcTJUUkVXeWQyNjRKZC1lS2UxdTAwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Upq5TGgZ6pXmvluXnywBJQS6092UwP-6DQjN7OPoqrkN2EtcixAs_aS9wo2eAwA5GO2eorSBVmZNdBvNZDnaR7FAXTqog"
+ ]
+ },
+ "Body": ""
+ }
+ },
+ {
+ "ID": "13d08364d3e115a4",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/copy?alt=json\u0026prettyPrint=false\u0026userProject=dulcet-port-762",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "042ea18a0bf0a95e4096fc95e538efa7/1274110744989939648;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/copy?alt=json\u0026prettyPrint=false\u0026userProject=dulcet-port-762"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 204,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "0"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:18 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051388000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vras90:4259,/bns/yv/borg/yv/bns/blobstore2/bitpusher/20.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=LsysW6-QJ8nMgASG3IeoCQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/20.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/20:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWVNNdC1OVDFNYTJvWXBrbG1qcDlJMlZaUFZ5bFl5Z2Q3Nk5tQXlXbWR3WVBoMm00dGI3ZmZjOUlzcTU4MmVFcFBhNzhNWGpNZmIzaE9WTE9xRHpNTUFfTG9NQXVJZkdkMGgzSWowZ1dxdW5DS1g3Qk1mQlJxM001TUtMMXBHOWNyU0ZBT29lVkZpTDhpWlBsUDI0VjE5THdzZ0d1ZnVrQTFtVzVJcTJUUkVXeWQyNjRKZC1lS2UxdTAwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UpW2F7l42ObaHTrp9Vow9C8oBA8ztqz41L3FLxjdhBOflM_KB5TyMH4CmJuSt83v9PPhYLC3H8qMnXrt2vTF7AVKwFNbMy8HC4JGEIw45kwP5ZwA00"
+ ]
+ },
+ "Body": ""
+ }
+ },
+ {
+ "ID": "ff21a30a8097c589",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/compose?alt=json\u0026prettyPrint=false\u0026userProject=dulcet-port-762",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "b90515bb73861fb4787571a44e507185/2033146614916286991;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003/o/compose?alt=json\u0026prettyPrint=false\u0026userProject=dulcet-port-762"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 204,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "0"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:19 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051388000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrbx80:4064,/bns/yw/borg/yw/bns/blobstore2/bitpusher/109.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=LsysW7emOYq-N6XaqtAB"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yw/borg/yw/bns/blobstore2/bitpusher/109.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yw/borg/yw/bns/blobstore2/bitpusher/109:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWVNNdC1OVDFNYTJvWXBrbG1qcDlJMlZaUFZ5bFl5Z2Q3Nk5tQXlXbWR3WVBoMm00dGI3ZmZjOUlzcTU4MmVFcFBhNzhNWGpNZmIzaE9WTE9xRHpNTUFfTG9NQXVJZkdkMGgzSWowZ1dxdW5DS1g3Qk1mQlJxM001TUtMMXBHOWNyU0ZBT29lVkZpTDhpWlBsUDI0VjE5THdzZ0d1ZnVrQTFtVzVJcTJUUkVXeWQyNjRKZC1lS2UxdTAwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UoqsotiuhmzO_3f-9ZFLFk8eV3K4K8QrlFJ-bJPr6u3w2s-12Xg44-XhDrluV1kKFGWvvDybBkaCVmbGH0leIcmJv44pg"
+ ]
+ },
+ "Body": ""
+ }
+ },
+ {
+ "ID": "de4b252e5c956234",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "3209c3194428722334c6c8069b679a20/3623558514688536494;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0003?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 204,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "0"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:19 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051388000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrk2:4119,/bns/yv/borg/yv/bns/blobstore2/bitpusher/277.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=L8ysW9GjEcjogAThu5aQBg"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/277.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/277:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWVNNdC1OVDFNYTJvWXBrbG1qcDlJMlZaUFZ5bFl5Z2Q3Nk5tQXlXbWR3WVBoMm00dGI3ZmZjOUlzcTU4MmVFcFBhNzhNWGpNZmIzaE9WTE9xRHpNTUFfTG9NQXVJZkdkMGgzSWowZ1dxdW5DS1g3Qk1mQlJxM001TUtMMXBHOWNyU0ZBT29lVkZpTDhpWlBsUDI0VjE5THdzZ0d1ZnVrQTFtVzVJcTJUUkVXeWQyNjRKZC1lS2UxdTAwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UrP-Q3OW_tl4K9YltEXTmq5_0_su8TykvlsV5YsalIA9InwpPJmCmdw0Cv2uroid62PFvdUiXZm6xlMQksd9UouJ8buBw"
+ ]
+ },
+ "Body": ""
+ }
+ },
+ {
+ "ID": "e3fcdc643d6a955f",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/notificationConfigs?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "9cf6f621d3ad5b7a0129dfd00640fe3f/5213970418738976076;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/notificationConfigs?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0, must-revalidate, no-transform"
+ ],
+ "Content-Length": [
+ "32"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:20 GMT"
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:25:20 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051419000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vro66:4347,/bns/yv/borg/yv/bns/blobstore2/bitpusher/289.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=L8ysW5rnM4b-gQTynLpY"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/289.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/289:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRWmMyX1YxcnlBTVZvR05vX19MeXBsclFqc1ZqRm5OZGFfaTNuekctMlgycHRhcERKcHluWjB0MWVWTzB4bWtOLXIwOE9ra3NCbUdkR3dxTEJjYmhMRXhqYzdwVVdDbGRWSjNoVW55ZEdfVE03b01kVnVNajhsU0xvMW9Bcm5EMVpEejJOeGhWeXRqSzc1OWNGc28yTGY5cE1LX3NGWUdtcGlxWVUwQXBPODNVMDJsVms4UHEwRlhWMzQwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UoDy81ffYtqpt9Im4ag9xtAsE3bkApK6xGw22mK0W4mKIahbq3sQHkR7qHzsIDLDTYzeiWuLYxnHM6ftzE_eI3avG7btw"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNub3RpZmljYXRpb25zIn0="
+ }
+ },
+ {
+ "ID": "30df2ed678a1bc12",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/notificationConfigs?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "121"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "0f92d17533d4f481259e5042dae0f8be/6804100852124383979;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/notificationConfigs?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJwYXlsb2FkX2Zvcm1hdCI6Ik5PTkUiLCJ0b3BpYyI6Ii8vcHVic3ViLmdvb2dsZWFwaXMuY29tL3Byb2plY3RzL2R1bGNldC1wb3J0LTc2Mi90b3BpY3MvZ28tc3RvcmFnZS1ub3RpZmljYXRpb24tdGVzdCJ9Cg=="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "297"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:20 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051420000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrsq4:4180,/bns/yr/borg/yr/bns/blobstore2/bitpusher/12.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=MMysW6LQAtCOkATL9oqABA"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/12.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/12:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp0ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4StK4wESxgF5YTI5LmMuRW93QkpRWmMyX1YxcnlBTVZvR05vX19MeXBsclFqc1ZqRm5OZGFfaTNuekctMlgycHRhcERKcHluWjB0MWVWTzB4bWtOLXIwOE9ra3NCbUdkR3dxTEJjYmhMRXhqYzdwVVdDbGRWSjNoVW55ZEdfVE03b01kVnVNajhsU0xvMW9Bcm5EMVpEejJOeGhWeXRqSzc1OWNGc28yTGY5cE1LX3NGWUdtcGlxWVUwQXBPODNVMDJsVms4UHEwRlhWMzQwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UqZ0JCvZ3jCfAdQU0U4oQQTdO4SSYDOnWO1_zcfk84rmXsRwywDGCcL3QeFDLvrXQ1kx8U7Kalb86sIQ1JhGV1yRC7G4Q"
+ ]
+ },
+ "Body": "eyJpZCI6IjEwIiwidG9waWMiOiIvL3B1YnN1Yi5nb29nbGVhcGlzLmNvbS9wcm9qZWN0cy9kdWxjZXQtcG9ydC03NjIvdG9waWNzL2dvLXN0b3JhZ2Utbm90aWZpY2F0aW9uLXRlc3QiLCJwYXlsb2FkX2Zvcm1hdCI6Ik5PTkUiLCJldGFnIjoiMTAiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvbm90aWZpY2F0aW9uQ29uZmlncy8xMCIsImtpbmQiOiJzdG9yYWdlI25vdGlmaWNhdGlvbiJ9"
+ }
+ },
+ {
+ "ID": "1a20023489e65b39",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/notificationConfigs?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "b707fc96aa6ecc8d21d239a9bf2ca897/8394512751879856266;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/notificationConfigs?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0, must-revalidate, no-transform"
+ ],
+ "Content-Length": [
+ "340"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:21 GMT"
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:25:21 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051419000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrp184:4188,/bns/yr/borg/yr/bns/blobstore2/bitpusher/91.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=MMysW9XCN8zn4QSk5KsQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/91.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/91:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRWmMyX1YxcnlBTVZvR05vX19MeXBsclFqc1ZqRm5OZGFfaTNuekctMlgycHRhcERKcHluWjB0MWVWTzB4bWtOLXIwOE9ra3NCbUdkR3dxTEJjYmhMRXhqYzdwVVdDbGRWSjNoVW55ZEdfVE03b01kVnVNajhsU0xvMW9Bcm5EMVpEejJOeGhWeXRqSzc1OWNGc28yTGY5cE1LX3NGWUdtcGlxWVUwQXBPODNVMDJsVms4UHEwRlhWMzQwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UrZMY5eFlGX9fTrWRJIZeUIwwpdodFT4ZAfmEWr8ZhnCpaqyDq4XZ6tkLLfnutcc80V5OA2fVD7YkN9a3Ty65mVW9X88Q"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNub3RpZmljYXRpb25zIiwiaXRlbXMiOlt7ImlkIjoiMTAiLCJ0b3BpYyI6Ii8vcHVic3ViLmdvb2dsZWFwaXMuY29tL3Byb2plY3RzL2R1bGNldC1wb3J0LTc2Mi90b3BpY3MvZ28tc3RvcmFnZS1ub3RpZmljYXRpb24tdGVzdCIsInBheWxvYWRfZm9ybWF0IjoiTk9ORSIsImV0YWciOiIxMCIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9ub3RpZmljYXRpb25Db25maWdzLzEwIiwia2luZCI6InN0b3JhZ2Ujbm90aWZpY2F0aW9uIn1dfQ=="
+ }
+ },
+ {
+ "ID": "1a78aa71539ea1f2",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/notificationConfigs/10?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "fe55897f2f9774caed6c3609bac29dab/9984923556452222248;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/notificationConfigs/10?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 204,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "0"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:21 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051421000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrns19:4209,/bns/yr/borg/yr/bns/blobstore2/bitpusher/7.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=McysW7rGCKWLkAT2zYCwBA"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/7.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/7:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWmMyX1YxcnlBTVZvR05vX19MeXBsclFqc1ZqRm5OZGFfaTNuekctMlgycHRhcERKcHluWjB0MWVWTzB4bWtOLXIwOE9ra3NCbUdkR3dxTEJjYmhMRXhqYzdwVVdDbGRWSjNoVW55ZEdfVE03b01kVnVNajhsU0xvMW9Bcm5EMVpEejJOeGhWeXRqSzc1OWNGc28yTGY5cE1LX3NGWUdtcGlxWVUwQXBPODNVMDJsVms4UHEwRlhWMzQwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Uo63KcORunH_frqXvDI7JVgIHDXzKXeJIoPivdBBNwv00ZNga7njUlQ5sJF3SxO0qTklKAE0kPJr1AZGFQZ2Y50dATW_w"
+ ]
+ },
+ "Body": ""
+ }
+ },
+ {
+ "ID": "147eb7c7f24b19bf",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/notificationConfigs?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "54ed24aadb7c2ae57e8c970c5e6bb756/11575335460502596551;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/notificationConfigs?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0, must-revalidate, no-transform"
+ ],
+ "Content-Length": [
+ "32"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:22 GMT"
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:25:22 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051421000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vnbc62:4021,/bns/yx/borg/yx/bns/blobstore2/bitpusher/14.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=McysW42ZM8vnzgLItoTIAw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yx/borg/yx/bns/blobstore2/bitpusher/14.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yx/borg/yx/bns/blobstore2/bitpusher/14:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRWmMyX1YxcnlBTVZvR05vX19MeXBsclFqc1ZqRm5OZGFfaTNuekctMlgycHRhcERKcHluWjB0MWVWTzB4bWtOLXIwOE9ra3NCbUdkR3dxTEJjYmhMRXhqYzdwVVdDbGRWSjNoVW55ZEdfVE03b01kVnVNajhsU0xvMW9Bcm5EMVpEejJOeGhWeXRqSzc1OWNGc28yTGY5cE1LX3NGWUdtcGlxWVUwQXBPODNVMDJsVms4UHEwRlhWMzQwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UoK37MBtKFjmQyT21pKKOfUeYJPKIc9VRKGvr-_P3kPVbGZ3u7KB6Xvh6XJ6LHjL-v9I8DWk2U9TfGo1XceVRalOdU1fQ"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNub3RpZmljYXRpb25zIn0="
+ }
+ },
+ {
+ "ID": "45d0a5288a60555b",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://storage.googleapis.com/gcp-public-data-landsat/LC08/PRE/044/034/LC80440342016259LGN00/LC80440342016259LGN00_MTL.txt",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "User-Agent": [
+ "Go-http-client/1.1"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "dbb282b28e87168b0a46837000c32388/13165465889593102438;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "storage.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://storage.googleapis.com/gcp-public-data-landsat/LC08/PRE/044/034/LC80440342016259LGN00/LC80440342016259LGN00_MTL.txt"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Accept-Ranges": [
+ "bytes"
+ ],
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "public, max-age=3600"
+ ],
+ "Content-Length": [
+ "7903"
+ ],
+ "Content-Type": [
+ "application/octet-stream"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:22 GMT"
+ ],
+ "Etag": [
+ "\"7a5fd4743bd647485f88496fadb05c51\""
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 13:25:22 GMT"
+ ],
+ "Last-Modified": [
+ "Tue, 04 Oct 2016 16:42:07 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "X-Goog-Generation": [
+ "1475599327662000"
+ ],
+ "X-Goog-Hash": [
+ "crc32c=PWBt8g==",
+ "md5=el/UdDvWR0hfiElvrbBcUQ=="
+ ],
+ "X-Goog-Metageneration": [
+ "1"
+ ],
+ "X-Goog-Storage-Class": [
+ "STANDARD"
+ ],
+ "X-Goog-Stored-Content-Encoding": [
+ "identity"
+ ],
+ "X-Goog-Stored-Content-Length": [
+ "7903"
+ ],
+ "X-Google-Backends": [
+ "/bns/xh/borg/xh/bns/cloud-storage/prod-cloud-storage-frontend.frontend/48,/bns/xh/borg/xh/bns/blobstore2/bitpusher/51.scotty,aclgag19:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=MsysW6OkAo6jswaw3ZvYCg"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "570399209098"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "aclgag19:443,/bns/xh/borg/xh/bns/blobstore2/bitpusher/51.scotty,aclgag19:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/xh/borg/xh/bns/blobstore2/bitpusher/51:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBJ"
+ ],
+ "X-Google-Storage-Location": [
+ "US"
+ ],
+ "X-Guploader-Customer": [
+ "cloud-storage"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Up6rXgTbuekXkWVQ0gCgVQ02Dr2-EROq2XGin7Ib3JLF9JHP_es5VxOpiGKZkBg_YEIA3jtZa4qxBjcX7UdqHLs_PGzsw"
+ ]
+ },
+ "Body": "R1JPVVAgPSBMMV9NRVRBREFUQV9GSUxFCiAgR1JPVVAgPSBNRVRBREFUQV9GSUxFX0lORk8KICAgIE9SSUdJTiA9ICJJbWFnZSBjb3VydGVzeSBvZiB0aGUgVS5TLiBHZW9sb2dpY2FsIFN1cnZleSIKICAgIFJFUVVFU1RfSUQgPSAiMDcwMTYwOTE5MTA1MV8wMDAwNCIKICAgIExBTkRTQVRfU0NFTkVfSUQgPSAiTEM4MDQ0MDM0MjAxNjI1OUxHTjAwIgogICAgRklMRV9EQVRFID0gMjAxNi0wOS0yMFQwMzoxMzowMloKICAgIFNUQVRJT05fSUQgPSAiTEdOIgogICAgUFJPQ0VTU0lOR19TT0ZUV0FSRV9WRVJTSU9OID0gIkxQR1NfMi42LjIiCiAgRU5EX0dST1VQID0gTUVUQURBVEFfRklMRV9JTkZPCiAgR1JPVVAgPSBQUk9EVUNUX01FVEFEQVRBCiAgICBEQVRBX1RZUEUgPSAiTDFUIgogICAgRUxFVkFUSU9OX1NPVVJDRSA9ICJHTFMyMDAwIgogICAgT1VUUFVUX0ZPUk1BVCA9ICJHRU9USUZGIgogICAgU1BBQ0VDUkFGVF9JRCA9ICJMQU5EU0FUXzgiCiAgICBTRU5TT1JfSUQgPSAiT0xJX1RJUlMiCiAgICBXUlNfUEFUSCA9IDQ0CiAgICBXUlNfUk9XID0gMzQKICAgIE5BRElSX09GRk5BRElSID0gIk5BRElSIgogICAgVEFSR0VUX1dSU19QQVRIID0gNDQKICAgIFRBUkdFVF9XUlNfUk9XID0gMzQKICAgIERBVEVfQUNRVUlSRUQgPSAyMDE2LTA5LTE1CiAgICBTQ0VORV9DRU5URVJfVElNRSA9ICIxODo0NjoxOC42ODY3MzgwWiIKICAgIENPUk5FUl9VTF9MQVRfUFJPRFVDVCA9IDM4LjUyODE5CiAgICBDT1JORVJfVUxfTE9OX1BST0RVQ1QgPSAtMTIzLjQwODQzCiAgICBDT1JORVJfVVJfTEFUX1BST0RVQ1QgPSAzOC41MDc2NQogICAgQ09STkVSX1VSX0xPTl9QUk9EVUNUID0gLTEyMC43NjkzMwogICAgQ09STkVSX0xMX0xBVF9QUk9EVUNUID0gMzYuNDE2MzMKICAgIENPUk5FUl9MTF9MT05fUFJPRFVDVCA9IC0xMjMuMzk3MDkKICAgIENPUk5FUl9MUl9MQVRfUFJPRFVDVCA9IDM2LjM5NzI5CiAgICBDT1JORVJfTFJfTE9OX1BST0RVQ1QgPSAtMTIwLjgzMTE3CiAgICBDT1JORVJfVUxfUFJPSkVDVElPTl9YX1BST0RVQ1QgPSA0NjQ0MDAuMDAwCiAgICBDT1JORVJfVUxfUFJPSkVDVElPTl9ZX1BST0RVQ1QgPSA0MjY0NTAwLjAwMAogICAgQ09STkVSX1VSX1BST0pFQ1RJT05fWF9QUk9EVUNUID0gNjk0NTAwLjAwMAogICAgQ09STkVSX1VSX1BST0pFQ1RJT05fWV9QUk9EVUNUID0gNDI2NDUwMC4wMDAKICAgIENPUk5FUl9MTF9QUk9KRUNUSU9OX1hfUFJPRFVDVCA9IDQ2NDQwMC4wMDAKICAgIENPUk5FUl9MTF9QUk9KRUNUSU9OX1lfUFJPRFVDVCA9IDQwMzAyMDAuMDAwCiAgICBDT1JORVJfTFJfUFJPSkVDVElPTl9YX1BST0RVQ1QgPSA2OTQ1MDAuMDAwCiAgICBDT1JORVJfTFJfUFJPSkVDVElPTl9ZX1BST0RVQ1QgPSA0MDMwMjAwLjAwMAogICAgUEFOQ0hST01BVElDX0xJTkVTID0gMTU2MjEKICAgIFBBTkNIUk9NQVRJQ19TQU1QTEVTID0gMTUzNDEKICAgIFJFRkxFQ1RJVkVfTElORVMgPSA3ODExCiAgICBSRUZMRUNUSVZFX1NBTVBMRVMgPSA3NjcxCiAgICBUSEVSTUFMX0xJTkVTID0gNzgxMQogICAgVEhFUk1BTF9TQU1QTEVTID0gNzY3MQogICAgRklMRV9OQU1FX0JBTkRfMSA9ICJMQzgwNDQwMzQyMDE2MjU5TEdOMDBfQjEuVElGIgogICAgRklMRV9OQU1FX0JBTkRfMiA9ICJMQzgwNDQwMzQyMDE2MjU5TEdOMDBfQjIuVElGIgogICAgRklMRV9OQU1FX0JBTkRfMyA9ICJMQzgwNDQwMzQyMDE2MjU5TEdOMDBfQjMuVElGIgogICAgRklMRV9OQU1FX0JBTkRfNCA9ICJMQzgwNDQwMzQyMDE2MjU5TEdOMDBfQjQuVElGIgogICAgRklMRV9OQU1FX0JBTkRfNSA9ICJMQzgwNDQwMzQyMDE2MjU5TEdOMDBfQjUuVElGIgogICAgRklMRV9OQU1FX0JBTkRfNiA9ICJMQzgwNDQwMzQyMDE2MjU5TEdOMDBfQjYuVElGIgogICAgRklMRV9OQU1FX0JBTkRfNyA9ICJMQzgwNDQwMzQyMDE2MjU5TEdOMDBfQjcuVElGIgogICAgRklMRV9OQU1FX0JBTkRfOCA9ICJMQzgwNDQwMzQyMDE2MjU5TEdOMDBfQjguVElGIgogICAgRklMRV9OQU1FX0JBTkRfOSA9ICJMQzgwNDQwMzQyMDE2MjU5TEdOMDBfQjkuVElGIgogICAgRklMRV9OQU1FX0JBTkRfMTAgPSAiTEM4MDQ0MDM0MjAxNjI1OUxHTjAwX0IxMC5USUYiCiAgICBGSUxFX05BTUVfQkFORF8xMSA9ICJMQzgwNDQwMzQyMDE2MjU5TEdOMDBfQjExLlRJRiIKICAgIEZJTEVfTkFNRV9CQU5EX1FVQUxJVFkgPSAiTEM4MDQ0MDM0MjAxNjI1OUxHTjAwX0JRQS5USUYiCiAgICBNRVRBREFUQV9GSUxFX05BTUUgPSAiTEM4MDQ0MDM0MjAxNjI1OUxHTjAwX01UTC50eHQiCiAgICBCUEZfTkFNRV9PTEkgPSAiTE84QlBGMjAxNjA5MTUxODMwNTdfMjAxNjA5MTUyMDA5NTAuMDEiCiAgICBCUEZfTkFNRV9USVJTID0gIkxUOEJQRjIwMTYwOTAyMDg0MTIyXzIwMTYwOTE3MDc0MDI3LjAyIgogICAgQ1BGX05BTUUgPSAiTDhDUEYyMDE2MDcwMV8yMDE2MDkzMC4wMiIKICAgIFJMVVRfRklMRV9OQU1FID0gIkw4UkxVVDIwMTUwMzAzXzIwNDMxMjMxdjExLmg1IgogIEVORF9HUk9VUCA9IFBST0RVQ1RfTUVUQURBVEEKICBHUk9VUCA9IElNQUdFX0FUVFJJQlVURVMKICAgIENMT1VEX0NPVkVSID0gMjkuNTYKICAgIENMT1VEX0NPVkVSX0xBTkQgPSAzLjMzCiAgICBJTUFHRV9RVUFMSVRZX09MSSA9IDkKICAgIElNQUdFX1FVQUxJVFlfVElSUyA9IDkKICAgIFRJUlNfU1NNX01PREVMID0gIkZJTkFMIgogICAgVElSU19TU01fUE9TSVRJT05fU1RBVFVTID0gIkVTVElNQVRFRCIKICAgIFJPTExfQU5HTEUgPSAtMC4wMDEKICAgIFNVTl9BWklNVVRIID0gMTQ4LjQ4MDQ5Mzk2CiAgICBTVU5fRUxFVkFUSU9OID0gNTAuOTM3NjgzOTkKICAgIEVBUlRIX1NVTl9ESVNUQU5DRSA9IDEuMDA1Mzc1MgogICAgR1JPVU5EX0NPTlRST0xfUE9JTlRTX1ZFUlNJT04gPSA0CiAgICBHUk9VTkRfQ09OVFJPTF9QT0lOVFNfTU9ERUwgPSA1NDgKICAgIEdFT01FVFJJQ19STVNFX01PREVMID0gNS44NTcKICAgIEdFT01FVFJJQ19STVNFX01PREVMX1kgPSAzLjg0MQogICAgR0VPTUVUUklDX1JNU0VfTU9ERUxfWCA9IDQuNDIyCiAgICBHUk9VTkRfQ09OVFJPTF9QT0lOVFNfVkVSSUZZID0gMjI4CiAgICBHRU9NRVRSSUNfUk1TRV9WRVJJRlkgPSAzLjM4MgogIEVORF9HUk9VUCA9IElNQUdFX0FUVFJJQlVURVMKICBHUk9VUCA9IE1JTl9NQVhfUkFESUFOQ0UKICAgIFJBRElBTkNFX01BWElNVU1fQkFORF8xID0gNzUxLjk1NzA5CiAgICBSQURJQU5DRV9NSU5JTVVNX0JBTkRfMSA9IC02Mi4wOTY4NgogICAgUkFESUFOQ0VfTUFYSU1VTV9CQU5EXzIgPSA3NzAuMDEzMTgKICAgIFJBRElBTkNFX01JTklNVU1fQkFORF8yID0gLTYzLjU4Nzk0CiAgICBSQURJQU5DRV9NQVhJTVVNX0JBTkRfMyA9IDcwOS41NjA2MQogICAgUkFESUFOQ0VfTUlOSU1VTV9CQU5EXzMgPSAtNTguNTk1NzUKICAgIFJBRElBTkNFX01BWElNVU1fQkFORF80ID0gNTk4LjM0MTQ5CiAgICBSQURJQU5DRV9NSU5JTVVNX0JBTkRfNCA9IC00OS40MTEyMwogICAgUkFESUFOQ0VfTUFYSU1VTV9CQU5EXzUgPSAzNjYuMTU1MTUKICAgIFJBRElBTkNFX01JTklNVU1fQkFORF81ID0gLTMwLjIzNzIxCiAgICBSQURJQU5DRV9NQVhJTVVNX0JBTkRfNiA9IDkxLjA1OTQ2CiAgICBSQURJQU5DRV9NSU5JTVVNX0JBTkRfNiA9IC03LjUxOTcyCiAgICBSQURJQU5DRV9NQVhJTVVNX0JBTkRfNyA9IDMwLjY5MTkxCiAgICBSQURJQU5DRV9NSU5JTVVNX0JBTkRfNyA9IC0yLjUzNDU1CiAgICBSQURJQU5DRV9NQVhJTVVNX0JBTkRfOCA9IDY3Ny4xNTc4NAogICAgUkFESUFOQ0VfTUlOSU1VTV9CQU5EXzggPSAtNTUuOTE5OTIKICAgIFJBRElBTkNFX01BWElNVU1fQkFORF85ID0gMTQzLjEwMTczCiAgICBSQURJQU5DRV9NSU5JTVVNX0JBTkRfOSA9IC0xMS44MTczOQogICAgUkFESUFOQ0VfTUFYSU1VTV9CQU5EXzEwID0gMjIuMDAxODAKICAgIFJBRElBTkNFX01JTklNVU1fQkFORF8xMCA9IDAuMTAwMzMKICAgIFJBRElBTkNFX01BWElNVU1fQkFORF8xMSA9IDIyLjAwMTgwCiAgICBSQURJQU5DRV9NSU5JTVVNX0JBTkRfMTEgPSAwLjEwMDMzCiAgRU5EX0dST1VQID0gTUlOX01BWF9SQURJQU5DRQogIEdST1VQID0gTUlOX01BWF9SRUZMRUNUQU5DRQogICAgUkVGTEVDVEFOQ0VfTUFYSU1VTV9CQU5EXzEgPSAxLjIxMDcwMAogICAgUkVGTEVDVEFOQ0VfTUlOSU1VTV9CQU5EXzEgPSAtMC4wOTk5ODAKICAgIFJFRkxFQ1RBTkNFX01BWElNVU1fQkFORF8yID0gMS4yMTA3MDAKICAgIFJFRkxFQ1RBTkNFX01JTklNVU1fQkFORF8yID0gLTAuMDk5OTgwCiAgICBSRUZMRUNUQU5DRV9NQVhJTVVNX0JBTkRfMyA9IDEuMjEwNzAwCiAgICBSRUZMRUNUQU5DRV9NSU5JTVVNX0JBTkRfMyA9IC0wLjA5OTk4MAogICAgUkVGTEVDVEFOQ0VfTUFYSU1VTV9CQU5EXzQgPSAxLjIxMDcwMAogICAgUkVGTEVDVEFOQ0VfTUlOSU1VTV9CQU5EXzQgPSAtMC4wOTk5ODAKICAgIFJFRkxFQ1RBTkNFX01BWElNVU1fQkFORF81ID0gMS4yMTA3MDAKICAgIFJFRkxFQ1RBTkNFX01JTklNVU1fQkFORF81ID0gLTAuMDk5OTgwCiAgICBSRUZMRUNUQU5DRV9NQVhJTVVNX0JBTkRfNiA9IDEuMjEwNzAwCiAgICBSRUZMRUNUQU5DRV9NSU5JTVVNX0JBTkRfNiA9IC0wLjA5OTk4MAogICAgUkVGTEVDVEFOQ0VfTUFYSU1VTV9CQU5EXzcgPSAxLjIxMDcwMAogICAgUkVGTEVDVEFOQ0VfTUlOSU1VTV9CQU5EXzcgPSAtMC4wOTk5ODAKICAgIFJFRkxFQ1RBTkNFX01BWElNVU1fQkFORF84ID0gMS4yMTA3MDAKICAgIFJFRkxFQ1RBTkNFX01JTklNVU1fQkFORF84ID0gLTAuMDk5OTgwCiAgICBSRUZMRUNUQU5DRV9NQVhJTVVNX0JBTkRfOSA9IDEuMjEwNzAwCiAgICBSRUZMRUNUQU5DRV9NSU5JTVVNX0JBTkRfOSA9IC0wLjA5OTk4MAogIEVORF9HUk9VUCA9IE1JTl9NQVhfUkVGTEVDVEFOQ0UKICBHUk9VUCA9IE1JTl9NQVhfUElYRUxfVkFMVUUKICAgIFFVQU5USVpFX0NBTF9NQVhfQkFORF8xID0gNjU1MzUKICAgIFFVQU5USVpFX0NBTF9NSU5fQkFORF8xID0gMQogICAgUVVBTlRJWkVfQ0FMX01BWF9CQU5EXzIgPSA2NTUzNQogICAgUVVBTlRJWkVfQ0FMX01JTl9CQU5EXzIgPSAxCiAgICBRVUFOVElaRV9DQUxfTUFYX0JBTkRfMyA9IDY1NTM1CiAgICBRVUFOVElaRV9DQUxfTUlOX0JBTkRfMyA9IDEKICAgIFFVQU5USVpFX0NBTF9NQVhfQkFORF80ID0gNjU1MzUKICAgIFFVQU5USVpFX0NBTF9NSU5fQkFORF80ID0gMQogICAgUVVBTlRJWkVfQ0FMX01BWF9CQU5EXzUgPSA2NTUzNQogICAgUVVBTlRJWkVfQ0FMX01JTl9CQU5EXzUgPSAxCiAgICBRVUFOVElaRV9DQUxfTUFYX0JBTkRfNiA9IDY1NTM1CiAgICBRVUFOVElaRV9DQUxfTUlOX0JBTkRfNiA9IDEKICAgIFFVQU5USVpFX0NBTF9NQVhfQkFORF83ID0gNjU1MzUKICAgIFFVQU5USVpFX0NBTF9NSU5fQkFORF83ID0gMQogICAgUVVBTlRJWkVfQ0FMX01BWF9CQU5EXzggPSA2NTUzNQogICAgUVVBTlRJWkVfQ0FMX01JTl9CQU5EXzggPSAxCiAgICBRVUFOVElaRV9DQUxfTUFYX0JBTkRfOSA9IDY1NTM1CiAgICBRVUFOVElaRV9DQUxfTUlOX0JBTkRfOSA9IDEKICAgIFFVQU5USVpFX0NBTF9NQVhfQkFORF8xMCA9IDY1NTM1CiAgICBRVUFOVElaRV9DQUxfTUlOX0JBTkRfMTAgPSAxCiAgICBRVUFOVElaRV9DQUxfTUFYX0JBTkRfMTEgPSA2NTUzNQogICAgUVVBTlRJWkVfQ0FMX01JTl9CQU5EXzExID0gMQogIEVORF9HUk9VUCA9IE1JTl9NQVhfUElYRUxfVkFMVUUKICBHUk9VUCA9IFJBRElPTUVUUklDX1JFU0NBTElORwogICAgUkFESUFOQ0VfTVVMVF9CQU5EXzEgPSAxLjI0MjJFLTAyCiAgICBSQURJQU5DRV9NVUxUX0JBTkRfMiA9IDEuMjcyMEUtMDIKICAgIFJBRElBTkNFX01VTFRfQkFORF8zID0gMS4xNzIxRS0wMgogICAgUkFESUFOQ0VfTVVMVF9CQU5EXzQgPSA5Ljg4NDJFLTAzCiAgICBSQURJQU5DRV9NVUxUX0JBTkRfNSA9IDYuMDQ4N0UtMDMKICAgIFJBRElBTkNFX01VTFRfQkFORF82ID0gMS41MDQyRS0wMwogICAgUkFESUFOQ0VfTVVMVF9CQU5EXzcgPSA1LjA3MDFFLTA0CiAgICBSQURJQU5DRV9NVUxUX0JBTkRfOCA9IDEuMTE4NkUtMDIKICAgIFJBRElBTkNFX01VTFRfQkFORF85ID0gMi4zNjQwRS0wMwogICAgUkFESUFOQ0VfTVVMVF9CQU5EXzEwID0gMy4zNDIwRS0wNAogICAgUkFESUFOQ0VfTVVMVF9CQU5EXzExID0gMy4zNDIwRS0wNAogICAgUkFESUFOQ0VfQUREX0JBTkRfMSA9IC02Mi4xMDkyOAogICAgUkFESUFOQ0VfQUREX0JBTkRfMiA9IC02My42MDA2NgogICAgUkFESUFOQ0VfQUREX0JBTkRfMyA9IC01OC42MDc0NwogICAgUkFESUFOQ0VfQUREX0JBTkRfNCA9IC00OS40MjExMgogICAgUkFESUFOQ0VfQUREX0JBTkRfNSA9IC0zMC4yNDMyNgogICAgUkFESUFOQ0VfQUREX0JBTkRfNiA9IC03LjUyMTIyCiAgICBSQURJQU5DRV9BRERfQkFORF83ID0gLTIuNTM1MDUKICAgIFJBRElBTkNFX0FERF9CQU5EXzggPSAtNTUuOTMxMTAKICAgIFJBRElBTkNFX0FERF9CQU5EXzkgPSAtMTEuODE5NzUKICAgIFJBRElBTkNFX0FERF9CQU5EXzEwID0gMC4xMDAwMAogICAgUkFESUFOQ0VfQUREX0JBTkRfMTEgPSAwLjEwMDAwCiAgICBSRUZMRUNUQU5DRV9NVUxUX0JBTkRfMSA9IDIuMDAwMEUtMDUKICAgIFJFRkxFQ1RBTkNFX01VTFRfQkFORF8yID0gMi4wMDAwRS0wNQogICAgUkVGTEVDVEFOQ0VfTVVMVF9CQU5EXzMgPSAyLjAwMDBFLTA1CiAgICBSRUZMRUNUQU5DRV9NVUxUX0JBTkRfNCA9IDIuMDAwMEUtMDUKICAgIFJFRkxFQ1RBTkNFX01VTFRfQkFORF81ID0gMi4wMDAwRS0wNQogICAgUkVGTEVDVEFOQ0VfTVVMVF9CQU5EXzYgPSAyLjAwMDBFLTA1CiAgICBSRUZMRUNUQU5DRV9NVUxUX0JBTkRfNyA9IDIuMDAwMEUtMDUKICAgIFJFRkxFQ1RBTkNFX01VTFRfQkFORF84ID0gMi4wMDAwRS0wNQogICAgUkVGTEVDVEFOQ0VfTVVMVF9CQU5EXzkgPSAyLjAwMDBFLTA1CiAgICBSRUZMRUNUQU5DRV9BRERfQkFORF8xID0gLTAuMTAwMDAwCiAgICBSRUZMRUNUQU5DRV9BRERfQkFORF8yID0gLTAuMTAwMDAwCiAgICBSRUZMRUNUQU5DRV9BRERfQkFORF8zID0gLTAuMTAwMDAwCiAgICBSRUZMRUNUQU5DRV9BRERfQkFORF80ID0gLTAuMTAwMDAwCiAgICBSRUZMRUNUQU5DRV9BRERfQkFORF81ID0gLTAuMTAwMDAwCiAgICBSRUZMRUNUQU5DRV9BRERfQkFORF82ID0gLTAuMTAwMDAwCiAgICBSRUZMRUNUQU5DRV9BRERfQkFORF83ID0gLTAuMTAwMDAwCiAgICBSRUZMRUNUQU5DRV9BRERfQkFORF84ID0gLTAuMTAwMDAwCiAgICBSRUZMRUNUQU5DRV9BRERfQkFORF85ID0gLTAuMTAwMDAwCiAgRU5EX0dST1VQID0gUkFESU9NRVRSSUNfUkVTQ0FMSU5HCiAgR1JPVVAgPSBUSVJTX1RIRVJNQUxfQ09OU1RBTlRTCiAgICBLMV9DT05TVEFOVF9CQU5EXzEwID0gNzc0Ljg4NTMKICAgIEsxX0NPTlNUQU5UX0JBTkRfMTEgPSA0ODAuODg4MwogICAgSzJfQ09OU1RBTlRfQkFORF8xMCA9IDEzMjEuMDc4OQogICAgSzJfQ09OU1RBTlRfQkFORF8xMSA9IDEyMDEuMTQ0MgogIEVORF9HUk9VUCA9IFRJUlNfVEhFUk1BTF9DT05TVEFOVFMKICBHUk9VUCA9IFBST0pFQ1RJT05fUEFSQU1FVEVSUwogICAgTUFQX1BST0pFQ1RJT04gPSAiVVRNIgogICAgREFUVU0gPSAiV0dTODQiCiAgICBFTExJUFNPSUQgPSAiV0dTODQiCiAgICBVVE1fWk9ORSA9IDEwCiAgICBHUklEX0NFTExfU0laRV9QQU5DSFJPTUFUSUMgPSAxNS4wMAogICAgR1JJRF9DRUxMX1NJWkVfUkVGTEVDVElWRSA9IDMwLjAwCiAgICBHUklEX0NFTExfU0laRV9USEVSTUFMID0gMzAuMDAKICAgIE9SSUVOVEFUSU9OID0gIk5PUlRIX1VQIgogICAgUkVTQU1QTElOR19PUFRJT04gPSAiQ1VCSUNfQ09OVk9MVVRJT04iCiAgRU5EX0dST1VQID0gUFJPSkVDVElPTl9QQVJBTUVURVJTCkVORF9HUk9VUCA9IEwxX01FVEFEQVRBX0ZJTEUKRU5ECg=="
+ }
+ },
+ {
+ "ID": "bae7504164fe4568",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/gcp-public-data-landsat/o?alt=json\u0026delimiter=\u0026pageToken=\u0026prefix=LC08%2FPRE%2F044%2F034%2FLC80440342016259LGN00%2F\u0026prettyPrint=false\u0026projection=full\u0026versions=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "3371507263865add4d1078e8a59589e5/13924784329696043957;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/gcp-public-data-landsat/o?alt=json\u0026delimiter=\u0026pageToken=\u0026prefix=LC08%2FPRE%2F044%2F034%2FLC80440342016259LGN00%2F\u0026prettyPrint=false\u0026projection=full\u0026versions=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0, must-revalidate, no-transform"
+ ],
+ "Content-Length": [
+ "12632"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:22 GMT"
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:25:22 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Backends": [
+ "vnns10:4437,/bns/yx/borg/yx/bns/blobstore2/bitpusher/171.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=MsysW7-rDoGczAK_vZWoDg"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yx/borg/yx/bns/blobstore2/bitpusher/171.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yx/borg/yx/bns/blobstore2/bitpusher/171:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "GgIYBiAB"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UoPpNMEoNzIsY9-tnx866qa9IS5nAVGL55dhuiLW3p0lfLVPHAlqtcguROClEpmEaHifrioDUOBOYq-N7-Al1bMt599WQ"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3RzIiwiaXRlbXMiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdCIsImlkIjoiZ2NwLXB1YmxpYy1kYXRhLWxhbmRzYXQvTEMwOC9QUkUvMDQ0LzAzNC9MQzgwNDQwMzQyMDE2MjU5TEdOMDAvTEM4MDQ0MDM0MjAxNjI1OUxHTjAwX0IxLlRJRi8xNDc1NTk5MTQ0NTc5MDAwIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ2NwLXB1YmxpYy1kYXRhLWxhbmRzYXQvby9MQzA4JTJGUFJFJTJGMDQ0JTJGMDM0JTJGTEM4MDQ0MDM0MjAxNjI1OUxHTjAwJTJGTEM4MDQ0MDM0MjAxNjI1OUxHTjAwX0IxLlRJRiIsIm5hbWUiOiJMQzA4L1BSRS8wNDQvMDM0L0xDODA0NDAzNDIwMTYyNTlMR04wMC9MQzgwNDQwMzQyMDE2MjU5TEdOMDBfQjEuVElGIiwiYnVja2V0IjoiZ2NwLXB1YmxpYy1kYXRhLWxhbmRzYXQiLCJnZW5lcmF0aW9uIjoiMTQ3NTU5OTE0NDU3OTAwMCIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoiYXBwbGljYXRpb24vb2N0ZXQtc3RyZWFtIiwidGltZUNyZWF0ZWQiOiIyMDE2LTEwLTA0VDE2OjM5OjA0LjU0NVoiLCJ1cGRhdGVkIjoiMjAxNi0xMC0wNFQxNjozOTowNC41NDVaIiwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJ0aW1lU3RvcmFnZUNsYXNzVXBkYXRlZCI6IjIwMTYtMTAtMDRUMTY6Mzk6MDQuNTQ1WiIsInNpemUiOiI3NDcyMTczNiIsIm1kNUhhc2giOiI4MzVMNkI1ZnJCMHpDQjZzMjJyMlN3PT0iLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ2NwLXB1YmxpYy1kYXRhLWxhbmRzYXQvby9MQzA4JTJGUFJFJTJGMDQ0JTJGMDM0JTJGTEM4MDQ0MDM0MjAxNjI1OUxHTjAwJTJGTEM4MDQ0MDM0MjAxNjI1OUxHTjAwX0IxLlRJRj9nZW5lcmF0aW9uPTE0NzU1OTkxNDQ1NzkwMDAmYWx0PW1lZGlhIiwiY3JjMzJjIjoiOTM0QnJnPT0iLCJldGFnIjoiQ0xqZjM1Ykx3YzhDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0IiwiaWQiOiJnY3AtcHVibGljLWRhdGEtbGFuZHNhdC9MQzA4L1BSRS8wNDQvMDM0L0xDODA0NDAzNDIwMTYyNTlMR04wMC9MQzgwNDQwMzQyMDE2MjU5TEdOMDBfQjEwLlRJRi8xNDc1NTk5MzEwMDQyMDAwIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ2NwLXB1YmxpYy1kYXRhLWxhbmRzYXQvby9MQzA4JTJGUFJFJTJGMDQ0JTJGMDM0JTJGTEM4MDQ0MDM0MjAxNjI1OUxHTjAwJTJGTEM4MDQ0MDM0MjAxNjI1OUxHTjAwX0IxMC5USUYiLCJuYW1lIjoiTEMwOC9QUkUvMDQ0LzAzNC9MQzgwNDQwMzQyMDE2MjU5TEdOMDAvTEM4MDQ0MDM0MjAxNjI1OUxHTjAwX0IxMC5USUYiLCJidWNrZXQiOiJnY3AtcHVibGljLWRhdGEtbGFuZHNhdCIsImdlbmVyYXRpb24iOiIxNDc1NTk5MzEwMDQyMDAwIiwibWV0YWdlbmVyYXRpb24iOiIxIiwiY29udGVudFR5cGUiOiJhcHBsaWNhdGlvbi9vY3RldC1zdHJlYW0iLCJ0aW1lQ3JlYXRlZCI6IjIwMTYtMTAtMDRUMTY6NDE6NTAuMDAyWiIsInVwZGF0ZWQiOiIyMDE2LTEwLTA0VDE2OjQxOjUwLjAwMloiLCJzdG9yYWdlQ2xhc3MiOiJTVEFOREFSRCIsInRpbWVTdG9yYWdlQ2xhc3NVcGRhdGVkIjoiMjAxNi0xMC0wNFQxNjo0MTo1MC4wMDJaIiwic2l6ZSI6IjU4NjgxMjI4IiwibWQ1SGFzaCI6IkJXNjIzeEhnMTVJaFYyNG1ickwrQXc9PSIsIm1lZGlhTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2Rvd25sb2FkL3N0b3JhZ2UvdjEvYi9nY3AtcHVibGljLWRhdGEtbGFuZHNhdC9vL0xDMDglMkZQUkUlMkYwNDQlMkYwMzQlMkZMQzgwNDQwMzQyMDE2MjU5TEdOMDAlMkZMQzgwNDQwMzQyMDE2MjU5TEdOMDBfQjEwLlRJRj9nZW5lcmF0aW9uPTE0NzU1OTkzMTAwNDIwMDAmYWx0PW1lZGlhIiwiY3JjMzJjIjoieHpWMmZnPT0iLCJldGFnIjoiQ0pEbjB1WEx3YzhDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0IiwiaWQiOiJnY3AtcHVibGljLWRhdGEtbGFuZHNhdC9MQzA4L1BSRS8wNDQvMDM0L0xDODA0NDAzNDIwMTYyNTlMR04wMC9MQzgwNDQwMzQyMDE2MjU5TEdOMDBfQjExLlRJRi8xNDc1NTk5MzE5MTg4MDAwIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ2NwLXB1YmxpYy1kYXRhLWxhbmRzYXQvby9MQzA4JTJGUFJFJTJGMDQ0JTJGMDM0JTJGTEM4MDQ0MDM0MjAxNjI1OUxHTjAwJTJGTEM4MDQ0MDM0MjAxNjI1OUxHTjAwX0IxMS5USUYiLCJuYW1lIjoiTEMwOC9QUkUvMDQ0LzAzNC9MQzgwNDQwMzQyMDE2MjU5TEdOMDAvTEM4MDQ0MDM0MjAxNjI1OUxHTjAwX0IxMS5USUYiLCJidWNrZXQiOiJnY3AtcHVibGljLWRhdGEtbGFuZHNhdCIsImdlbmVyYXRpb24iOiIxNDc1NTk5MzE5MTg4MDAwIiwibWV0YWdlbmVyYXRpb24iOiIxIiwiY29udGVudFR5cGUiOiJhcHBsaWNhdGlvbi9vY3RldC1zdHJlYW0iLCJ0aW1lQ3JlYXRlZCI6IjIwMTYtMTAtMDRUMTY6NDE6NTkuMTQ5WiIsInVwZGF0ZWQiOiIyMDE2LTEwLTA0VDE2OjQxOjU5LjE0OVoiLCJzdG9yYWdlQ2xhc3MiOiJTVEFOREFSRCIsInRpbWVTdG9yYWdlQ2xhc3NVcGRhdGVkIjoiMjAxNi0xMC0wNFQxNjo0MTo1OS4xNDlaIiwic2l6ZSI6IjU2Nzk2NDM5IiwibWQ1SGFzaCI6IkZPeGl5eEpYcUFmbFJUOGxGblNkT2c9PSIsIm1lZGlhTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2Rvd25sb2FkL3N0b3JhZ2UvdjEvYi9nY3AtcHVibGljLWRhdGEtbGFuZHNhdC9vL0xDMDglMkZQUkUlMkYwNDQlMkYwMzQlMkZMQzgwNDQwMzQyMDE2MjU5TEdOMDAlMkZMQzgwNDQwMzQyMDE2MjU5TEdOMDBfQjExLlRJRj9nZW5lcmF0aW9uPTE0NzU1OTkzMTkxODgwMDAmYWx0PW1lZGlhIiwiY3JjMzJjIjoicC9IRlZ3PT0iLCJldGFnIjoiQ0tDRWdlckx3YzhDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0IiwiaWQiOiJnY3AtcHVibGljLWRhdGEtbGFuZHNhdC9MQzA4L1BSRS8wNDQvMDM0L0xDODA0NDAzNDIwMTYyNTlMR04wMC9MQzgwNDQwMzQyMDE2MjU5TEdOMDBfQjIuVElGLzE0NzU1OTkxNjEyMjQwMDAiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nY3AtcHVibGljLWRhdGEtbGFuZHNhdC9vL0xDMDglMkZQUkUlMkYwNDQlMkYwMzQlMkZMQzgwNDQwMzQyMDE2MjU5TEdOMDAlMkZMQzgwNDQwMzQyMDE2MjU5TEdOMDBfQjIuVElGIiwibmFtZSI6IkxDMDgvUFJFLzA0NC8wMzQvTEM4MDQ0MDM0MjAxNjI1OUxHTjAwL0xDODA0NDAzNDIwMTYyNTlMR04wMF9CMi5USUYiLCJidWNrZXQiOiJnY3AtcHVibGljLWRhdGEtbGFuZHNhdCIsImdlbmVyYXRpb24iOiIxNDc1NTk5MTYxMjI0MDAwIiwibWV0YWdlbmVyYXRpb24iOiIxIiwiY29udGVudFR5cGUiOiJhcHBsaWNhdGlvbi9vY3RldC1zdHJlYW0iLCJ0aW1lQ3JlYXRlZCI6IjIwMTYtMTAtMDRUMTY6Mzk6MjEuMTYwWiIsInVwZGF0ZWQiOiIyMDE2LTEwLTA0VDE2OjM5OjIxLjE2MFoiLCJzdG9yYWdlQ2xhc3MiOiJTVEFOREFSRCIsInRpbWVTdG9yYWdlQ2xhc3NVcGRhdGVkIjoiMjAxNi0xMC0wNFQxNjozOToyMS4xNjBaIiwic2l6ZSI6Ijc3MTQ5NzcxIiwibWQ1SGFzaCI6Ik1QMjJ6ak9vMk5zMGlZNE1UUEpSd0E9PSIsIm1lZGlhTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2Rvd25sb2FkL3N0b3JhZ2UvdjEvYi9nY3AtcHVibGljLWRhdGEtbGFuZHNhdC9vL0xDMDglMkZQUkUlMkYwNDQlMkYwMzQlMkZMQzgwNDQwMzQyMDE2MjU5TEdOMDAlMkZMQzgwNDQwMzQyMDE2MjU5TEdOMDBfQjIuVElGP2dlbmVyYXRpb249MTQ3NTU5OTE2MTIyNDAwMCZhbHQ9bWVkaWEiLCJjcmMzMmMiOiJySThZUmc9PSIsImV0YWciOiJDTURXMTU3THdjOENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdjcC1wdWJsaWMtZGF0YS1sYW5kc2F0L0xDMDgvUFJFLzA0NC8wMzQvTEM4MDQ0MDM0MjAxNjI1OUxHTjAwL0xDODA0NDAzNDIwMTYyNTlMR04wMF9CMy5USUYvMTQ3NTU5OTE3ODQzNTAwMCIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2djcC1wdWJsaWMtZGF0YS1sYW5kc2F0L28vTEMwOCUyRlBSRSUyRjA0NCUyRjAzNCUyRkxDODA0NDAzNDIwMTYyNTlMR04wMCUyRkxDODA0NDAzNDIwMTYyNTlMR04wMF9CMy5USUYiLCJuYW1lIjoiTEMwOC9QUkUvMDQ0LzAzNC9MQzgwNDQwMzQyMDE2MjU5TEdOMDAvTEM4MDQ0MDM0MjAxNjI1OUxHTjAwX0IzLlRJRiIsImJ1Y2tldCI6ImdjcC1wdWJsaWMtZGF0YS1sYW5kc2F0IiwiZ2VuZXJhdGlvbiI6IjE0NzU1OTkxNzg0MzUwMDAiLCJtZXRhZ2VuZXJhdGlvbiI6IjEiLCJjb250ZW50VHlwZSI6ImFwcGxpY2F0aW9uL29jdGV0LXN0cmVhbSIsInRpbWVDcmVhdGVkIjoiMjAxNi0xMC0wNFQxNjozOTozOC4zNzZaIiwidXBkYXRlZCI6IjIwMTYtMTAtMDRUMTY6Mzk6MzguMzc2WiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE2LTEwLTA0VDE2OjM5OjM4LjM3NloiLCJzaXplIjoiODAyOTM2ODciLCJtZDVIYXNoIjoidlFNaUdlRHVCZzZjcjNYc2ZJRWpvUT09IiwibWVkaWFMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vZG93bmxvYWQvc3RvcmFnZS92MS9iL2djcC1wdWJsaWMtZGF0YS1sYW5kc2F0L28vTEMwOCUyRlBSRSUyRjA0NCUyRjAzNCUyRkxDODA0NDAzNDIwMTYyNTlMR04wMCUyRkxDODA0NDAzNDIwMTYyNTlMR04wMF9CMy5USUY/Z2VuZXJhdGlvbj0xNDc1NTk5MTc4NDM1MDAwJmFsdD1tZWRpYSIsImNyYzMyYyI6InVaQnJuQT09IiwiZXRhZyI6IkNMaVQ4cWJMd2M4Q0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdCIsImlkIjoiZ2NwLXB1YmxpYy1kYXRhLWxhbmRzYXQvTEMwOC9QUkUvMDQ0LzAzNC9MQzgwNDQwMzQyMDE2MjU5TEdOMDAvTEM4MDQ0MDM0MjAxNjI1OUxHTjAwX0I0LlRJRi8xNDc1NTk5MTk0MjY4MDAwIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ2NwLXB1YmxpYy1kYXRhLWxhbmRzYXQvby9MQzA4JTJGUFJFJTJGMDQ0JTJGMDM0JTJGTEM4MDQ0MDM0MjAxNjI1OUxHTjAwJTJGTEM4MDQ0MDM0MjAxNjI1OUxHTjAwX0I0LlRJRiIsIm5hbWUiOiJMQzA4L1BSRS8wNDQvMDM0L0xDODA0NDAzNDIwMTYyNTlMR04wMC9MQzgwNDQwMzQyMDE2MjU5TEdOMDBfQjQuVElGIiwiYnVja2V0IjoiZ2NwLXB1YmxpYy1kYXRhLWxhbmRzYXQiLCJnZW5lcmF0aW9uIjoiMTQ3NTU5OTE5NDI2ODAwMCIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoiYXBwbGljYXRpb24vb2N0ZXQtc3RyZWFtIiwidGltZUNyZWF0ZWQiOiIyMDE2LTEwLTA0VDE2OjM5OjU0LjIxMVoiLCJ1cGRhdGVkIjoiMjAxNi0xMC0wNFQxNjozOTo1NC4yMTFaIiwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJ0aW1lU3RvcmFnZUNsYXNzVXBkYXRlZCI6IjIwMTYtMTAtMDRUMTY6Mzk6NTQuMjExWiIsInNpemUiOiI4NDQ5NDM3NSIsIm1kNUhhc2giOiJGV2VWQTAxWk8wK21BK0VSRmN6dWhBPT0iLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ2NwLXB1YmxpYy1kYXRhLWxhbmRzYXQvby9MQzA4JTJGUFJFJTJGMDQ0JTJGMDM0JTJGTEM4MDQ0MDM0MjAxNjI1OUxHTjAwJTJGTEM4MDQ0MDM0MjAxNjI1OUxHTjAwX0I0LlRJRj9nZW5lcmF0aW9uPTE0NzU1OTkxOTQyNjgwMDAmYWx0PW1lZGlhIiwiY3JjMzJjIjoiV2VzNW9RPT0iLCJldGFnIjoiQ09EQ3VLN0x3YzhDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0IiwiaWQiOiJnY3AtcHVibGljLWRhdGEtbGFuZHNhdC9MQzA4L1BSRS8wNDQvMDM0L0xDODA0NDAzNDIwMTYyNTlMR04wMC9MQzgwNDQwMzQyMDE2MjU5TEdOMDBfQjUuVElGLzE0NzU1OTkyMDI5NzkwMDAiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nY3AtcHVibGljLWRhdGEtbGFuZHNhdC9vL0xDMDglMkZQUkUlMkYwNDQlMkYwMzQlMkZMQzgwNDQwMzQyMDE2MjU5TEdOMDAlMkZMQzgwNDQwMzQyMDE2MjU5TEdOMDBfQjUuVElGIiwibmFtZSI6IkxDMDgvUFJFLzA0NC8wMzQvTEM4MDQ0MDM0MjAxNjI1OUxHTjAwL0xDODA0NDAzNDIwMTYyNTlMR04wMF9CNS5USUYiLCJidWNrZXQiOiJnY3AtcHVibGljLWRhdGEtbGFuZHNhdCIsImdlbmVyYXRpb24iOiIxNDc1NTk5MjAyOTc5MDAwIiwibWV0YWdlbmVyYXRpb24iOiIxIiwiY29udGVudFR5cGUiOiJhcHBsaWNhdGlvbi9vY3RldC1zdHJlYW0iLCJ0aW1lQ3JlYXRlZCI6IjIwMTYtMTAtMDRUMTY6NDA6MDIuOTM3WiIsInVwZGF0ZWQiOiIyMDE2LTEwLTA0VDE2OjQwOjAyLjkzN1oiLCJzdG9yYWdlQ2xhc3MiOiJTVEFOREFSRCIsInRpbWVTdG9yYWdlQ2xhc3NVcGRhdGVkIjoiMjAxNi0xMC0wNFQxNjo0MDowMi45MzdaIiwic2l6ZSI6Ijg5MzE4NDY3IiwibWQ1SGFzaCI6InA0b3lLSEFHbzVLeTNLZzFUSzFaUXc9PSIsIm1lZGlhTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2Rvd25sb2FkL3N0b3JhZ2UvdjEvYi9nY3AtcHVibGljLWRhdGEtbGFuZHNhdC9vL0xDMDglMkZQUkUlMkYwNDQlMkYwMzQlMkZMQzgwNDQwMzQyMDE2MjU5TEdOMDAlMkZMQzgwNDQwMzQyMDE2MjU5TEdOMDBfQjUuVElGP2dlbmVyYXRpb249MTQ3NTU5OTIwMjk3OTAwMCZhbHQ9bWVkaWEiLCJjcmMzMmMiOiJwVFl1dXc9PSIsImV0YWciOiJDTGlaekxMTHdjOENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdjcC1wdWJsaWMtZGF0YS1sYW5kc2F0L0xDMDgvUFJFLzA0NC8wMzQvTEM4MDQ0MDM0MjAxNjI1OUxHTjAwL0xDODA0NDAzNDIwMTYyNTlMR04wMF9CNi5USUYvMTQ3NTU5OTIzMzQ4MTAwMCIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2djcC1wdWJsaWMtZGF0YS1sYW5kc2F0L28vTEMwOCUyRlBSRSUyRjA0NCUyRjAzNCUyRkxDODA0NDAzNDIwMTYyNTlMR04wMCUyRkxDODA0NDAzNDIwMTYyNTlMR04wMF9CNi5USUYiLCJuYW1lIjoiTEMwOC9QUkUvMDQ0LzAzNC9MQzgwNDQwMzQyMDE2MjU5TEdOMDAvTEM4MDQ0MDM0MjAxNjI1OUxHTjAwX0I2LlRJRiIsImJ1Y2tldCI6ImdjcC1wdWJsaWMtZGF0YS1sYW5kc2F0IiwiZ2VuZXJhdGlvbiI6IjE0NzU1OTkyMzM0ODEwMDAiLCJtZXRhZ2VuZXJhdGlvbiI6IjEiLCJjb250ZW50VHlwZSI6ImFwcGxpY2F0aW9uL29jdGV0LXN0cmVhbSIsInRpbWVDcmVhdGVkIjoiMjAxNi0xMC0wNFQxNjo0MDozMy4zNDlaIiwidXBkYXRlZCI6IjIwMTYtMTAtMDRUMTY6NDA6MzMuMzQ5WiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE2LTEwLTA0VDE2OjQwOjMzLjM0OVoiLCJzaXplIjoiODk0NjU3NjciLCJtZDVIYXNoIjoiMlo3MkdVT0t0bGd6VDlWUlNHWVhqQT09IiwibWVkaWFMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vZG93bmxvYWQvc3RvcmFnZS92MS9iL2djcC1wdWJsaWMtZGF0YS1sYW5kc2F0L28vTEMwOCUyRlBSRSUyRjA0NCUyRjAzNCUyRkxDODA0NDAzNDIwMTYyNTlMR04wMCUyRkxDODA0NDAzNDIwMTYyNTlMR04wMF9CNi5USUY/Z2VuZXJhdGlvbj0xNDc1NTk5MjMzNDgxMDAwJmFsdD1tZWRpYSIsImNyYzMyYyI6IklOWEhiUT09IiwiZXRhZyI6IkNLanlrY0hMd2M4Q0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdCIsImlkIjoiZ2NwLXB1YmxpYy1kYXRhLWxhbmRzYXQvTEMwOC9QUkUvMDQ0LzAzNC9MQzgwNDQwMzQyMDE2MjU5TEdOMDAvTEM4MDQ0MDM0MjAxNjI1OUxHTjAwX0I3LlRJRi8xNDc1NTk5MjQxMDU1MDAwIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ2NwLXB1YmxpYy1kYXRhLWxhbmRzYXQvby9MQzA4JTJGUFJFJTJGMDQ0JTJGMDM0JTJGTEM4MDQ0MDM0MjAxNjI1OUxHTjAwJTJGTEM4MDQ0MDM0MjAxNjI1OUxHTjAwX0I3LlRJRiIsIm5hbWUiOiJMQzA4L1BSRS8wNDQvMDM0L0xDODA0NDAzNDIwMTYyNTlMR04wMC9MQzgwNDQwMzQyMDE2MjU5TEdOMDBfQjcuVElGIiwiYnVja2V0IjoiZ2NwLXB1YmxpYy1kYXRhLWxhbmRzYXQiLCJnZW5lcmF0aW9uIjoiMTQ3NTU5OTI0MTA1NTAwMCIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoiYXBwbGljYXRpb24vb2N0ZXQtc3RyZWFtIiwidGltZUNyZWF0ZWQiOiIyMDE2LTEwLTA0VDE2OjQwOjQxLjAyMVoiLCJ1cGRhdGVkIjoiMjAxNi0xMC0wNFQxNjo0MDo0MS4wMjFaIiwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJ0aW1lU3RvcmFnZUNsYXNzVXBkYXRlZCI6IjIwMTYtMTAtMDRUMTY6NDA6NDEuMDIxWiIsInNpemUiOiI4NjQ2MjYxNCIsIm1kNUhhc2giOiI4Z1BOUTdRWm9GMkNOWlo5RW1ybG9nPT0iLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ2NwLXB1YmxpYy1kYXRhLWxhbmRzYXQvby9MQzA4JTJGUFJFJTJGMDQ0JTJGMDM0JTJGTEM4MDQ0MDM0MjAxNjI1OUxHTjAwJTJGTEM4MDQ0MDM0MjAxNjI1OUxHTjAwX0I3LlRJRj9nZW5lcmF0aW9uPTE0NzU1OTkyNDEwNTUwMDAmYWx0PW1lZGlhIiwiY3JjMzJjIjoidXdDRCtBPT0iLCJldGFnIjoiQ0ppVzRNVEx3YzhDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0IiwiaWQiOiJnY3AtcHVibGljLWRhdGEtbGFuZHNhdC9MQzA4L1BSRS8wNDQvMDM0L0xDODA0NDAzNDIwMTYyNTlMR04wMC9MQzgwNDQwMzQyMDE2MjU5TEdOMDBfQjguVElGLzE0NzU1OTkyODEzMzgwMDAiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nY3AtcHVibGljLWRhdGEtbGFuZHNhdC9vL0xDMDglMkZQUkUlMkYwNDQlMkYwMzQlMkZMQzgwNDQwMzQyMDE2MjU5TEdOMDAlMkZMQzgwNDQwMzQyMDE2MjU5TEdOMDBfQjguVElGIiwibmFtZSI6IkxDMDgvUFJFLzA0NC8wMzQvTEM4MDQ0MDM0MjAxNjI1OUxHTjAwL0xDODA0NDAzNDIwMTYyNTlMR04wMF9COC5USUYiLCJidWNrZXQiOiJnY3AtcHVibGljLWRhdGEtbGFuZHNhdCIsImdlbmVyYXRpb24iOiIxNDc1NTk5MjgxMzM4MDAwIiwibWV0YWdlbmVyYXRpb24iOiIxIiwiY29udGVudFR5cGUiOiJhcHBsaWNhdGlvbi9vY3RldC1zdHJlYW0iLCJ0aW1lQ3JlYXRlZCI6IjIwMTYtMTAtMDRUMTY6NDE6MjEuMzAwWiIsInVwZGF0ZWQiOiIyMDE2LTEwLTA0VDE2OjQxOjIxLjMwMFoiLCJzdG9yYWdlQ2xhc3MiOiJTVEFOREFSRCIsInRpbWVTdG9yYWdlQ2xhc3NVcGRhdGVkIjoiMjAxNi0xMC0wNFQxNjo0MToyMS4zMDBaIiwic2l6ZSI6IjMxODg4Nzc3NCIsIm1kNUhhc2giOiJ5Nzk1THJVekJ3azJ0TDZQTTAxY0VBPT0iLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ2NwLXB1YmxpYy1kYXRhLWxhbmRzYXQvby9MQzA4JTJGUFJFJTJGMDQ0JTJGMDM0JTJGTEM4MDQ0MDM0MjAxNjI1OUxHTjAwJTJGTEM4MDQ0MDM0MjAxNjI1OUxHTjAwX0I4LlRJRj9nZW5lcmF0aW9uPTE0NzU1OTkyODEzMzgwMDAmYWx0PW1lZGlhIiwiY3JjMzJjIjoiWjMrWmhRPT0iLCJldGFnIjoiQ0pEdCt0Zkx3YzhDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0IiwiaWQiOiJnY3AtcHVibGljLWRhdGEtbGFuZHNhdC9MQzA4L1BSRS8wNDQvMDM0L0xDODA0NDAzNDIwMTYyNTlMR04wMC9MQzgwNDQwMzQyMDE2MjU5TEdOMDBfQjkuVElGLzE0NzU1OTkyOTE0MjUwMDAiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nY3AtcHVibGljLWRhdGEtbGFuZHNhdC9vL0xDMDglMkZQUkUlMkYwNDQlMkYwMzQlMkZMQzgwNDQwMzQyMDE2MjU5TEdOMDAlMkZMQzgwNDQwMzQyMDE2MjU5TEdOMDBfQjkuVElGIiwibmFtZSI6IkxDMDgvUFJFLzA0NC8wMzQvTEM4MDQ0MDM0MjAxNjI1OUxHTjAwL0xDODA0NDAzNDIwMTYyNTlMR04wMF9COS5USUYiLCJidWNrZXQiOiJnY3AtcHVibGljLWRhdGEtbGFuZHNhdCIsImdlbmVyYXRpb24iOiIxNDc1NTk5MjkxNDI1MDAwIiwibWV0YWdlbmVyYXRpb24iOiIxIiwiY29udGVudFR5cGUiOiJhcHBsaWNhdGlvbi9vY3RldC1zdHJlYW0iLCJ0aW1lQ3JlYXRlZCI6IjIwMTYtMTAtMDRUMTY6NDE6MzEuMzYxWiIsInVwZGF0ZWQiOiIyMDE2LTEwLTA0VDE2OjQxOjMxLjM2MVoiLCJzdG9yYWdlQ2xhc3MiOiJTVEFOREFSRCIsInRpbWVTdG9yYWdlQ2xhc3NVcGRhdGVkIjoiMjAxNi0xMC0wNFQxNjo0MTozMS4zNjFaIiwic2l6ZSI6IjQ0MzA4MjA1IiwibWQ1SGFzaCI6IjVCNDFFMkRCYlk1MnBZUFVHVmg5NWc9PSIsIm1lZGlhTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2Rvd25sb2FkL3N0b3JhZ2UvdjEvYi9nY3AtcHVibGljLWRhdGEtbGFuZHNhdC9vL0xDMDglMkZQUkUlMkYwNDQlMkYwMzQlMkZMQzgwNDQwMzQyMDE2MjU5TEdOMDAlMkZMQzgwNDQwMzQyMDE2MjU5TEdOMDBfQjkuVElGP2dlbmVyYXRpb249MTQ3NTU5OTI5MTQyNTAwMCZhbHQ9bWVkaWEiLCJjcmMzMmMiOiJhME9EUXc9PSIsImV0YWciOiJDT2pCNHR6THdjOENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdjcC1wdWJsaWMtZGF0YS1sYW5kc2F0L0xDMDgvUFJFLzA0NC8wMzQvTEM4MDQ0MDM0MjAxNjI1OUxHTjAwL0xDODA0NDAzNDIwMTYyNTlMR04wMF9CUUEuVElGLzE0NzU1OTkzMjcyMjIwMDAiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nY3AtcHVibGljLWRhdGEtbGFuZHNhdC9vL0xDMDglMkZQUkUlMkYwNDQlMkYwMzQlMkZMQzgwNDQwMzQyMDE2MjU5TEdOMDAlMkZMQzgwNDQwMzQyMDE2MjU5TEdOMDBfQlFBLlRJRiIsIm5hbWUiOiJMQzA4L1BSRS8wNDQvMDM0L0xDODA0NDAzNDIwMTYyNTlMR04wMC9MQzgwNDQwMzQyMDE2MjU5TEdOMDBfQlFBLlRJRiIsImJ1Y2tldCI6ImdjcC1wdWJsaWMtZGF0YS1sYW5kc2F0IiwiZ2VuZXJhdGlvbiI6IjE0NzU1OTkzMjcyMjIwMDAiLCJtZXRhZ2VuZXJhdGlvbiI6IjEiLCJjb250ZW50VHlwZSI6ImFwcGxpY2F0aW9uL29jdGV0LXN0cmVhbSIsInRpbWVDcmVhdGVkIjoiMjAxNi0xMC0wNFQxNjo0MjowNy4xNTlaIiwidXBkYXRlZCI6IjIwMTYtMTAtMDRUMTY6NDI6MDcuMTU5WiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE2LTEwLTA0VDE2OjQyOjA3LjE1OVoiLCJzaXplIjoiMzM1NDcxOSIsIm1kNUhhc2giOiJ6cWlndmw1RW52bWkvR0xjOHlINTFBPT0iLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ2NwLXB1YmxpYy1kYXRhLWxhbmRzYXQvby9MQzA4JTJGUFJFJTJGMDQ0JTJGMDM0JTJGTEM4MDQ0MDM0MjAxNjI1OUxHTjAwJTJGTEM4MDQ0MDM0MjAxNjI1OUxHTjAwX0JRQS5USUY/Z2VuZXJhdGlvbj0xNDc1NTk5MzI3MjIyMDAwJmFsdD1tZWRpYSIsImNyYzMyYyI6IldPQmdLQT09IiwiZXRhZyI6IkNQQ3g2KzNMd2M4Q0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdCIsImlkIjoiZ2NwLXB1YmxpYy1kYXRhLWxhbmRzYXQvTEMwOC9QUkUvMDQ0LzAzNC9MQzgwNDQwMzQyMDE2MjU5TEdOMDAvTEM4MDQ0MDM0MjAxNjI1OUxHTjAwX01UTC50eHQvMTQ3NTU5OTMyNzY2MjAwMCIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2djcC1wdWJsaWMtZGF0YS1sYW5kc2F0L28vTEMwOCUyRlBSRSUyRjA0NCUyRjAzNCUyRkxDODA0NDAzNDIwMTYyNTlMR04wMCUyRkxDODA0NDAzNDIwMTYyNTlMR04wMF9NVEwudHh0IiwibmFtZSI6IkxDMDgvUFJFLzA0NC8wMzQvTEM4MDQ0MDM0MjAxNjI1OUxHTjAwL0xDODA0NDAzNDIwMTYyNTlMR04wMF9NVEwudHh0IiwiYnVja2V0IjoiZ2NwLXB1YmxpYy1kYXRhLWxhbmRzYXQiLCJnZW5lcmF0aW9uIjoiMTQ3NTU5OTMyNzY2MjAwMCIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoiYXBwbGljYXRpb24vb2N0ZXQtc3RyZWFtIiwidGltZUNyZWF0ZWQiOiIyMDE2LTEwLTA0VDE2OjQyOjA3LjYxOFoiLCJ1cGRhdGVkIjoiMjAxNi0xMC0wNFQxNjo0MjowNy42MThaIiwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJ0aW1lU3RvcmFnZUNsYXNzVXBkYXRlZCI6IjIwMTYtMTAtMDRUMTY6NDI6MDcuNjE4WiIsInNpemUiOiI3OTAzIiwibWQ1SGFzaCI6ImVsL1VkRHZXUjBoZmlFbHZyYkJjVVE9PSIsIm1lZGlhTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2Rvd25sb2FkL3N0b3JhZ2UvdjEvYi9nY3AtcHVibGljLWRhdGEtbGFuZHNhdC9vL0xDMDglMkZQUkUlMkYwNDQlMkYwMzQlMkZMQzgwNDQwMzQyMDE2MjU5TEdOMDAlMkZMQzgwNDQwMzQyMDE2MjU5TEdOMDBfTVRMLnR4dD9nZW5lcmF0aW9uPTE0NzU1OTkzMjc2NjIwMDAmYWx0PW1lZGlhIiwiY3JjMzJjIjoiUFdCdDhnPT0iLCJldGFnIjoiQ0xDZmh1N0x3YzhDRUFFPSJ9XX0="
+ }
+ },
+ {
+ "ID": "c7689e7bd54ed467",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://storage.googleapis.com/go-integration-test-20180927-44630911863640-0001/noauth",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "User-Agent": [
+ "Go-http-client/1.1"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "0662fa93d955eeb17a6331e1cf6e0447/15514914763081451604;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "storage.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://storage.googleapis.com/go-integration-test-20180927-44630911863640-0001/noauth"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 403,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0"
+ ],
+ "Content-Length": [
+ "247"
+ ],
+ "Content-Type": [
+ "application/xml; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:22 GMT"
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:25:22 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "X-Google-Backends": [
+ "/bns/xh/borg/xh/bns/cloud-storage/prod-cloud-storage-frontend.frontend/2,/bns/xh/borg/xh/bns/blobstore2/bitpusher/8.scotty,aclgag19:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=MsysW9eyIO-pswargaYo"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "aclgag19:443,/bns/xh/borg/xh/bns/blobstore2/bitpusher/8.scotty,aclgag19:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/xh/borg/xh/bns/blobstore2/bitpusher/8:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBJ"
+ ],
+ "X-Guploader-Customer": [
+ "cloud-storage"
+ ],
+ "X-Guploader-Request-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Upload-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UqSWX6bbSACxWtisyOqrB0FFhXZvIKKF-1cOgd0ZqNByKVEy5Q1lWj1qHMWRQt3MxzCYbUkOAR2SUmGHE5OR-FZX-WY6Q"
+ ]
+ },
+ "Body": "PD94bWwgdmVyc2lvbj0nMS4wJyBlbmNvZGluZz0nVVRGLTgnPz48RXJyb3I+PENvZGU+QWNjZXNzRGVuaWVkPC9Db2RlPjxNZXNzYWdlPkFjY2VzcyBkZW5pZWQuPC9NZXNzYWdlPjxEZXRhaWxzPkFub255bW91cyBjYWxsZXIgZG9lcyBub3QgaGF2ZSBzdG9yYWdlLm9iamVjdHMuZ2V0IGFjY2VzcyB0byBnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvbm9hdXRoLjwvRGV0YWlscz48L0Vycm9yPg=="
+ }
+ },
+ {
+ "ID": "96502a977c21b138",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Content-Type": [
+ "multipart/related; boundary=00e007d7435d4eaf0875edb23883d9d4bbfaded1bae201e5f54a947851a5"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "38c6656bc98c27aef7b61563fb1e9022/16346289697710693283;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "LS0wMGUwMDdkNzQzNWQ0ZWFmMDg3NWVkYjIzODgzZDlkNGJiZmFkZWQxYmFlMjAxZTVmNTRhOTQ3ODUxYTUNCkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vanNvbg0KDQp7ImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsImNhY2hlQ29udHJvbCI6InB1YmxpYywgbWF4LWFnZT02MCIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbiIsIm5hbWUiOiJub2F1dGgifQoNCi0tMDBlMDA3ZDc0MzVkNGVhZjA4NzVlZGIyMzg4M2Q5ZDRiYmZhZGVkMWJhZTIwMWU1ZjU0YTk0Nzg1MWE1DQpDb250ZW50LVR5cGU6IHRleHQvcGxhaW4NCg0KYg0KLS0wMGUwMDdkNzQzNWQ0ZWFmMDg3NWVkYjIzODgzZDlkNGJiZmFkZWQxYmFlMjAxZTVmNTRhOTQ3ODUxYTUtLQ0K"
+ },
+ "Response": {
+ "StatusCode": 401,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Content-Length": [
+ "30201"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:23 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "Www-Authenticate": [
+ "Bearer realm=\"https://accounts.google.com/\""
+ ],
+ "X-Google-Backends": [
+ "vrqn25:4154,/bns/yv/borg/yv/bns/blobstore2/bitpusher/382.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=MsysW8ieMteFggSMxJTIBQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/382.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/382:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "GgIYBiAB"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_single_post_uploads"
+ ],
+ "X-Guploader-Request-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Upload-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Uqp-fy5ql5YosFNoW2Ob6gd1EZdom7gCNISKx9v42hqbTrP0Q0Cry_pxzCAPHGXPMO8LuXmBEIylU3Z5u2Xcl57AYd52A"
+ ]
+ },
+ "Body": "eyJlcnJvciI6eyJlcnJvcnMiOlt7ImRvbWFpbiI6Imdsb2JhbCIsInJlYXNvbiI6InJlcXVpcmVkIiwibWVzc2FnZSI6IkFub255bW91cyBjYWxsZXIgZG9lcyBub3QgaGF2ZSBzdG9yYWdlLm9iamVjdHMuY3JlYXRlIGFjY2VzcyB0byBnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvbm9hdXRoLiIsImxvY2F0aW9uVHlwZSI6ImhlYWRlciIsImxvY2F0aW9uIjoiQXV0aG9yaXphdGlvbiIsImRlYnVnSW5mbyI6ImNvbS5nb29nbGUubmV0LnJwYzMuUnBjRXhjZXB0aW9uOiBjbG91ZC5iaWdzdG9yZS5SZXNwb25zZUNvZGUuRXJyb3JDb2RlOjpBQ0NFU1NfREVOSUVEOiBBbm9ueW1vdXMgY2FsbGVyIGRvZXMgbm90IGhhdmUgc3RvcmFnZS5vYmplY3RzLmNyZWF0ZSBhY2Nlc3MgdG8gZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL25vYXV0aC5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udG9ScGMzRXhjZXB0aW9uKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MTM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuSW5zZXJ0T2JqZWN0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChJbnNlcnRPYmplY3QuamF2YToyMTcpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5JbnNlcnRPYmplY3QuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKEluc2VydE9iamVjdC5qYXZhOjUxKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmZyYW1ld29yay5SZXF1ZXN0SGFuZGxlci5oYW5kbGUoUmVxdWVzdEhhbmRsZXIuamF2YToyOTQpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uT2JqZWN0c0RlbGVnYXRvci5pbnNlcnQoT2JqZWN0c0RlbGVnYXRvci5qYXZhOjk1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5ScGNSZWNlaXZlci5sYW1iZGEkcHJvY2Vzc1JlcXVlc3RBc3luYyQ0KFJwY1JlY2VpdmVyLmphdmE6MjAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5Bc3luY0V4ZWN1dG9yLmxhbWJkYSRzdWJtaXQkMChBc3luY0V4ZWN1dG9yLmphdmE6MjcyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoQ29udGV4dFJ1bm5hYmxlLmphdmE6NTApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlJDEucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM5KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo3Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5FeGVjdXRvcnMkUnVubmFibGVBZGFwdGVyLmNhbGwoRXhlY3V0b3JzLmphdmE6NTExKVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5GdXR1cmVUYXNrLnJ1bihGdXR1cmVUYXNrLmphdmE6MjY2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IucnVuV29ya2VyKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjExNDkpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvciRXb3JrZXIucnVuKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjYyNClcblx0YXQgamF2YS5sYW5nLlRocmVhZC5ydW4oVGhyZWFkLmphdmE6NzQ4KVxuQ2F1c2VkIGJ5OiBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbjogQW5vbnltb3VzIGNhbGxlciBkb2VzIG5vdCBoYXZlIHN0b3JhZ2Uub2JqZWN0cy5jcmVhdGUgYWNjZXNzIHRvIGdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9ub2F1dGguXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93T25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjI5MClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMSlcblx0Li4uIDE3IG1vcmVcblxuY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUuRmF1bHQ6IEltbXV0YWJsZUVycm9yRGVmaW5pdGlvbntiYXNlPUxPR0lOX1JFUVVJUkVELCBjYXRlZ29yeT1VU0VSX0VSUk9SLCBjYXVzZT1jb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS5GYXVsdDogSW1tdXRhYmxlRXJyb3JEZWZpbml0aW9ue2Jhc2U9TE9HSU5fUkVRVUlSRUQsIGNhdGVnb3J5PVVTRVJfRVJST1IsIGNhdXNlPW51bGwsIGRlYnVnSW5mbz1jb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6QUNDRVNTX0RFTklFRDogQW5vbnltb3VzIGNhbGxlciBkb2VzIG5vdCBoYXZlIHN0b3JhZ2Uub2JqZWN0cy5jcmVhdGUgYWNjZXNzIHRvIGdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9ub2F1dGguXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRvUnBjM0V4Y2VwdGlvbihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjEzNSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5vYmplY3RzLkluc2VydE9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoSW5zZXJ0T2JqZWN0LmphdmE6MjE3KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuSW5zZXJ0T2JqZWN0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChJbnNlcnRPYmplY3QuamF2YTo1MSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLk9iamVjdHNEZWxlZ2F0b3IuaW5zZXJ0KE9iamVjdHNEZWxlZ2F0b3IuamF2YTo5NSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uUnBjUmVjZWl2ZXIubGFtYmRhJHByb2Nlc3NSZXF1ZXN0QXN5bmMkNChScGNSZWNlaXZlci5qYXZhOjIwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uQXN5bmNFeGVjdXRvci5sYW1iZGEkc3VibWl0JDAoQXN5bmNFeGVjdXRvci5qYXZhOjI3Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KENvbnRleHRSdW5uYWJsZS5qYXZhOjUwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZSQxLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozOSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NzIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozNilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRXhlY3V0b3JzJFJ1bm5hYmxlQWRhcHRlci5jYWxsKEV4ZWN1dG9ycy5qYXZhOjUxMSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRnV0dXJlVGFzay5ydW4oRnV0dXJlVGFzay5qYXZhOjI2Nilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yLnJ1bldvcmtlcihUaHJlYWRQb29sRXhlY3V0b3IuamF2YToxMTQ5KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IkV29ya2VyLnJ1bihUaHJlYWRQb29sRXhlY3V0b3IuamF2YTo2MjQpXG5cdGF0IGphdmEubGFuZy5UaHJlYWQucnVuKFRocmVhZC5qYXZhOjc0OClcbkNhdXNlZCBieTogY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb246IEFub255bW91cyBjYWxsZXIgZG9lcyBub3QgaGF2ZSBzdG9yYWdlLm9iamVjdHMuY3JlYXRlIGFjY2VzcyB0byBnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvbm9hdXRoLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxNyBtb3JlXG4sIGRvbWFpbj1nbG9iYWwsIGV4dGVuZGVkSGVscD1udWxsLCBodHRwSGVhZGVycz17fSwgaHR0cFN0YXR1cz11bmF1dGhvcml6ZWQsIGludGVybmFsUmVhc29uPVJlYXNvbnthcmd1bWVudHM9e30sIGNhdXNlPW51bGwsIGNvZGU9Z2RhdGEuQ29yZUVycm9yRG9tYWluLlJFUVVJUkVELCBjcmVhdGVkQnlCYWNrZW5kPXRydWUsIGRlYnVnTWVzc2FnZT1jb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6QUNDRVNTX0RFTklFRDogQW5vbnltb3VzIGNhbGxlciBkb2VzIG5vdCBoYXZlIHN0b3JhZ2Uub2JqZWN0cy5jcmVhdGUgYWNjZXNzIHRvIGdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9ub2F1dGguXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRvUnBjM0V4Y2VwdGlvbihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjEzNSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5vYmplY3RzLkluc2VydE9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoSW5zZXJ0T2JqZWN0LmphdmE6MjE3KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuSW5zZXJ0T2JqZWN0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChJbnNlcnRPYmplY3QuamF2YTo1MSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLk9iamVjdHNEZWxlZ2F0b3IuaW5zZXJ0KE9iamVjdHNEZWxlZ2F0b3IuamF2YTo5NSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uUnBjUmVjZWl2ZXIubGFtYmRhJHByb2Nlc3NSZXF1ZXN0QXN5bmMkNChScGNSZWNlaXZlci5qYXZhOjIwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uQXN5bmNFeGVjdXRvci5sYW1iZGEkc3VibWl0JDAoQXN5bmNFeGVjdXRvci5qYXZhOjI3Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KENvbnRleHRSdW5uYWJsZS5qYXZhOjUwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZSQxLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozOSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NzIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozNilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRXhlY3V0b3JzJFJ1bm5hYmxlQWRhcHRlci5jYWxsKEV4ZWN1dG9ycy5qYXZhOjUxMSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRnV0dXJlVGFzay5ydW4oRnV0dXJlVGFzay5qYXZhOjI2Nilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yLnJ1bldvcmtlcihUaHJlYWRQb29sRXhlY3V0b3IuamF2YToxMTQ5KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IkV29ya2VyLnJ1bihUaHJlYWRQb29sRXhlY3V0b3IuamF2YTo2MjQpXG5cdGF0IGphdmEubGFuZy5UaHJlYWQucnVuKFRocmVhZC5qYXZhOjc0OClcbkNhdXNlZCBieTogY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb246IEFub255bW91cyBjYWxsZXIgZG9lcyBub3QgaGF2ZSBzdG9yYWdlLm9iamVjdHMuY3JlYXRlIGFjY2VzcyB0byBnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvbm9hdXRoLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxNyBtb3JlXG4sIGVycm9yUHJvdG9Db2RlPVJFUVVJUkVELCBlcnJvclByb3RvRG9tYWluPWdkYXRhLkNvcmVFcnJvckRvbWFpbiwgZmlsdGVyZWRNZXNzYWdlPW51bGwsIGxvY2F0aW9uPWVudGl0eS5hdXRoZW50aWNhdGVkX3VzZXIsIG1lc3NhZ2U9QW5vbnltb3VzIGNhbGxlciBkb2VzIG5vdCBoYXZlIHN0b3JhZ2Uub2JqZWN0cy5jcmVhdGUgYWNjZXNzIHRvIGdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9ub2F1dGguLCB1bm5hbWVkQXJndW1lbnRzPVtdfSwgbG9jYXRpb249aGVhZGVycy5BdXRob3JpemF0aW9uLCBtZXNzYWdlPUFub255bW91cyBjYWxsZXIgZG9lcyBub3QgaGF2ZSBzdG9yYWdlLm9iamVjdHMuY3JlYXRlIGFjY2VzcyB0byBnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvbm9hdXRoLiwgcmVhc29uPXJlcXVpcmVkLCBycGNDb2RlPTQwMX0gQW5vbnltb3VzIGNhbGxlciBkb2VzIG5vdCBoYXZlIHN0b3JhZ2Uub2JqZWN0cy5jcmVhdGUgYWNjZXNzIHRvIGdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9ub2F1dGguOiBjb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6QUNDRVNTX0RFTklFRDogQW5vbnltb3VzIGNhbGxlciBkb2VzIG5vdCBoYXZlIHN0b3JhZ2Uub2JqZWN0cy5jcmVhdGUgYWNjZXNzIHRvIGdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9ub2F1dGguXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRvUnBjM0V4Y2VwdGlvbihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjEzNSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5vYmplY3RzLkluc2VydE9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoSW5zZXJ0T2JqZWN0LmphdmE6MjE3KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuSW5zZXJ0T2JqZWN0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChJbnNlcnRPYmplY3QuamF2YTo1MSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLk9iamVjdHNEZWxlZ2F0b3IuaW5zZXJ0KE9iamVjdHNEZWxlZ2F0b3IuamF2YTo5NSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uUnBjUmVjZWl2ZXIubGFtYmRhJHByb2Nlc3NSZXF1ZXN0QXN5bmMkNChScGNSZWNlaXZlci5qYXZhOjIwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uQXN5bmNFeGVjdXRvci5sYW1iZGEkc3VibWl0JDAoQXN5bmNFeGVjdXRvci5qYXZhOjI3Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KENvbnRleHRSdW5uYWJsZS5qYXZhOjUwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZSQxLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozOSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NzIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozNilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRXhlY3V0b3JzJFJ1bm5hYmxlQWRhcHRlci5jYWxsKEV4ZWN1dG9ycy5qYXZhOjUxMSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRnV0dXJlVGFzay5ydW4oRnV0dXJlVGFzay5qYXZhOjI2Nilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yLnJ1bldvcmtlcihUaHJlYWRQb29sRXhlY3V0b3IuamF2YToxMTQ5KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IkV29ya2VyLnJ1bihUaHJlYWRQb29sRXhlY3V0b3IuamF2YTo2MjQpXG5cdGF0IGphdmEubGFuZy5UaHJlYWQucnVuKFRocmVhZC5qYXZhOjc0OClcbkNhdXNlZCBieTogY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb246IEFub255bW91cyBjYWxsZXIgZG9lcyBub3QgaGF2ZSBzdG9yYWdlLm9iamVjdHMuY3JlYXRlIGFjY2VzcyB0byBnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvbm9hdXRoLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxNyBtb3JlXG4sIGRlYnVnSW5mbz1jb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6QUNDRVNTX0RFTklFRDogQW5vbnltb3VzIGNhbGxlciBkb2VzIG5vdCBoYXZlIHN0b3JhZ2Uub2JqZWN0cy5jcmVhdGUgYWNjZXNzIHRvIGdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9ub2F1dGguXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRvUnBjM0V4Y2VwdGlvbihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjEzNSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5vYmplY3RzLkluc2VydE9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoSW5zZXJ0T2JqZWN0LmphdmE6MjE3KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuSW5zZXJ0T2JqZWN0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChJbnNlcnRPYmplY3QuamF2YTo1MSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLk9iamVjdHNEZWxlZ2F0b3IuaW5zZXJ0KE9iamVjdHNEZWxlZ2F0b3IuamF2YTo5NSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uUnBjUmVjZWl2ZXIubGFtYmRhJHByb2Nlc3NSZXF1ZXN0QXN5bmMkNChScGNSZWNlaXZlci5qYXZhOjIwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uQXN5bmNFeGVjdXRvci5sYW1iZGEkc3VibWl0JDAoQXN5bmNFeGVjdXRvci5qYXZhOjI3Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KENvbnRleHRSdW5uYWJsZS5qYXZhOjUwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZSQxLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozOSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NzIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozNilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRXhlY3V0b3JzJFJ1bm5hYmxlQWRhcHRlci5jYWxsKEV4ZWN1dG9ycy5qYXZhOjUxMSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRnV0dXJlVGFzay5ydW4oRnV0dXJlVGFzay5qYXZhOjI2Nilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yLnJ1bldvcmtlcihUaHJlYWRQb29sRXhlY3V0b3IuamF2YToxMTQ5KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IkV29ya2VyLnJ1bihUaHJlYWRQb29sRXhlY3V0b3IuamF2YTo2MjQpXG5cdGF0IGphdmEubGFuZy5UaHJlYWQucnVuKFRocmVhZC5qYXZhOjc0OClcbkNhdXNlZCBieTogY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb246IEFub255bW91cyBjYWxsZXIgZG9lcyBub3QgaGF2ZSBzdG9yYWdlLm9iamVjdHMuY3JlYXRlIGFjY2VzcyB0byBnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvbm9hdXRoLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxNyBtb3JlXG4sIGRvbWFpbj1nbG9iYWwsIGV4dGVuZGVkSGVscD1udWxsLCBodHRwSGVhZGVycz17V1dXLUF1dGhlbnRpY2F0ZT1bQmVhcmVyIHJlYWxtPVwiaHR0cHM6Ly9hY2NvdW50cy5nb29nbGUuY29tL1wiXX0sIGh0dHBTdGF0dXM9dW5hdXRob3JpemVkLCBpbnRlcm5hbFJlYXNvbj1SZWFzb257YXJndW1lbnRzPXt9LCBjYXVzZT1udWxsLCBjb2RlPWdkYXRhLkNvcmVFcnJvckRvbWFpbi5SRVFVSVJFRCwgY3JlYXRlZEJ5QmFja2VuZD10cnVlLCBkZWJ1Z01lc3NhZ2U9Y29tLmdvb2dsZS5uZXQucnBjMy5ScGNFeGNlcHRpb246IGNsb3VkLmJpZ3N0b3JlLlJlc3BvbnNlQ29kZS5FcnJvckNvZGU6OkFDQ0VTU19ERU5JRUQ6IEFub255bW91cyBjYWxsZXIgZG9lcyBub3QgaGF2ZSBzdG9yYWdlLm9iamVjdHMuY3JlYXRlIGFjY2VzcyB0byBnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvbm9hdXRoLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5JbnNlcnRPYmplY3QuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKEluc2VydE9iamVjdC5qYXZhOjIxNylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5vYmplY3RzLkluc2VydE9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoSW5zZXJ0T2JqZWN0LmphdmE6NTEpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5PYmplY3RzRGVsZWdhdG9yLmluc2VydChPYmplY3RzRGVsZWdhdG9yLmphdmE6OTUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBBbm9ueW1vdXMgY2FsbGVyIGRvZXMgbm90IGhhdmUgc3RvcmFnZS5vYmplY3RzLmNyZWF0ZSBhY2Nlc3MgdG8gZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL25vYXV0aC5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MjkwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAxKVxuXHQuLi4gMTcgbW9yZVxuLCBlcnJvclByb3RvQ29kZT1SRVFVSVJFRCwgZXJyb3JQcm90b0RvbWFpbj1nZGF0YS5Db3JlRXJyb3JEb21haW4sIGZpbHRlcmVkTWVzc2FnZT1udWxsLCBsb2NhdGlvbj1lbnRpdHkuYXV0aGVudGljYXRlZF91c2VyLCBtZXNzYWdlPUFub255bW91cyBjYWxsZXIgZG9lcyBub3QgaGF2ZSBzdG9yYWdlLm9iamVjdHMuY3JlYXRlIGFjY2VzcyB0byBnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvbm9hdXRoLiwgdW5uYW1lZEFyZ3VtZW50cz1bXX0sIGxvY2F0aW9uPWhlYWRlcnMuQXV0aG9yaXphdGlvbiwgbWVzc2FnZT1Bbm9ueW1vdXMgY2FsbGVyIGRvZXMgbm90IGhhdmUgc3RvcmFnZS5vYmplY3RzLmNyZWF0ZSBhY2Nlc3MgdG8gZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL25vYXV0aC4sIHJlYXNvbj1yZXF1aXJlZCwgcnBjQ29kZT00MDF9IEFub255bW91cyBjYWxsZXIgZG9lcyBub3QgaGF2ZSBzdG9yYWdlLm9iamVjdHMuY3JlYXRlIGFjY2VzcyB0byBnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvbm9hdXRoLjogY29tLmdvb2dsZS5uZXQucnBjMy5ScGNFeGNlcHRpb246IGNsb3VkLmJpZ3N0b3JlLlJlc3BvbnNlQ29kZS5FcnJvckNvZGU6OkFDQ0VTU19ERU5JRUQ6IEFub255bW91cyBjYWxsZXIgZG9lcyBub3QgaGF2ZSBzdG9yYWdlLm9iamVjdHMuY3JlYXRlIGFjY2VzcyB0byBnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvbm9hdXRoLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5JbnNlcnRPYmplY3QuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKEluc2VydE9iamVjdC5qYXZhOjIxNylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5vYmplY3RzLkluc2VydE9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoSW5zZXJ0T2JqZWN0LmphdmE6NTEpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5PYmplY3RzRGVsZWdhdG9yLmluc2VydChPYmplY3RzRGVsZWdhdG9yLmphdmE6OTUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBBbm9ueW1vdXMgY2FsbGVyIGRvZXMgbm90IGhhdmUgc3RvcmFnZS5vYmplY3RzLmNyZWF0ZSBhY2Nlc3MgdG8gZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL25vYXV0aC5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MjkwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAxKVxuXHQuLi4gMTcgbW9yZVxuXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5hdXRoLkF1dGhlbnRpY2F0b3JJbnRlcmNlcHRvci5hZGRDaGFsbGVuZ2VIZWFkZXIoQXV0aGVudGljYXRvckludGVyY2VwdG9yLmphdmE6MjY0KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuYXV0aC5BdXRoZW50aWNhdG9ySW50ZXJjZXB0b3IucHJvY2Vzc0Vycm9yUmVzcG9uc2UoQXV0aGVudGljYXRvckludGVyY2VwdG9yLmphdmE6MjMxKVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuYXV0aC5HYWlhTWludEludGVyY2VwdG9yLnByb2Nlc3NFcnJvclJlc3BvbnNlKEdhaWFNaW50SW50ZXJjZXB0b3IuamF2YTo3NjQpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLmludGVyY2VwdC5Bcm91bmRJbnRlcmNlcHRvcldyYXBwZXIucHJvY2Vzc0Vycm9yUmVzcG9uc2UoQXJvdW5kSW50ZXJjZXB0b3JXcmFwcGVyLmphdmE6MjgpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5zdGF0cy5TdGF0c0Jvb3RzdHJhcCRJbnRlcmNlcHRvclN0YXRzUmVjb3JkZXIucHJvY2Vzc0Vycm9yUmVzcG9uc2UoU3RhdHNCb290c3RyYXAuamF2YTozMTIpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLmludGVyY2VwdC5JbnRlcmNlcHRpb25zJEFyb3VuZEludGVyY2VwdGlvbi5oYW5kbGVFcnJvclJlc3BvbnNlKEludGVyY2VwdGlvbnMuamF2YToyMDIpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLmludGVyY2VwdC5JbnRlcmNlcHRpb25zJEFyb3VuZEludGVyY2VwdGlvbi5hY2Nlc3MkMjAwKEludGVyY2VwdGlvbnMuamF2YToxMDMpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLmludGVyY2VwdC5JbnRlcmNlcHRpb25zJEFyb3VuZEludGVyY2VwdGlvbiQxLmNhbGwoSW50ZXJjZXB0aW9ucy5qYXZhOjE0NClcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUuaW50ZXJjZXB0LkludGVyY2VwdGlvbnMkQXJvdW5kSW50ZXJjZXB0aW9uJDEuY2FsbChJbnRlcmNlcHRpb25zLmphdmE6MTM3KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS51dGlsLkNhbGxhYmxlRnV0dXJlLnJ1bihDYWxsYWJsZUZ1dHVyZS5qYXZhOjYyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuRGlyZWN0RXhlY3V0b3IuZXhlY3V0ZShEaXJlY3RFeGVjdXRvci5qYXZhOjMwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuZXhlY3V0ZUxpc3RlbmVyKEFic3RyYWN0RnV0dXJlLmphdmE6MTE0Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmNvbXBsZXRlKEFic3RyYWN0RnV0dXJlLmphdmE6OTYzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuc2V0RXhjZXB0aW9uKEFic3RyYWN0RnV0dXJlLmphdmE6NzUzKVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS51dGlsLkNhbGxhYmxlRnV0dXJlLnJ1bihDYWxsYWJsZUZ1dHVyZS5qYXZhOjY4KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuRGlyZWN0RXhlY3V0b3IuZXhlY3V0ZShEaXJlY3RFeGVjdXRvci5qYXZhOjMwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuZXhlY3V0ZUxpc3RlbmVyKEFic3RyYWN0RnV0dXJlLmphdmE6MTE0Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmNvbXBsZXRlKEFic3RyYWN0RnV0dXJlLmphdmE6OTYzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuc2V0KEFic3RyYWN0RnV0dXJlLmphdmE6NzMxKVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS51dGlsLkNhbGxhYmxlRnV0dXJlLnJ1bihDYWxsYWJsZUZ1dHVyZS5qYXZhOjYyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuRGlyZWN0RXhlY3V0b3IuZXhlY3V0ZShEaXJlY3RFeGVjdXRvci5qYXZhOjMwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuZXhlY3V0ZUxpc3RlbmVyKEFic3RyYWN0RnV0dXJlLmphdmE6MTE0Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmNvbXBsZXRlKEFic3RyYWN0RnV0dXJlLmphdmE6OTYzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuc2V0KEFic3RyYWN0RnV0dXJlLmphdmE6NzMxKVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS51dGlsLkNhbGxhYmxlRnV0dXJlLnJ1bihDYWxsYWJsZUZ1dHVyZS5qYXZhOjYyKVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIudGhyZWFkLlRocmVhZFRyYWNrZXJzJFRocmVhZFRyYWNraW5nUnVubmFibGUucnVuKFRocmVhZFRyYWNrZXJzLmphdmE6MTI2KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JFRyYWNlQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChUcmFjZUNvbnRleHQuamF2YTo0NTUpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5zZXJ2ZXIuQ29tbW9uTW9kdWxlJENvbnRleHRDYXJyeWluZ0V4ZWN1dG9yU2VydmljZSQxLnJ1bkluQ29udGV4dChDb21tb25Nb2R1bGUuamF2YTo4NDYpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkVHJhY2VDb250ZXh0UnVubmFibGUkMS5ydW4oVHJhY2VDb250ZXh0LmphdmE6NDYyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JEFic3RyYWN0VHJhY2VDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihUcmFjZUNvbnRleHQuamF2YTozMjEpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkQWJzdHJhY3RUcmFjZUNvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoVHJhY2VDb250ZXh0LmphdmE6MzEzKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JFRyYWNlQ29udGV4dFJ1bm5hYmxlLnJ1bihUcmFjZUNvbnRleHQuamF2YTo0NTkpXG5cdGF0IGNvbS5nb29nbGUuZ3NlLmludGVybmFsLkRpc3BhdGNoUXVldWVJbXBsJFdvcmtlclRocmVhZC5ydW4oRGlzcGF0Y2hRdWV1ZUltcGwuamF2YTo0MDMpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLkZhdWx0OiBJbW11dGFibGVFcnJvckRlZmluaXRpb257YmFzZT1MT0dJTl9SRVFVSVJFRCwgY2F0ZWdvcnk9VVNFUl9FUlJPUiwgY2F1c2U9bnVsbCwgZGVidWdJbmZvPWNvbS5nb29nbGUubmV0LnJwYzMuUnBjRXhjZXB0aW9uOiBjbG91ZC5iaWdzdG9yZS5SZXNwb25zZUNvZGUuRXJyb3JDb2RlOjpBQ0NFU1NfREVOSUVEOiBBbm9ueW1vdXMgY2FsbGVyIGRvZXMgbm90IGhhdmUgc3RvcmFnZS5vYmplY3RzLmNyZWF0ZSBhY2Nlc3MgdG8gZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL25vYXV0aC5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udG9ScGMzRXhjZXB0aW9uKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MTM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuSW5zZXJ0T2JqZWN0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChJbnNlcnRPYmplY3QuamF2YToyMTcpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5JbnNlcnRPYmplY3QuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKEluc2VydE9iamVjdC5qYXZhOjUxKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmZyYW1ld29yay5SZXF1ZXN0SGFuZGxlci5oYW5kbGUoUmVxdWVzdEhhbmRsZXIuamF2YToyOTQpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uT2JqZWN0c0RlbGVnYXRvci5pbnNlcnQoT2JqZWN0c0RlbGVnYXRvci5qYXZhOjk1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5ScGNSZWNlaXZlci5sYW1iZGEkcHJvY2Vzc1JlcXVlc3RBc3luYyQ0KFJwY1JlY2VpdmVyLmphdmE6MjAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5Bc3luY0V4ZWN1dG9yLmxhbWJkYSRzdWJtaXQkMChBc3luY0V4ZWN1dG9yLmphdmE6MjcyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoQ29udGV4dFJ1bm5hYmxlLmphdmE6NTApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlJDEucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM5KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo3Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5FeGVjdXRvcnMkUnVubmFibGVBZGFwdGVyLmNhbGwoRXhlY3V0b3JzLmphdmE6NTExKVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5GdXR1cmVUYXNrLnJ1bihGdXR1cmVUYXNrLmphdmE6MjY2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IucnVuV29ya2VyKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjExNDkpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvciRXb3JrZXIucnVuKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjYyNClcblx0YXQgamF2YS5sYW5nLlRocmVhZC5ydW4oVGhyZWFkLmphdmE6NzQ4KVxuQ2F1c2VkIGJ5OiBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbjogQW5vbnltb3VzIGNhbGxlciBkb2VzIG5vdCBoYXZlIHN0b3JhZ2Uub2JqZWN0cy5jcmVhdGUgYWNjZXNzIHRvIGdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9ub2F1dGguXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93T25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjI5MClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMSlcblx0Li4uIDE3IG1vcmVcbiwgZG9tYWluPWdsb2JhbCwgZXh0ZW5kZWRIZWxwPW51bGwsIGh0dHBIZWFkZXJzPXt9LCBodHRwU3RhdHVzPXVuYXV0aG9yaXplZCwgaW50ZXJuYWxSZWFzb249UmVhc29ue2FyZ3VtZW50cz17fSwgY2F1c2U9bnVsbCwgY29kZT1nZGF0YS5Db3JlRXJyb3JEb21haW4uUkVRVUlSRUQsIGNyZWF0ZWRCeUJhY2tlbmQ9dHJ1ZSwgZGVidWdNZXNzYWdlPWNvbS5nb29nbGUubmV0LnJwYzMuUnBjRXhjZXB0aW9uOiBjbG91ZC5iaWdzdG9yZS5SZXNwb25zZUNvZGUuRXJyb3JDb2RlOjpBQ0NFU1NfREVOSUVEOiBBbm9ueW1vdXMgY2FsbGVyIGRvZXMgbm90IGhhdmUgc3RvcmFnZS5vYmplY3RzLmNyZWF0ZSBhY2Nlc3MgdG8gZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL25vYXV0aC5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udG9ScGMzRXhjZXB0aW9uKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MTM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuSW5zZXJ0T2JqZWN0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChJbnNlcnRPYmplY3QuamF2YToyMTcpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5JbnNlcnRPYmplY3QuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKEluc2VydE9iamVjdC5qYXZhOjUxKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmZyYW1ld29yay5SZXF1ZXN0SGFuZGxlci5oYW5kbGUoUmVxdWVzdEhhbmRsZXIuamF2YToyOTQpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uT2JqZWN0c0RlbGVnYXRvci5pbnNlcnQoT2JqZWN0c0RlbGVnYXRvci5qYXZhOjk1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5ScGNSZWNlaXZlci5sYW1iZGEkcHJvY2Vzc1JlcXVlc3RBc3luYyQ0KFJwY1JlY2VpdmVyLmphdmE6MjAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5Bc3luY0V4ZWN1dG9yLmxhbWJkYSRzdWJtaXQkMChBc3luY0V4ZWN1dG9yLmphdmE6MjcyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoQ29udGV4dFJ1bm5hYmxlLmphdmE6NTApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlJDEucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM5KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo3Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5FeGVjdXRvcnMkUnVubmFibGVBZGFwdGVyLmNhbGwoRXhlY3V0b3JzLmphdmE6NTExKVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5GdXR1cmVUYXNrLnJ1bihGdXR1cmVUYXNrLmphdmE6MjY2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IucnVuV29ya2VyKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjExNDkpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvciRXb3JrZXIucnVuKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjYyNClcblx0YXQgamF2YS5sYW5nLlRocmVhZC5ydW4oVGhyZWFkLmphdmE6NzQ4KVxuQ2F1c2VkIGJ5OiBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbjogQW5vbnltb3VzIGNhbGxlciBkb2VzIG5vdCBoYXZlIHN0b3JhZ2Uub2JqZWN0cy5jcmVhdGUgYWNjZXNzIHRvIGdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9ub2F1dGguXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93T25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjI5MClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMSlcblx0Li4uIDE3IG1vcmVcbiwgZXJyb3JQcm90b0NvZGU9UkVRVUlSRUQsIGVycm9yUHJvdG9Eb21haW49Z2RhdGEuQ29yZUVycm9yRG9tYWluLCBmaWx0ZXJlZE1lc3NhZ2U9bnVsbCwgbG9jYXRpb249ZW50aXR5LmF1dGhlbnRpY2F0ZWRfdXNlciwgbWVzc2FnZT1Bbm9ueW1vdXMgY2FsbGVyIGRvZXMgbm90IGhhdmUgc3RvcmFnZS5vYmplY3RzLmNyZWF0ZSBhY2Nlc3MgdG8gZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL25vYXV0aC4sIHVubmFtZWRBcmd1bWVudHM9W119LCBsb2NhdGlvbj1oZWFkZXJzLkF1dGhvcml6YXRpb24sIG1lc3NhZ2U9QW5vbnltb3VzIGNhbGxlciBkb2VzIG5vdCBoYXZlIHN0b3JhZ2Uub2JqZWN0cy5jcmVhdGUgYWNjZXNzIHRvIGdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9ub2F1dGguLCByZWFzb249cmVxdWlyZWQsIHJwY0NvZGU9NDAxfSBBbm9ueW1vdXMgY2FsbGVyIGRvZXMgbm90IGhhdmUgc3RvcmFnZS5vYmplY3RzLmNyZWF0ZSBhY2Nlc3MgdG8gZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL25vYXV0aC46IGNvbS5nb29nbGUubmV0LnJwYzMuUnBjRXhjZXB0aW9uOiBjbG91ZC5iaWdzdG9yZS5SZXNwb25zZUNvZGUuRXJyb3JDb2RlOjpBQ0NFU1NfREVOSUVEOiBBbm9ueW1vdXMgY2FsbGVyIGRvZXMgbm90IGhhdmUgc3RvcmFnZS5vYmplY3RzLmNyZWF0ZSBhY2Nlc3MgdG8gZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL25vYXV0aC5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udG9ScGMzRXhjZXB0aW9uKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MTM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuSW5zZXJ0T2JqZWN0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChJbnNlcnRPYmplY3QuamF2YToyMTcpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5JbnNlcnRPYmplY3QuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKEluc2VydE9iamVjdC5qYXZhOjUxKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmZyYW1ld29yay5SZXF1ZXN0SGFuZGxlci5oYW5kbGUoUmVxdWVzdEhhbmRsZXIuamF2YToyOTQpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uT2JqZWN0c0RlbGVnYXRvci5pbnNlcnQoT2JqZWN0c0RlbGVnYXRvci5qYXZhOjk1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5ScGNSZWNlaXZlci5sYW1iZGEkcHJvY2Vzc1JlcXVlc3RBc3luYyQ0KFJwY1JlY2VpdmVyLmphdmE6MjAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5Bc3luY0V4ZWN1dG9yLmxhbWJkYSRzdWJtaXQkMChBc3luY0V4ZWN1dG9yLmphdmE6MjcyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoQ29udGV4dFJ1bm5hYmxlLmphdmE6NTApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlJDEucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM5KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo3Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5FeGVjdXRvcnMkUnVubmFibGVBZGFwdGVyLmNhbGwoRXhlY3V0b3JzLmphdmE6NTExKVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5GdXR1cmVUYXNrLnJ1bihGdXR1cmVUYXNrLmphdmE6MjY2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IucnVuV29ya2VyKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjExNDkpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvciRXb3JrZXIucnVuKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjYyNClcblx0YXQgamF2YS5sYW5nLlRocmVhZC5ydW4oVGhyZWFkLmphdmE6NzQ4KVxuQ2F1c2VkIGJ5OiBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbjogQW5vbnltb3VzIGNhbGxlciBkb2VzIG5vdCBoYXZlIHN0b3JhZ2Uub2JqZWN0cy5jcmVhdGUgYWNjZXNzIHRvIGdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9ub2F1dGguXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93T25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjI5MClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMSlcblx0Li4uIDE3IG1vcmVcblxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS5FcnJvckNvbGxlY3Rvci50b0ZhdWx0KEVycm9yQ29sbGVjdG9yLmphdmE6NTQpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5yZXN0LmFkYXB0ZXIucm9zeS5Sb3N5RXJyb3JDb252ZXJ0ZXIudG9GYXVsdChSb3N5RXJyb3JDb252ZXJ0ZXIuamF2YTo2Nylcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnJlc3QuYWRhcHRlci5yb3N5LlJvc3lIYW5kbGVyJDIuY2FsbChSb3N5SGFuZGxlci5qYXZhOjI1OClcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnJlc3QuYWRhcHRlci5yb3N5LlJvc3lIYW5kbGVyJDIuY2FsbChSb3N5SGFuZGxlci5qYXZhOjIzOClcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0Li4uIDE5IG1vcmVcbiJ9XSwiY29kZSI6NDAxLCJtZXNzYWdlIjoiQW5vbnltb3VzIGNhbGxlciBkb2VzIG5vdCBoYXZlIHN0b3JhZ2Uub2JqZWN0cy5jcmVhdGUgYWNjZXNzIHRvIGdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9ub2F1dGguIn19"
+ }
+ },
+ {
+ "ID": "8607aa9eb0964439",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://storage.googleapis.com/gcp-public-data-landsat/LC08/PRE/044/034/LC80440342016259LGN00/LC80440342016259LGN00_MTL.txt",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "User-Agent": [
+ "Go-http-client/1.1"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "d93163707f2d013836306547b4dbcd8e/17936700502266216770;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "storage.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://storage.googleapis.com/gcp-public-data-landsat/LC08/PRE/044/034/LC80440342016259LGN00/LC80440342016259LGN00_MTL.txt"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Accept-Ranges": [
+ "bytes"
+ ],
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "public, max-age=3600"
+ ],
+ "Content-Length": [
+ "7903"
+ ],
+ "Content-Type": [
+ "application/octet-stream"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:23 GMT"
+ ],
+ "Etag": [
+ "\"7a5fd4743bd647485f88496fadb05c51\""
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 13:25:23 GMT"
+ ],
+ "Last-Modified": [
+ "Tue, 04 Oct 2016 16:42:07 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "X-Goog-Generation": [
+ "1475599327662000"
+ ],
+ "X-Goog-Hash": [
+ "crc32c=PWBt8g==",
+ "md5=el/UdDvWR0hfiElvrbBcUQ=="
+ ],
+ "X-Goog-Metageneration": [
+ "1"
+ ],
+ "X-Goog-Storage-Class": [
+ "STANDARD"
+ ],
+ "X-Goog-Stored-Content-Encoding": [
+ "identity"
+ ],
+ "X-Goog-Stored-Content-Length": [
+ "7903"
+ ],
+ "X-Google-Backends": [
+ "/bns/xh/borg/xh/bns/cloud-storage/prod-cloud-storage-frontend.frontend/46,/bns/xh/borg/xh/bns/blobstore2/bitpusher/15.scotty,aclgag19:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=M8ysW8T2B-ShswbYw67IAw"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "570399209098"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "aclgag19:443,/bns/xh/borg/xh/bns/blobstore2/bitpusher/15.scotty,aclgag19:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/xh/borg/xh/bns/blobstore2/bitpusher/15:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBJ"
+ ],
+ "X-Google-Storage-Location": [
+ "US"
+ ],
+ "X-Guploader-Customer": [
+ "cloud-storage"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Uo3fxL6bHvnU8nsWyoPO4uYF9iyasj5Qltu6jAK4p0aCtdJC8ETwmXOR7L7KeIRvEUUt8ty9hzcDNO535kFdMIU7RPaCg"
+ ]
+ },
+ "Body": "R1JPVVAgPSBMMV9NRVRBREFUQV9GSUxFCiAgR1JPVVAgPSBNRVRBREFUQV9GSUxFX0lORk8KICAgIE9SSUdJTiA9ICJJbWFnZSBjb3VydGVzeSBvZiB0aGUgVS5TLiBHZW9sb2dpY2FsIFN1cnZleSIKICAgIFJFUVVFU1RfSUQgPSAiMDcwMTYwOTE5MTA1MV8wMDAwNCIKICAgIExBTkRTQVRfU0NFTkVfSUQgPSAiTEM4MDQ0MDM0MjAxNjI1OUxHTjAwIgogICAgRklMRV9EQVRFID0gMjAxNi0wOS0yMFQwMzoxMzowMloKICAgIFNUQVRJT05fSUQgPSAiTEdOIgogICAgUFJPQ0VTU0lOR19TT0ZUV0FSRV9WRVJTSU9OID0gIkxQR1NfMi42LjIiCiAgRU5EX0dST1VQID0gTUVUQURBVEFfRklMRV9JTkZPCiAgR1JPVVAgPSBQUk9EVUNUX01FVEFEQVRBCiAgICBEQVRBX1RZUEUgPSAiTDFUIgogICAgRUxFVkFUSU9OX1NPVVJDRSA9ICJHTFMyMDAwIgogICAgT1VUUFVUX0ZPUk1BVCA9ICJHRU9USUZGIgogICAgU1BBQ0VDUkFGVF9JRCA9ICJMQU5EU0FUXzgiCiAgICBTRU5TT1JfSUQgPSAiT0xJX1RJUlMiCiAgICBXUlNfUEFUSCA9IDQ0CiAgICBXUlNfUk9XID0gMzQKICAgIE5BRElSX09GRk5BRElSID0gIk5BRElSIgogICAgVEFSR0VUX1dSU19QQVRIID0gNDQKICAgIFRBUkdFVF9XUlNfUk9XID0gMzQKICAgIERBVEVfQUNRVUlSRUQgPSAyMDE2LTA5LTE1CiAgICBTQ0VORV9DRU5URVJfVElNRSA9ICIxODo0NjoxOC42ODY3MzgwWiIKICAgIENPUk5FUl9VTF9MQVRfUFJPRFVDVCA9IDM4LjUyODE5CiAgICBDT1JORVJfVUxfTE9OX1BST0RVQ1QgPSAtMTIzLjQwODQzCiAgICBDT1JORVJfVVJfTEFUX1BST0RVQ1QgPSAzOC41MDc2NQogICAgQ09STkVSX1VSX0xPTl9QUk9EVUNUID0gLTEyMC43NjkzMwogICAgQ09STkVSX0xMX0xBVF9QUk9EVUNUID0gMzYuNDE2MzMKICAgIENPUk5FUl9MTF9MT05fUFJPRFVDVCA9IC0xMjMuMzk3MDkKICAgIENPUk5FUl9MUl9MQVRfUFJPRFVDVCA9IDM2LjM5NzI5CiAgICBDT1JORVJfTFJfTE9OX1BST0RVQ1QgPSAtMTIwLjgzMTE3CiAgICBDT1JORVJfVUxfUFJPSkVDVElPTl9YX1BST0RVQ1QgPSA0NjQ0MDAuMDAwCiAgICBDT1JORVJfVUxfUFJPSkVDVElPTl9ZX1BST0RVQ1QgPSA0MjY0NTAwLjAwMAogICAgQ09STkVSX1VSX1BST0pFQ1RJT05fWF9QUk9EVUNUID0gNjk0NTAwLjAwMAogICAgQ09STkVSX1VSX1BST0pFQ1RJT05fWV9QUk9EVUNUID0gNDI2NDUwMC4wMDAKICAgIENPUk5FUl9MTF9QUk9KRUNUSU9OX1hfUFJPRFVDVCA9IDQ2NDQwMC4wMDAKICAgIENPUk5FUl9MTF9QUk9KRUNUSU9OX1lfUFJPRFVDVCA9IDQwMzAyMDAuMDAwCiAgICBDT1JORVJfTFJfUFJPSkVDVElPTl9YX1BST0RVQ1QgPSA2OTQ1MDAuMDAwCiAgICBDT1JORVJfTFJfUFJPSkVDVElPTl9ZX1BST0RVQ1QgPSA0MDMwMjAwLjAwMAogICAgUEFOQ0hST01BVElDX0xJTkVTID0gMTU2MjEKICAgIFBBTkNIUk9NQVRJQ19TQU1QTEVTID0gMTUzNDEKICAgIFJFRkxFQ1RJVkVfTElORVMgPSA3ODExCiAgICBSRUZMRUNUSVZFX1NBTVBMRVMgPSA3NjcxCiAgICBUSEVSTUFMX0xJTkVTID0gNzgxMQogICAgVEhFUk1BTF9TQU1QTEVTID0gNzY3MQogICAgRklMRV9OQU1FX0JBTkRfMSA9ICJMQzgwNDQwMzQyMDE2MjU5TEdOMDBfQjEuVElGIgogICAgRklMRV9OQU1FX0JBTkRfMiA9ICJMQzgwNDQwMzQyMDE2MjU5TEdOMDBfQjIuVElGIgogICAgRklMRV9OQU1FX0JBTkRfMyA9ICJMQzgwNDQwMzQyMDE2MjU5TEdOMDBfQjMuVElGIgogICAgRklMRV9OQU1FX0JBTkRfNCA9ICJMQzgwNDQwMzQyMDE2MjU5TEdOMDBfQjQuVElGIgogICAgRklMRV9OQU1FX0JBTkRfNSA9ICJMQzgwNDQwMzQyMDE2MjU5TEdOMDBfQjUuVElGIgogICAgRklMRV9OQU1FX0JBTkRfNiA9ICJMQzgwNDQwMzQyMDE2MjU5TEdOMDBfQjYuVElGIgogICAgRklMRV9OQU1FX0JBTkRfNyA9ICJMQzgwNDQwMzQyMDE2MjU5TEdOMDBfQjcuVElGIgogICAgRklMRV9OQU1FX0JBTkRfOCA9ICJMQzgwNDQwMzQyMDE2MjU5TEdOMDBfQjguVElGIgogICAgRklMRV9OQU1FX0JBTkRfOSA9ICJMQzgwNDQwMzQyMDE2MjU5TEdOMDBfQjkuVElGIgogICAgRklMRV9OQU1FX0JBTkRfMTAgPSAiTEM4MDQ0MDM0MjAxNjI1OUxHTjAwX0IxMC5USUYiCiAgICBGSUxFX05BTUVfQkFORF8xMSA9ICJMQzgwNDQwMzQyMDE2MjU5TEdOMDBfQjExLlRJRiIKICAgIEZJTEVfTkFNRV9CQU5EX1FVQUxJVFkgPSAiTEM4MDQ0MDM0MjAxNjI1OUxHTjAwX0JRQS5USUYiCiAgICBNRVRBREFUQV9GSUxFX05BTUUgPSAiTEM4MDQ0MDM0MjAxNjI1OUxHTjAwX01UTC50eHQiCiAgICBCUEZfTkFNRV9PTEkgPSAiTE84QlBGMjAxNjA5MTUxODMwNTdfMjAxNjA5MTUyMDA5NTAuMDEiCiAgICBCUEZfTkFNRV9USVJTID0gIkxUOEJQRjIwMTYwOTAyMDg0MTIyXzIwMTYwOTE3MDc0MDI3LjAyIgogICAgQ1BGX05BTUUgPSAiTDhDUEYyMDE2MDcwMV8yMDE2MDkzMC4wMiIKICAgIFJMVVRfRklMRV9OQU1FID0gIkw4UkxVVDIwMTUwMzAzXzIwNDMxMjMxdjExLmg1IgogIEVORF9HUk9VUCA9IFBST0RVQ1RfTUVUQURBVEEKICBHUk9VUCA9IElNQUdFX0FUVFJJQlVURVMKICAgIENMT1VEX0NPVkVSID0gMjkuNTYKICAgIENMT1VEX0NPVkVSX0xBTkQgPSAzLjMzCiAgICBJTUFHRV9RVUFMSVRZX09MSSA9IDkKICAgIElNQUdFX1FVQUxJVFlfVElSUyA9IDkKICAgIFRJUlNfU1NNX01PREVMID0gIkZJTkFMIgogICAgVElSU19TU01fUE9TSVRJT05fU1RBVFVTID0gIkVTVElNQVRFRCIKICAgIFJPTExfQU5HTEUgPSAtMC4wMDEKICAgIFNVTl9BWklNVVRIID0gMTQ4LjQ4MDQ5Mzk2CiAgICBTVU5fRUxFVkFUSU9OID0gNTAuOTM3NjgzOTkKICAgIEVBUlRIX1NVTl9ESVNUQU5DRSA9IDEuMDA1Mzc1MgogICAgR1JPVU5EX0NPTlRST0xfUE9JTlRTX1ZFUlNJT04gPSA0CiAgICBHUk9VTkRfQ09OVFJPTF9QT0lOVFNfTU9ERUwgPSA1NDgKICAgIEdFT01FVFJJQ19STVNFX01PREVMID0gNS44NTcKICAgIEdFT01FVFJJQ19STVNFX01PREVMX1kgPSAzLjg0MQogICAgR0VPTUVUUklDX1JNU0VfTU9ERUxfWCA9IDQuNDIyCiAgICBHUk9VTkRfQ09OVFJPTF9QT0lOVFNfVkVSSUZZID0gMjI4CiAgICBHRU9NRVRSSUNfUk1TRV9WRVJJRlkgPSAzLjM4MgogIEVORF9HUk9VUCA9IElNQUdFX0FUVFJJQlVURVMKICBHUk9VUCA9IE1JTl9NQVhfUkFESUFOQ0UKICAgIFJBRElBTkNFX01BWElNVU1fQkFORF8xID0gNzUxLjk1NzA5CiAgICBSQURJQU5DRV9NSU5JTVVNX0JBTkRfMSA9IC02Mi4wOTY4NgogICAgUkFESUFOQ0VfTUFYSU1VTV9CQU5EXzIgPSA3NzAuMDEzMTgKICAgIFJBRElBTkNFX01JTklNVU1fQkFORF8yID0gLTYzLjU4Nzk0CiAgICBSQURJQU5DRV9NQVhJTVVNX0JBTkRfMyA9IDcwOS41NjA2MQogICAgUkFESUFOQ0VfTUlOSU1VTV9CQU5EXzMgPSAtNTguNTk1NzUKICAgIFJBRElBTkNFX01BWElNVU1fQkFORF80ID0gNTk4LjM0MTQ5CiAgICBSQURJQU5DRV9NSU5JTVVNX0JBTkRfNCA9IC00OS40MTEyMwogICAgUkFESUFOQ0VfTUFYSU1VTV9CQU5EXzUgPSAzNjYuMTU1MTUKICAgIFJBRElBTkNFX01JTklNVU1fQkFORF81ID0gLTMwLjIzNzIxCiAgICBSQURJQU5DRV9NQVhJTVVNX0JBTkRfNiA9IDkxLjA1OTQ2CiAgICBSQURJQU5DRV9NSU5JTVVNX0JBTkRfNiA9IC03LjUxOTcyCiAgICBSQURJQU5DRV9NQVhJTVVNX0JBTkRfNyA9IDMwLjY5MTkxCiAgICBSQURJQU5DRV9NSU5JTVVNX0JBTkRfNyA9IC0yLjUzNDU1CiAgICBSQURJQU5DRV9NQVhJTVVNX0JBTkRfOCA9IDY3Ny4xNTc4NAogICAgUkFESUFOQ0VfTUlOSU1VTV9CQU5EXzggPSAtNTUuOTE5OTIKICAgIFJBRElBTkNFX01BWElNVU1fQkFORF85ID0gMTQzLjEwMTczCiAgICBSQURJQU5DRV9NSU5JTVVNX0JBTkRfOSA9IC0xMS44MTczOQogICAgUkFESUFOQ0VfTUFYSU1VTV9CQU5EXzEwID0gMjIuMDAxODAKICAgIFJBRElBTkNFX01JTklNVU1fQkFORF8xMCA9IDAuMTAwMzMKICAgIFJBRElBTkNFX01BWElNVU1fQkFORF8xMSA9IDIyLjAwMTgwCiAgICBSQURJQU5DRV9NSU5JTVVNX0JBTkRfMTEgPSAwLjEwMDMzCiAgRU5EX0dST1VQID0gTUlOX01BWF9SQURJQU5DRQogIEdST1VQID0gTUlOX01BWF9SRUZMRUNUQU5DRQogICAgUkVGTEVDVEFOQ0VfTUFYSU1VTV9CQU5EXzEgPSAxLjIxMDcwMAogICAgUkVGTEVDVEFOQ0VfTUlOSU1VTV9CQU5EXzEgPSAtMC4wOTk5ODAKICAgIFJFRkxFQ1RBTkNFX01BWElNVU1fQkFORF8yID0gMS4yMTA3MDAKICAgIFJFRkxFQ1RBTkNFX01JTklNVU1fQkFORF8yID0gLTAuMDk5OTgwCiAgICBSRUZMRUNUQU5DRV9NQVhJTVVNX0JBTkRfMyA9IDEuMjEwNzAwCiAgICBSRUZMRUNUQU5DRV9NSU5JTVVNX0JBTkRfMyA9IC0wLjA5OTk4MAogICAgUkVGTEVDVEFOQ0VfTUFYSU1VTV9CQU5EXzQgPSAxLjIxMDcwMAogICAgUkVGTEVDVEFOQ0VfTUlOSU1VTV9CQU5EXzQgPSAtMC4wOTk5ODAKICAgIFJFRkxFQ1RBTkNFX01BWElNVU1fQkFORF81ID0gMS4yMTA3MDAKICAgIFJFRkxFQ1RBTkNFX01JTklNVU1fQkFORF81ID0gLTAuMDk5OTgwCiAgICBSRUZMRUNUQU5DRV9NQVhJTVVNX0JBTkRfNiA9IDEuMjEwNzAwCiAgICBSRUZMRUNUQU5DRV9NSU5JTVVNX0JBTkRfNiA9IC0wLjA5OTk4MAogICAgUkVGTEVDVEFOQ0VfTUFYSU1VTV9CQU5EXzcgPSAxLjIxMDcwMAogICAgUkVGTEVDVEFOQ0VfTUlOSU1VTV9CQU5EXzcgPSAtMC4wOTk5ODAKICAgIFJFRkxFQ1RBTkNFX01BWElNVU1fQkFORF84ID0gMS4yMTA3MDAKICAgIFJFRkxFQ1RBTkNFX01JTklNVU1fQkFORF84ID0gLTAuMDk5OTgwCiAgICBSRUZMRUNUQU5DRV9NQVhJTVVNX0JBTkRfOSA9IDEuMjEwNzAwCiAgICBSRUZMRUNUQU5DRV9NSU5JTVVNX0JBTkRfOSA9IC0wLjA5OTk4MAogIEVORF9HUk9VUCA9IE1JTl9NQVhfUkVGTEVDVEFOQ0UKICBHUk9VUCA9IE1JTl9NQVhfUElYRUxfVkFMVUUKICAgIFFVQU5USVpFX0NBTF9NQVhfQkFORF8xID0gNjU1MzUKICAgIFFVQU5USVpFX0NBTF9NSU5fQkFORF8xID0gMQogICAgUVVBTlRJWkVfQ0FMX01BWF9CQU5EXzIgPSA2NTUzNQogICAgUVVBTlRJWkVfQ0FMX01JTl9CQU5EXzIgPSAxCiAgICBRVUFOVElaRV9DQUxfTUFYX0JBTkRfMyA9IDY1NTM1CiAgICBRVUFOVElaRV9DQUxfTUlOX0JBTkRfMyA9IDEKICAgIFFVQU5USVpFX0NBTF9NQVhfQkFORF80ID0gNjU1MzUKICAgIFFVQU5USVpFX0NBTF9NSU5fQkFORF80ID0gMQogICAgUVVBTlRJWkVfQ0FMX01BWF9CQU5EXzUgPSA2NTUzNQogICAgUVVBTlRJWkVfQ0FMX01JTl9CQU5EXzUgPSAxCiAgICBRVUFOVElaRV9DQUxfTUFYX0JBTkRfNiA9IDY1NTM1CiAgICBRVUFOVElaRV9DQUxfTUlOX0JBTkRfNiA9IDEKICAgIFFVQU5USVpFX0NBTF9NQVhfQkFORF83ID0gNjU1MzUKICAgIFFVQU5USVpFX0NBTF9NSU5fQkFORF83ID0gMQogICAgUVVBTlRJWkVfQ0FMX01BWF9CQU5EXzggPSA2NTUzNQogICAgUVVBTlRJWkVfQ0FMX01JTl9CQU5EXzggPSAxCiAgICBRVUFOVElaRV9DQUxfTUFYX0JBTkRfOSA9IDY1NTM1CiAgICBRVUFOVElaRV9DQUxfTUlOX0JBTkRfOSA9IDEKICAgIFFVQU5USVpFX0NBTF9NQVhfQkFORF8xMCA9IDY1NTM1CiAgICBRVUFOVElaRV9DQUxfTUlOX0JBTkRfMTAgPSAxCiAgICBRVUFOVElaRV9DQUxfTUFYX0JBTkRfMTEgPSA2NTUzNQogICAgUVVBTlRJWkVfQ0FMX01JTl9CQU5EXzExID0gMQogIEVORF9HUk9VUCA9IE1JTl9NQVhfUElYRUxfVkFMVUUKICBHUk9VUCA9IFJBRElPTUVUUklDX1JFU0NBTElORwogICAgUkFESUFOQ0VfTVVMVF9CQU5EXzEgPSAxLjI0MjJFLTAyCiAgICBSQURJQU5DRV9NVUxUX0JBTkRfMiA9IDEuMjcyMEUtMDIKICAgIFJBRElBTkNFX01VTFRfQkFORF8zID0gMS4xNzIxRS0wMgogICAgUkFESUFOQ0VfTVVMVF9CQU5EXzQgPSA5Ljg4NDJFLTAzCiAgICBSQURJQU5DRV9NVUxUX0JBTkRfNSA9IDYuMDQ4N0UtMDMKICAgIFJBRElBTkNFX01VTFRfQkFORF82ID0gMS41MDQyRS0wMwogICAgUkFESUFOQ0VfTVVMVF9CQU5EXzcgPSA1LjA3MDFFLTA0CiAgICBSQURJQU5DRV9NVUxUX0JBTkRfOCA9IDEuMTE4NkUtMDIKICAgIFJBRElBTkNFX01VTFRfQkFORF85ID0gMi4zNjQwRS0wMwogICAgUkFESUFOQ0VfTVVMVF9CQU5EXzEwID0gMy4zNDIwRS0wNAogICAgUkFESUFOQ0VfTVVMVF9CQU5EXzExID0gMy4zNDIwRS0wNAogICAgUkFESUFOQ0VfQUREX0JBTkRfMSA9IC02Mi4xMDkyOAogICAgUkFESUFOQ0VfQUREX0JBTkRfMiA9IC02My42MDA2NgogICAgUkFESUFOQ0VfQUREX0JBTkRfMyA9IC01OC42MDc0NwogICAgUkFESUFOQ0VfQUREX0JBTkRfNCA9IC00OS40MjExMgogICAgUkFESUFOQ0VfQUREX0JBTkRfNSA9IC0zMC4yNDMyNgogICAgUkFESUFOQ0VfQUREX0JBTkRfNiA9IC03LjUyMTIyCiAgICBSQURJQU5DRV9BRERfQkFORF83ID0gLTIuNTM1MDUKICAgIFJBRElBTkNFX0FERF9CQU5EXzggPSAtNTUuOTMxMTAKICAgIFJBRElBTkNFX0FERF9CQU5EXzkgPSAtMTEuODE5NzUKICAgIFJBRElBTkNFX0FERF9CQU5EXzEwID0gMC4xMDAwMAogICAgUkFESUFOQ0VfQUREX0JBTkRfMTEgPSAwLjEwMDAwCiAgICBSRUZMRUNUQU5DRV9NVUxUX0JBTkRfMSA9IDIuMDAwMEUtMDUKICAgIFJFRkxFQ1RBTkNFX01VTFRfQkFORF8yID0gMi4wMDAwRS0wNQogICAgUkVGTEVDVEFOQ0VfTVVMVF9CQU5EXzMgPSAyLjAwMDBFLTA1CiAgICBSRUZMRUNUQU5DRV9NVUxUX0JBTkRfNCA9IDIuMDAwMEUtMDUKICAgIFJFRkxFQ1RBTkNFX01VTFRfQkFORF81ID0gMi4wMDAwRS0wNQogICAgUkVGTEVDVEFOQ0VfTVVMVF9CQU5EXzYgPSAyLjAwMDBFLTA1CiAgICBSRUZMRUNUQU5DRV9NVUxUX0JBTkRfNyA9IDIuMDAwMEUtMDUKICAgIFJFRkxFQ1RBTkNFX01VTFRfQkFORF84ID0gMi4wMDAwRS0wNQogICAgUkVGTEVDVEFOQ0VfTVVMVF9CQU5EXzkgPSAyLjAwMDBFLTA1CiAgICBSRUZMRUNUQU5DRV9BRERfQkFORF8xID0gLTAuMTAwMDAwCiAgICBSRUZMRUNUQU5DRV9BRERfQkFORF8yID0gLTAuMTAwMDAwCiAgICBSRUZMRUNUQU5DRV9BRERfQkFORF8zID0gLTAuMTAwMDAwCiAgICBSRUZMRUNUQU5DRV9BRERfQkFORF80ID0gLTAuMTAwMDAwCiAgICBSRUZMRUNUQU5DRV9BRERfQkFORF81ID0gLTAuMTAwMDAwCiAgICBSRUZMRUNUQU5DRV9BRERfQkFORF82ID0gLTAuMTAwMDAwCiAgICBSRUZMRUNUQU5DRV9BRERfQkFORF83ID0gLTAuMTAwMDAwCiAgICBSRUZMRUNUQU5DRV9BRERfQkFORF84ID0gLTAuMTAwMDAwCiAgICBSRUZMRUNUQU5DRV9BRERfQkFORF85ID0gLTAuMTAwMDAwCiAgRU5EX0dST1VQID0gUkFESU9NRVRSSUNfUkVTQ0FMSU5HCiAgR1JPVVAgPSBUSVJTX1RIRVJNQUxfQ09OU1RBTlRTCiAgICBLMV9DT05TVEFOVF9CQU5EXzEwID0gNzc0Ljg4NTMKICAgIEsxX0NPTlNUQU5UX0JBTkRfMTEgPSA0ODAuODg4MwogICAgSzJfQ09OU1RBTlRfQkFORF8xMCA9IDEzMjEuMDc4OQogICAgSzJfQ09OU1RBTlRfQkFORF8xMSA9IDEyMDEuMTQ0MgogIEVORF9HUk9VUCA9IFRJUlNfVEhFUk1BTF9DT05TVEFOVFMKICBHUk9VUCA9IFBST0pFQ1RJT05fUEFSQU1FVEVSUwogICAgTUFQX1BST0pFQ1RJT04gPSAiVVRNIgogICAgREFUVU0gPSAiV0dTODQiCiAgICBFTExJUFNPSUQgPSAiV0dTODQiCiAgICBVVE1fWk9ORSA9IDEwCiAgICBHUklEX0NFTExfU0laRV9QQU5DSFJPTUFUSUMgPSAxNS4wMAogICAgR1JJRF9DRUxMX1NJWkVfUkVGTEVDVElWRSA9IDMwLjAwCiAgICBHUklEX0NFTExfU0laRV9USEVSTUFMID0gMzAuMDAKICAgIE9SSUVOVEFUSU9OID0gIk5PUlRIX1VQIgogICAgUkVTQU1QTElOR19PUFRJT04gPSAiQ1VCSUNfQ09OVk9MVVRJT04iCiAgRU5EX0dST1VQID0gUFJPSkVDVElPTl9QQVJBTUVURVJTCkVORF9HUk9VUCA9IEwxX01FVEFEQVRBX0ZJTEUKRU5ECg=="
+ }
+ },
+ {
+ "ID": "e2c9f4af9bbfcf61",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://storage.googleapis.com/gcp-public-data-landsat/LC08/PRE/044/034/LC80440342016259LGN00/LC80440342016259LGN00_MTL.txt",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "User-Agent": [
+ "Go-http-client/1.1"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "69db1d4acd1dab1a05e8020d75e69a96/1080368332623947488;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "storage.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://storage.googleapis.com/gcp-public-data-landsat/LC08/PRE/044/034/LC80440342016259LGN00/LC80440342016259LGN00_MTL.txt"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Accept-Ranges": [
+ "bytes"
+ ],
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "public, max-age=3600"
+ ],
+ "Content-Length": [
+ "7903"
+ ],
+ "Content-Type": [
+ "application/octet-stream"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:23 GMT"
+ ],
+ "Etag": [
+ "\"7a5fd4743bd647485f88496fadb05c51\""
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 13:25:23 GMT"
+ ],
+ "Last-Modified": [
+ "Tue, 04 Oct 2016 16:42:07 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "X-Goog-Generation": [
+ "1475599327662000"
+ ],
+ "X-Goog-Hash": [
+ "crc32c=PWBt8g==",
+ "md5=el/UdDvWR0hfiElvrbBcUQ=="
+ ],
+ "X-Goog-Metageneration": [
+ "1"
+ ],
+ "X-Goog-Storage-Class": [
+ "STANDARD"
+ ],
+ "X-Goog-Stored-Content-Encoding": [
+ "identity"
+ ],
+ "X-Goog-Stored-Content-Length": [
+ "7903"
+ ],
+ "X-Google-Backends": [
+ "/bns/xh/borg/xh/bns/cloud-storage/prod-cloud-storage-frontend.frontend/38,/bns/xh/borg/xh/bns/blobstore2/bitpusher/68.scotty,aclgag19:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=M8ysW9CvC8GtswbB8IvgCQ"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "570399209098"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "aclgag19:443,/bns/xh/borg/xh/bns/blobstore2/bitpusher/68.scotty,aclgag19:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/xh/borg/xh/bns/blobstore2/bitpusher/68:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBJ"
+ ],
+ "X-Google-Storage-Location": [
+ "US"
+ ],
+ "X-Guploader-Customer": [
+ "cloud-storage"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UrHSEfW3gOHJga9kM0Pmg6J0nyVfHMmECSPbLUU9cgmDPy1u4tlWjQr1iWWGrmDplvE3AqXPnIH9B0qW2KILY169X1coQ"
+ ]
+ },
+ "Body": "R1JPVVAgPSBMMV9NRVRBREFUQV9GSUxFCiAgR1JPVVAgPSBNRVRBREFUQV9GSUxFX0lORk8KICAgIE9SSUdJTiA9ICJJbWFnZSBjb3VydGVzeSBvZiB0aGUgVS5TLiBHZW9sb2dpY2FsIFN1cnZleSIKICAgIFJFUVVFU1RfSUQgPSAiMDcwMTYwOTE5MTA1MV8wMDAwNCIKICAgIExBTkRTQVRfU0NFTkVfSUQgPSAiTEM4MDQ0MDM0MjAxNjI1OUxHTjAwIgogICAgRklMRV9EQVRFID0gMjAxNi0wOS0yMFQwMzoxMzowMloKICAgIFNUQVRJT05fSUQgPSAiTEdOIgogICAgUFJPQ0VTU0lOR19TT0ZUV0FSRV9WRVJTSU9OID0gIkxQR1NfMi42LjIiCiAgRU5EX0dST1VQID0gTUVUQURBVEFfRklMRV9JTkZPCiAgR1JPVVAgPSBQUk9EVUNUX01FVEFEQVRBCiAgICBEQVRBX1RZUEUgPSAiTDFUIgogICAgRUxFVkFUSU9OX1NPVVJDRSA9ICJHTFMyMDAwIgogICAgT1VUUFVUX0ZPUk1BVCA9ICJHRU9USUZGIgogICAgU1BBQ0VDUkFGVF9JRCA9ICJMQU5EU0FUXzgiCiAgICBTRU5TT1JfSUQgPSAiT0xJX1RJUlMiCiAgICBXUlNfUEFUSCA9IDQ0CiAgICBXUlNfUk9XID0gMzQKICAgIE5BRElSX09GRk5BRElSID0gIk5BRElSIgogICAgVEFSR0VUX1dSU19QQVRIID0gNDQKICAgIFRBUkdFVF9XUlNfUk9XID0gMzQKICAgIERBVEVfQUNRVUlSRUQgPSAyMDE2LTA5LTE1CiAgICBTQ0VORV9DRU5URVJfVElNRSA9ICIxODo0NjoxOC42ODY3MzgwWiIKICAgIENPUk5FUl9VTF9MQVRfUFJPRFVDVCA9IDM4LjUyODE5CiAgICBDT1JORVJfVUxfTE9OX1BST0RVQ1QgPSAtMTIzLjQwODQzCiAgICBDT1JORVJfVVJfTEFUX1BST0RVQ1QgPSAzOC41MDc2NQogICAgQ09STkVSX1VSX0xPTl9QUk9EVUNUID0gLTEyMC43NjkzMwogICAgQ09STkVSX0xMX0xBVF9QUk9EVUNUID0gMzYuNDE2MzMKICAgIENPUk5FUl9MTF9MT05fUFJPRFVDVCA9IC0xMjMuMzk3MDkKICAgIENPUk5FUl9MUl9MQVRfUFJPRFVDVCA9IDM2LjM5NzI5CiAgICBDT1JORVJfTFJfTE9OX1BST0RVQ1QgPSAtMTIwLjgzMTE3CiAgICBDT1JORVJfVUxfUFJPSkVDVElPTl9YX1BST0RVQ1QgPSA0NjQ0MDAuMDAwCiAgICBDT1JORVJfVUxfUFJPSkVDVElPTl9ZX1BST0RVQ1QgPSA0MjY0NTAwLjAwMAogICAgQ09STkVSX1VSX1BST0pFQ1RJT05fWF9QUk9EVUNUID0gNjk0NTAwLjAwMAogICAgQ09STkVSX1VSX1BST0pFQ1RJT05fWV9QUk9EVUNUID0gNDI2NDUwMC4wMDAKICAgIENPUk5FUl9MTF9QUk9KRUNUSU9OX1hfUFJPRFVDVCA9IDQ2NDQwMC4wMDAKICAgIENPUk5FUl9MTF9QUk9KRUNUSU9OX1lfUFJPRFVDVCA9IDQwMzAyMDAuMDAwCiAgICBDT1JORVJfTFJfUFJPSkVDVElPTl9YX1BST0RVQ1QgPSA2OTQ1MDAuMDAwCiAgICBDT1JORVJfTFJfUFJPSkVDVElPTl9ZX1BST0RVQ1QgPSA0MDMwMjAwLjAwMAogICAgUEFOQ0hST01BVElDX0xJTkVTID0gMTU2MjEKICAgIFBBTkNIUk9NQVRJQ19TQU1QTEVTID0gMTUzNDEKICAgIFJFRkxFQ1RJVkVfTElORVMgPSA3ODExCiAgICBSRUZMRUNUSVZFX1NBTVBMRVMgPSA3NjcxCiAgICBUSEVSTUFMX0xJTkVTID0gNzgxMQogICAgVEhFUk1BTF9TQU1QTEVTID0gNzY3MQogICAgRklMRV9OQU1FX0JBTkRfMSA9ICJMQzgwNDQwMzQyMDE2MjU5TEdOMDBfQjEuVElGIgogICAgRklMRV9OQU1FX0JBTkRfMiA9ICJMQzgwNDQwMzQyMDE2MjU5TEdOMDBfQjIuVElGIgogICAgRklMRV9OQU1FX0JBTkRfMyA9ICJMQzgwNDQwMzQyMDE2MjU5TEdOMDBfQjMuVElGIgogICAgRklMRV9OQU1FX0JBTkRfNCA9ICJMQzgwNDQwMzQyMDE2MjU5TEdOMDBfQjQuVElGIgogICAgRklMRV9OQU1FX0JBTkRfNSA9ICJMQzgwNDQwMzQyMDE2MjU5TEdOMDBfQjUuVElGIgogICAgRklMRV9OQU1FX0JBTkRfNiA9ICJMQzgwNDQwMzQyMDE2MjU5TEdOMDBfQjYuVElGIgogICAgRklMRV9OQU1FX0JBTkRfNyA9ICJMQzgwNDQwMzQyMDE2MjU5TEdOMDBfQjcuVElGIgogICAgRklMRV9OQU1FX0JBTkRfOCA9ICJMQzgwNDQwMzQyMDE2MjU5TEdOMDBfQjguVElGIgogICAgRklMRV9OQU1FX0JBTkRfOSA9ICJMQzgwNDQwMzQyMDE2MjU5TEdOMDBfQjkuVElGIgogICAgRklMRV9OQU1FX0JBTkRfMTAgPSAiTEM4MDQ0MDM0MjAxNjI1OUxHTjAwX0IxMC5USUYiCiAgICBGSUxFX05BTUVfQkFORF8xMSA9ICJMQzgwNDQwMzQyMDE2MjU5TEdOMDBfQjExLlRJRiIKICAgIEZJTEVfTkFNRV9CQU5EX1FVQUxJVFkgPSAiTEM4MDQ0MDM0MjAxNjI1OUxHTjAwX0JRQS5USUYiCiAgICBNRVRBREFUQV9GSUxFX05BTUUgPSAiTEM4MDQ0MDM0MjAxNjI1OUxHTjAwX01UTC50eHQiCiAgICBCUEZfTkFNRV9PTEkgPSAiTE84QlBGMjAxNjA5MTUxODMwNTdfMjAxNjA5MTUyMDA5NTAuMDEiCiAgICBCUEZfTkFNRV9USVJTID0gIkxUOEJQRjIwMTYwOTAyMDg0MTIyXzIwMTYwOTE3MDc0MDI3LjAyIgogICAgQ1BGX05BTUUgPSAiTDhDUEYyMDE2MDcwMV8yMDE2MDkzMC4wMiIKICAgIFJMVVRfRklMRV9OQU1FID0gIkw4UkxVVDIwMTUwMzAzXzIwNDMxMjMxdjExLmg1IgogIEVORF9HUk9VUCA9IFBST0RVQ1RfTUVUQURBVEEKICBHUk9VUCA9IElNQUdFX0FUVFJJQlVURVMKICAgIENMT1VEX0NPVkVSID0gMjkuNTYKICAgIENMT1VEX0NPVkVSX0xBTkQgPSAzLjMzCiAgICBJTUFHRV9RVUFMSVRZX09MSSA9IDkKICAgIElNQUdFX1FVQUxJVFlfVElSUyA9IDkKICAgIFRJUlNfU1NNX01PREVMID0gIkZJTkFMIgogICAgVElSU19TU01fUE9TSVRJT05fU1RBVFVTID0gIkVTVElNQVRFRCIKICAgIFJPTExfQU5HTEUgPSAtMC4wMDEKICAgIFNVTl9BWklNVVRIID0gMTQ4LjQ4MDQ5Mzk2CiAgICBTVU5fRUxFVkFUSU9OID0gNTAuOTM3NjgzOTkKICAgIEVBUlRIX1NVTl9ESVNUQU5DRSA9IDEuMDA1Mzc1MgogICAgR1JPVU5EX0NPTlRST0xfUE9JTlRTX1ZFUlNJT04gPSA0CiAgICBHUk9VTkRfQ09OVFJPTF9QT0lOVFNfTU9ERUwgPSA1NDgKICAgIEdFT01FVFJJQ19STVNFX01PREVMID0gNS44NTcKICAgIEdFT01FVFJJQ19STVNFX01PREVMX1kgPSAzLjg0MQogICAgR0VPTUVUUklDX1JNU0VfTU9ERUxfWCA9IDQuNDIyCiAgICBHUk9VTkRfQ09OVFJPTF9QT0lOVFNfVkVSSUZZID0gMjI4CiAgICBHRU9NRVRSSUNfUk1TRV9WRVJJRlkgPSAzLjM4MgogIEVORF9HUk9VUCA9IElNQUdFX0FUVFJJQlVURVMKICBHUk9VUCA9IE1JTl9NQVhfUkFESUFOQ0UKICAgIFJBRElBTkNFX01BWElNVU1fQkFORF8xID0gNzUxLjk1NzA5CiAgICBSQURJQU5DRV9NSU5JTVVNX0JBTkRfMSA9IC02Mi4wOTY4NgogICAgUkFESUFOQ0VfTUFYSU1VTV9CQU5EXzIgPSA3NzAuMDEzMTgKICAgIFJBRElBTkNFX01JTklNVU1fQkFORF8yID0gLTYzLjU4Nzk0CiAgICBSQURJQU5DRV9NQVhJTVVNX0JBTkRfMyA9IDcwOS41NjA2MQogICAgUkFESUFOQ0VfTUlOSU1VTV9CQU5EXzMgPSAtNTguNTk1NzUKICAgIFJBRElBTkNFX01BWElNVU1fQkFORF80ID0gNTk4LjM0MTQ5CiAgICBSQURJQU5DRV9NSU5JTVVNX0JBTkRfNCA9IC00OS40MTEyMwogICAgUkFESUFOQ0VfTUFYSU1VTV9CQU5EXzUgPSAzNjYuMTU1MTUKICAgIFJBRElBTkNFX01JTklNVU1fQkFORF81ID0gLTMwLjIzNzIxCiAgICBSQURJQU5DRV9NQVhJTVVNX0JBTkRfNiA9IDkxLjA1OTQ2CiAgICBSQURJQU5DRV9NSU5JTVVNX0JBTkRfNiA9IC03LjUxOTcyCiAgICBSQURJQU5DRV9NQVhJTVVNX0JBTkRfNyA9IDMwLjY5MTkxCiAgICBSQURJQU5DRV9NSU5JTVVNX0JBTkRfNyA9IC0yLjUzNDU1CiAgICBSQURJQU5DRV9NQVhJTVVNX0JBTkRfOCA9IDY3Ny4xNTc4NAogICAgUkFESUFOQ0VfTUlOSU1VTV9CQU5EXzggPSAtNTUuOTE5OTIKICAgIFJBRElBTkNFX01BWElNVU1fQkFORF85ID0gMTQzLjEwMTczCiAgICBSQURJQU5DRV9NSU5JTVVNX0JBTkRfOSA9IC0xMS44MTczOQogICAgUkFESUFOQ0VfTUFYSU1VTV9CQU5EXzEwID0gMjIuMDAxODAKICAgIFJBRElBTkNFX01JTklNVU1fQkFORF8xMCA9IDAuMTAwMzMKICAgIFJBRElBTkNFX01BWElNVU1fQkFORF8xMSA9IDIyLjAwMTgwCiAgICBSQURJQU5DRV9NSU5JTVVNX0JBTkRfMTEgPSAwLjEwMDMzCiAgRU5EX0dST1VQID0gTUlOX01BWF9SQURJQU5DRQogIEdST1VQID0gTUlOX01BWF9SRUZMRUNUQU5DRQogICAgUkVGTEVDVEFOQ0VfTUFYSU1VTV9CQU5EXzEgPSAxLjIxMDcwMAogICAgUkVGTEVDVEFOQ0VfTUlOSU1VTV9CQU5EXzEgPSAtMC4wOTk5ODAKICAgIFJFRkxFQ1RBTkNFX01BWElNVU1fQkFORF8yID0gMS4yMTA3MDAKICAgIFJFRkxFQ1RBTkNFX01JTklNVU1fQkFORF8yID0gLTAuMDk5OTgwCiAgICBSRUZMRUNUQU5DRV9NQVhJTVVNX0JBTkRfMyA9IDEuMjEwNzAwCiAgICBSRUZMRUNUQU5DRV9NSU5JTVVNX0JBTkRfMyA9IC0wLjA5OTk4MAogICAgUkVGTEVDVEFOQ0VfTUFYSU1VTV9CQU5EXzQgPSAxLjIxMDcwMAogICAgUkVGTEVDVEFOQ0VfTUlOSU1VTV9CQU5EXzQgPSAtMC4wOTk5ODAKICAgIFJFRkxFQ1RBTkNFX01BWElNVU1fQkFORF81ID0gMS4yMTA3MDAKICAgIFJFRkxFQ1RBTkNFX01JTklNVU1fQkFORF81ID0gLTAuMDk5OTgwCiAgICBSRUZMRUNUQU5DRV9NQVhJTVVNX0JBTkRfNiA9IDEuMjEwNzAwCiAgICBSRUZMRUNUQU5DRV9NSU5JTVVNX0JBTkRfNiA9IC0wLjA5OTk4MAogICAgUkVGTEVDVEFOQ0VfTUFYSU1VTV9CQU5EXzcgPSAxLjIxMDcwMAogICAgUkVGTEVDVEFOQ0VfTUlOSU1VTV9CQU5EXzcgPSAtMC4wOTk5ODAKICAgIFJFRkxFQ1RBTkNFX01BWElNVU1fQkFORF84ID0gMS4yMTA3MDAKICAgIFJFRkxFQ1RBTkNFX01JTklNVU1fQkFORF84ID0gLTAuMDk5OTgwCiAgICBSRUZMRUNUQU5DRV9NQVhJTVVNX0JBTkRfOSA9IDEuMjEwNzAwCiAgICBSRUZMRUNUQU5DRV9NSU5JTVVNX0JBTkRfOSA9IC0wLjA5OTk4MAogIEVORF9HUk9VUCA9IE1JTl9NQVhfUkVGTEVDVEFOQ0UKICBHUk9VUCA9IE1JTl9NQVhfUElYRUxfVkFMVUUKICAgIFFVQU5USVpFX0NBTF9NQVhfQkFORF8xID0gNjU1MzUKICAgIFFVQU5USVpFX0NBTF9NSU5fQkFORF8xID0gMQogICAgUVVBTlRJWkVfQ0FMX01BWF9CQU5EXzIgPSA2NTUzNQogICAgUVVBTlRJWkVfQ0FMX01JTl9CQU5EXzIgPSAxCiAgICBRVUFOVElaRV9DQUxfTUFYX0JBTkRfMyA9IDY1NTM1CiAgICBRVUFOVElaRV9DQUxfTUlOX0JBTkRfMyA9IDEKICAgIFFVQU5USVpFX0NBTF9NQVhfQkFORF80ID0gNjU1MzUKICAgIFFVQU5USVpFX0NBTF9NSU5fQkFORF80ID0gMQogICAgUVVBTlRJWkVfQ0FMX01BWF9CQU5EXzUgPSA2NTUzNQogICAgUVVBTlRJWkVfQ0FMX01JTl9CQU5EXzUgPSAxCiAgICBRVUFOVElaRV9DQUxfTUFYX0JBTkRfNiA9IDY1NTM1CiAgICBRVUFOVElaRV9DQUxfTUlOX0JBTkRfNiA9IDEKICAgIFFVQU5USVpFX0NBTF9NQVhfQkFORF83ID0gNjU1MzUKICAgIFFVQU5USVpFX0NBTF9NSU5fQkFORF83ID0gMQogICAgUVVBTlRJWkVfQ0FMX01BWF9CQU5EXzggPSA2NTUzNQogICAgUVVBTlRJWkVfQ0FMX01JTl9CQU5EXzggPSAxCiAgICBRVUFOVElaRV9DQUxfTUFYX0JBTkRfOSA9IDY1NTM1CiAgICBRVUFOVElaRV9DQUxfTUlOX0JBTkRfOSA9IDEKICAgIFFVQU5USVpFX0NBTF9NQVhfQkFORF8xMCA9IDY1NTM1CiAgICBRVUFOVElaRV9DQUxfTUlOX0JBTkRfMTAgPSAxCiAgICBRVUFOVElaRV9DQUxfTUFYX0JBTkRfMTEgPSA2NTUzNQogICAgUVVBTlRJWkVfQ0FMX01JTl9CQU5EXzExID0gMQogIEVORF9HUk9VUCA9IE1JTl9NQVhfUElYRUxfVkFMVUUKICBHUk9VUCA9IFJBRElPTUVUUklDX1JFU0NBTElORwogICAgUkFESUFOQ0VfTVVMVF9CQU5EXzEgPSAxLjI0MjJFLTAyCiAgICBSQURJQU5DRV9NVUxUX0JBTkRfMiA9IDEuMjcyMEUtMDIKICAgIFJBRElBTkNFX01VTFRfQkFORF8zID0gMS4xNzIxRS0wMgogICAgUkFESUFOQ0VfTVVMVF9CQU5EXzQgPSA5Ljg4NDJFLTAzCiAgICBSQURJQU5DRV9NVUxUX0JBTkRfNSA9IDYuMDQ4N0UtMDMKICAgIFJBRElBTkNFX01VTFRfQkFORF82ID0gMS41MDQyRS0wMwogICAgUkFESUFOQ0VfTVVMVF9CQU5EXzcgPSA1LjA3MDFFLTA0CiAgICBSQURJQU5DRV9NVUxUX0JBTkRfOCA9IDEuMTE4NkUtMDIKICAgIFJBRElBTkNFX01VTFRfQkFORF85ID0gMi4zNjQwRS0wMwogICAgUkFESUFOQ0VfTVVMVF9CQU5EXzEwID0gMy4zNDIwRS0wNAogICAgUkFESUFOQ0VfTVVMVF9CQU5EXzExID0gMy4zNDIwRS0wNAogICAgUkFESUFOQ0VfQUREX0JBTkRfMSA9IC02Mi4xMDkyOAogICAgUkFESUFOQ0VfQUREX0JBTkRfMiA9IC02My42MDA2NgogICAgUkFESUFOQ0VfQUREX0JBTkRfMyA9IC01OC42MDc0NwogICAgUkFESUFOQ0VfQUREX0JBTkRfNCA9IC00OS40MjExMgogICAgUkFESUFOQ0VfQUREX0JBTkRfNSA9IC0zMC4yNDMyNgogICAgUkFESUFOQ0VfQUREX0JBTkRfNiA9IC03LjUyMTIyCiAgICBSQURJQU5DRV9BRERfQkFORF83ID0gLTIuNTM1MDUKICAgIFJBRElBTkNFX0FERF9CQU5EXzggPSAtNTUuOTMxMTAKICAgIFJBRElBTkNFX0FERF9CQU5EXzkgPSAtMTEuODE5NzUKICAgIFJBRElBTkNFX0FERF9CQU5EXzEwID0gMC4xMDAwMAogICAgUkFESUFOQ0VfQUREX0JBTkRfMTEgPSAwLjEwMDAwCiAgICBSRUZMRUNUQU5DRV9NVUxUX0JBTkRfMSA9IDIuMDAwMEUtMDUKICAgIFJFRkxFQ1RBTkNFX01VTFRfQkFORF8yID0gMi4wMDAwRS0wNQogICAgUkVGTEVDVEFOQ0VfTVVMVF9CQU5EXzMgPSAyLjAwMDBFLTA1CiAgICBSRUZMRUNUQU5DRV9NVUxUX0JBTkRfNCA9IDIuMDAwMEUtMDUKICAgIFJFRkxFQ1RBTkNFX01VTFRfQkFORF81ID0gMi4wMDAwRS0wNQogICAgUkVGTEVDVEFOQ0VfTVVMVF9CQU5EXzYgPSAyLjAwMDBFLTA1CiAgICBSRUZMRUNUQU5DRV9NVUxUX0JBTkRfNyA9IDIuMDAwMEUtMDUKICAgIFJFRkxFQ1RBTkNFX01VTFRfQkFORF84ID0gMi4wMDAwRS0wNQogICAgUkVGTEVDVEFOQ0VfTVVMVF9CQU5EXzkgPSAyLjAwMDBFLTA1CiAgICBSRUZMRUNUQU5DRV9BRERfQkFORF8xID0gLTAuMTAwMDAwCiAgICBSRUZMRUNUQU5DRV9BRERfQkFORF8yID0gLTAuMTAwMDAwCiAgICBSRUZMRUNUQU5DRV9BRERfQkFORF8zID0gLTAuMTAwMDAwCiAgICBSRUZMRUNUQU5DRV9BRERfQkFORF80ID0gLTAuMTAwMDAwCiAgICBSRUZMRUNUQU5DRV9BRERfQkFORF81ID0gLTAuMTAwMDAwCiAgICBSRUZMRUNUQU5DRV9BRERfQkFORF82ID0gLTAuMTAwMDAwCiAgICBSRUZMRUNUQU5DRV9BRERfQkFORF83ID0gLTAuMTAwMDAwCiAgICBSRUZMRUNUQU5DRV9BRERfQkFORF84ID0gLTAuMTAwMDAwCiAgICBSRUZMRUNUQU5DRV9BRERfQkFORF85ID0gLTAuMTAwMDAwCiAgRU5EX0dST1VQID0gUkFESU9NRVRSSUNfUkVTQ0FMSU5HCiAgR1JPVVAgPSBUSVJTX1RIRVJNQUxfQ09OU1RBTlRTCiAgICBLMV9DT05TVEFOVF9CQU5EXzEwID0gNzc0Ljg4NTMKICAgIEsxX0NPTlNUQU5UX0JBTkRfMTEgPSA0ODAuODg4MwogICAgSzJfQ09OU1RBTlRfQkFORF8xMCA9IDEzMjEuMDc4OQogICAgSzJfQ09OU1RBTlRfQkFORF8xMSA9IDEyMDEuMTQ0MgogIEVORF9HUk9VUCA9IFRJUlNfVEhFUk1BTF9DT05TVEFOVFMKICBHUk9VUCA9IFBST0pFQ1RJT05fUEFSQU1FVEVSUwogICAgTUFQX1BST0pFQ1RJT04gPSAiVVRNIgogICAgREFUVU0gPSAiV0dTODQiCiAgICBFTExJUFNPSUQgPSAiV0dTODQiCiAgICBVVE1fWk9ORSA9IDEwCiAgICBHUklEX0NFTExfU0laRV9QQU5DSFJPTUFUSUMgPSAxNS4wMAogICAgR1JJRF9DRUxMX1NJWkVfUkVGTEVDVElWRSA9IDMwLjAwCiAgICBHUklEX0NFTExfU0laRV9USEVSTUFMID0gMzAuMDAKICAgIE9SSUVOVEFUSU9OID0gIk5PUlRIX1VQIgogICAgUkVTQU1QTElOR19PUFRJT04gPSAiQ1VCSUNfQ09OVk9MVVRJT04iCiAgRU5EX0dST1VQID0gUFJPSkVDVElPTl9QQVJBTUVURVJTCkVORF9HUk9VUCA9IEwxX01FVEFEQVRBX0ZJTEUKRU5ECg=="
+ }
+ },
+ {
+ "ID": "29af8223e2f49bec",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://storage.googleapis.com/gcp-public-data-landsat/LC08/PRE/044/034/LC80440342016259LGN00/LC80440342016259LGN00_MTL.txt",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Range": [
+ "bytes=1-"
+ ],
+ "User-Agent": [
+ "Go-http-client/1.1"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "4db663877b8e7c5ce86381f47f69dc9b/2598723742148021375;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "storage.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://storage.googleapis.com/gcp-public-data-landsat/LC08/PRE/044/034/LC80440342016259LGN00/LC80440342016259LGN00_MTL.txt"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 206,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Accept-Ranges": [
+ "bytes"
+ ],
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "public, max-age=3600"
+ ],
+ "Content-Length": [
+ "7902"
+ ],
+ "Content-Range": [
+ "bytes 1-7902/7903"
+ ],
+ "Content-Type": [
+ "application/octet-stream"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:23 GMT"
+ ],
+ "Etag": [
+ "\"7a5fd4743bd647485f88496fadb05c51\""
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 13:25:23 GMT"
+ ],
+ "Last-Modified": [
+ "Tue, 04 Oct 2016 16:42:07 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "X-Goog-Generation": [
+ "1475599327662000"
+ ],
+ "X-Goog-Hash": [
+ "crc32c=PWBt8g==",
+ "md5=el/UdDvWR0hfiElvrbBcUQ=="
+ ],
+ "X-Goog-Metageneration": [
+ "1"
+ ],
+ "X-Goog-Storage-Class": [
+ "STANDARD"
+ ],
+ "X-Goog-Stored-Content-Encoding": [
+ "identity"
+ ],
+ "X-Goog-Stored-Content-Length": [
+ "7903"
+ ],
+ "X-Google-Backends": [
+ "/bns/xh/borg/xh/bns/cloud-storage/prod-cloud-storage-frontend.frontend/11,/bns/xh/borg/xh/bns/blobstore2/bitpusher/20.scotty,aclgag19:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=M8ysW_K3DsesswbQ_qAo"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "570399209098"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "aclgag19:443,/bns/xh/borg/xh/bns/blobstore2/bitpusher/20.scotty,aclgag19:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/xh/borg/xh/bns/blobstore2/bitpusher/20:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBJ"
+ ],
+ "X-Google-Storage-Location": [
+ "US"
+ ],
+ "X-Guploader-Customer": [
+ "cloud-storage"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UrRbfvlTsqaOds6NXN9V0K3HKwwKP_aBuUP58gtsNFXA6Gi_ax4I6i1qLfhCvzKZkkBnu7C5O-C1rd5h_N3_zzQjwYIhg"
+ ]
+ },
+ "Body": "Uk9VUCA9IEwxX01FVEFEQVRBX0ZJTEUKICBHUk9VUCA9IE1FVEFEQVRBX0ZJTEVfSU5GTwogICAgT1JJR0lOID0gIkltYWdlIGNvdXJ0ZXN5IG9mIHRoZSBVLlMuIEdlb2xvZ2ljYWwgU3VydmV5IgogICAgUkVRVUVTVF9JRCA9ICIwNzAxNjA5MTkxMDUxXzAwMDA0IgogICAgTEFORFNBVF9TQ0VORV9JRCA9ICJMQzgwNDQwMzQyMDE2MjU5TEdOMDAiCiAgICBGSUxFX0RBVEUgPSAyMDE2LTA5LTIwVDAzOjEzOjAyWgogICAgU1RBVElPTl9JRCA9ICJMR04iCiAgICBQUk9DRVNTSU5HX1NPRlRXQVJFX1ZFUlNJT04gPSAiTFBHU18yLjYuMiIKICBFTkRfR1JPVVAgPSBNRVRBREFUQV9GSUxFX0lORk8KICBHUk9VUCA9IFBST0RVQ1RfTUVUQURBVEEKICAgIERBVEFfVFlQRSA9ICJMMVQiCiAgICBFTEVWQVRJT05fU09VUkNFID0gIkdMUzIwMDAiCiAgICBPVVRQVVRfRk9STUFUID0gIkdFT1RJRkYiCiAgICBTUEFDRUNSQUZUX0lEID0gIkxBTkRTQVRfOCIKICAgIFNFTlNPUl9JRCA9ICJPTElfVElSUyIKICAgIFdSU19QQVRIID0gNDQKICAgIFdSU19ST1cgPSAzNAogICAgTkFESVJfT0ZGTkFESVIgPSAiTkFESVIiCiAgICBUQVJHRVRfV1JTX1BBVEggPSA0NAogICAgVEFSR0VUX1dSU19ST1cgPSAzNAogICAgREFURV9BQ1FVSVJFRCA9IDIwMTYtMDktMTUKICAgIFNDRU5FX0NFTlRFUl9USU1FID0gIjE4OjQ2OjE4LjY4NjczODBaIgogICAgQ09STkVSX1VMX0xBVF9QUk9EVUNUID0gMzguNTI4MTkKICAgIENPUk5FUl9VTF9MT05fUFJPRFVDVCA9IC0xMjMuNDA4NDMKICAgIENPUk5FUl9VUl9MQVRfUFJPRFVDVCA9IDM4LjUwNzY1CiAgICBDT1JORVJfVVJfTE9OX1BST0RVQ1QgPSAtMTIwLjc2OTMzCiAgICBDT1JORVJfTExfTEFUX1BST0RVQ1QgPSAzNi40MTYzMwogICAgQ09STkVSX0xMX0xPTl9QUk9EVUNUID0gLTEyMy4zOTcwOQogICAgQ09STkVSX0xSX0xBVF9QUk9EVUNUID0gMzYuMzk3MjkKICAgIENPUk5FUl9MUl9MT05fUFJPRFVDVCA9IC0xMjAuODMxMTcKICAgIENPUk5FUl9VTF9QUk9KRUNUSU9OX1hfUFJPRFVDVCA9IDQ2NDQwMC4wMDAKICAgIENPUk5FUl9VTF9QUk9KRUNUSU9OX1lfUFJPRFVDVCA9IDQyNjQ1MDAuMDAwCiAgICBDT1JORVJfVVJfUFJPSkVDVElPTl9YX1BST0RVQ1QgPSA2OTQ1MDAuMDAwCiAgICBDT1JORVJfVVJfUFJPSkVDVElPTl9ZX1BST0RVQ1QgPSA0MjY0NTAwLjAwMAogICAgQ09STkVSX0xMX1BST0pFQ1RJT05fWF9QUk9EVUNUID0gNDY0NDAwLjAwMAogICAgQ09STkVSX0xMX1BST0pFQ1RJT05fWV9QUk9EVUNUID0gNDAzMDIwMC4wMDAKICAgIENPUk5FUl9MUl9QUk9KRUNUSU9OX1hfUFJPRFVDVCA9IDY5NDUwMC4wMDAKICAgIENPUk5FUl9MUl9QUk9KRUNUSU9OX1lfUFJPRFVDVCA9IDQwMzAyMDAuMDAwCiAgICBQQU5DSFJPTUFUSUNfTElORVMgPSAxNTYyMQogICAgUEFOQ0hST01BVElDX1NBTVBMRVMgPSAxNTM0MQogICAgUkVGTEVDVElWRV9MSU5FUyA9IDc4MTEKICAgIFJFRkxFQ1RJVkVfU0FNUExFUyA9IDc2NzEKICAgIFRIRVJNQUxfTElORVMgPSA3ODExCiAgICBUSEVSTUFMX1NBTVBMRVMgPSA3NjcxCiAgICBGSUxFX05BTUVfQkFORF8xID0gIkxDODA0NDAzNDIwMTYyNTlMR04wMF9CMS5USUYiCiAgICBGSUxFX05BTUVfQkFORF8yID0gIkxDODA0NDAzNDIwMTYyNTlMR04wMF9CMi5USUYiCiAgICBGSUxFX05BTUVfQkFORF8zID0gIkxDODA0NDAzNDIwMTYyNTlMR04wMF9CMy5USUYiCiAgICBGSUxFX05BTUVfQkFORF80ID0gIkxDODA0NDAzNDIwMTYyNTlMR04wMF9CNC5USUYiCiAgICBGSUxFX05BTUVfQkFORF81ID0gIkxDODA0NDAzNDIwMTYyNTlMR04wMF9CNS5USUYiCiAgICBGSUxFX05BTUVfQkFORF82ID0gIkxDODA0NDAzNDIwMTYyNTlMR04wMF9CNi5USUYiCiAgICBGSUxFX05BTUVfQkFORF83ID0gIkxDODA0NDAzNDIwMTYyNTlMR04wMF9CNy5USUYiCiAgICBGSUxFX05BTUVfQkFORF84ID0gIkxDODA0NDAzNDIwMTYyNTlMR04wMF9COC5USUYiCiAgICBGSUxFX05BTUVfQkFORF85ID0gIkxDODA0NDAzNDIwMTYyNTlMR04wMF9COS5USUYiCiAgICBGSUxFX05BTUVfQkFORF8xMCA9ICJMQzgwNDQwMzQyMDE2MjU5TEdOMDBfQjEwLlRJRiIKICAgIEZJTEVfTkFNRV9CQU5EXzExID0gIkxDODA0NDAzNDIwMTYyNTlMR04wMF9CMTEuVElGIgogICAgRklMRV9OQU1FX0JBTkRfUVVBTElUWSA9ICJMQzgwNDQwMzQyMDE2MjU5TEdOMDBfQlFBLlRJRiIKICAgIE1FVEFEQVRBX0ZJTEVfTkFNRSA9ICJMQzgwNDQwMzQyMDE2MjU5TEdOMDBfTVRMLnR4dCIKICAgIEJQRl9OQU1FX09MSSA9ICJMTzhCUEYyMDE2MDkxNTE4MzA1N18yMDE2MDkxNTIwMDk1MC4wMSIKICAgIEJQRl9OQU1FX1RJUlMgPSAiTFQ4QlBGMjAxNjA5MDIwODQxMjJfMjAxNjA5MTcwNzQwMjcuMDIiCiAgICBDUEZfTkFNRSA9ICJMOENQRjIwMTYwNzAxXzIwMTYwOTMwLjAyIgogICAgUkxVVF9GSUxFX05BTUUgPSAiTDhSTFVUMjAxNTAzMDNfMjA0MzEyMzF2MTEuaDUiCiAgRU5EX0dST1VQID0gUFJPRFVDVF9NRVRBREFUQQogIEdST1VQID0gSU1BR0VfQVRUUklCVVRFUwogICAgQ0xPVURfQ09WRVIgPSAyOS41NgogICAgQ0xPVURfQ09WRVJfTEFORCA9IDMuMzMKICAgIElNQUdFX1FVQUxJVFlfT0xJID0gOQogICAgSU1BR0VfUVVBTElUWV9USVJTID0gOQogICAgVElSU19TU01fTU9ERUwgPSAiRklOQUwiCiAgICBUSVJTX1NTTV9QT1NJVElPTl9TVEFUVVMgPSAiRVNUSU1BVEVEIgogICAgUk9MTF9BTkdMRSA9IC0wLjAwMQogICAgU1VOX0FaSU1VVEggPSAxNDguNDgwNDkzOTYKICAgIFNVTl9FTEVWQVRJT04gPSA1MC45Mzc2ODM5OQogICAgRUFSVEhfU1VOX0RJU1RBTkNFID0gMS4wMDUzNzUyCiAgICBHUk9VTkRfQ09OVFJPTF9QT0lOVFNfVkVSU0lPTiA9IDQKICAgIEdST1VORF9DT05UUk9MX1BPSU5UU19NT0RFTCA9IDU0OAogICAgR0VPTUVUUklDX1JNU0VfTU9ERUwgPSA1Ljg1NwogICAgR0VPTUVUUklDX1JNU0VfTU9ERUxfWSA9IDMuODQxCiAgICBHRU9NRVRSSUNfUk1TRV9NT0RFTF9YID0gNC40MjIKICAgIEdST1VORF9DT05UUk9MX1BPSU5UU19WRVJJRlkgPSAyMjgKICAgIEdFT01FVFJJQ19STVNFX1ZFUklGWSA9IDMuMzgyCiAgRU5EX0dST1VQID0gSU1BR0VfQVRUUklCVVRFUwogIEdST1VQID0gTUlOX01BWF9SQURJQU5DRQogICAgUkFESUFOQ0VfTUFYSU1VTV9CQU5EXzEgPSA3NTEuOTU3MDkKICAgIFJBRElBTkNFX01JTklNVU1fQkFORF8xID0gLTYyLjA5Njg2CiAgICBSQURJQU5DRV9NQVhJTVVNX0JBTkRfMiA9IDc3MC4wMTMxOAogICAgUkFESUFOQ0VfTUlOSU1VTV9CQU5EXzIgPSAtNjMuNTg3OTQKICAgIFJBRElBTkNFX01BWElNVU1fQkFORF8zID0gNzA5LjU2MDYxCiAgICBSQURJQU5DRV9NSU5JTVVNX0JBTkRfMyA9IC01OC41OTU3NQogICAgUkFESUFOQ0VfTUFYSU1VTV9CQU5EXzQgPSA1OTguMzQxNDkKICAgIFJBRElBTkNFX01JTklNVU1fQkFORF80ID0gLTQ5LjQxMTIzCiAgICBSQURJQU5DRV9NQVhJTVVNX0JBTkRfNSA9IDM2Ni4xNTUxNQogICAgUkFESUFOQ0VfTUlOSU1VTV9CQU5EXzUgPSAtMzAuMjM3MjEKICAgIFJBRElBTkNFX01BWElNVU1fQkFORF82ID0gOTEuMDU5NDYKICAgIFJBRElBTkNFX01JTklNVU1fQkFORF82ID0gLTcuNTE5NzIKICAgIFJBRElBTkNFX01BWElNVU1fQkFORF83ID0gMzAuNjkxOTEKICAgIFJBRElBTkNFX01JTklNVU1fQkFORF83ID0gLTIuNTM0NTUKICAgIFJBRElBTkNFX01BWElNVU1fQkFORF84ID0gNjc3LjE1Nzg0CiAgICBSQURJQU5DRV9NSU5JTVVNX0JBTkRfOCA9IC01NS45MTk5MgogICAgUkFESUFOQ0VfTUFYSU1VTV9CQU5EXzkgPSAxNDMuMTAxNzMKICAgIFJBRElBTkNFX01JTklNVU1fQkFORF85ID0gLTExLjgxNzM5CiAgICBSQURJQU5DRV9NQVhJTVVNX0JBTkRfMTAgPSAyMi4wMDE4MAogICAgUkFESUFOQ0VfTUlOSU1VTV9CQU5EXzEwID0gMC4xMDAzMwogICAgUkFESUFOQ0VfTUFYSU1VTV9CQU5EXzExID0gMjIuMDAxODAKICAgIFJBRElBTkNFX01JTklNVU1fQkFORF8xMSA9IDAuMTAwMzMKICBFTkRfR1JPVVAgPSBNSU5fTUFYX1JBRElBTkNFCiAgR1JPVVAgPSBNSU5fTUFYX1JFRkxFQ1RBTkNFCiAgICBSRUZMRUNUQU5DRV9NQVhJTVVNX0JBTkRfMSA9IDEuMjEwNzAwCiAgICBSRUZMRUNUQU5DRV9NSU5JTVVNX0JBTkRfMSA9IC0wLjA5OTk4MAogICAgUkVGTEVDVEFOQ0VfTUFYSU1VTV9CQU5EXzIgPSAxLjIxMDcwMAogICAgUkVGTEVDVEFOQ0VfTUlOSU1VTV9CQU5EXzIgPSAtMC4wOTk5ODAKICAgIFJFRkxFQ1RBTkNFX01BWElNVU1fQkFORF8zID0gMS4yMTA3MDAKICAgIFJFRkxFQ1RBTkNFX01JTklNVU1fQkFORF8zID0gLTAuMDk5OTgwCiAgICBSRUZMRUNUQU5DRV9NQVhJTVVNX0JBTkRfNCA9IDEuMjEwNzAwCiAgICBSRUZMRUNUQU5DRV9NSU5JTVVNX0JBTkRfNCA9IC0wLjA5OTk4MAogICAgUkVGTEVDVEFOQ0VfTUFYSU1VTV9CQU5EXzUgPSAxLjIxMDcwMAogICAgUkVGTEVDVEFOQ0VfTUlOSU1VTV9CQU5EXzUgPSAtMC4wOTk5ODAKICAgIFJFRkxFQ1RBTkNFX01BWElNVU1fQkFORF82ID0gMS4yMTA3MDAKICAgIFJFRkxFQ1RBTkNFX01JTklNVU1fQkFORF82ID0gLTAuMDk5OTgwCiAgICBSRUZMRUNUQU5DRV9NQVhJTVVNX0JBTkRfNyA9IDEuMjEwNzAwCiAgICBSRUZMRUNUQU5DRV9NSU5JTVVNX0JBTkRfNyA9IC0wLjA5OTk4MAogICAgUkVGTEVDVEFOQ0VfTUFYSU1VTV9CQU5EXzggPSAxLjIxMDcwMAogICAgUkVGTEVDVEFOQ0VfTUlOSU1VTV9CQU5EXzggPSAtMC4wOTk5ODAKICAgIFJFRkxFQ1RBTkNFX01BWElNVU1fQkFORF85ID0gMS4yMTA3MDAKICAgIFJFRkxFQ1RBTkNFX01JTklNVU1fQkFORF85ID0gLTAuMDk5OTgwCiAgRU5EX0dST1VQID0gTUlOX01BWF9SRUZMRUNUQU5DRQogIEdST1VQID0gTUlOX01BWF9QSVhFTF9WQUxVRQogICAgUVVBTlRJWkVfQ0FMX01BWF9CQU5EXzEgPSA2NTUzNQogICAgUVVBTlRJWkVfQ0FMX01JTl9CQU5EXzEgPSAxCiAgICBRVUFOVElaRV9DQUxfTUFYX0JBTkRfMiA9IDY1NTM1CiAgICBRVUFOVElaRV9DQUxfTUlOX0JBTkRfMiA9IDEKICAgIFFVQU5USVpFX0NBTF9NQVhfQkFORF8zID0gNjU1MzUKICAgIFFVQU5USVpFX0NBTF9NSU5fQkFORF8zID0gMQogICAgUVVBTlRJWkVfQ0FMX01BWF9CQU5EXzQgPSA2NTUzNQogICAgUVVBTlRJWkVfQ0FMX01JTl9CQU5EXzQgPSAxCiAgICBRVUFOVElaRV9DQUxfTUFYX0JBTkRfNSA9IDY1NTM1CiAgICBRVUFOVElaRV9DQUxfTUlOX0JBTkRfNSA9IDEKICAgIFFVQU5USVpFX0NBTF9NQVhfQkFORF82ID0gNjU1MzUKICAgIFFVQU5USVpFX0NBTF9NSU5fQkFORF82ID0gMQogICAgUVVBTlRJWkVfQ0FMX01BWF9CQU5EXzcgPSA2NTUzNQogICAgUVVBTlRJWkVfQ0FMX01JTl9CQU5EXzcgPSAxCiAgICBRVUFOVElaRV9DQUxfTUFYX0JBTkRfOCA9IDY1NTM1CiAgICBRVUFOVElaRV9DQUxfTUlOX0JBTkRfOCA9IDEKICAgIFFVQU5USVpFX0NBTF9NQVhfQkFORF85ID0gNjU1MzUKICAgIFFVQU5USVpFX0NBTF9NSU5fQkFORF85ID0gMQogICAgUVVBTlRJWkVfQ0FMX01BWF9CQU5EXzEwID0gNjU1MzUKICAgIFFVQU5USVpFX0NBTF9NSU5fQkFORF8xMCA9IDEKICAgIFFVQU5USVpFX0NBTF9NQVhfQkFORF8xMSA9IDY1NTM1CiAgICBRVUFOVElaRV9DQUxfTUlOX0JBTkRfMTEgPSAxCiAgRU5EX0dST1VQID0gTUlOX01BWF9QSVhFTF9WQUxVRQogIEdST1VQID0gUkFESU9NRVRSSUNfUkVTQ0FMSU5HCiAgICBSQURJQU5DRV9NVUxUX0JBTkRfMSA9IDEuMjQyMkUtMDIKICAgIFJBRElBTkNFX01VTFRfQkFORF8yID0gMS4yNzIwRS0wMgogICAgUkFESUFOQ0VfTVVMVF9CQU5EXzMgPSAxLjE3MjFFLTAyCiAgICBSQURJQU5DRV9NVUxUX0JBTkRfNCA9IDkuODg0MkUtMDMKICAgIFJBRElBTkNFX01VTFRfQkFORF81ID0gNi4wNDg3RS0wMwogICAgUkFESUFOQ0VfTVVMVF9CQU5EXzYgPSAxLjUwNDJFLTAzCiAgICBSQURJQU5DRV9NVUxUX0JBTkRfNyA9IDUuMDcwMUUtMDQKICAgIFJBRElBTkNFX01VTFRfQkFORF84ID0gMS4xMTg2RS0wMgogICAgUkFESUFOQ0VfTVVMVF9CQU5EXzkgPSAyLjM2NDBFLTAzCiAgICBSQURJQU5DRV9NVUxUX0JBTkRfMTAgPSAzLjM0MjBFLTA0CiAgICBSQURJQU5DRV9NVUxUX0JBTkRfMTEgPSAzLjM0MjBFLTA0CiAgICBSQURJQU5DRV9BRERfQkFORF8xID0gLTYyLjEwOTI4CiAgICBSQURJQU5DRV9BRERfQkFORF8yID0gLTYzLjYwMDY2CiAgICBSQURJQU5DRV9BRERfQkFORF8zID0gLTU4LjYwNzQ3CiAgICBSQURJQU5DRV9BRERfQkFORF80ID0gLTQ5LjQyMTEyCiAgICBSQURJQU5DRV9BRERfQkFORF81ID0gLTMwLjI0MzI2CiAgICBSQURJQU5DRV9BRERfQkFORF82ID0gLTcuNTIxMjIKICAgIFJBRElBTkNFX0FERF9CQU5EXzcgPSAtMi41MzUwNQogICAgUkFESUFOQ0VfQUREX0JBTkRfOCA9IC01NS45MzExMAogICAgUkFESUFOQ0VfQUREX0JBTkRfOSA9IC0xMS44MTk3NQogICAgUkFESUFOQ0VfQUREX0JBTkRfMTAgPSAwLjEwMDAwCiAgICBSQURJQU5DRV9BRERfQkFORF8xMSA9IDAuMTAwMDAKICAgIFJFRkxFQ1RBTkNFX01VTFRfQkFORF8xID0gMi4wMDAwRS0wNQogICAgUkVGTEVDVEFOQ0VfTVVMVF9CQU5EXzIgPSAyLjAwMDBFLTA1CiAgICBSRUZMRUNUQU5DRV9NVUxUX0JBTkRfMyA9IDIuMDAwMEUtMDUKICAgIFJFRkxFQ1RBTkNFX01VTFRfQkFORF80ID0gMi4wMDAwRS0wNQogICAgUkVGTEVDVEFOQ0VfTVVMVF9CQU5EXzUgPSAyLjAwMDBFLTA1CiAgICBSRUZMRUNUQU5DRV9NVUxUX0JBTkRfNiA9IDIuMDAwMEUtMDUKICAgIFJFRkxFQ1RBTkNFX01VTFRfQkFORF83ID0gMi4wMDAwRS0wNQogICAgUkVGTEVDVEFOQ0VfTVVMVF9CQU5EXzggPSAyLjAwMDBFLTA1CiAgICBSRUZMRUNUQU5DRV9NVUxUX0JBTkRfOSA9IDIuMDAwMEUtMDUKICAgIFJFRkxFQ1RBTkNFX0FERF9CQU5EXzEgPSAtMC4xMDAwMDAKICAgIFJFRkxFQ1RBTkNFX0FERF9CQU5EXzIgPSAtMC4xMDAwMDAKICAgIFJFRkxFQ1RBTkNFX0FERF9CQU5EXzMgPSAtMC4xMDAwMDAKICAgIFJFRkxFQ1RBTkNFX0FERF9CQU5EXzQgPSAtMC4xMDAwMDAKICAgIFJFRkxFQ1RBTkNFX0FERF9CQU5EXzUgPSAtMC4xMDAwMDAKICAgIFJFRkxFQ1RBTkNFX0FERF9CQU5EXzYgPSAtMC4xMDAwMDAKICAgIFJFRkxFQ1RBTkNFX0FERF9CQU5EXzcgPSAtMC4xMDAwMDAKICAgIFJFRkxFQ1RBTkNFX0FERF9CQU5EXzggPSAtMC4xMDAwMDAKICAgIFJFRkxFQ1RBTkNFX0FERF9CQU5EXzkgPSAtMC4xMDAwMDAKICBFTkRfR1JPVVAgPSBSQURJT01FVFJJQ19SRVNDQUxJTkcKICBHUk9VUCA9IFRJUlNfVEhFUk1BTF9DT05TVEFOVFMKICAgIEsxX0NPTlNUQU5UX0JBTkRfMTAgPSA3NzQuODg1MwogICAgSzFfQ09OU1RBTlRfQkFORF8xMSA9IDQ4MC44ODgzCiAgICBLMl9DT05TVEFOVF9CQU5EXzEwID0gMTMyMS4wNzg5CiAgICBLMl9DT05TVEFOVF9CQU5EXzExID0gMTIwMS4xNDQyCiAgRU5EX0dST1VQID0gVElSU19USEVSTUFMX0NPTlNUQU5UUwogIEdST1VQID0gUFJPSkVDVElPTl9QQVJBTUVURVJTCiAgICBNQVBfUFJPSkVDVElPTiA9ICJVVE0iCiAgICBEQVRVTSA9ICJXR1M4NCIKICAgIEVMTElQU09JRCA9ICJXR1M4NCIKICAgIFVUTV9aT05FID0gMTAKICAgIEdSSURfQ0VMTF9TSVpFX1BBTkNIUk9NQVRJQyA9IDE1LjAwCiAgICBHUklEX0NFTExfU0laRV9SRUZMRUNUSVZFID0gMzAuMDAKICAgIEdSSURfQ0VMTF9TSVpFX1RIRVJNQUwgPSAzMC4wMAogICAgT1JJRU5UQVRJT04gPSAiTk9SVEhfVVAiCiAgICBSRVNBTVBMSU5HX09QVElPTiA9ICJDVUJJQ19DT05WT0xVVElPTiIKICBFTkRfR1JPVVAgPSBQUk9KRUNUSU9OX1BBUkFNRVRFUlMKRU5EX0dST1VQID0gTDFfTUVUQURBVEFfRklMRQpFTkQK"
+ }
+ },
+ {
+ "ID": "a5cc268bb6d1901b",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://storage.googleapis.com/gcp-public-data-landsat/LC08/PRE/044/034/LC80440342016259LGN00/LC80440342016259LGN00_MTL.txt",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Range": [
+ "bytes=0-17"
+ ],
+ "User-Agent": [
+ "Go-http-client/1.1"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "09ad91b6f03772df950fe8e60e38b515/4189135646215237917;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "storage.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://storage.googleapis.com/gcp-public-data-landsat/LC08/PRE/044/034/LC80440342016259LGN00/LC80440342016259LGN00_MTL.txt"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 206,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Accept-Ranges": [
+ "bytes"
+ ],
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "public, max-age=3600"
+ ],
+ "Content-Length": [
+ "18"
+ ],
+ "Content-Range": [
+ "bytes 0-17/7903"
+ ],
+ "Content-Type": [
+ "application/octet-stream"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:23 GMT"
+ ],
+ "Etag": [
+ "\"7a5fd4743bd647485f88496fadb05c51\""
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 13:25:23 GMT"
+ ],
+ "Last-Modified": [
+ "Tue, 04 Oct 2016 16:42:07 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "X-Goog-Generation": [
+ "1475599327662000"
+ ],
+ "X-Goog-Hash": [
+ "crc32c=PWBt8g==",
+ "md5=el/UdDvWR0hfiElvrbBcUQ=="
+ ],
+ "X-Goog-Metageneration": [
+ "1"
+ ],
+ "X-Goog-Storage-Class": [
+ "STANDARD"
+ ],
+ "X-Goog-Stored-Content-Encoding": [
+ "identity"
+ ],
+ "X-Goog-Stored-Content-Length": [
+ "7903"
+ ],
+ "X-Google-Backends": [
+ "/bns/xh/borg/xh/bns/cloud-storage/prod-cloud-storage-frontend.frontend/9,/bns/xh/borg/xh/bns/blobstore2/bitpusher/84.scotty,aclgag19:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=M8ysW6m8Ee6iswap5okY"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "570399209098"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "aclgag19:443,/bns/xh/borg/xh/bns/blobstore2/bitpusher/84.scotty,aclgag19:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/xh/borg/xh/bns/blobstore2/bitpusher/84:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBJ"
+ ],
+ "X-Google-Storage-Location": [
+ "US"
+ ],
+ "X-Guploader-Customer": [
+ "cloud-storage"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UqkVgj_WF9UVLkpunOc4f5drxYHK8wCMGJ7_8XXUZHjlPkkeMgAoXxEItBA_PzaL4caKEF9IdpCYBJ3TGiRJVImw-TsSw"
+ ]
+ },
+ "Body": "R1JPVVAgPSBMMV9NRVRBREFU"
+ }
+ },
+ {
+ "ID": "574c045ea3cf3804",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://storage.googleapis.com/storage-library-test-bucket/gzipped-text.txt",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "User-Agent": [
+ "Go-http-client/1.1"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "da531b177a2f61995e226a1dbd8bddba/5779266075288967100;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "storage.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://storage.googleapis.com/storage-library-test-bucket/gzipped-text.txt"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Accept-Ranges": [
+ "bytes"
+ ],
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "public, max-age=3600"
+ ],
+ "Content-Encoding": [
+ "gzip"
+ ],
+ "Content-Type": [
+ "text/plain"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:23 GMT"
+ ],
+ "Etag": [
+ "\"c6117833aa4d1510d09ef69144d56790\""
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 13:25:23 GMT"
+ ],
+ "Last-Modified": [
+ "Tue, 14 Nov 2017 13:07:32 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Accept-Encoding"
+ ],
+ "X-Goog-Generation": [
+ "1510664852486988"
+ ],
+ "X-Goog-Hash": [
+ "crc32c=T1s5RQ==",
+ "md5=xhF4M6pNFRDQnvaRRNVnkA=="
+ ],
+ "X-Goog-Metageneration": [
+ "2"
+ ],
+ "X-Goog-Storage-Class": [
+ "MULTI_REGIONAL"
+ ],
+ "X-Goog-Stored-Content-Encoding": [
+ "gzip"
+ ],
+ "X-Goog-Stored-Content-Length": [
+ "31"
+ ],
+ "X-Google-Backends": [
+ "/bns/xh/borg/xh/bns/cloud-storage/prod-cloud-storage-frontend.frontend/34,/bns/xh/borg/xh/bns/blobstore2/bitpusher/70.scotty,aclgag19:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=M8ysW4fJE4-nswav84G4Aw"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "149776848335"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "aclgag19:443,/bns/xh/borg/xh/bns/blobstore2/bitpusher/70.scotty,aclgag19:443"
+ ],
+ "X-Google-Gfe-Response-Body-Transformations": [
+ "chunked"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/xh/borg/xh/bns/blobstore2/bitpusher/70:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBJ"
+ ],
+ "X-Google-Storage-Location": [
+ "US"
+ ],
+ "X-Guploader-Customer": [
+ "cloud-storage"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Uo9Aj65b1Br7RgKAI30zOrcX8vmaoramy1cI5Ecx8HOMYG4EgpcqnaTGYdlH3irWvCrEeseqO2eVWcLhXryI224usemaQ"
+ ]
+ },
+ "Body": "H4sIAAAAAAAAC8tIzcnJVyjPL8pJAQCFEUoNCwAAAA=="
+ }
+ },
+ {
+ "ID": "027b227c73085f2e",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://storage.googleapis.com/storage-library-test-bucket/gzipped-text.txt",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "User-Agent": [
+ "Go-http-client/1.1"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "6e48de6be47e1726efca75ecf91cc67f/7369676879861267547;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "storage.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://storage.googleapis.com/storage-library-test-bucket/gzipped-text.txt"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Accept-Ranges": [
+ "bytes"
+ ],
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "public, max-age=3600"
+ ],
+ "Content-Encoding": [
+ "gzip"
+ ],
+ "Content-Type": [
+ "text/plain"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:23 GMT"
+ ],
+ "Etag": [
+ "\"c6117833aa4d1510d09ef69144d56790\""
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 13:25:23 GMT"
+ ],
+ "Last-Modified": [
+ "Tue, 14 Nov 2017 13:07:32 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Accept-Encoding"
+ ],
+ "X-Goog-Generation": [
+ "1510664852486988"
+ ],
+ "X-Goog-Hash": [
+ "crc32c=T1s5RQ==",
+ "md5=xhF4M6pNFRDQnvaRRNVnkA=="
+ ],
+ "X-Goog-Metageneration": [
+ "2"
+ ],
+ "X-Goog-Storage-Class": [
+ "MULTI_REGIONAL"
+ ],
+ "X-Goog-Stored-Content-Encoding": [
+ "gzip"
+ ],
+ "X-Goog-Stored-Content-Length": [
+ "31"
+ ],
+ "X-Google-Backends": [
+ "/bns/xh/borg/xh/bns/cloud-storage/prod-cloud-storage-frontend.frontend/10,/bns/xh/borg/xh/bns/blobstore2/bitpusher/29.scotty,aclgag19:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=M8ysW42-IqunswbA1YPwDQ"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "149776848335"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "aclgag19:443,/bns/xh/borg/xh/bns/blobstore2/bitpusher/29.scotty,aclgag19:443"
+ ],
+ "X-Google-Gfe-Response-Body-Transformations": [
+ "chunked"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/xh/borg/xh/bns/blobstore2/bitpusher/29:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBJ"
+ ],
+ "X-Google-Storage-Location": [
+ "US"
+ ],
+ "X-Guploader-Customer": [
+ "cloud-storage"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UqNTsfcXgqxyenoWbH8XJlTngFOKqu9awa6fdF9AQIuGB20Yt5aSpNaZW5_v89qJTm-X1F0f9wI_IuIjUYNTUmTc5uHYw"
+ ]
+ },
+ "Body": "H4sIAAAAAAAAC8tIzcnJVyjPL8pJAQCFEUoNCwAAAA=="
+ }
+ },
+ {
+ "ID": "65a7840a56398b21",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://storage.googleapis.com/storage-library-test-bucket/gzipped-text.txt",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Range": [
+ "bytes=1-8"
+ ],
+ "User-Agent": [
+ "Go-http-client/1.1"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "3766269e952d05c271145eb0fd87c8ee/8960088783911707385;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "storage.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://storage.googleapis.com/storage-library-test-bucket/gzipped-text.txt"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "public, max-age=3600"
+ ],
+ "Content-Type": [
+ "text/plain"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:23 GMT"
+ ],
+ "Etag": [
+ "W/\"c6117833aa4d1510d09ef69144d56790\""
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 13:25:23 GMT"
+ ],
+ "Last-Modified": [
+ "Tue, 14 Nov 2017 13:07:32 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Accept-Encoding"
+ ],
+ "Warning": [
+ "214 UploadServer gunzipped"
+ ],
+ "X-Goog-Generation": [
+ "1510664852486988"
+ ],
+ "X-Goog-Hash": [
+ "crc32c=T1s5RQ==",
+ "md5=xhF4M6pNFRDQnvaRRNVnkA=="
+ ],
+ "X-Goog-Metageneration": [
+ "2"
+ ],
+ "X-Goog-Storage-Class": [
+ "MULTI_REGIONAL"
+ ],
+ "X-Goog-Stored-Content-Encoding": [
+ "gzip"
+ ],
+ "X-Goog-Stored-Content-Length": [
+ "31"
+ ],
+ "X-Google-Backends": [
+ "/bns/xh/borg/xh/bns/cloud-storage/prod-cloud-storage-frontend.frontend/45,/bns/xh/borg/xh/bns/blobstore2/bitpusher/80.scotty,aclgag19:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=M8ysW57NJc6kswbMy5uwDQ"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "149776848335"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "aclgag19:443,/bns/xh/borg/xh/bns/blobstore2/bitpusher/80.scotty,aclgag19:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/xh/borg/xh/bns/blobstore2/bitpusher/80:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBJ"
+ ],
+ "X-Google-Storage-Location": [
+ "US"
+ ],
+ "X-Guploader-Customer": [
+ "cloud-storage"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Response-Body-Transformations": [
+ "gunzipped"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UoCc2I6_fp7BwCazBRuRPMhs5e3Cb1CjNL8hf2WwiHrn7M9O2VYBnD8dGiXXE7OjpzmNwMs_p79POAwtNGqirsz6xeq_g"
+ ]
+ },
+ "Body": "aGVsbG8gd29ybGQ="
+ }
+ },
+ {
+ "ID": "f4246d20764d26ad",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://storage.googleapis.com/storage-library-test-bucket/gzipped-text.txt",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Range": [
+ "bytes=1-8"
+ ],
+ "User-Agent": [
+ "Go-http-client/1.1"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "e75f866fd5e45b56d113d16373ec968e/10550500683683956632;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "storage.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://storage.googleapis.com/storage-library-test-bucket/gzipped-text.txt"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 206,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Accept-Ranges": [
+ "bytes"
+ ],
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "public, max-age=3600"
+ ],
+ "Content-Encoding": [
+ "gzip"
+ ],
+ "Content-Range": [
+ "bytes 1-8/31"
+ ],
+ "Content-Type": [
+ "text/plain"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:23 GMT"
+ ],
+ "Etag": [
+ "\"c6117833aa4d1510d09ef69144d56790\""
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 13:25:23 GMT"
+ ],
+ "Last-Modified": [
+ "Tue, 14 Nov 2017 13:07:32 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Accept-Encoding"
+ ],
+ "X-Goog-Generation": [
+ "1510664852486988"
+ ],
+ "X-Goog-Hash": [
+ "crc32c=T1s5RQ==",
+ "md5=xhF4M6pNFRDQnvaRRNVnkA=="
+ ],
+ "X-Goog-Metageneration": [
+ "2"
+ ],
+ "X-Goog-Storage-Class": [
+ "MULTI_REGIONAL"
+ ],
+ "X-Goog-Stored-Content-Encoding": [
+ "gzip"
+ ],
+ "X-Goog-Stored-Content-Length": [
+ "31"
+ ],
+ "X-Google-Backends": [
+ "/bns/xh/borg/xh/bns/cloud-storage/prod-cloud-storage-frontend.frontend/36,/bns/xh/borg/xh/bns/blobstore2/bitpusher/25.scotty,aclgag19:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=M8ysW7TbLsuiswbL5ISoCw"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "149776848335"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "aclgag19:443,/bns/xh/borg/xh/bns/blobstore2/bitpusher/25.scotty,aclgag19:443"
+ ],
+ "X-Google-Gfe-Response-Body-Transformations": [
+ "chunked"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/xh/borg/xh/bns/blobstore2/bitpusher/25:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBJ"
+ ],
+ "X-Google-Storage-Location": [
+ "US"
+ ],
+ "X-Guploader-Customer": [
+ "cloud-storage"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UqAL855d-gxFgB7THGC-650cvXihw5lB59ggNnDFfjg6XIgDXyuFTpLW-pmFjXgB8CNqbblqfCMo_-TRThQ1RXYXnsZvA"
+ ]
+ },
+ "Body": "iwgAAAAAAAA="
+ }
+ },
+ {
+ "ID": "a51b58139c178bc6",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/storage/v1/b?alt=json\u0026prettyPrint=false\u0026project=dulcet-port-762",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "168"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "e7e4e8d35d137df1fe1d2c0195b8596f/12899949557172305798;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b?alt=json\u0026prettyPrint=false\u0026project=dulcet-port-762"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJjb3JzIjpbeyJtYXhBZ2VTZWNvbmRzIjozNjAwLCJtZXRob2QiOlsiUE9TVCJdLCJvcmlnaW4iOlsic29tZS1vcmlnaW4uY29tIl0sInJlc3BvbnNlSGVhZGVyIjpbImZvby1iYXIiXX1dLCJuYW1lIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA0In0K"
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "534"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:24 GMT"
+ ],
+ "Etag": [
+ "CAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051423000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vncf185:4324,/bns/yx/borg/yx/bns/blobstore2/bitpusher/43.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=M8ysW5ehOszUzwKklI3gBA"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yx/borg/yx/bns/blobstore2/bitpusher/43.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yx/borg/yx/bns/blobstore2/bitpusher/43:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWXA3ZUxTdWNBTVN4aWpIaGJ4VldlcTlheV9Zb3I5dEQ4cFplQ0NNUklKLXJMQ29yX2JvaXdtdVhYRGNISTRfdURWYUtTRHVfVFhtWTl4dXBBOC1JUGZudFFaRnRLOTNlbTg3ZTNlbUFkYjFaUVA3cWo5Mjg0YmM3cllER3ZKRUFrZ0tVT1FiWUZJcmtReWs5WFZIZEpKOHd2NmJPX3FGNl9pZ2Uxcl8yX0pLb2dfenJSUHJlU2JnYUEwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Up-M82G1RCRAc4_k2TYOnb54Ji0mbQimQSLP7qmP1TJf7ZRPv4LLs5J5r7Hq4Rdkww8v4v9YsGo_Un_5Pzb_4JhXoxKGg"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwNCIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwNCIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDQiLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjU6MjQuNTg1WiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI1OjI0LjU4NVoiLCJtZXRhZ2VuZXJhdGlvbiI6IjEiLCJsb2NhdGlvbiI6IlVTIiwiY29ycyI6W3sib3JpZ2luIjpbInNvbWUtb3JpZ2luLmNvbSJdLCJtZXRob2QiOlsiUE9TVCJdLCJyZXNwb25zZUhlYWRlciI6WyJmb28tYmFyIl0sIm1heEFnZVNlY29uZHMiOjM2MDB9XSwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJldGFnIjoiQ0FFPSJ9"
+ }
+ },
+ {
+ "ID": "42f28f433400a58f",
+ "Request": {
+ "Method": "PATCH",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0004?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "99"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "3f718e5ff9b55972984cc82b6fbdcae7/14490079990540936485;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0004?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJjb3JzIjpbeyJtYXhBZ2VTZWNvbmRzIjozNjAwLCJtZXRob2QiOlsiR0VUIl0sIm9yaWdpbiI6WyIqIl0sInJlc3BvbnNlSGVhZGVyIjpbInNvbWUtaGVhZGVyIl19XX0K"
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "2450"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:26 GMT"
+ ],
+ "Etag": [
+ "CAI="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051425000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vnu199:4210,/bns/yx/borg/yx/bns/blobstore2/bitpusher/22.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=NMysW-G4MY3kzgKkyrfoBQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yx/borg/yx/bns/blobstore2/bitpusher/22.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yx/borg/yx/bns/blobstore2/bitpusher/22:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATpxChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4CtK4wESxgF5YTI5LmMuRW93QkpRWXA3ZUxTdWNBTVN4aWpIaGJ4VldlcTlheV9Zb3I5dEQ4cFplQ0NNUklKLXJMQ29yX2JvaXdtdVhYRGNISTRfdURWYUtTRHVfVFhtWTl4dXBBOC1JUGZudFFaRnRLOTNlbTg3ZTNlbUFkYjFaUVA3cWo5Mjg0YmM3cllER3ZKRUFrZ0tVT1FiWUZJcmtReWs5WFZIZEpKOHd2NmJPX3FGNl9pZ2Uxcl8yX0pLb2dfenJSUHJlU2JnYUEwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UpCe8icExj8XMpYK1TObRcXWmSYabbYDaYeKKLNa4ElTNYmug1iz39xmlHlwvVla0d8DUorCDA1nCJfEmcy28KN9CoA-A"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwNCIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwNCIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDQiLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjU6MjQuNTg1WiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI1OjI2LjI4NloiLCJtZXRhZ2VuZXJhdGlvbiI6IjIiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwNC9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwNC9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDQiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBST0ifSx7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwNC9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDQvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwNCIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDQUk9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDQvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA0L2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDQiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNBST0ifV0sImRlZmF1bHRPYmplY3RBY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBST0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0FJPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0FJPSJ9XSwib3duZXIiOnsiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUifSwibG9jYXRpb24iOiJVUyIsImNvcnMiOlt7Im9yaWdpbiI6WyIqIl0sIm1ldGhvZCI6WyJHRVQiXSwicmVzcG9uc2VIZWFkZXIiOlsic29tZS1oZWFkZXIiXSwibWF4QWdlU2Vjb25kcyI6MzYwMH1dLCJzdG9yYWdlQ2xhc3MiOiJTVEFOREFSRCIsImV0YWciOiJDQUk9In0="
+ }
+ },
+ {
+ "ID": "38e349c8d229e705",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0004?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "95faa0d1e208bca5ba1106e6ea570244/16080490790818400963;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0004?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0, must-revalidate, no-transform"
+ ],
+ "Content-Length": [
+ "2450"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:26 GMT"
+ ],
+ "Etag": [
+ "CAI="
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:25:26 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051426000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrcb128:4027,/bns/yv/borg/yv/bns/blobstore2/bitpusher/190.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=NsysW8OWHoOxgAT7pqv4Bg"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/190.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/190:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRWXA3ZUxTdWNBTVN4aWpIaGJ4VldlcTlheV9Zb3I5dEQ4cFplQ0NNUklKLXJMQ29yX2JvaXdtdVhYRGNISTRfdURWYUtTRHVfVFhtWTl4dXBBOC1JUGZudFFaRnRLOTNlbTg3ZTNlbUFkYjFaUVA3cWo5Mjg0YmM3cllER3ZKRUFrZ0tVT1FiWUZJcmtReWs5WFZIZEpKOHd2NmJPX3FGNl9pZ2Uxcl8yX0pLb2dfenJSUHJlU2JnYUEwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Ur_SZVOmSR3gw9aBQWrXPXpmAsXUZBMfCAN8ENQ_RN82GUM4ABJX22dwPm4swzz7-fMmky7rvfvKnYnl6_c6YJ9j07hrw"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwNCIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwNCIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDQiLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjU6MjQuNTg1WiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI1OjI2LjI4NloiLCJtZXRhZ2VuZXJhdGlvbiI6IjIiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwNC9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwNC9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDQiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBST0ifSx7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwNC9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDQvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwNCIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDQUk9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDQvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA0L2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDQiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNBST0ifV0sImRlZmF1bHRPYmplY3RBY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBST0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0FJPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0FJPSJ9XSwib3duZXIiOnsiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUifSwibG9jYXRpb24iOiJVUyIsImNvcnMiOlt7Im9yaWdpbiI6WyIqIl0sIm1ldGhvZCI6WyJHRVQiXSwicmVzcG9uc2VIZWFkZXIiOlsic29tZS1oZWFkZXIiXSwibWF4QWdlU2Vjb25kcyI6MzYwMH1dLCJzdG9yYWdlQ2xhc3MiOiJTVEFOREFSRCIsImV0YWciOiJDQUk9In0="
+ }
+ },
+ {
+ "ID": "201a3cf4195f61d8",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/storage/v1/b?alt=json\u0026prettyPrint=false\u0026project=dulcet-port-762",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "168"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "c3052cb0ee7da0aa57130dd12681b838/17670902694868775010;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b?alt=json\u0026prettyPrint=false\u0026project=dulcet-port-762"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJjb3JzIjpbeyJtYXhBZ2VTZWNvbmRzIjozNjAwLCJtZXRob2QiOlsiUE9TVCJdLCJvcmlnaW4iOlsic29tZS1vcmlnaW4uY29tIl0sInJlc3BvbnNlSGVhZGVyIjpbImZvby1iYXIiXX1dLCJuYW1lIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA1In0K"
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "534"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:27 GMT"
+ ],
+ "Etag": [
+ "CAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051426000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrnj6:4466,/bns/yr/borg/yr/bns/blobstore2/bitpusher/84.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=NsysW5DdN8zukAPMwpbQAw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/84.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/84:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWXA3ZUxTdWNBTVN4aWpIaGJ4VldlcTlheV9Zb3I5dEQ4cFplQ0NNUklKLXJMQ29yX2JvaXdtdVhYRGNISTRfdURWYUtTRHVfVFhtWTl4dXBBOC1JUGZudFFaRnRLOTNlbTg3ZTNlbUFkYjFaUVA3cWo5Mjg0YmM3cllER3ZKRUFrZ0tVT1FiWUZJcmtReWs5WFZIZEpKOHd2NmJPX3FGNl9pZ2Uxcl8yX0pLb2dfenJSUHJlU2JnYUEwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UoG59nolJu6P0lapnCNLBjPlFcDG0CVkGRFPV3BFR1UfhJQCi9yzi6WMFaNAMnYw9Bb3a-9hRBOBzwpOb4uVLG_EE92Eg"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwNSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwNSIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDUiLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjU6MjcuMzU5WiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI1OjI3LjM1OVoiLCJtZXRhZ2VuZXJhdGlvbiI6IjEiLCJsb2NhdGlvbiI6IlVTIiwiY29ycyI6W3sib3JpZ2luIjpbInNvbWUtb3JpZ2luLmNvbSJdLCJtZXRob2QiOlsiUE9TVCJdLCJyZXNwb25zZUhlYWRlciI6WyJmb28tYmFyIl0sIm1heEFnZVNlY29uZHMiOjM2MDB9XSwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJldGFnIjoiQ0FFPSJ9"
+ }
+ },
+ {
+ "ID": "eb6d0b7663c27948",
+ "Request": {
+ "Method": "PATCH",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0005?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "12"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "b6ba08a729c3d3528af9897e48ea3fa4/814852000203085057;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0005?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJjb3JzIjpbXX0K"
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "2353"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:29 GMT"
+ ],
+ "Etag": [
+ "CAI="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051428000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrbj188:4240,/bns/yv/borg/yv/bns/blobstore2/bitpusher/68.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=N8ysW_irKov0ggTO1KqQAw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/68.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/68:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATpxChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4CtK4wESxgF5YTI5LmMuRW93QkpRWXA3ZUxTdWNBTVN4aWpIaGJ4VldlcTlheV9Zb3I5dEQ4cFplQ0NNUklKLXJMQ29yX2JvaXdtdVhYRGNISTRfdURWYUtTRHVfVFhtWTl4dXBBOC1JUGZudFFaRnRLOTNlbTg3ZTNlbUFkYjFaUVA3cWo5Mjg0YmM3cllER3ZKRUFrZ0tVT1FiWUZJcmtReWs5WFZIZEpKOHd2NmJPX3FGNl9pZ2Uxcl8yX0pLb2dfenJSUHJlU2JnYUEwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UpV3QRgy3NWsoMryLKJvL-m47BJL6PJuLe0N1ojy-oAm-7ejokRnRHuXMf5DomXVKnET0EIQVCK6D2oh0QWy5bDHA9vYg"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwNSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwNSIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDUiLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjU6MjcuMzU5WiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI1OjI5LjEyNloiLCJtZXRhZ2VuZXJhdGlvbiI6IjIiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwNS9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwNS9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDUiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBST0ifSx7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwNS9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDUvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwNSIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDQUk9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDUvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA1L2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDUiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNBST0ifV0sImRlZmF1bHRPYmplY3RBY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBST0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0FJPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0FJPSJ9XSwib3duZXIiOnsiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUifSwibG9jYXRpb24iOiJVUyIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwiZXRhZyI6IkNBST0ifQ=="
+ }
+ },
+ {
+ "ID": "cdf00ab26a2eecdb",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0005?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "1cea50076c2bab86b3ce930141093eab/2404982433571781535;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0005?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0, must-revalidate, no-transform"
+ ],
+ "Content-Length": [
+ "2353"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:29 GMT"
+ ],
+ "Etag": [
+ "CAI="
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:25:29 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051426000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vryy20:4108,/bns/yv/borg/yv/bns/blobstore2/bitpusher/192.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=OcysW7DjFMHMggTy3YG4Bw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/192.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/192:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRWXA3ZUxTdWNBTVN4aWpIaGJ4VldlcTlheV9Zb3I5dEQ4cFplQ0NNUklKLXJMQ29yX2JvaXdtdVhYRGNISTRfdURWYUtTRHVfVFhtWTl4dXBBOC1JUGZudFFaRnRLOTNlbTg3ZTNlbUFkYjFaUVA3cWo5Mjg0YmM3cllER3ZKRUFrZ0tVT1FiWUZJcmtReWs5WFZIZEpKOHd2NmJPX3FGNl9pZ2Uxcl8yX0pLb2dfenJSUHJlU2JnYUEwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UpyfPH9R-BUYTQzVBjOfEEm9o1nvg54Vz71KBk2t11KwyBI2oi6DYTIPU9Cup_5FPyy5kh-VfhAstvK1mjD1YQx-RPgkw"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwNSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwNSIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDUiLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjU6MjcuMzU5WiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI1OjI5LjEyNloiLCJtZXRhZ2VuZXJhdGlvbiI6IjIiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwNS9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwNS9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDUiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBST0ifSx7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwNS9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDUvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwNSIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDQUk9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDUvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA1L2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDUiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNBST0ifV0sImRlZmF1bHRPYmplY3RBY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBST0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0FJPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0FJPSJ9XSwib3duZXIiOnsiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUifSwibG9jYXRpb24iOiJVUyIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwiZXRhZyI6IkNBST0ifQ=="
+ }
+ },
+ {
+ "ID": "f9c38c019794b168",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/storage/v1/b?alt=json\u0026prettyPrint=false\u0026project=dulcet-port-762",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "168"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "8295ef2a2a15de2124b88197b9465c54/3995394333344030782;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b?alt=json\u0026prettyPrint=false\u0026project=dulcet-port-762"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJjb3JzIjpbeyJtYXhBZ2VTZWNvbmRzIjozNjAwLCJtZXRob2QiOlsiUE9TVCJdLCJvcmlnaW4iOlsic29tZS1vcmlnaW4uY29tIl0sInJlc3BvbnNlSGVhZGVyIjpbImZvby1iYXIiXX1dLCJuYW1lIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA2In0K"
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "534"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:30 GMT"
+ ],
+ "Etag": [
+ "CAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051426000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrqe11:4421,/bns/yv/borg/yv/bns/blobstore2/bitpusher/396.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=OcysW86nJZGegQT-37-ACg"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/396.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/396:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWXA3ZUxTdWNBTVN4aWpIaGJ4VldlcTlheV9Zb3I5dEQ4cFplQ0NNUklKLXJMQ29yX2JvaXdtdVhYRGNISTRfdURWYUtTRHVfVFhtWTl4dXBBOC1JUGZudFFaRnRLOTNlbTg3ZTNlbUFkYjFaUVA3cWo5Mjg0YmM3cllER3ZKRUFrZ0tVT1FiWUZJcmtReWs5WFZIZEpKOHd2NmJPX3FGNl9pZ2Uxcl8yX0pLb2dfenJSUHJlU2JnYUEwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Uo_my9bAu29KvP4rzQoJzMdiiYYqWd8m1uzJtVPqV3kOjqBRbGx8OquWEnvo1F7y7f6PVuoXBgsm9NPw2yJ6o6aWH2PkA"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwNiIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwNiIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDYiLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjU6MzAuMDczWiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI1OjMwLjA3M1oiLCJtZXRhZ2VuZXJhdGlvbiI6IjEiLCJsb2NhdGlvbiI6IlVTIiwiY29ycyI6W3sib3JpZ2luIjpbInNvbWUtb3JpZ2luLmNvbSJdLCJtZXRob2QiOlsiUE9TVCJdLCJyZXNwb25zZUhlYWRlciI6WyJmb28tYmFyIl0sIm1heEFnZVNlY29uZHMiOjM2MDB9XSwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJldGFnIjoiQ0FFPSJ9"
+ }
+ },
+ {
+ "ID": "5d0109fed5cee25f",
+ "Request": {
+ "Method": "PATCH",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0006?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "3"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "4a0a65366ac125c025782d5fd149b821/5585805137899554525;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0006?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "e30K"
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "2461"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:31 GMT"
+ ],
+ "Etag": [
+ "CAI="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051425000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vnqq187:4192,/bns/yx/borg/yx/bns/blobstore2/bitpusher/119.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=OsysW7_8EcTazALWu7ngBw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yx/borg/yx/bns/blobstore2/bitpusher/119.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yx/borg/yx/bns/blobstore2/bitpusher/119:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATpxChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4CtK4wESxgF5YTI5LmMuRW93QkpRWXA3ZUxTdWNBTVN4aWpIaGJ4VldlcTlheV9Zb3I5dEQ4cFplQ0NNUklKLXJMQ29yX2JvaXdtdVhYRGNISTRfdURWYUtTRHVfVFhtWTl4dXBBOC1JUGZudFFaRnRLOTNlbTg3ZTNlbUFkYjFaUVA3cWo5Mjg0YmM3cllER3ZKRUFrZ0tVT1FiWUZJcmtReWs5WFZIZEpKOHd2NmJPX3FGNl9pZ2Uxcl8yX0pLb2dfenJSUHJlU2JnYUEwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UoOkjse13ks1uQtqU-WbIvtpBa6yVJ6A5Qp1A2-N34QjdmA2cc9r6ndxNskGAEOHhNXZUOmh8jUb5P9eV9ZEMwkMiG7IQ"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwNiIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwNiIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDYiLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjU6MzAuMDczWiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI1OjMxLjcxOVoiLCJtZXRhZ2VuZXJhdGlvbiI6IjIiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwNi9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwNi9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDYiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBST0ifSx7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwNi9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDYvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwNiIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDQUk9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDYvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA2L2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDYiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNBST0ifV0sImRlZmF1bHRPYmplY3RBY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBST0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0FJPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0FJPSJ9XSwib3duZXIiOnsiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUifSwibG9jYXRpb24iOiJVUyIsImNvcnMiOlt7Im9yaWdpbiI6WyJzb21lLW9yaWdpbi5jb20iXSwibWV0aG9kIjpbIlBPU1QiXSwicmVzcG9uc2VIZWFkZXIiOlsiZm9vLWJhciJdLCJtYXhBZ2VTZWNvbmRzIjozNjAwfV0sInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwiZXRhZyI6IkNBST0ifQ=="
+ }
+ },
+ {
+ "ID": "483300c086bf9ae9",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0006?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "675dc0a89aa84ed882e3a11dfc3730f2/7175935571285027707;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0006?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0, must-revalidate, no-transform"
+ ],
+ "Content-Length": [
+ "2461"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:32 GMT"
+ ],
+ "Etag": [
+ "CAI="
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:25:32 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051426000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrnb2:4089,/bns/yr/borg/yr/bns/blobstore2/bitpusher/100.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=O8ysW7TNOM3WkAPE_IHQBA"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/100.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/100:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRWXA3ZUxTdWNBTVN4aWpIaGJ4VldlcTlheV9Zb3I5dEQ4cFplQ0NNUklKLXJMQ29yX2JvaXdtdVhYRGNISTRfdURWYUtTRHVfVFhtWTl4dXBBOC1JUGZudFFaRnRLOTNlbTg3ZTNlbUFkYjFaUVA3cWo5Mjg0YmM3cllER3ZKRUFrZ0tVT1FiWUZJcmtReWs5WFZIZEpKOHd2NmJPX3FGNl9pZ2Uxcl8yX0pLb2dfenJSUHJlU2JnYUEwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UpRsZHqvgZPQpv14ylowOLinJDJpespKmK-QjuUL3ZKrxs7YV-WnDO6S7a3PpiKRf66PPEkvVIGhKLNYbHcQlZS8oOq0Q"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwNiIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwNiIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDYiLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjU6MzAuMDczWiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI1OjMxLjcxOVoiLCJtZXRhZ2VuZXJhdGlvbiI6IjIiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwNi9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwNi9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDYiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBST0ifSx7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwNi9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDYvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwNiIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDQUk9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDYvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA2L2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDYiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNBST0ifV0sImRlZmF1bHRPYmplY3RBY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBST0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0FJPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0FJPSJ9XSwib3duZXIiOnsiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUifSwibG9jYXRpb24iOiJVUyIsImNvcnMiOlt7Im9yaWdpbiI6WyJzb21lLW9yaWdpbi5jb20iXSwibWV0aG9kIjpbIlBPU1QiXSwicmVzcG9uc2VIZWFkZXIiOlsiZm9vLWJhciJdLCJtYXhBZ2VTZWNvbmRzIjozNjAwfV0sInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwiZXRhZyI6IkNBST0ifQ=="
+ }
+ },
+ {
+ "ID": "0a993f21217a7c27",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0006?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "e4ddf1ae658880bee0b64eeb36e42981/8766347471040499994;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0006?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 204,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "0"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:32 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051426000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrfn8:4395,/bns/yv/borg/yv/bns/blobstore2/bitpusher/181.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=PMysW_LpDMfugwS5tIzoDQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/181.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/181:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWXA3ZUxTdWNBTVN4aWpIaGJ4VldlcTlheV9Zb3I5dEQ4cFplQ0NNUklKLXJMQ29yX2JvaXdtdVhYRGNISTRfdURWYUtTRHVfVFhtWTl4dXBBOC1JUGZudFFaRnRLOTNlbTg3ZTNlbUFkYjFaUVA3cWo5Mjg0YmM3cllER3ZKRUFrZ0tVT1FiWUZJcmtReWs5WFZIZEpKOHd2NmJPX3FGNl9pZ2Uxcl8yX0pLb2dfenJSUHJlU2JnYUEwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UpYoiT9dFZEe3bYZpKBDdNo1qGJBj162YN_q2mfCF_Cu5UIhC_Ib0VD7PPM6Z1VcjdiHoVEw9wba5WuX-B3x5i3I9fm9Q"
+ ]
+ },
+ "Body": ""
+ }
+ },
+ {
+ "ID": "e8642f6985fa8167",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0005?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "4a1637b431168dd8d2277b2854b6f278/10356759375107716792;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0005?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 204,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "0"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:33 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051426000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrdm4:4150,/bns/yw/borg/yw/bns/blobstore2/bitpusher/164.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=PMysW9aXKc22hAS_5bvYCw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yw/borg/yw/bns/blobstore2/bitpusher/164.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yw/borg/yw/bns/blobstore2/bitpusher/164:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWXA3ZUxTdWNBTVN4aWpIaGJ4VldlcTlheV9Zb3I5dEQ4cFplQ0NNUklKLXJMQ29yX2JvaXdtdVhYRGNISTRfdURWYUtTRHVfVFhtWTl4dXBBOC1JUGZudFFaRnRLOTNlbTg3ZTNlbUFkYjFaUVA3cWo5Mjg0YmM3cllER3ZKRUFrZ0tVT1FiWUZJcmtReWs5WFZIZEpKOHd2NmJPX3FGNl9pZ2Uxcl8yX0pLb2dfenJSUHJlU2JnYUEwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UrlJunYzNiZ4k0A_LqRHm4z2KBn7d1n1oGjjxubNDFJyV2A-_4zxyOnt2gruJckXZXPqElJtv2294941mmIre0KfiIXrg"
+ ]
+ },
+ "Body": ""
+ }
+ },
+ {
+ "ID": "1311ecad1f217ee7",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0004?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "86e26ae2e91c98c6d858aa23da3cb616/11947171279174867799;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0004?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 204,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "0"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:33 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051426000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrlj28:4249,/bns/yv/borg/yv/bns/blobstore2/bitpusher/28.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=PcysW_HtCaGeggTshbKAAw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/28.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/28:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWXA3ZUxTdWNBTVN4aWpIaGJ4VldlcTlheV9Zb3I5dEQ4cFplQ0NNUklKLXJMQ29yX2JvaXdtdVhYRGNISTRfdURWYUtTRHVfVFhtWTl4dXBBOC1JUGZudFFaRnRLOTNlbTg3ZTNlbUFkYjFaUVA3cWo5Mjg0YmM3cllER3ZKRUFrZ0tVT1FiWUZJcmtReWs5WFZIZEpKOHd2NmJPX3FGNl9pZ2Uxcl8yX0pLb2dfenJSUHJlU2JnYUEwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UqLJGRwcwdpiAlh0ePB0ISuYu9FlsEpZ3h5iTHzsEVGBUhR7u_OU3vT_S8kXM9NBplmomCJEJnrR4UEd6FnPhbPMtCG8A"
+ ]
+ },
+ "Body": ""
+ }
+ },
+ {
+ "ID": "f30064255790a2af",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/storage/v1/b?alt=json\u0026prettyPrint=false\u0026project=dulcet-port-762",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "60"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "3c8bd795d7c1a203f1bae8d0ab810313/13537300608753746422;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b?alt=json\u0026prettyPrint=false\u0026project=dulcet-port-762"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJuYW1lIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA3In0K"
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "426"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:34 GMT"
+ ],
+ "Etag": [
+ "CAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051433000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrks2:4058,/bns/yv/borg/yv/bns/blobstore2/bitpusher/13.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=PcysW8CfJtCuggSokbuwAQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/13.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/13:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRYi1PQjdMLThUMnZyYTB2bmdDZG5Fcy1LcUZWSXdtNkVRelFHbGZaVklXSU5rZW13RTJrNFBMVXh1UWo0RFRtYVBCdWxseXRyRXpsT0lHU2xzN1dEemZKM19Ra01WNmpHamVLUGJ1Z1RvZlhMTGtwNjFocHVIMV9nQTBLb01jdUJ3V092OUdPaXo5Slk0Vzh4M09EVUhFa00tQjFYSGxHQXpzWlhkT0VOenZPOXBHWm1oRklaODBwaE0wBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UrX9H1l8bHhu8BqnaOvrWr7wtB68Ft1FDeOFpqId9pv3vtPqFJjXeFBLQSvGYWFQ3ZN8EQsk7AnKRjU3u2iE9xhK5vykQ"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwNyIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwNyIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDciLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjU6MzQuMDcyWiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI1OjM0LjA3MloiLCJtZXRhZ2VuZXJhdGlvbiI6IjEiLCJsb2NhdGlvbiI6IlVTIiwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJldGFnIjoiQ0FFPSJ9"
+ }
+ },
+ {
+ "ID": "59578f52a5f0077e",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0007?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "bc0ab534806ff533a56aec2f744ee2b5/15127712512820962964;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0007?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0, must-revalidate, no-transform"
+ ],
+ "Content-Length": [
+ "2353"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:34 GMT"
+ ],
+ "Etag": [
+ "CAE="
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:25:34 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051434000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrhq4:4312,/bns/yr/borg/yr/bns/blobstore2/bitpusher/115.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=PsysW-KPHIvykAO0grpg"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/115.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/115:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRYi1PQjdMLThUMnZyYTB2bmdDZG5Fcy1LcUZWSXdtNkVRelFHbGZaVklXSU5rZW13RTJrNFBMVXh1UWo0RFRtYVBCdWxseXRyRXpsT0lHU2xzN1dEemZKM19Ra01WNmpHamVLUGJ1Z1RvZlhMTGtwNjFocHVIMV9nQTBLb01jdUJ3V092OUdPaXo5Slk0Vzh4M09EVUhFa00tQjFYSGxHQXpzWlhkT0VOenZPOXBHWm1oRklaODBwaE0wBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UqwryHXSpXa_3TP9lnjG7MuIY4Q5mztKCJrgUSoYoDze9zLlxy1hZ2v9u1kRpBHROyDnBQ70gC3JhfY4GF-uMl6d51JLg"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwNyIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwNyIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDciLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjU6MzQuMDcyWiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI1OjM0LjA3MloiLCJtZXRhZ2VuZXJhdGlvbiI6IjEiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwNy9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwNy9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDciLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwNy9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDcvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwNyIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDQUU9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDcvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA3L2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDciLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNBRT0ifV0sImRlZmF1bHRPYmplY3RBY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0FFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0FFPSJ9XSwib3duZXIiOnsiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUifSwibG9jYXRpb24iOiJVUyIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwiZXRhZyI6IkNBRT0ifQ=="
+ }
+ },
+ {
+ "ID": "1fc47512e39433d9",
+ "Request": {
+ "Method": "PATCH",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0007?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "31"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "f56bd42d61719e5d5394eb0093b2999b/16646067922345036851;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0007?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJkZWZhdWx0RXZlbnRCYXNlZEhvbGQiOnRydWV9Cg=="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "2382"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:36 GMT"
+ ],
+ "Etag": [
+ "CAI="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051435000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrlm74:4305,/bns/yv/borg/yv/bns/blobstore2/bitpusher/290.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=PsysW_XeLIvRgQTe5JKYDw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/290.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/290:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATpxChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4CtK4wESxgF5YTI5LmMuRW93QkpRYi1PQjdMLThUMnZyYTB2bmdDZG5Fcy1LcUZWSXdtNkVRelFHbGZaVklXSU5rZW13RTJrNFBMVXh1UWo0RFRtYVBCdWxseXRyRXpsT0lHU2xzN1dEemZKM19Ra01WNmpHamVLUGJ1Z1RvZlhMTGtwNjFocHVIMV9nQTBLb01jdUJ3V092OUdPaXo5Slk0Vzh4M09EVUhFa00tQjFYSGxHQXpzWlhkT0VOenZPOXBHWm1oRklaODBwaE0wBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UoRKpiybYkviqDw7fneNk_UqWCvNv7c_YIwoSOkNKZy7vD8vPynoCS3vuKPgXgpTIRom4njyLpqFT2D7omgRPQqiv0PKw"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwNyIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwNyIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDciLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjU6MzQuMDcyWiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI1OjM2LjEyMloiLCJtZXRhZ2VuZXJhdGlvbiI6IjIiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwNy9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwNy9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDciLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBST0ifSx7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwNy9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDcvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwNyIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDQUk9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDcvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA3L2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDciLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNBST0ifV0sImRlZmF1bHRPYmplY3RBY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBST0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0FJPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0FJPSJ9XSwib3duZXIiOnsiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUifSwibG9jYXRpb24iOiJVUyIsImRlZmF1bHRFdmVudEJhc2VkSG9sZCI6dHJ1ZSwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJldGFnIjoiQ0FJPSJ9"
+ }
+ },
+ {
+ "ID": "71f85ffea051d16c",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0007?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "09d86e943aa5cba8e06dd981791e0a0e/18236479826412188114;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0007?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0, must-revalidate, no-transform"
+ ],
+ "Content-Length": [
+ "2382"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:36 GMT"
+ ],
+ "Etag": [
+ "CAI="
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:25:36 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051434000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrtg21:4099,/bns/yr/borg/yr/bns/blobstore2/bitpusher/29.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=QMysW_CjFISz4QT5n6jACQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/29.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/29:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRYi1PQjdMLThUMnZyYTB2bmdDZG5Fcy1LcUZWSXdtNkVRelFHbGZaVklXSU5rZW13RTJrNFBMVXh1UWo0RFRtYVBCdWxseXRyRXpsT0lHU2xzN1dEemZKM19Ra01WNmpHamVLUGJ1Z1RvZlhMTGtwNjFocHVIMV9nQTBLb01jdUJ3V092OUdPaXo5Slk0Vzh4M09EVUhFa00tQjFYSGxHQXpzWlhkT0VOenZPOXBHWm1oRklaODBwaE0wBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UowVyCkB2mA474S_48RgPdZ2QPyUaTI8UwGuVPpNhCLh8yU9jJCxtTsTyFvI1pg5jtqGhx-TRklbSiIVcsU5MZbIDzc3A"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwNyIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwNyIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDciLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjU6MzQuMDcyWiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI1OjM2LjEyMloiLCJtZXRhZ2VuZXJhdGlvbiI6IjIiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwNy9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwNy9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDciLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBST0ifSx7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwNy9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDcvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwNyIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDQUk9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDcvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA3L2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDciLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNBST0ifV0sImRlZmF1bHRPYmplY3RBY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBST0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0FJPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0FJPSJ9XSwib3duZXIiOnsiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUifSwibG9jYXRpb24iOiJVUyIsImRlZmF1bHRFdmVudEJhc2VkSG9sZCI6dHJ1ZSwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJldGFnIjoiQ0FJPSJ9"
+ }
+ },
+ {
+ "ID": "730e0f88fcfb808c",
+ "Request": {
+ "Method": "PATCH",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0007?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "35"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "ff1adbcb58c978e9ea27b7abbc181386/1380147656753141616;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0007?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJiaWxsaW5nIjp7InJlcXVlc3RlclBheXMiOnRydWV9fQo="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "2415"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:38 GMT"
+ ],
+ "Etag": [
+ "CAM="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051435000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrw127:4318,/bns/yv/borg/yv/bns/blobstore2/bitpusher/178.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=QMysW_nCJcTIggSEmZeoDA"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/178.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/178:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATpxChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4CtK4wESxgF5YTI5LmMuRW93QkpRYi1PQjdMLThUMnZyYTB2bmdDZG5Fcy1LcUZWSXdtNkVRelFHbGZaVklXSU5rZW13RTJrNFBMVXh1UWo0RFRtYVBCdWxseXRyRXpsT0lHU2xzN1dEemZKM19Ra01WNmpHamVLUGJ1Z1RvZlhMTGtwNjFocHVIMV9nQTBLb01jdUJ3V092OUdPaXo5Slk0Vzh4M09EVUhFa00tQjFYSGxHQXpzWlhkT0VOenZPOXBHWm1oRklaODBwaE0wBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Uq79m0pVSBsXB0mmUTWEnrP1CqxwCQzUZUOAZCkXG-y4JXjctCThCoxM8yjvmJfnanm-nZ-USf3cXWOpF0M6PSknqeVdg"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwNyIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwNyIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDciLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjU6MzQuMDcyWiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI1OjM4LjEzNFoiLCJtZXRhZ2VuZXJhdGlvbiI6IjMiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwNy9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwNy9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDciLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBTT0ifSx7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwNy9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDcvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwNyIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDQU09In0seyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDcvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA3L2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDciLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNBTT0ifV0sImRlZmF1bHRPYmplY3RBY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBTT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0FNPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0FNPSJ9XSwib3duZXIiOnsiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUifSwibG9jYXRpb24iOiJVUyIsImRlZmF1bHRFdmVudEJhc2VkSG9sZCI6dHJ1ZSwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJiaWxsaW5nIjp7InJlcXVlc3RlclBheXMiOnRydWV9LCJldGFnIjoiQ0FNPSJ9"
+ }
+ },
+ {
+ "ID": "a02f1f35cab4348d",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0007?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "cf218679be1b3e915c329ce5ba4659e3/2970558461325442063;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0007?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0, must-revalidate, no-transform"
+ ],
+ "Content-Length": [
+ "2415"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:38 GMT"
+ ],
+ "Etag": [
+ "CAM="
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:25:38 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051434000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrea4:4208,/bns/yv/borg/yv/bns/blobstore2/bitpusher/227.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=QsysW__5FMTDswat-Z-oBg"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/227.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/227:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRYi1PQjdMLThUMnZyYTB2bmdDZG5Fcy1LcUZWSXdtNkVRelFHbGZaVklXSU5rZW13RTJrNFBMVXh1UWo0RFRtYVBCdWxseXRyRXpsT0lHU2xzN1dEemZKM19Ra01WNmpHamVLUGJ1Z1RvZlhMTGtwNjFocHVIMV9nQTBLb01jdUJ3V092OUdPaXo5Slk0Vzh4M09EVUhFa00tQjFYSGxHQXpzWlhkT0VOenZPOXBHWm1oRklaODBwaE0wBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UqO7KixMVW5oE-Z7rTf-05a3MQ7VchJb6xKl00oDhmuidN9aTQxAk6MHGDdLfH0VHouT8tPJQ970eKq17raRD5PRlAJNw"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwNyIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwNyIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDciLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjU6MzQuMDcyWiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI1OjM4LjEzNFoiLCJtZXRhZ2VuZXJhdGlvbiI6IjMiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwNy9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwNy9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDciLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBTT0ifSx7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwNy9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDcvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwNyIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDQU09In0seyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDcvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA3L2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDciLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNBTT0ifV0sImRlZmF1bHRPYmplY3RBY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBTT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0FNPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0FNPSJ9XSwib3duZXIiOnsiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUifSwibG9jYXRpb24iOiJVUyIsImRlZmF1bHRFdmVudEJhc2VkSG9sZCI6dHJ1ZSwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJiaWxsaW5nIjp7InJlcXVlc3RlclBheXMiOnRydWV9LCJldGFnIjoiQ0FNPSJ9"
+ }
+ },
+ {
+ "ID": "e1a268e954e19280",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0007?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "3b85dca22884f6881cd7a4358ea80207/4560970365375816366;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0007?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 204,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "0"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:39 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051433000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrbv22:4137,/bns/yv/borg/yv/bns/blobstore2/bitpusher/243.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=QsysW5qeJYGngASMt5uwAw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/243.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/243:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRYi1PQjdMLThUMnZyYTB2bmdDZG5Fcy1LcUZWSXdtNkVRelFHbGZaVklXSU5rZW13RTJrNFBMVXh1UWo0RFRtYVBCdWxseXRyRXpsT0lHU2xzN1dEemZKM19Ra01WNmpHamVLUGJ1Z1RvZlhMTGtwNjFocHVIMV9nQTBLb01jdUJ3V092OUdPaXo5Slk0Vzh4M09EVUhFa00tQjFYSGxHQXpzWlhkT0VOenZPOXBHWm1oRklaODBwaE0wBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UozX15bN75-vGZh_C0BLNyjVXwQGxTMEvRMmqkwiAsFxzfvp3GD9EWWWWdhKj7q5B3eNGH5KXxPXIT29zNUZR0qwIvOAg"
+ ]
+ },
+ "Body": ""
+ }
+ },
+ {
+ "ID": "4dd057f60283835e",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/storage/v1/b?alt=json\u0026prettyPrint=false\u0026project=dulcet-port-762",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "60"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "bac2f7e7df855709cfa2912eec59313f/6151100794466387788;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b?alt=json\u0026prettyPrint=false\u0026project=dulcet-port-762"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJuYW1lIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA4In0K"
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "426"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:39 GMT"
+ ],
+ "Etag": [
+ "CAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051439000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrm128:4106,/bns/yv/borg/yv/bns/blobstore2/bitpusher/286.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=Q8ysW8W1DMnNgASH64bQDA"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/286.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/286:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRYW8tTi1VN3BXbjFWaEhPYml5Z2FjMzBQSzdFQXpIUlJHYkl1WkdrUl9hNE9PM3dOeFk1bFdBWFB2WTFJQ2FuWDlxSXZqeHFXZ0VHcUtueDdUQ1dMMm5INkZTY0dITnM3ZTMxMjcyc3lrLUZVdEFlNWNyekNrN0l1OVdUZ3BSVHFPdDVMYjBrSTVHdF9LbWtQTnN2M2FBVFJ6Q1VvdlRaYWUxeFAwdUJZSjNud0VOcTllS3JCZ3ZZWk0wBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UqPxwA-ixx9ZAr4xf2ZQ3g4Aeh9jaFfgwKTM_fr3eh-ik43c09moeWAUeoQvn9S9AhnDzxYTBfRwij5e4HFASVemXjsGg"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwOCIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwOCIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDgiLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjU6MzkuODAxWiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI1OjM5LjgwMVoiLCJtZXRhZ2VuZXJhdGlvbiI6IjEiLCJsb2NhdGlvbiI6IlVTIiwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJldGFnIjoiQ0FFPSJ9"
+ }
+ },
+ {
+ "ID": "37d7110f7cc94406",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0008/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Type": [
+ "multipart/related; boundary=0a2912504a9ce020eae7958dfe430a523c7be1ecf30776eef91e989784f6"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "fa2c5b7c49cfad80d49fbbf42d27145d/6982475729095563932;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0008/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "LS0wYTI5MTI1MDRhOWNlMDIwZWFlNzk1OGRmZTQzMGE1MjNjN2JlMWVjZjMwNzc2ZWVmOTFlOTg5Nzg0ZjYNCkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vanNvbg0KDQp7ImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwOCIsIm5hbWUiOiJzb21lLW9iaiJ9Cg0KLS0wYTI5MTI1MDRhOWNlMDIwZWFlNzk1OGRmZTQzMGE1MjNjN2JlMWVjZjMwNzc2ZWVmOTFlOTg5Nzg0ZjYNCkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vb2N0ZXQtc3RyZWFtDQoNCiHe8gVi7cUy1yj2YdH/SBwNCi0tMGEyOTEyNTA0YTljZTAyMGVhZTc5NThkZmU0MzBhNTIzYzdiZTFlY2YzMDc3NmVlZjkxZTk4OTc4NGY2LS0NCg=="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3285"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:40 GMT"
+ ],
+ "Etag": [
+ "CIbX9/6W290CEAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051439000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrbq123:4158,/bns/yv/borg/yv/bns/blobstore2/bitpusher/293.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=Q8ysW7iWPIrHggTf2qigAw"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/293.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/293:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRYW8tTi1VN3BXbjFWaEhPYml5Z2FjMzBQSzdFQXpIUlJHYkl1WkdrUl9hNE9PM3dOeFk1bFdBWFB2WTFJQ2FuWDlxSXZqeHFXZ0VHcUtueDdUQ1dMMm5INkZTY0dITnM3ZTMxMjcyc3lrLUZVdEFlNWNyekNrN0l1OVdUZ3BSVHFPdDVMYjBrSTVHdF9LbWtQTnN2M2FBVFJ6Q1VvdlRaYWUxeFAwdUJZSjNud0VOcTllS3JCZ3ZZWk0wBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_single_post_uploads"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Ur6aYjGujjKgLW1Bhh-arBoYeTSpBZn1ncAgDZ3jqg5e4U9kuQhNPLKlfULMw23Tfheb7-2Csjg1cwUOBbywxBMKdpP-g"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwOC9zb21lLW9iai8xNTM4MDUxMTQwMzQ4ODA2Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA4L28vc29tZS1vYmoiLCJuYW1lIjoic29tZS1vYmoiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDgiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE0MDM0ODgwNiIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoiYXBwbGljYXRpb24vb2N0ZXQtc3RyZWFtIiwidGltZUNyZWF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI1OjQwLjM0OFoiLCJ1cGRhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNTo0MC4zNDhaIiwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJ0aW1lU3RvcmFnZUNsYXNzVXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjU6NDAuMzQ4WiIsInNpemUiOiIxNiIsIm1kNUhhc2giOiJZU0dkNy9lVm56cmFJM285MGorUDdBPT0iLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA4L28vc29tZS1vYmo/Z2VuZXJhdGlvbj0xNTM4MDUxMTQwMzQ4ODA2JmFsdD1tZWRpYSIsImFjbCI6W3sia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA4L3NvbWUtb2JqLzE1MzgwNTExNDAzNDg4MDYvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDgvby9zb21lLW9iai9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDgiLCJvYmplY3QiOiJzb21lLW9iaiIsImdlbmVyYXRpb24iOiIxNTM4MDUxMTQwMzQ4ODA2IiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDSWJYOS82VzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDgvc29tZS1vYmovMTUzODA1MTE0MDM0ODgwNi9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDgvby9zb21lLW9iai9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA4Iiwib2JqZWN0Ijoic29tZS1vYmoiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE0MDM0ODgwNiIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDSWJYOS82VzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDgvc29tZS1vYmovMTUzODA1MTE0MDM0ODgwNi9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDgvby9zb21lLW9iai9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA4Iiwib2JqZWN0Ijoic29tZS1vYmoiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE0MDM0ODgwNiIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0liWDkvNlcyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA4L3NvbWUtb2JqLzE1MzgwNTExNDAzNDg4MDYvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwOC9vL3NvbWUtb2JqL2FjbC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA4Iiwib2JqZWN0Ijoic29tZS1vYmoiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE0MDM0ODgwNiIsImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJyb2xlIjoiT1dORVIiLCJlbWFpbCI6IjM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiZXRhZyI6IkNJYlg5LzZXMjkwQ0VBRT0ifV0sIm93bmVyIjp7ImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20ifSwiY3JjMzJjIjoibU1SVG5nPT0iLCJldGFnIjoiQ0liWDkvNlcyOTBDRUFFPSJ9"
+ }
+ },
+ {
+ "ID": "a5e7a973054cd9eb",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0008/o/some-obj?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "72b674888ea6ba2e2000c02ed2425059/8572606162464260154;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0008/o/some-obj?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3285"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:40 GMT"
+ ],
+ "Etag": [
+ "CIbX9/6W290CEAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051440000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vnat135:4299,/bns/yx/borg/yx/bns/blobstore2/bitpusher/155.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=RMysW9yGHZGezQLUipSACw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yx/borg/yx/bns/blobstore2/bitpusher/155.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yx/borg/yx/bns/blobstore2/bitpusher/155:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRYW8tTi1VN3BXbjFWaEhPYml5Z2FjMzBQSzdFQXpIUlJHYkl1WkdrUl9hNE9PM3dOeFk1bFdBWFB2WTFJQ2FuWDlxSXZqeHFXZ0VHcUtueDdUQ1dMMm5INkZTY0dITnM3ZTMxMjcyc3lrLUZVdEFlNWNyekNrN0l1OVdUZ3BSVHFPdDVMYjBrSTVHdF9LbWtQTnN2M2FBVFJ6Q1VvdlRaYWUxeFAwdUJZSjNud0VOcTllS3JCZ3ZZWk0wBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UpbUSEl8lVOXpkbanVm3TZbe3inmlKBD8z0dxTDy0Jmws3ee-ZbsIcCS3UCPp4UnOysMml-2tROHVKDfUhOzZRF1fW6DA"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwOC9zb21lLW9iai8xNTM4MDUxMTQwMzQ4ODA2Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA4L28vc29tZS1vYmoiLCJuYW1lIjoic29tZS1vYmoiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDgiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE0MDM0ODgwNiIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoiYXBwbGljYXRpb24vb2N0ZXQtc3RyZWFtIiwidGltZUNyZWF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI1OjQwLjM0OFoiLCJ1cGRhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNTo0MC4zNDhaIiwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJ0aW1lU3RvcmFnZUNsYXNzVXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjU6NDAuMzQ4WiIsInNpemUiOiIxNiIsIm1kNUhhc2giOiJZU0dkNy9lVm56cmFJM285MGorUDdBPT0iLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA4L28vc29tZS1vYmo/Z2VuZXJhdGlvbj0xNTM4MDUxMTQwMzQ4ODA2JmFsdD1tZWRpYSIsImFjbCI6W3sia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA4L3NvbWUtb2JqLzE1MzgwNTExNDAzNDg4MDYvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDgvby9zb21lLW9iai9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDgiLCJvYmplY3QiOiJzb21lLW9iaiIsImdlbmVyYXRpb24iOiIxNTM4MDUxMTQwMzQ4ODA2IiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDSWJYOS82VzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDgvc29tZS1vYmovMTUzODA1MTE0MDM0ODgwNi9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDgvby9zb21lLW9iai9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA4Iiwib2JqZWN0Ijoic29tZS1vYmoiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE0MDM0ODgwNiIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDSWJYOS82VzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDgvc29tZS1vYmovMTUzODA1MTE0MDM0ODgwNi9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDgvby9zb21lLW9iai9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA4Iiwib2JqZWN0Ijoic29tZS1vYmoiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE0MDM0ODgwNiIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0liWDkvNlcyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA4L3NvbWUtb2JqLzE1MzgwNTExNDAzNDg4MDYvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwOC9vL3NvbWUtb2JqL2FjbC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA4Iiwib2JqZWN0Ijoic29tZS1vYmoiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE0MDM0ODgwNiIsImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJyb2xlIjoiT1dORVIiLCJlbWFpbCI6IjM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiZXRhZyI6IkNJYlg5LzZXMjkwQ0VBRT0ifV0sIm93bmVyIjp7ImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20ifSwiY3JjMzJjIjoibU1SVG5nPT0iLCJldGFnIjoiQ0liWDkvNlcyOTBDRUFFPSJ9"
+ }
+ },
+ {
+ "ID": "aaacb912d25964e2",
+ "Request": {
+ "Method": "PATCH",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0008/o/some-obj?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "84"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "f36e3abdbbb5cd513afef505376b0b55/10090960472510260697;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0008/o/some-obj?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDgiLCJldmVudEJhc2VkSG9sZCI6dHJ1ZX0K"
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3307"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:40 GMT"
+ ],
+ "Etag": [
+ "CIbX9/6W290CEAI="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051440000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrnm23:4163,/bns/yw/borg/yw/bns/blobstore2/bitpusher/33.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=RMysW8ezJJS8hgSYgLfICQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yw/borg/yw/bns/blobstore2/bitpusher/33.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yw/borg/yw/bns/blobstore2/bitpusher/33:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATpxChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4CtK4wESxgF5YTI5LmMuRW93QkpRYW8tTi1VN3BXbjFWaEhPYml5Z2FjMzBQSzdFQXpIUlJHYkl1WkdrUl9hNE9PM3dOeFk1bFdBWFB2WTFJQ2FuWDlxSXZqeHFXZ0VHcUtueDdUQ1dMMm5INkZTY0dITnM3ZTMxMjcyc3lrLUZVdEFlNWNyekNrN0l1OVdUZ3BSVHFPdDVMYjBrSTVHdF9LbWtQTnN2M2FBVFJ6Q1VvdlRaYWUxeFAwdUJZSjNud0VOcTllS3JCZ3ZZWk0wBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Ur79Q63MXhT1ocHhwJI-YRY2WVWTCXb82hlaPk7243LyKIdSCWWwKf2ACbFhLI_TKRmh94UJkNYheGo38lWBmG91M_Esw"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwOC9zb21lLW9iai8xNTM4MDUxMTQwMzQ4ODA2Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA4L28vc29tZS1vYmoiLCJuYW1lIjoic29tZS1vYmoiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDgiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE0MDM0ODgwNiIsIm1ldGFnZW5lcmF0aW9uIjoiMiIsImNvbnRlbnRUeXBlIjoiYXBwbGljYXRpb24vb2N0ZXQtc3RyZWFtIiwidGltZUNyZWF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI1OjQwLjM0OFoiLCJ1cGRhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNTo0MC42ODlaIiwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJ0aW1lU3RvcmFnZUNsYXNzVXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjU6NDAuMzQ4WiIsInNpemUiOiIxNiIsIm1kNUhhc2giOiJZU0dkNy9lVm56cmFJM285MGorUDdBPT0iLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA4L28vc29tZS1vYmo/Z2VuZXJhdGlvbj0xNTM4MDUxMTQwMzQ4ODA2JmFsdD1tZWRpYSIsImFjbCI6W3sia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA4L3NvbWUtb2JqLzE1MzgwNTExNDAzNDg4MDYvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDgvby9zb21lLW9iai9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDgiLCJvYmplY3QiOiJzb21lLW9iaiIsImdlbmVyYXRpb24iOiIxNTM4MDUxMTQwMzQ4ODA2IiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDSWJYOS82VzI5MENFQUk9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDgvc29tZS1vYmovMTUzODA1MTE0MDM0ODgwNi9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDgvby9zb21lLW9iai9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA4Iiwib2JqZWN0Ijoic29tZS1vYmoiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE0MDM0ODgwNiIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDSWJYOS82VzI5MENFQUk9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDgvc29tZS1vYmovMTUzODA1MTE0MDM0ODgwNi9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDgvby9zb21lLW9iai9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA4Iiwib2JqZWN0Ijoic29tZS1vYmoiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE0MDM0ODgwNiIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0liWDkvNlcyOTBDRUFJPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA4L3NvbWUtb2JqLzE1MzgwNTExNDAzNDg4MDYvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwOC9vL3NvbWUtb2JqL2FjbC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA4Iiwib2JqZWN0Ijoic29tZS1vYmoiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE0MDM0ODgwNiIsImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJyb2xlIjoiT1dORVIiLCJlbWFpbCI6IjM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiZXRhZyI6IkNJYlg5LzZXMjkwQ0VBST0ifV0sIm93bmVyIjp7ImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20ifSwiY3JjMzJjIjoibU1SVG5nPT0iLCJldGFnIjoiQ0liWDkvNlcyOTBDRUFJPSIsImV2ZW50QmFzZWRIb2xkIjp0cnVlfQ=="
+ }
+ },
+ {
+ "ID": "76fbc9f0b99b2f49",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0008/o/some-obj?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "669db8763b6bd4dd603ecdcace4864c6/11681372372282509944;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0008/o/some-obj?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3307"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:40 GMT"
+ ],
+ "Etag": [
+ "CIbX9/6W290CEAI="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051440000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrrr16:4447,/bns/yv/borg/yv/bns/blobstore2/bitpusher/88.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=RMysW9iUMcKZgQTw9ZIQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/88.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/88:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRYW8tTi1VN3BXbjFWaEhPYml5Z2FjMzBQSzdFQXpIUlJHYkl1WkdrUl9hNE9PM3dOeFk1bFdBWFB2WTFJQ2FuWDlxSXZqeHFXZ0VHcUtueDdUQ1dMMm5INkZTY0dITnM3ZTMxMjcyc3lrLUZVdEFlNWNyekNrN0l1OVdUZ3BSVHFPdDVMYjBrSTVHdF9LbWtQTnN2M2FBVFJ6Q1VvdlRaYWUxeFAwdUJZSjNud0VOcTllS3JCZ3ZZWk0wBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UpypyDzoPkWQvudGbMqnEjZPiWP2UshpaXFL0GnKW3XMLtJGzWDVn0M1Zgu2dMjPaY7fj86Y5MnB33QfPfPk7Ox1CLdfg"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwOC9zb21lLW9iai8xNTM4MDUxMTQwMzQ4ODA2Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA4L28vc29tZS1vYmoiLCJuYW1lIjoic29tZS1vYmoiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDgiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE0MDM0ODgwNiIsIm1ldGFnZW5lcmF0aW9uIjoiMiIsImNvbnRlbnRUeXBlIjoiYXBwbGljYXRpb24vb2N0ZXQtc3RyZWFtIiwidGltZUNyZWF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI1OjQwLjM0OFoiLCJ1cGRhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNTo0MC42ODlaIiwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJ0aW1lU3RvcmFnZUNsYXNzVXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjU6NDAuMzQ4WiIsInNpemUiOiIxNiIsIm1kNUhhc2giOiJZU0dkNy9lVm56cmFJM285MGorUDdBPT0iLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA4L28vc29tZS1vYmo/Z2VuZXJhdGlvbj0xNTM4MDUxMTQwMzQ4ODA2JmFsdD1tZWRpYSIsImFjbCI6W3sia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA4L3NvbWUtb2JqLzE1MzgwNTExNDAzNDg4MDYvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDgvby9zb21lLW9iai9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDgiLCJvYmplY3QiOiJzb21lLW9iaiIsImdlbmVyYXRpb24iOiIxNTM4MDUxMTQwMzQ4ODA2IiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDSWJYOS82VzI5MENFQUk9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDgvc29tZS1vYmovMTUzODA1MTE0MDM0ODgwNi9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDgvby9zb21lLW9iai9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA4Iiwib2JqZWN0Ijoic29tZS1vYmoiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE0MDM0ODgwNiIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDSWJYOS82VzI5MENFQUk9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDgvc29tZS1vYmovMTUzODA1MTE0MDM0ODgwNi9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDgvby9zb21lLW9iai9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA4Iiwib2JqZWN0Ijoic29tZS1vYmoiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE0MDM0ODgwNiIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0liWDkvNlcyOTBDRUFJPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA4L3NvbWUtb2JqLzE1MzgwNTExNDAzNDg4MDYvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwOC9vL3NvbWUtb2JqL2FjbC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA4Iiwib2JqZWN0Ijoic29tZS1vYmoiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE0MDM0ODgwNiIsImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJyb2xlIjoiT1dORVIiLCJlbWFpbCI6IjM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiZXRhZyI6IkNJYlg5LzZXMjkwQ0VBST0ifV0sIm93bmVyIjp7ImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20ifSwiY3JjMzJjIjoibU1SVG5nPT0iLCJldGFnIjoiQ0liWDkvNlcyOTBDRUFJPSIsImV2ZW50QmFzZWRIb2xkIjp0cnVlfQ=="
+ }
+ },
+ {
+ "ID": "78aae384aa961deb",
+ "Request": {
+ "Method": "PATCH",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0008/o/some-obj?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "82"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "7d56df310958932c8e9f768c4f493f3f/13271784276332949526;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0008/o/some-obj?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDgiLCJjb250ZW50VHlwZSI6ImZvbyJ9Cg=="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3286"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:41 GMT"
+ ],
+ "Etag": [
+ "CIbX9/6W290CEAM="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051440000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrdv10:4196,/bns/yv/borg/yv/bns/blobstore2/bitpusher/21.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=RMysW4izN4quggSVlrrQAQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/21.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/21:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATpxChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4CtK4wESxgF5YTI5LmMuRW93QkpRYW8tTi1VN3BXbjFWaEhPYml5Z2FjMzBQSzdFQXpIUlJHYkl1WkdrUl9hNE9PM3dOeFk1bFdBWFB2WTFJQ2FuWDlxSXZqeHFXZ0VHcUtueDdUQ1dMMm5INkZTY0dITnM3ZTMxMjcyc3lrLUZVdEFlNWNyekNrN0l1OVdUZ3BSVHFPdDVMYjBrSTVHdF9LbWtQTnN2M2FBVFJ6Q1VvdlRaYWUxeFAwdUJZSjNud0VOcTllS3JCZ3ZZWk0wBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UpZzkXCMOe7dNiTX_3OFre5VukWstUkiWl2b0wgLfUBOd285bNQ2ztHV883ZEFh_lyekWInaXl0JH8CiJ40u4gen6707A"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwOC9zb21lLW9iai8xNTM4MDUxMTQwMzQ4ODA2Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA4L28vc29tZS1vYmoiLCJuYW1lIjoic29tZS1vYmoiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDgiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE0MDM0ODgwNiIsIm1ldGFnZW5lcmF0aW9uIjoiMyIsImNvbnRlbnRUeXBlIjoiZm9vIiwidGltZUNyZWF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI1OjQwLjM0OFoiLCJ1cGRhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNTo0MC45ODNaIiwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJ0aW1lU3RvcmFnZUNsYXNzVXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjU6NDAuMzQ4WiIsInNpemUiOiIxNiIsIm1kNUhhc2giOiJZU0dkNy9lVm56cmFJM285MGorUDdBPT0iLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA4L28vc29tZS1vYmo/Z2VuZXJhdGlvbj0xNTM4MDUxMTQwMzQ4ODA2JmFsdD1tZWRpYSIsImFjbCI6W3sia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA4L3NvbWUtb2JqLzE1MzgwNTExNDAzNDg4MDYvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDgvby9zb21lLW9iai9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDgiLCJvYmplY3QiOiJzb21lLW9iaiIsImdlbmVyYXRpb24iOiIxNTM4MDUxMTQwMzQ4ODA2IiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDSWJYOS82VzI5MENFQU09In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDgvc29tZS1vYmovMTUzODA1MTE0MDM0ODgwNi9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDgvby9zb21lLW9iai9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA4Iiwib2JqZWN0Ijoic29tZS1vYmoiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE0MDM0ODgwNiIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDSWJYOS82VzI5MENFQU09In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDgvc29tZS1vYmovMTUzODA1MTE0MDM0ODgwNi9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDgvby9zb21lLW9iai9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA4Iiwib2JqZWN0Ijoic29tZS1vYmoiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE0MDM0ODgwNiIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0liWDkvNlcyOTBDRUFNPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA4L3NvbWUtb2JqLzE1MzgwNTExNDAzNDg4MDYvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwOC9vL3NvbWUtb2JqL2FjbC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA4Iiwib2JqZWN0Ijoic29tZS1vYmoiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE0MDM0ODgwNiIsImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJyb2xlIjoiT1dORVIiLCJlbWFpbCI6IjM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiZXRhZyI6IkNJYlg5LzZXMjkwQ0VBTT0ifV0sIm93bmVyIjp7ImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20ifSwiY3JjMzJjIjoibU1SVG5nPT0iLCJldGFnIjoiQ0liWDkvNlcyOTBDRUFNPSIsImV2ZW50QmFzZWRIb2xkIjp0cnVlfQ=="
+ }
+ },
+ {
+ "ID": "b6f9e84970bde86e",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0008/o/some-obj?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "69fd5e5c0a5397d780834aa8ca559a36/14861914709718357429;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0008/o/some-obj?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3286"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:41 GMT"
+ ],
+ "Etag": [
+ "CIbX9/6W290CEAM="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051440000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vnpp189:4374,/bns/yx/borg/yx/bns/blobstore2/bitpusher/45.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=RcysW9ijBpKrzALq86GoBg"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yx/borg/yx/bns/blobstore2/bitpusher/45.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yx/borg/yx/bns/blobstore2/bitpusher/45:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRYW8tTi1VN3BXbjFWaEhPYml5Z2FjMzBQSzdFQXpIUlJHYkl1WkdrUl9hNE9PM3dOeFk1bFdBWFB2WTFJQ2FuWDlxSXZqeHFXZ0VHcUtueDdUQ1dMMm5INkZTY0dITnM3ZTMxMjcyc3lrLUZVdEFlNWNyekNrN0l1OVdUZ3BSVHFPdDVMYjBrSTVHdF9LbWtQTnN2M2FBVFJ6Q1VvdlRaYWUxeFAwdUJZSjNud0VOcTllS3JCZ3ZZWk0wBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Urhrjx4L0FkFYcxk3TEaGXYaCAz_Iwa_R_TsU9fwVuFkO7FpYAB1LKwqWqO0TocvFMeGFwyd_7ke352CB7-cnX_Dsr04Q"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwOC9zb21lLW9iai8xNTM4MDUxMTQwMzQ4ODA2Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA4L28vc29tZS1vYmoiLCJuYW1lIjoic29tZS1vYmoiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDgiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE0MDM0ODgwNiIsIm1ldGFnZW5lcmF0aW9uIjoiMyIsImNvbnRlbnRUeXBlIjoiZm9vIiwidGltZUNyZWF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI1OjQwLjM0OFoiLCJ1cGRhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNTo0MC45ODNaIiwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJ0aW1lU3RvcmFnZUNsYXNzVXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjU6NDAuMzQ4WiIsInNpemUiOiIxNiIsIm1kNUhhc2giOiJZU0dkNy9lVm56cmFJM285MGorUDdBPT0iLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA4L28vc29tZS1vYmo/Z2VuZXJhdGlvbj0xNTM4MDUxMTQwMzQ4ODA2JmFsdD1tZWRpYSIsImFjbCI6W3sia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA4L3NvbWUtb2JqLzE1MzgwNTExNDAzNDg4MDYvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDgvby9zb21lLW9iai9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDgiLCJvYmplY3QiOiJzb21lLW9iaiIsImdlbmVyYXRpb24iOiIxNTM4MDUxMTQwMzQ4ODA2IiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDSWJYOS82VzI5MENFQU09In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDgvc29tZS1vYmovMTUzODA1MTE0MDM0ODgwNi9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDgvby9zb21lLW9iai9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA4Iiwib2JqZWN0Ijoic29tZS1vYmoiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE0MDM0ODgwNiIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDSWJYOS82VzI5MENFQU09In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDgvc29tZS1vYmovMTUzODA1MTE0MDM0ODgwNi9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDgvby9zb21lLW9iai9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA4Iiwib2JqZWN0Ijoic29tZS1vYmoiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE0MDM0ODgwNiIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0liWDkvNlcyOTBDRUFNPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA4L3NvbWUtb2JqLzE1MzgwNTExNDAzNDg4MDYvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwOC9vL3NvbWUtb2JqL2FjbC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA4Iiwib2JqZWN0Ijoic29tZS1vYmoiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE0MDM0ODgwNiIsImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJyb2xlIjoiT1dORVIiLCJlbWFpbCI6IjM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiZXRhZyI6IkNJYlg5LzZXMjkwQ0VBTT0ifV0sIm93bmVyIjp7ImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20ifSwiY3JjMzJjIjoibU1SVG5nPT0iLCJldGFnIjoiQ0liWDkvNlcyOTBDRUFNPSIsImV2ZW50QmFzZWRIb2xkIjp0cnVlfQ=="
+ }
+ },
+ {
+ "ID": "6e80bc4210ff38e8",
+ "Request": {
+ "Method": "PATCH",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0008/o/some-obj?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "85"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "908b325ceff7af773f3ae514b5d7fdeb/16452326609473895251;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0008/o/some-obj?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDgiLCJldmVudEJhc2VkSG9sZCI6ZmFsc2V9Cg=="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3287"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:41 GMT"
+ ],
+ "Etag": [
+ "CIbX9/6W290CEAQ="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051440000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrhq15:4330,/bns/yv/borg/yv/bns/blobstore2/bitpusher/4.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=RcysW6q5C4OlggT477xY"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/4.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/4:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATpxChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4CtK4wESxgF5YTI5LmMuRW93QkpRYW8tTi1VN3BXbjFWaEhPYml5Z2FjMzBQSzdFQXpIUlJHYkl1WkdrUl9hNE9PM3dOeFk1bFdBWFB2WTFJQ2FuWDlxSXZqeHFXZ0VHcUtueDdUQ1dMMm5INkZTY0dITnM3ZTMxMjcyc3lrLUZVdEFlNWNyekNrN0l1OVdUZ3BSVHFPdDVMYjBrSTVHdF9LbWtQTnN2M2FBVFJ6Q1VvdlRaYWUxeFAwdUJZSjNud0VOcTllS3JCZ3ZZWk0wBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UqR4YYdh9xEeNHy3xSzUablg3lgP_gFT4RbOP8RgJFz-sQ9ugVz8WuHUSLmtuItC_hyR_AvyhkZimBD005OZvEPPWGtNA"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwOC9zb21lLW9iai8xNTM4MDUxMTQwMzQ4ODA2Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA4L28vc29tZS1vYmoiLCJuYW1lIjoic29tZS1vYmoiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDgiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE0MDM0ODgwNiIsIm1ldGFnZW5lcmF0aW9uIjoiNCIsImNvbnRlbnRUeXBlIjoiZm9vIiwidGltZUNyZWF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI1OjQwLjM0OFoiLCJ1cGRhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNTo0MS4yNTZaIiwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJ0aW1lU3RvcmFnZUNsYXNzVXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjU6NDAuMzQ4WiIsInNpemUiOiIxNiIsIm1kNUhhc2giOiJZU0dkNy9lVm56cmFJM285MGorUDdBPT0iLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA4L28vc29tZS1vYmo/Z2VuZXJhdGlvbj0xNTM4MDUxMTQwMzQ4ODA2JmFsdD1tZWRpYSIsImFjbCI6W3sia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA4L3NvbWUtb2JqLzE1MzgwNTExNDAzNDg4MDYvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDgvby9zb21lLW9iai9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDgiLCJvYmplY3QiOiJzb21lLW9iaiIsImdlbmVyYXRpb24iOiIxNTM4MDUxMTQwMzQ4ODA2IiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDSWJYOS82VzI5MENFQVE9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDgvc29tZS1vYmovMTUzODA1MTE0MDM0ODgwNi9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDgvby9zb21lLW9iai9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA4Iiwib2JqZWN0Ijoic29tZS1vYmoiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE0MDM0ODgwNiIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDSWJYOS82VzI5MENFQVE9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDgvc29tZS1vYmovMTUzODA1MTE0MDM0ODgwNi9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDgvby9zb21lLW9iai9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA4Iiwib2JqZWN0Ijoic29tZS1vYmoiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE0MDM0ODgwNiIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0liWDkvNlcyOTBDRUFRPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA4L3NvbWUtb2JqLzE1MzgwNTExNDAzNDg4MDYvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwOC9vL3NvbWUtb2JqL2FjbC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA4Iiwib2JqZWN0Ijoic29tZS1vYmoiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE0MDM0ODgwNiIsImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJyb2xlIjoiT1dORVIiLCJlbWFpbCI6IjM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiZXRhZyI6IkNJYlg5LzZXMjkwQ0VBUT0ifV0sIm93bmVyIjp7ImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20ifSwiY3JjMzJjIjoibU1SVG5nPT0iLCJldGFnIjoiQ0liWDkvNlcyOTBDRUFRPSIsImV2ZW50QmFzZWRIb2xkIjpmYWxzZX0="
+ }
+ },
+ {
+ "ID": "97d438b968fe32c8",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0008/o/some-obj?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "2ae0c9abf22f8613130b760ed0f25db8/17283420073421328035;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0008/o/some-obj?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 204,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "0"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:41 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051439000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrlw11:4360,/bns/yv/borg/yv/bns/blobstore2/bitpusher/235.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=RcysW_r4FonuggSJ1Lr4CQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/235.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/235:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRYW8tTi1VN3BXbjFWaEhPYml5Z2FjMzBQSzdFQXpIUlJHYkl1WkdrUl9hNE9PM3dOeFk1bFdBWFB2WTFJQ2FuWDlxSXZqeHFXZ0VHcUtueDdUQ1dMMm5INkZTY0dITnM3ZTMxMjcyc3lrLUZVdEFlNWNyekNrN0l1OVdUZ3BSVHFPdDVMYjBrSTVHdF9LbWtQTnN2M2FBVFJ6Q1VvdlRaYWUxeFAwdUJZSjNud0VOcTllS3JCZ3ZZWk0wBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UrdiEc0xjlqkDsbTeOVLT489iN9y6sLywT23V6xAxTn2LpfZSlYEcJpJ-9Gog_DBTNVFBs0pJkQJKJG0iykjVNOO2uyYw"
+ ]
+ },
+ "Body": ""
+ }
+ },
+ {
+ "ID": "f80d68a7124d0884",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0008?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "92467cd80ac62acc5f3fdfd1f0b095bc/427368279260853057;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0008?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 204,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "0"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:42 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051439000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vray3:4145,/bns/yv/borg/yv/bns/blobstore2/bitpusher/360.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=RcysW9PrLJfJgASEx7egAQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/360.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/360:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRYW8tTi1VN3BXbjFWaEhPYml5Z2FjMzBQSzdFQXpIUlJHYkl1WkdrUl9hNE9PM3dOeFk1bFdBWFB2WTFJQ2FuWDlxSXZqeHFXZ0VHcUtueDdUQ1dMMm5INkZTY0dITnM3ZTMxMjcyc3lrLUZVdEFlNWNyekNrN0l1OVdUZ3BSVHFPdDVMYjBrSTVHdF9LbWtQTnN2M2FBVFJ6Q1VvdlRaYWUxeFAwdUJZSjNud0VOcTllS3JCZ3ZZWk0wBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UoSGI76du_R-KAywyZHtMJCD98ezW_k2SyAXFJU1hNQs_4Gmef8a8PRhUnVR0vq4UtMsNRYTZvsueKQpnfFbkMsAYaeUA"
+ ]
+ },
+ "Body": ""
+ }
+ },
+ {
+ "ID": "16c9b99ace40675c",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/storage/v1/b?alt=json\u0026prettyPrint=false\u0026project=dulcet-port-762",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "60"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "3192e57753f54de047527a0f7c734937/1945723688784927200;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b?alt=json\u0026prettyPrint=false\u0026project=dulcet-port-762"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJuYW1lIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA5In0K"
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "426"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:43 GMT"
+ ],
+ "Etag": [
+ "CAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051442000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrli74:4433,/bns/yv/borg/yv/bns/blobstore2/bitpusher/329.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=RsysW6nYEMHSggSJ44SQDA"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/329.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/329:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRYm55eUhjUWpNWkU0aTFCOGpNWG9GOHRvNDlSNWRjTUJnOFRGMDJkT2lZdHhhZ3MzVklHZmVzXzByNTlISDRvNEtudW96RTBQa2FVZVIzNkRlelFXcnlfMXpKUjRScTRYcFdDYjJKUkl3NTFYUW8yc2hncy0td1duX1B3Vk9hSy1hWUVQLVN6Uk1zcmlUN0ZtaFZ2WUxRRHhSTy1nd29sRXlFNWJCWXhqQmJybkxfZ3pxTTNQREZFZ0kwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UrNyakak05lR1Q2WId23z_m1L9zXqPQG42itWpjchRBWAuwh51w0ufLjK7GnNIdUwsmpT6kzUdtz66v9-_iZWp69aOP9w"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwOSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwOSIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDkiLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjU6NDIuOTAwWiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI1OjQyLjkwMFoiLCJtZXRhZ2VuZXJhdGlvbiI6IjEiLCJsb2NhdGlvbiI6IlVTIiwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJldGFnIjoiQ0FFPSJ9"
+ }
+ },
+ {
+ "ID": "125a0f566fb957a2",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0009/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Type": [
+ "multipart/related; boundary=28057963d603e97cd943670bb09dea0b37721dcbee4de7f44ddce95f66d3"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "23787329c84d271578a4b254783707aa/2776817152749202223;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0009/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "LS0yODA1Nzk2M2Q2MDNlOTdjZDk0MzY3MGJiMDlkZWEwYjM3NzIxZGNiZWU0ZGU3ZjQ0ZGRjZTk1ZjY2ZDMNCkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vanNvbg0KDQp7ImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwOSIsIm5hbWUiOiJzb21lLW9iaiJ9Cg0KLS0yODA1Nzk2M2Q2MDNlOTdjZDk0MzY3MGJiMDlkZWEwYjM3NzIxZGNiZWU0ZGU3ZjQ0ZGRjZTk1ZjY2ZDMNCkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vb2N0ZXQtc3RyZWFtDQoNCh3phU9nPeKTspnhdkB1G0oNCi0tMjgwNTc5NjNkNjAzZTk3Y2Q5NDM2NzBiYjA5ZGVhMGIzNzcyMWRjYmVlNGRlN2Y0NGRkY2U5NWY2NmQzLS0NCg=="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3285"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:43 GMT"
+ ],
+ "Etag": [
+ "COLHs4CX290CEAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051442000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrlv9:4242,/bns/yr/borg/yr/bns/blobstore2/bitpusher/112.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=R8ysW7yABYiVkASQyLSgCw"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/112.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/112:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRYm55eUhjUWpNWkU0aTFCOGpNWG9GOHRvNDlSNWRjTUJnOFRGMDJkT2lZdHhhZ3MzVklHZmVzXzByNTlISDRvNEtudW96RTBQa2FVZVIzNkRlelFXcnlfMXpKUjRScTRYcFdDYjJKUkl3NTFYUW8yc2hncy0td1duX1B3Vk9hSy1hWUVQLVN6Uk1zcmlUN0ZtaFZ2WUxRRHhSTy1nd29sRXlFNWJCWXhqQmJybkxfZ3pxTTNQREZFZ0kwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_single_post_uploads"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Urul9azluGg9ubAfjVZBRTvxzf-9xDlfuKHaTDYFJmzn-4UQlkJt_LJyOU2Y-yfGMr-pdfjbTVxT0vujaoIVra1WyliEA"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwOS9zb21lLW9iai8xNTM4MDUxMTQzNDI3MDQyIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA5L28vc29tZS1vYmoiLCJuYW1lIjoic29tZS1vYmoiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDkiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE0MzQyNzA0MiIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoiYXBwbGljYXRpb24vb2N0ZXQtc3RyZWFtIiwidGltZUNyZWF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI1OjQzLjQyNloiLCJ1cGRhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNTo0My40MjZaIiwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJ0aW1lU3RvcmFnZUNsYXNzVXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjU6NDMuNDI2WiIsInNpemUiOiIxNiIsIm1kNUhhc2giOiJVT2h5QmY1OHg2VElzaGNIS1FvNmpBPT0iLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA5L28vc29tZS1vYmo/Z2VuZXJhdGlvbj0xNTM4MDUxMTQzNDI3MDQyJmFsdD1tZWRpYSIsImFjbCI6W3sia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA5L3NvbWUtb2JqLzE1MzgwNTExNDM0MjcwNDIvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDkvby9zb21lLW9iai9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDkiLCJvYmplY3QiOiJzb21lLW9iaiIsImdlbmVyYXRpb24iOiIxNTM4MDUxMTQzNDI3MDQyIiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDT0xIczRDWDI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDkvc29tZS1vYmovMTUzODA1MTE0MzQyNzA0Mi9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDkvby9zb21lLW9iai9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA5Iiwib2JqZWN0Ijoic29tZS1vYmoiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE0MzQyNzA0MiIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDT0xIczRDWDI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDkvc29tZS1vYmovMTUzODA1MTE0MzQyNzA0Mi9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDkvby9zb21lLW9iai9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA5Iiwib2JqZWN0Ijoic29tZS1vYmoiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE0MzQyNzA0MiIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ09MSHM0Q1gyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA5L3NvbWUtb2JqLzE1MzgwNTExNDM0MjcwNDIvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwOS9vL3NvbWUtb2JqL2FjbC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA5Iiwib2JqZWN0Ijoic29tZS1vYmoiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE0MzQyNzA0MiIsImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJyb2xlIjoiT1dORVIiLCJlbWFpbCI6IjM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiZXRhZyI6IkNPTEhzNENYMjkwQ0VBRT0ifV0sIm93bmVyIjp7ImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20ifSwiY3JjMzJjIjoiVk5jdHBnPT0iLCJldGFnIjoiQ09MSHM0Q1gyOTBDRUFFPSJ9"
+ }
+ },
+ {
+ "ID": "e83fd8d4a5d6afd3",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0009/o/some-obj?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "ef9e1f91badb126602160267cee85176/4367229052504674766;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0009/o/some-obj?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3285"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:43 GMT"
+ ],
+ "Etag": [
+ "COLHs4CX290CEAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051443000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrtj9:4196,/bns/yv/borg/yv/bns/blobstore2/bitpusher/208.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=R8ysW9isKMvWgwSzu6-IBw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/208.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/208:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRYm55eUhjUWpNWkU0aTFCOGpNWG9GOHRvNDlSNWRjTUJnOFRGMDJkT2lZdHhhZ3MzVklHZmVzXzByNTlISDRvNEtudW96RTBQa2FVZVIzNkRlelFXcnlfMXpKUjRScTRYcFdDYjJKUkl3NTFYUW8yc2hncy0td1duX1B3Vk9hSy1hWUVQLVN6Uk1zcmlUN0ZtaFZ2WUxRRHhSTy1nd29sRXlFNWJCWXhqQmJybkxfZ3pxTTNQREZFZ0kwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Urbmysb5MvX3wH-2EyUwAeomINPZbRZpMP_aDaTJjYffjWZrxE-vaZ6QPh4MxX9nvgUSEyOBtJErQ-JZ3GXBaqR9Gatrw"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwOS9zb21lLW9iai8xNTM4MDUxMTQzNDI3MDQyIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA5L28vc29tZS1vYmoiLCJuYW1lIjoic29tZS1vYmoiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDkiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE0MzQyNzA0MiIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoiYXBwbGljYXRpb24vb2N0ZXQtc3RyZWFtIiwidGltZUNyZWF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI1OjQzLjQyNloiLCJ1cGRhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNTo0My40MjZaIiwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJ0aW1lU3RvcmFnZUNsYXNzVXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjU6NDMuNDI2WiIsInNpemUiOiIxNiIsIm1kNUhhc2giOiJVT2h5QmY1OHg2VElzaGNIS1FvNmpBPT0iLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA5L28vc29tZS1vYmo/Z2VuZXJhdGlvbj0xNTM4MDUxMTQzNDI3MDQyJmFsdD1tZWRpYSIsImFjbCI6W3sia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA5L3NvbWUtb2JqLzE1MzgwNTExNDM0MjcwNDIvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDkvby9zb21lLW9iai9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDkiLCJvYmplY3QiOiJzb21lLW9iaiIsImdlbmVyYXRpb24iOiIxNTM4MDUxMTQzNDI3MDQyIiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDT0xIczRDWDI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDkvc29tZS1vYmovMTUzODA1MTE0MzQyNzA0Mi9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDkvby9zb21lLW9iai9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA5Iiwib2JqZWN0Ijoic29tZS1vYmoiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE0MzQyNzA0MiIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDT0xIczRDWDI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDkvc29tZS1vYmovMTUzODA1MTE0MzQyNzA0Mi9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDkvby9zb21lLW9iai9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA5Iiwib2JqZWN0Ijoic29tZS1vYmoiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE0MzQyNzA0MiIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ09MSHM0Q1gyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA5L3NvbWUtb2JqLzE1MzgwNTExNDM0MjcwNDIvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwOS9vL3NvbWUtb2JqL2FjbC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA5Iiwib2JqZWN0Ijoic29tZS1vYmoiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE0MzQyNzA0MiIsImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJyb2xlIjoiT1dORVIiLCJlbWFpbCI6IjM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiZXRhZyI6IkNPTEhzNENYMjkwQ0VBRT0ifV0sIm93bmVyIjp7ImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20ifSwiY3JjMzJjIjoiVk5jdHBnPT0iLCJldGFnIjoiQ09MSHM0Q1gyOTBDRUFFPSJ9"
+ }
+ },
+ {
+ "ID": "21a66e45cdb8667d",
+ "Request": {
+ "Method": "PATCH",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0009/o/some-obj?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "83"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "570f7ccbf052f85a5e3a8e354bfba434/5957640956571825773;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0009/o/some-obj?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDkiLCJ0ZW1wb3JhcnlIb2xkIjp0cnVlfQo="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3306"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:43 GMT"
+ ],
+ "Etag": [
+ "COLHs4CX290CEAI="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051443000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrsw14:4204,/bns/yv/borg/yv/bns/blobstore2/bitpusher/388.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=R8ysW_eLMJTOgASAo6ugAQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/388.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/388:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATpxChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4CtK4wESxgF5YTI5LmMuRW93QkpRYm55eUhjUWpNWkU0aTFCOGpNWG9GOHRvNDlSNWRjTUJnOFRGMDJkT2lZdHhhZ3MzVklHZmVzXzByNTlISDRvNEtudW96RTBQa2FVZVIzNkRlelFXcnlfMXpKUjRScTRYcFdDYjJKUkl3NTFYUW8yc2hncy0td1duX1B3Vk9hSy1hWUVQLVN6Uk1zcmlUN0ZtaFZ2WUxRRHhSTy1nd29sRXlFNWJCWXhqQmJybkxfZ3pxTTNQREZFZ0kwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UoUSJsAp4AliWt6x8Y7V9BKhu6YRa_3kTlmIlHRBXeKe39DdevzD3oH8vIstiigiJkx0jLGaQUbBYRkZINHby4RAQqDUA"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwOS9zb21lLW9iai8xNTM4MDUxMTQzNDI3MDQyIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA5L28vc29tZS1vYmoiLCJuYW1lIjoic29tZS1vYmoiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDkiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE0MzQyNzA0MiIsIm1ldGFnZW5lcmF0aW9uIjoiMiIsImNvbnRlbnRUeXBlIjoiYXBwbGljYXRpb24vb2N0ZXQtc3RyZWFtIiwidGltZUNyZWF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI1OjQzLjQyNloiLCJ1cGRhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNTo0My44NjVaIiwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJ0aW1lU3RvcmFnZUNsYXNzVXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjU6NDMuNDI2WiIsInNpemUiOiIxNiIsIm1kNUhhc2giOiJVT2h5QmY1OHg2VElzaGNIS1FvNmpBPT0iLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA5L28vc29tZS1vYmo/Z2VuZXJhdGlvbj0xNTM4MDUxMTQzNDI3MDQyJmFsdD1tZWRpYSIsImFjbCI6W3sia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA5L3NvbWUtb2JqLzE1MzgwNTExNDM0MjcwNDIvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDkvby9zb21lLW9iai9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDkiLCJvYmplY3QiOiJzb21lLW9iaiIsImdlbmVyYXRpb24iOiIxNTM4MDUxMTQzNDI3MDQyIiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDT0xIczRDWDI5MENFQUk9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDkvc29tZS1vYmovMTUzODA1MTE0MzQyNzA0Mi9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDkvby9zb21lLW9iai9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA5Iiwib2JqZWN0Ijoic29tZS1vYmoiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE0MzQyNzA0MiIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDT0xIczRDWDI5MENFQUk9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDkvc29tZS1vYmovMTUzODA1MTE0MzQyNzA0Mi9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDkvby9zb21lLW9iai9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA5Iiwib2JqZWN0Ijoic29tZS1vYmoiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE0MzQyNzA0MiIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ09MSHM0Q1gyOTBDRUFJPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA5L3NvbWUtb2JqLzE1MzgwNTExNDM0MjcwNDIvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwOS9vL3NvbWUtb2JqL2FjbC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA5Iiwib2JqZWN0Ijoic29tZS1vYmoiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE0MzQyNzA0MiIsImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJyb2xlIjoiT1dORVIiLCJlbWFpbCI6IjM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiZXRhZyI6IkNPTEhzNENYMjkwQ0VBST0ifV0sIm93bmVyIjp7ImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20ifSwiY3JjMzJjIjoiVk5jdHBnPT0iLCJldGFnIjoiQ09MSHM0Q1gyOTBDRUFJPSIsInRlbXBvcmFyeUhvbGQiOnRydWV9"
+ }
+ },
+ {
+ "ID": "88e95beed2c0ec76",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0009/o/some-obj?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "3bf057c037eafaa278687db43e4b09d9/7547770290445671435;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0009/o/some-obj?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3306"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:44 GMT"
+ ],
+ "Etag": [
+ "COLHs4CX290CEAI="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051443000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrda17:4188,/bns/yv/borg/yv/bns/blobstore2/bitpusher/118.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=SMysW78N37CCBMGqjeAK"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/118.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/118:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRYm55eUhjUWpNWkU0aTFCOGpNWG9GOHRvNDlSNWRjTUJnOFRGMDJkT2lZdHhhZ3MzVklHZmVzXzByNTlISDRvNEtudW96RTBQa2FVZVIzNkRlelFXcnlfMXpKUjRScTRYcFdDYjJKUkl3NTFYUW8yc2hncy0td1duX1B3Vk9hSy1hWUVQLVN6Uk1zcmlUN0ZtaFZ2WUxRRHhSTy1nd29sRXlFNWJCWXhqQmJybkxfZ3pxTTNQREZFZ0kwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UpGFZ1rGj8u2nmVl9wHkhlgWycEQUTNBfnjLfBazqJeL52WiB5_5_uT9vqKlddCeAULH0E0KsJBrsXr3k2iWlWstsGvUg"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwOS9zb21lLW9iai8xNTM4MDUxMTQzNDI3MDQyIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA5L28vc29tZS1vYmoiLCJuYW1lIjoic29tZS1vYmoiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDkiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE0MzQyNzA0MiIsIm1ldGFnZW5lcmF0aW9uIjoiMiIsImNvbnRlbnRUeXBlIjoiYXBwbGljYXRpb24vb2N0ZXQtc3RyZWFtIiwidGltZUNyZWF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI1OjQzLjQyNloiLCJ1cGRhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNTo0My44NjVaIiwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJ0aW1lU3RvcmFnZUNsYXNzVXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjU6NDMuNDI2WiIsInNpemUiOiIxNiIsIm1kNUhhc2giOiJVT2h5QmY1OHg2VElzaGNIS1FvNmpBPT0iLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA5L28vc29tZS1vYmo/Z2VuZXJhdGlvbj0xNTM4MDUxMTQzNDI3MDQyJmFsdD1tZWRpYSIsImFjbCI6W3sia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA5L3NvbWUtb2JqLzE1MzgwNTExNDM0MjcwNDIvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDkvby9zb21lLW9iai9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDkiLCJvYmplY3QiOiJzb21lLW9iaiIsImdlbmVyYXRpb24iOiIxNTM4MDUxMTQzNDI3MDQyIiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDT0xIczRDWDI5MENFQUk9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDkvc29tZS1vYmovMTUzODA1MTE0MzQyNzA0Mi9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDkvby9zb21lLW9iai9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA5Iiwib2JqZWN0Ijoic29tZS1vYmoiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE0MzQyNzA0MiIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDT0xIczRDWDI5MENFQUk9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDkvc29tZS1vYmovMTUzODA1MTE0MzQyNzA0Mi9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDkvby9zb21lLW9iai9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA5Iiwib2JqZWN0Ijoic29tZS1vYmoiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE0MzQyNzA0MiIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ09MSHM0Q1gyOTBDRUFJPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA5L3NvbWUtb2JqLzE1MzgwNTExNDM0MjcwNDIvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwOS9vL3NvbWUtb2JqL2FjbC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA5Iiwib2JqZWN0Ijoic29tZS1vYmoiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE0MzQyNzA0MiIsImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJyb2xlIjoiT1dORVIiLCJlbWFpbCI6IjM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiZXRhZyI6IkNPTEhzNENYMjkwQ0VBST0ifV0sIm93bmVyIjp7ImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20ifSwiY3JjMzJjIjoiVk5jdHBnPT0iLCJldGFnIjoiQ09MSHM0Q1gyOTBDRUFJPSIsInRlbXBvcmFyeUhvbGQiOnRydWV9"
+ }
+ },
+ {
+ "ID": "139aa9cf44ba2500",
+ "Request": {
+ "Method": "PATCH",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0009/o/some-obj?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "82"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "2ed4cfa83cda4c4f833e638e5a3acab8/9138182190217920938;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0009/o/some-obj?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDkiLCJjb250ZW50VHlwZSI6ImZvbyJ9Cg=="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3285"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:44 GMT"
+ ],
+ "Etag": [
+ "COLHs4CX290CEAM="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051443000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vruh3:4140,/bns/yv/borg/yv/bns/blobstore2/bitpusher/140.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=SMysW-qCBZKCgwS2iqKgDw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/140.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/140:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATpxChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4CtK4wESxgF5YTI5LmMuRW93QkpRYm55eUhjUWpNWkU0aTFCOGpNWG9GOHRvNDlSNWRjTUJnOFRGMDJkT2lZdHhhZ3MzVklHZmVzXzByNTlISDRvNEtudW96RTBQa2FVZVIzNkRlelFXcnlfMXpKUjRScTRYcFdDYjJKUkl3NTFYUW8yc2hncy0td1duX1B3Vk9hSy1hWUVQLVN6Uk1zcmlUN0ZtaFZ2WUxRRHhSTy1nd29sRXlFNWJCWXhqQmJybkxfZ3pxTTNQREZFZ0kwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Upn6yFG5Mlqp-GofUkiY0KgjJBckaYdHghjSruHNtANQIY94tfqerEqXVz-Y18pWQtDuxkJEr09eJ26sjVyPp9llinNpw"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwOS9zb21lLW9iai8xNTM4MDUxMTQzNDI3MDQyIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA5L28vc29tZS1vYmoiLCJuYW1lIjoic29tZS1vYmoiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDkiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE0MzQyNzA0MiIsIm1ldGFnZW5lcmF0aW9uIjoiMyIsImNvbnRlbnRUeXBlIjoiZm9vIiwidGltZUNyZWF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI1OjQzLjQyNloiLCJ1cGRhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNTo0NC4xNTFaIiwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJ0aW1lU3RvcmFnZUNsYXNzVXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjU6NDMuNDI2WiIsInNpemUiOiIxNiIsIm1kNUhhc2giOiJVT2h5QmY1OHg2VElzaGNIS1FvNmpBPT0iLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA5L28vc29tZS1vYmo/Z2VuZXJhdGlvbj0xNTM4MDUxMTQzNDI3MDQyJmFsdD1tZWRpYSIsImFjbCI6W3sia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA5L3NvbWUtb2JqLzE1MzgwNTExNDM0MjcwNDIvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDkvby9zb21lLW9iai9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDkiLCJvYmplY3QiOiJzb21lLW9iaiIsImdlbmVyYXRpb24iOiIxNTM4MDUxMTQzNDI3MDQyIiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDT0xIczRDWDI5MENFQU09In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDkvc29tZS1vYmovMTUzODA1MTE0MzQyNzA0Mi9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDkvby9zb21lLW9iai9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA5Iiwib2JqZWN0Ijoic29tZS1vYmoiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE0MzQyNzA0MiIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDT0xIczRDWDI5MENFQU09In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDkvc29tZS1vYmovMTUzODA1MTE0MzQyNzA0Mi9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDkvby9zb21lLW9iai9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA5Iiwib2JqZWN0Ijoic29tZS1vYmoiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE0MzQyNzA0MiIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ09MSHM0Q1gyOTBDRUFNPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA5L3NvbWUtb2JqLzE1MzgwNTExNDM0MjcwNDIvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwOS9vL3NvbWUtb2JqL2FjbC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA5Iiwib2JqZWN0Ijoic29tZS1vYmoiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE0MzQyNzA0MiIsImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJyb2xlIjoiT1dORVIiLCJlbWFpbCI6IjM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiZXRhZyI6IkNPTEhzNENYMjkwQ0VBTT0ifV0sIm93bmVyIjp7ImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20ifSwiY3JjMzJjIjoiVk5jdHBnPT0iLCJldGFnIjoiQ09MSHM0Q1gyOTBDRUFNPSIsInRlbXBvcmFyeUhvbGQiOnRydWV9"
+ }
+ },
+ {
+ "ID": "2bf008511cf7f3ca",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0009/o/some-obj?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "a515f52484a43b168274b74481a46e8e/10728594094268294985;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0009/o/some-obj?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3285"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:44 GMT"
+ ],
+ "Etag": [
+ "COLHs4CX290CEAM="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051443000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrqj25:4236,/bns/yr/borg/yr/bns/blobstore2/bitpusher/44.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=SMysW-PJEcTvkAPC4IGgCQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/44.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/44:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRYm55eUhjUWpNWkU0aTFCOGpNWG9GOHRvNDlSNWRjTUJnOFRGMDJkT2lZdHhhZ3MzVklHZmVzXzByNTlISDRvNEtudW96RTBQa2FVZVIzNkRlelFXcnlfMXpKUjRScTRYcFdDYjJKUkl3NTFYUW8yc2hncy0td1duX1B3Vk9hSy1hWUVQLVN6Uk1zcmlUN0ZtaFZ2WUxRRHhSTy1nd29sRXlFNWJCWXhqQmJybkxfZ3pxTTNQREZFZ0kwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UomllJXP0WL8d5rWkRPZE8tECJWI63BBawFctUcrI2eVu2DPtJf8AIWjJvmORIpDaq76cuFqfbfZ3yuuBFd9qoTYdafKw"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwOS9zb21lLW9iai8xNTM4MDUxMTQzNDI3MDQyIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA5L28vc29tZS1vYmoiLCJuYW1lIjoic29tZS1vYmoiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDkiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE0MzQyNzA0MiIsIm1ldGFnZW5lcmF0aW9uIjoiMyIsImNvbnRlbnRUeXBlIjoiZm9vIiwidGltZUNyZWF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI1OjQzLjQyNloiLCJ1cGRhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNTo0NC4xNTFaIiwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJ0aW1lU3RvcmFnZUNsYXNzVXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjU6NDMuNDI2WiIsInNpemUiOiIxNiIsIm1kNUhhc2giOiJVT2h5QmY1OHg2VElzaGNIS1FvNmpBPT0iLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA5L28vc29tZS1vYmo/Z2VuZXJhdGlvbj0xNTM4MDUxMTQzNDI3MDQyJmFsdD1tZWRpYSIsImFjbCI6W3sia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA5L3NvbWUtb2JqLzE1MzgwNTExNDM0MjcwNDIvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDkvby9zb21lLW9iai9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDkiLCJvYmplY3QiOiJzb21lLW9iaiIsImdlbmVyYXRpb24iOiIxNTM4MDUxMTQzNDI3MDQyIiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDT0xIczRDWDI5MENFQU09In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDkvc29tZS1vYmovMTUzODA1MTE0MzQyNzA0Mi9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDkvby9zb21lLW9iai9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA5Iiwib2JqZWN0Ijoic29tZS1vYmoiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE0MzQyNzA0MiIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDT0xIczRDWDI5MENFQU09In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDkvc29tZS1vYmovMTUzODA1MTE0MzQyNzA0Mi9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDkvby9zb21lLW9iai9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA5Iiwib2JqZWN0Ijoic29tZS1vYmoiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE0MzQyNzA0MiIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ09MSHM0Q1gyOTBDRUFNPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA5L3NvbWUtb2JqLzE1MzgwNTExNDM0MjcwNDIvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwOS9vL3NvbWUtb2JqL2FjbC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA5Iiwib2JqZWN0Ijoic29tZS1vYmoiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE0MzQyNzA0MiIsImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJyb2xlIjoiT1dORVIiLCJlbWFpbCI6IjM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiZXRhZyI6IkNPTEhzNENYMjkwQ0VBTT0ifV0sIm93bmVyIjp7ImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20ifSwiY3JjMzJjIjoiVk5jdHBnPT0iLCJldGFnIjoiQ09MSHM0Q1gyOTBDRUFNPSIsInRlbXBvcmFyeUhvbGQiOnRydWV9"
+ }
+ },
+ {
+ "ID": "b7766305bfa56d5a",
+ "Request": {
+ "Method": "PATCH",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0009/o/some-obj?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "84"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "736de9a2bdf5c8988d3d2b206d31dfe0/12319005998335511783;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0009/o/some-obj?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDkiLCJ0ZW1wb3JhcnlIb2xkIjpmYWxzZX0K"
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3286"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:44 GMT"
+ ],
+ "Etag": [
+ "COLHs4CX290CEAQ="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051443000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrk4:4182,/bns/yv/borg/yv/bns/blobstore2/bitpusher/349.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=SMysW5KeF9PXgATL46nICA"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/349.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/349:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATpxChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4CtK4wESxgF5YTI5LmMuRW93QkpRYm55eUhjUWpNWkU0aTFCOGpNWG9GOHRvNDlSNWRjTUJnOFRGMDJkT2lZdHhhZ3MzVklHZmVzXzByNTlISDRvNEtudW96RTBQa2FVZVIzNkRlelFXcnlfMXpKUjRScTRYcFdDYjJKUkl3NTFYUW8yc2hncy0td1duX1B3Vk9hSy1hWUVQLVN6Uk1zcmlUN0ZtaFZ2WUxRRHhSTy1nd29sRXlFNWJCWXhqQmJybkxfZ3pxTTNQREZFZ0kwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UoKsb53RjbCrsBQdPjt_eu8_pnouQqM-A4nUtfknw5u5dzQXJ_Hsv8B0j-DTtjN9PDfqh-iKDNvh5QpFb54dc4oDg6t_g"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwOS9zb21lLW9iai8xNTM4MDUxMTQzNDI3MDQyIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA5L28vc29tZS1vYmoiLCJuYW1lIjoic29tZS1vYmoiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDkiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE0MzQyNzA0MiIsIm1ldGFnZW5lcmF0aW9uIjoiNCIsImNvbnRlbnRUeXBlIjoiZm9vIiwidGltZUNyZWF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI1OjQzLjQyNloiLCJ1cGRhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNTo0NC40ODNaIiwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJ0aW1lU3RvcmFnZUNsYXNzVXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjU6NDMuNDI2WiIsInNpemUiOiIxNiIsIm1kNUhhc2giOiJVT2h5QmY1OHg2VElzaGNIS1FvNmpBPT0iLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA5L28vc29tZS1vYmo/Z2VuZXJhdGlvbj0xNTM4MDUxMTQzNDI3MDQyJmFsdD1tZWRpYSIsImFjbCI6W3sia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA5L3NvbWUtb2JqLzE1MzgwNTExNDM0MjcwNDIvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDkvby9zb21lLW9iai9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDkiLCJvYmplY3QiOiJzb21lLW9iaiIsImdlbmVyYXRpb24iOiIxNTM4MDUxMTQzNDI3MDQyIiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDT0xIczRDWDI5MENFQVE9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDkvc29tZS1vYmovMTUzODA1MTE0MzQyNzA0Mi9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDkvby9zb21lLW9iai9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA5Iiwib2JqZWN0Ijoic29tZS1vYmoiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE0MzQyNzA0MiIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDT0xIczRDWDI5MENFQVE9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDkvc29tZS1vYmovMTUzODA1MTE0MzQyNzA0Mi9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDkvby9zb21lLW9iai9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA5Iiwib2JqZWN0Ijoic29tZS1vYmoiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE0MzQyNzA0MiIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ09MSHM0Q1gyOTBDRUFRPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA5L3NvbWUtb2JqLzE1MzgwNTExNDM0MjcwNDIvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwOS9vL3NvbWUtb2JqL2FjbC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDA5Iiwib2JqZWN0Ijoic29tZS1vYmoiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE0MzQyNzA0MiIsImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJyb2xlIjoiT1dORVIiLCJlbWFpbCI6IjM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiZXRhZyI6IkNPTEhzNENYMjkwQ0VBUT0ifV0sIm93bmVyIjp7ImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20ifSwiY3JjMzJjIjoiVk5jdHBnPT0iLCJldGFnIjoiQ09MSHM0Q1gyOTBDRUFRPSIsInRlbXBvcmFyeUhvbGQiOmZhbHNlfQ=="
+ }
+ },
+ {
+ "ID": "4d4bf3d6a690c4ad",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0009/o/some-obj?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "6196048cde2e4d6c53fd5cb570b00693/13078042967756644151;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0009/o/some-obj?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 204,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "0"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:44 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051444000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vnch65:4276,/bns/yx/borg/yx/bns/blobstore2/bitpusher/26.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=SMysW_zuJIqvzwLJp5_ABw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yx/borg/yx/bns/blobstore2/bitpusher/26.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yx/borg/yx/bns/blobstore2/bitpusher/26:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRYm55eUhjUWpNWkU0aTFCOGpNWG9GOHRvNDlSNWRjTUJnOFRGMDJkT2lZdHhhZ3MzVklHZmVzXzByNTlISDRvNEtudW96RTBQa2FVZVIzNkRlelFXcnlfMXpKUjRScTRYcFdDYjJKUkl3NTFYUW8yc2hncy0td1duX1B3Vk9hSy1hWUVQLVN6Uk1zcmlUN0ZtaFZ2WUxRRHhSTy1nd29sRXlFNWJCWXhqQmJybkxfZ3pxTTNQREZFZ0kwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UoT9Ov0jDXHY9uhhhBStlSHg2jyEeNKw2MCJCdrOoF3PgmfOTr2X1r0HPd9xSO4x_WgY6C_ydyWxG1PH9TG3ZZ-rT4sKw"
+ ]
+ },
+ "Body": ""
+ }
+ },
+ {
+ "ID": "8a63a72d8af7ceba",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0009?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "cb299b1ebb95e40d39867cbc9543231a/14668454867528959189;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0009?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 204,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "0"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:45 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051442000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrdm189:4345,/bns/yr/borg/yr/bns/blobstore2/bitpusher/117.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=SMysW9-XOcKnkASClZioBg"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/117.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/117:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRYm55eUhjUWpNWkU0aTFCOGpNWG9GOHRvNDlSNWRjTUJnOFRGMDJkT2lZdHhhZ3MzVklHZmVzXzByNTlISDRvNEtudW96RTBQa2FVZVIzNkRlelFXcnlfMXpKUjRScTRYcFdDYjJKUkl3NTFYUW8yc2hncy0td1duX1B3Vk9hSy1hWUVQLVN6Uk1zcmlUN0ZtaFZ2WUxRRHhSTy1nd29sRXlFNWJCWXhqQmJybkxfZ3pxTTNQREZFZ0kwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UruDTxj-5sNUNL5TgdK2N8Y5h_ubbWt_65r-y1dKu9-7GSNIld2Ii1hrFsyLY-by8sNpTzoshjKed_fvWtm_4qDcgA_Vg"
+ ]
+ },
+ "Body": ""
+ }
+ },
+ {
+ "ID": "6ed823f9572a2abb",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/storage/v1/b?alt=json\u0026prettyPrint=false\u0026project=dulcet-port-762",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "105"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "5d64adfcef1874b28e27c12b019bfbd9/16258584201402739316;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b?alt=json\u0026prettyPrint=false\u0026project=dulcet-port-762"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJuYW1lIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDEwIiwicmV0ZW50aW9uUG9saWN5Ijp7InJldGVudGlvblBlcmlvZCI6IjM2MDAifX0K"
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "514"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:46 GMT"
+ ],
+ "Etag": [
+ "CAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051445000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vnll124:4447,/bns/yx/borg/yx/bns/blobstore2/bitpusher/118.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=ScysW_ynGdbQzAL6lov4DQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yx/borg/yx/bns/blobstore2/bitpusher/118.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yx/borg/yx/bns/blobstore2/bitpusher/118:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWWhLRWRJS21GUEgxdEtyUnZ6LTVHcEpFV2I3OTF6d2FCanpvT0REdnVuTmhHVVBINWJHX1BHc1ljQ2JIS0hpR1QtR1ZSOHdaTlZqMFJQdml6U2NZUnRQUWg3QkdWU1UzbXNkXzNJSERFRUFoQVVXU3ZQZHNMSmZocVBubWZlZUgtb3pCMEtxQ3hFRTBob2FQbTRqQmlvMXVidF9WSlVuZmVvcl9sZkhCLTMxWkpsNENCQ1dIRXVRQ1EwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Uol_YBnpQvchvCCc4fF4UAzRDezAG-jZp1Q5dR-8d3_56yA5lZp2tYMVP9VBnPA8rc9-g99iXEA5muatm50TW0VfftSmQ"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxMCIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxMCIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTAiLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjU6NDUuODU3WiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI1OjQ1Ljg1N1oiLCJtZXRhZ2VuZXJhdGlvbiI6IjEiLCJsb2NhdGlvbiI6IlVTIiwicmV0ZW50aW9uUG9saWN5Ijp7InJldGVudGlvblBlcmlvZCI6IjM2MDAiLCJlZmZlY3RpdmVUaW1lIjoiMjAxOC0wOS0yN1QxMjoyNTo0NS44NTdaIn0sInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwiZXRhZyI6IkNBRT0ifQ=="
+ }
+ },
+ {
+ "ID": "07b5dd5807cb4e76",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0010/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Type": [
+ "multipart/related; boundary=60f031f9c7f83e6753f9064062bf236631fe19faf4e9f2501b9a1cf4e8e8"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "ba4c24b367d04339d0eb4e34c234e7e2/17017902641505680835;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0010/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "LS02MGYwMzFmOWM3ZjgzZTY3NTNmOTA2NDA2MmJmMjM2NjMxZmUxOWZhZjRlOWYyNTAxYjlhMWNmNGU4ZTgNCkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vanNvbg0KDQp7ImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxMCIsIm5hbWUiOiJzb21lLW9iaiJ9Cg0KLS02MGYwMzFmOWM3ZjgzZTY3NTNmOTA2NDA2MmJmMjM2NjMxZmUxOWZhZjRlOWYyNTAxYjlhMWNmNGU4ZTgNCkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vb2N0ZXQtc3RyZWFtDQoNCku3Qm/7wRsR3az70rmpwPANCi0tNjBmMDMxZjljN2Y4M2U2NzUzZjkwNjQwNjJiZjIzNjYzMWZlMTlmYWY0ZTlmMjUwMWI5YTFjZjRlOGU4LS0NCg=="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3338"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:46 GMT"
+ ],
+ "Etag": [
+ "CPq47IGX290CEAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051446000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrdg20:4229,/bns/yr/borg/yr/bns/blobstore2/bitpusher/99.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=SsysW7SWB4i44QT15L5A"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/99.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/99:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWWhLRWRJS21GUEgxdEtyUnZ6LTVHcEpFV2I3OTF6d2FCanpvT0REdnVuTmhHVVBINWJHX1BHc1ljQ2JIS0hpR1QtR1ZSOHdaTlZqMFJQdml6U2NZUnRQUWg3QkdWU1UzbXNkXzNJSERFRUFoQVVXU3ZQZHNMSmZocVBubWZlZUgtb3pCMEtxQ3hFRTBob2FQbTRqQmlvMXVidF9WSlVuZmVvcl9sZkhCLTMxWkpsNENCQ1dIRXVRQ1EwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_single_post_uploads"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UoVq1g900fUkQrYVUWxjF80ZfcD75WfF1p0bn_P3bXv1wH-zRd-vMpaPLWBfYQS90SCPPb1fc0gTkjxsuc_fy74O6R2aw"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxMC9zb21lLW9iai8xNTM4MDUxMTQ2NDU2MTg2Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDEwL28vc29tZS1vYmoiLCJuYW1lIjoic29tZS1vYmoiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTAiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE0NjQ1NjE4NiIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoiYXBwbGljYXRpb24vb2N0ZXQtc3RyZWFtIiwidGltZUNyZWF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI1OjQ2LjQ1NFoiLCJ1cGRhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNTo0Ni40NTRaIiwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJ0aW1lU3RvcmFnZUNsYXNzVXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjU6NDYuNDU0WiIsInNpemUiOiIxNiIsIm1kNUhhc2giOiJRWm5CNUtSZSs4aTJ4d2w3K2pGMVJRPT0iLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDEwL28vc29tZS1vYmo/Z2VuZXJhdGlvbj0xNTM4MDUxMTQ2NDU2MTg2JmFsdD1tZWRpYSIsImFjbCI6W3sia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDEwL3NvbWUtb2JqLzE1MzgwNTExNDY0NTYxODYvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTAvby9zb21lLW9iai9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTAiLCJvYmplY3QiOiJzb21lLW9iaiIsImdlbmVyYXRpb24iOiIxNTM4MDUxMTQ2NDU2MTg2IiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDUHE0N0lHWDI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTAvc29tZS1vYmovMTUzODA1MTE0NjQ1NjE4Ni9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTAvby9zb21lLW9iai9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDEwIiwib2JqZWN0Ijoic29tZS1vYmoiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE0NjQ1NjE4NiIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDUHE0N0lHWDI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTAvc29tZS1vYmovMTUzODA1MTE0NjQ1NjE4Ni9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTAvby9zb21lLW9iai9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDEwIiwib2JqZWN0Ijoic29tZS1vYmoiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE0NjQ1NjE4NiIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ1BxNDdJR1gyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDEwL3NvbWUtb2JqLzE1MzgwNTExNDY0NTYxODYvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxMC9vL3NvbWUtb2JqL2FjbC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDEwIiwib2JqZWN0Ijoic29tZS1vYmoiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE0NjQ1NjE4NiIsImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJyb2xlIjoiT1dORVIiLCJlbWFpbCI6IjM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiZXRhZyI6IkNQcTQ3SUdYMjkwQ0VBRT0ifV0sIm93bmVyIjp7ImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20ifSwiY3JjMzJjIjoid2VWZjBRPT0iLCJldGFnIjoiQ1BxNDdJR1gyOTBDRUFFPSIsInJldGVudGlvbkV4cGlyYXRpb25UaW1lIjoiMjAxOC0wOS0yN1QxMzoyNTo0Ni40NTRaIn0="
+ }
+ },
+ {
+ "ID": "6cd308150938c9ed",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0010/o/some-obj?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "b7b72476a97dc563ea515dd0419a2d50/161570476158247522;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0010/o/some-obj?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3338"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:46 GMT"
+ ],
+ "Etag": [
+ "CPq47IGX290CEAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051446000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vneg3:4091,/bns/yx/borg/yx/bns/blobstore2/bitpusher/152.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=SsysW9ykKoaJzgLa9JeAAw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yx/borg/yx/bns/blobstore2/bitpusher/152.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yx/borg/yx/bns/blobstore2/bitpusher/152:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRWWhLRWRJS21GUEgxdEtyUnZ6LTVHcEpFV2I3OTF6d2FCanpvT0REdnVuTmhHVVBINWJHX1BHc1ljQ2JIS0hpR1QtR1ZSOHdaTlZqMFJQdml6U2NZUnRQUWg3QkdWU1UzbXNkXzNJSERFRUFoQVVXU3ZQZHNMSmZocVBubWZlZUgtb3pCMEtxQ3hFRTBob2FQbTRqQmlvMXVidF9WSlVuZmVvcl9sZkhCLTMxWkpsNENCQ1dIRXVRQ1EwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Upwz4yjfKZJQXT-HE1cBx9y61M5M7GcsWo_go1oLuR8khJs4XxiRj3nJg-ujAWf-tnN7hNKuXHv8p9abUc27DobK2BkcA"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxMC9zb21lLW9iai8xNTM4MDUxMTQ2NDU2MTg2Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDEwL28vc29tZS1vYmoiLCJuYW1lIjoic29tZS1vYmoiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTAiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE0NjQ1NjE4NiIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoiYXBwbGljYXRpb24vb2N0ZXQtc3RyZWFtIiwidGltZUNyZWF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI1OjQ2LjQ1NFoiLCJ1cGRhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNTo0Ni40NTRaIiwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJ0aW1lU3RvcmFnZUNsYXNzVXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjU6NDYuNDU0WiIsInNpemUiOiIxNiIsIm1kNUhhc2giOiJRWm5CNUtSZSs4aTJ4d2w3K2pGMVJRPT0iLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDEwL28vc29tZS1vYmo/Z2VuZXJhdGlvbj0xNTM4MDUxMTQ2NDU2MTg2JmFsdD1tZWRpYSIsImFjbCI6W3sia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDEwL3NvbWUtb2JqLzE1MzgwNTExNDY0NTYxODYvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTAvby9zb21lLW9iai9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTAiLCJvYmplY3QiOiJzb21lLW9iaiIsImdlbmVyYXRpb24iOiIxNTM4MDUxMTQ2NDU2MTg2IiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDUHE0N0lHWDI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTAvc29tZS1vYmovMTUzODA1MTE0NjQ1NjE4Ni9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTAvby9zb21lLW9iai9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDEwIiwib2JqZWN0Ijoic29tZS1vYmoiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE0NjQ1NjE4NiIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDUHE0N0lHWDI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTAvc29tZS1vYmovMTUzODA1MTE0NjQ1NjE4Ni9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTAvby9zb21lLW9iai9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDEwIiwib2JqZWN0Ijoic29tZS1vYmoiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE0NjQ1NjE4NiIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ1BxNDdJR1gyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDEwL3NvbWUtb2JqLzE1MzgwNTExNDY0NTYxODYvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxMC9vL3NvbWUtb2JqL2FjbC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDEwIiwib2JqZWN0Ijoic29tZS1vYmoiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE0NjQ1NjE4NiIsImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJyb2xlIjoiT1dORVIiLCJlbWFpbCI6IjM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiZXRhZyI6IkNQcTQ3SUdYMjkwQ0VBRT0ifV0sIm93bmVyIjp7ImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20ifSwiY3JjMzJjIjoid2VWZjBRPT0iLCJldGFnIjoiQ1BxNDdJR1gyOTBDRUFFPSIsInJldGVudGlvbkV4cGlyYXRpb25UaW1lIjoiMjAxOC0wOS0yN1QxMzoyNTo0Ni40NTRaIn0="
+ }
+ },
+ {
+ "ID": "f52f400fa7e43a90",
+ "Request": {
+ "Method": "PATCH",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0010?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "25"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "b86e7859e62fb9ea4a7c82cbf53f7e0b/1751982375913719809;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0010?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJyZXRlbnRpb25Qb2xpY3kiOm51bGx9Cg=="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "2353"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:48 GMT"
+ ],
+ "Etag": [
+ "CAI="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051447000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vnaz64:4220,/bns/yx/borg/yx/bns/blobstore2/bitpusher/147.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=SsysW_bNL46YzQKvubuIDg"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yx/borg/yx/bns/blobstore2/bitpusher/147.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yx/borg/yx/bns/blobstore2/bitpusher/147:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATpxChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4CtK4wESxgF5YTI5LmMuRW93QkpRWWhLRWRJS21GUEgxdEtyUnZ6LTVHcEpFV2I3OTF6d2FCanpvT0REdnVuTmhHVVBINWJHX1BHc1ljQ2JIS0hpR1QtR1ZSOHdaTlZqMFJQdml6U2NZUnRQUWg3QkdWU1UzbXNkXzNJSERFRUFoQVVXU3ZQZHNMSmZocVBubWZlZUgtb3pCMEtxQ3hFRTBob2FQbTRqQmlvMXVidF9WSlVuZmVvcl9sZkhCLTMxWkpsNENCQ1dIRXVRQ1EwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UpDMEyndQWEVKJnGEtbhRAyCqFEjYGH6cqgGiUAmmrf4CTeY9phBbXpQxFAl0RLmwwilggpY04j79eA0cxPBBnZCG3lIQ"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxMCIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxMCIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTAiLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjU6NDUuODU3WiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI1OjQ4LjEyMFoiLCJtZXRhZ2VuZXJhdGlvbiI6IjIiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxMC9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxMC9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTAiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBST0ifSx7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxMC9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTAvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxMCIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDQUk9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTAvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDEwL2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTAiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNBST0ifV0sImRlZmF1bHRPYmplY3RBY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBST0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0FJPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0FJPSJ9XSwib3duZXIiOnsiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUifSwibG9jYXRpb24iOiJVUyIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwiZXRhZyI6IkNBST0ifQ=="
+ }
+ },
+ {
+ "ID": "b2ec087cf2118f91",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0010/o/some-obj?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "d6b2b26a710f3d11142874553579d124/2583357310559738448;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0010/o/some-obj?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 204,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "0"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:48 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051446000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrdx87:4375,/bns/yv/borg/yv/bns/blobstore2/bitpusher/339.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=TMysW92LFMrqgwTa5YP4AQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/339.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/339:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWWhLRWRJS21GUEgxdEtyUnZ6LTVHcEpFV2I3OTF6d2FCanpvT0REdnVuTmhHVVBINWJHX1BHc1ljQ2JIS0hpR1QtR1ZSOHdaTlZqMFJQdml6U2NZUnRQUWg3QkdWU1UzbXNkXzNJSERFRUFoQVVXU3ZQZHNMSmZocVBubWZlZUgtb3pCMEtxQ3hFRTBob2FQbTRqQmlvMXVidF9WSlVuZmVvcl9sZkhCLTMxWkpsNENCQ1dIRXVRQ1EwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UodSFemSWw3f41ZGelIJMWcecf1K1IJI-BDg-FGF7JngeV5eeYZY1QJbmlh6M3HYaBxdOadLCvOH-CMy1xYTZflI3cPFA"
+ ]
+ },
+ "Body": ""
+ }
+ },
+ {
+ "ID": "350aa556ebfb5939",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0010?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "0c824b79369ca5b0582093808bcfc251/4173487743928369391;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0010?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 429,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0"
+ ],
+ "Content-Length": [
+ "12085"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:48 GMT"
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:25:48 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051446000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrl7:4233,/bns/yw/borg/yw/bns/blobstore2/bitpusher/117.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=TMysW5vmJsWThQT875SgCg"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yw/borg/yw/bns/blobstore2/bitpusher/117.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yw/borg/yw/bns/blobstore2/bitpusher/117:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWWhLRWRJS21GUEgxdEtyUnZ6LTVHcEpFV2I3OTF6d2FCanpvT0REdnVuTmhHVVBINWJHX1BHc1ljQ2JIS0hpR1QtR1ZSOHdaTlZqMFJQdml6U2NZUnRQUWg3QkdWU1UzbXNkXzNJSERFRUFoQVVXU3ZQZHNMSmZocVBubWZlZUgtb3pCMEtxQ3hFRTBob2FQbTRqQmlvMXVidF9WSlVuZmVvcl9sZkhCLTMxWkpsNENCQ1dIRXVRQ1EwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Upload-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Uo3ylDcXvoHItOtoj6RY5otQx8n7iP_-eEGL30SzZrQeFXj3J1cwR69rTGuf6rY9RzGK2sHqAPBdd-gQLsua2H81DOkFQ"
+ ]
+ },
+ "Body": "eyJlcnJvciI6eyJlcnJvcnMiOlt7ImRvbWFpbiI6InVzYWdlTGltaXRzIiwicmVhc29uIjoicmF0ZUxpbWl0RXhjZWVkZWQiLCJtZXNzYWdlIjoiVGhlIHByb2plY3QgZXhjZWVkZWQgdGhlIHJhdGUgbGltaXQgZm9yIGNyZWF0aW5nIGFuZCBkZWxldGluZyBidWNrZXRzLiIsImRlYnVnSW5mbyI6ImNvbS5nb29nbGUubmV0LnJwYzMuUnBjRXhjZXB0aW9uOiBjbG91ZC5iaWdzdG9yZS5SZXNwb25zZUNvZGUuRXJyb3JDb2RlOjpQUk9KRUNUX0JVQ0tFVF9PUF9SQVRFX1RPT19ISUdIOiBEZWxldGluZyBidWNrZXRzIHRvbyBxdWlja2x5LCBwbGVhc2Ugc2xvdyBkb3duXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRvUnBjM0V4Y2VwdGlvbihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjEzNSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5idWNrZXRzLkRlbGV0ZUJ1Y2tldC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoRGVsZXRlQnVja2V0LmphdmE6NzEpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYnVja2V0cy5EZWxldGVCdWNrZXQuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKERlbGV0ZUJ1Y2tldC5qYXZhOjIzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmZyYW1ld29yay5SZXF1ZXN0SGFuZGxlci5oYW5kbGUoUmVxdWVzdEhhbmRsZXIuamF2YToyOTQpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uQnVja2V0c0RlbGVnYXRvci5kZWxldGUoQnVja2V0c0RlbGVnYXRvci5qYXZhOjExNSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uUnBjUmVjZWl2ZXIubGFtYmRhJHByb2Nlc3NSZXF1ZXN0QXN5bmMkNChScGNSZWNlaXZlci5qYXZhOjIwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uQXN5bmNFeGVjdXRvci5sYW1iZGEkc3VibWl0JDAoQXN5bmNFeGVjdXRvci5qYXZhOjI3Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KENvbnRleHRSdW5uYWJsZS5qYXZhOjUwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZSQxLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozOSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NzIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozNilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRXhlY3V0b3JzJFJ1bm5hYmxlQWRhcHRlci5jYWxsKEV4ZWN1dG9ycy5qYXZhOjUxMSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRnV0dXJlVGFzay5ydW4oRnV0dXJlVGFzay5qYXZhOjI2Nilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yLnJ1bldvcmtlcihUaHJlYWRQb29sRXhlY3V0b3IuamF2YToxMTQ5KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IkV29ya2VyLnJ1bihUaHJlYWRQb29sRXhlY3V0b3IuamF2YTo2MjQpXG5cdGF0IGphdmEubGFuZy5UaHJlYWQucnVuKFRocmVhZC5qYXZhOjc0OClcbkNhdXNlZCBieTogY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb246IERlbGV0aW5nIGJ1Y2tldHMgdG9vIHF1aWNrbHksIHBsZWFzZSBzbG93IGRvd25cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MjkwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAxKVxuXHQuLi4gMTcgbW9yZVxuXG5jb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS5GYXVsdDogSW1tdXRhYmxlRXJyb3JEZWZpbml0aW9ue2Jhc2U9VE9PX01BTllfUkVRVUVTVFMsIGNhdGVnb3J5PVFVT1RBX0VSUk9SLCBjYXVzZT1udWxsLCBkZWJ1Z0luZm89Y29tLmdvb2dsZS5uZXQucnBjMy5ScGNFeGNlcHRpb246IGNsb3VkLmJpZ3N0b3JlLlJlc3BvbnNlQ29kZS5FcnJvckNvZGU6OlBST0pFQ1RfQlVDS0VUX09QX1JBVEVfVE9PX0hJR0g6IERlbGV0aW5nIGJ1Y2tldHMgdG9vIHF1aWNrbHksIHBsZWFzZSBzbG93IGRvd25cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udG9ScGMzRXhjZXB0aW9uKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MTM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmJ1Y2tldHMuRGVsZXRlQnVja2V0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChEZWxldGVCdWNrZXQuamF2YTo3MSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5idWNrZXRzLkRlbGV0ZUJ1Y2tldC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoRGVsZXRlQnVja2V0LmphdmE6MjMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5CdWNrZXRzRGVsZWdhdG9yLmRlbGV0ZShCdWNrZXRzRGVsZWdhdG9yLmphdmE6MTE1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5ScGNSZWNlaXZlci5sYW1iZGEkcHJvY2Vzc1JlcXVlc3RBc3luYyQ0KFJwY1JlY2VpdmVyLmphdmE6MjAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5Bc3luY0V4ZWN1dG9yLmxhbWJkYSRzdWJtaXQkMChBc3luY0V4ZWN1dG9yLmphdmE6MjcyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoQ29udGV4dFJ1bm5hYmxlLmphdmE6NTApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlJDEucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM5KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo3Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5FeGVjdXRvcnMkUnVubmFibGVBZGFwdGVyLmNhbGwoRXhlY3V0b3JzLmphdmE6NTExKVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5GdXR1cmVUYXNrLnJ1bihGdXR1cmVUYXNrLmphdmE6MjY2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IucnVuV29ya2VyKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjExNDkpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvciRXb3JrZXIucnVuKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjYyNClcblx0YXQgamF2YS5sYW5nLlRocmVhZC5ydW4oVGhyZWFkLmphdmE6NzQ4KVxuQ2F1c2VkIGJ5OiBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbjogRGVsZXRpbmcgYnVja2V0cyB0b28gcXVpY2tseSwgcGxlYXNlIHNsb3cgZG93blxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxNyBtb3JlXG4sIGRvbWFpbj11c2FnZUxpbWl0cywgZXh0ZW5kZWRIZWxwPW51bGwsIGh0dHBIZWFkZXJzPXt9LCBodHRwU3RhdHVzPXRvb01hbnlSZXF1ZXN0cywgaW50ZXJuYWxSZWFzb249UmVhc29ue2FyZ3VtZW50cz17fSwgY2F1c2U9bnVsbCwgY29kZT1jbG91ZC5iaWdzdG9yZS5hcGkuQmlnc3RvcmVFcnJvckRvbWFpbi5DTElFTlRfUVVPVEFfRVhDRUVERUQsIGNyZWF0ZWRCeUJhY2tlbmQ9dHJ1ZSwgZGVidWdNZXNzYWdlPWNvbS5nb29nbGUubmV0LnJwYzMuUnBjRXhjZXB0aW9uOiBjbG91ZC5iaWdzdG9yZS5SZXNwb25zZUNvZGUuRXJyb3JDb2RlOjpQUk9KRUNUX0JVQ0tFVF9PUF9SQVRFX1RPT19ISUdIOiBEZWxldGluZyBidWNrZXRzIHRvbyBxdWlja2x5LCBwbGVhc2Ugc2xvdyBkb3duXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRvUnBjM0V4Y2VwdGlvbihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjEzNSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5idWNrZXRzLkRlbGV0ZUJ1Y2tldC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoRGVsZXRlQnVja2V0LmphdmE6NzEpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYnVja2V0cy5EZWxldGVCdWNrZXQuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKERlbGV0ZUJ1Y2tldC5qYXZhOjIzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmZyYW1ld29yay5SZXF1ZXN0SGFuZGxlci5oYW5kbGUoUmVxdWVzdEhhbmRsZXIuamF2YToyOTQpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uQnVja2V0c0RlbGVnYXRvci5kZWxldGUoQnVja2V0c0RlbGVnYXRvci5qYXZhOjExNSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uUnBjUmVjZWl2ZXIubGFtYmRhJHByb2Nlc3NSZXF1ZXN0QXN5bmMkNChScGNSZWNlaXZlci5qYXZhOjIwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uQXN5bmNFeGVjdXRvci5sYW1iZGEkc3VibWl0JDAoQXN5bmNFeGVjdXRvci5qYXZhOjI3Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KENvbnRleHRSdW5uYWJsZS5qYXZhOjUwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZSQxLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozOSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NzIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozNilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRXhlY3V0b3JzJFJ1bm5hYmxlQWRhcHRlci5jYWxsKEV4ZWN1dG9ycy5qYXZhOjUxMSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRnV0dXJlVGFzay5ydW4oRnV0dXJlVGFzay5qYXZhOjI2Nilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yLnJ1bldvcmtlcihUaHJlYWRQb29sRXhlY3V0b3IuamF2YToxMTQ5KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IkV29ya2VyLnJ1bihUaHJlYWRQb29sRXhlY3V0b3IuamF2YTo2MjQpXG5cdGF0IGphdmEubGFuZy5UaHJlYWQucnVuKFRocmVhZC5qYXZhOjc0OClcbkNhdXNlZCBieTogY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb246IERlbGV0aW5nIGJ1Y2tldHMgdG9vIHF1aWNrbHksIHBsZWFzZSBzbG93IGRvd25cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MjkwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAxKVxuXHQuLi4gMTcgbW9yZVxuLCBlcnJvclByb3RvQ29kZT1DTElFTlRfUVVPVEFfRVhDRUVERUQsIGVycm9yUHJvdG9Eb21haW49Y2xvdWQuYmlnc3RvcmUuYXBpLkJpZ3N0b3JlRXJyb3JEb21haW4sIGZpbHRlcmVkTWVzc2FnZT1udWxsLCBsb2NhdGlvbj1lbnRpdHkucmVzb3VyY2VfaWQubmFtZSwgbWVzc2FnZT1UaGUgcHJvamVjdCBleGNlZWRlZCB0aGUgcmF0ZSBsaW1pdCBmb3IgY3JlYXRpbmcgYW5kIGRlbGV0aW5nIGJ1Y2tldHMuLCB1bm5hbWVkQXJndW1lbnRzPVtdfSwgbG9jYXRpb249ZW50aXR5LnJlc291cmNlX2lkLm5hbWUsIG1lc3NhZ2U9VGhlIHByb2plY3QgZXhjZWVkZWQgdGhlIHJhdGUgbGltaXQgZm9yIGNyZWF0aW5nIGFuZCBkZWxldGluZyBidWNrZXRzLiwgcmVhc29uPXJhdGVMaW1pdEV4Y2VlZGVkLCBycGNDb2RlPTQyOX0gVGhlIHByb2plY3QgZXhjZWVkZWQgdGhlIHJhdGUgbGltaXQgZm9yIGNyZWF0aW5nIGFuZCBkZWxldGluZyBidWNrZXRzLjogY29tLmdvb2dsZS5uZXQucnBjMy5ScGNFeGNlcHRpb246IGNsb3VkLmJpZ3N0b3JlLlJlc3BvbnNlQ29kZS5FcnJvckNvZGU6OlBST0pFQ1RfQlVDS0VUX09QX1JBVEVfVE9PX0hJR0g6IERlbGV0aW5nIGJ1Y2tldHMgdG9vIHF1aWNrbHksIHBsZWFzZSBzbG93IGRvd25cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udG9ScGMzRXhjZXB0aW9uKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MTM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmJ1Y2tldHMuRGVsZXRlQnVja2V0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChEZWxldGVCdWNrZXQuamF2YTo3MSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5idWNrZXRzLkRlbGV0ZUJ1Y2tldC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoRGVsZXRlQnVja2V0LmphdmE6MjMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5CdWNrZXRzRGVsZWdhdG9yLmRlbGV0ZShCdWNrZXRzRGVsZWdhdG9yLmphdmE6MTE1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5ScGNSZWNlaXZlci5sYW1iZGEkcHJvY2Vzc1JlcXVlc3RBc3luYyQ0KFJwY1JlY2VpdmVyLmphdmE6MjAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5Bc3luY0V4ZWN1dG9yLmxhbWJkYSRzdWJtaXQkMChBc3luY0V4ZWN1dG9yLmphdmE6MjcyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoQ29udGV4dFJ1bm5hYmxlLmphdmE6NTApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlJDEucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM5KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo3Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5FeGVjdXRvcnMkUnVubmFibGVBZGFwdGVyLmNhbGwoRXhlY3V0b3JzLmphdmE6NTExKVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5GdXR1cmVUYXNrLnJ1bihGdXR1cmVUYXNrLmphdmE6MjY2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IucnVuV29ya2VyKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjExNDkpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvciRXb3JrZXIucnVuKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjYyNClcblx0YXQgamF2YS5sYW5nLlRocmVhZC5ydW4oVGhyZWFkLmphdmE6NzQ4KVxuQ2F1c2VkIGJ5OiBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbjogRGVsZXRpbmcgYnVja2V0cyB0b28gcXVpY2tseSwgcGxlYXNlIHNsb3cgZG93blxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxNyBtb3JlXG5cblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUuRXJyb3JDb2xsZWN0b3IudG9GYXVsdChFcnJvckNvbGxlY3Rvci5qYXZhOjU0KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIucmVzdC5hZGFwdGVyLnJvc3kuUm9zeUVycm9yQ29udmVydGVyLnRvRmF1bHQoUm9zeUVycm9yQ29udmVydGVyLmphdmE6NjcpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5yZXN0LmFkYXB0ZXIucm9zeS5Sb3N5SGFuZGxlciQyLmNhbGwoUm9zeUhhbmRsZXIuamF2YToyNTgpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5yZXN0LmFkYXB0ZXIucm9zeS5Sb3N5SGFuZGxlciQyLmNhbGwoUm9zeUhhbmRsZXIuamF2YToyMzgpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLnV0aWwuQ2FsbGFibGVGdXR1cmUucnVuKENhbGxhYmxlRnV0dXJlLmphdmE6NjIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5EaXJlY3RFeGVjdXRvci5leGVjdXRlKERpcmVjdEV4ZWN1dG9yLmphdmE6MzApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5leGVjdXRlTGlzdGVuZXIoQWJzdHJhY3RGdXR1cmUuamF2YToxMTQzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuY29tcGxldGUoQWJzdHJhY3RGdXR1cmUuamF2YTo5NjMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5zZXQoQWJzdHJhY3RGdXR1cmUuamF2YTo3MzEpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLnV0aWwuQ2FsbGFibGVGdXR1cmUucnVuKENhbGxhYmxlRnV0dXJlLmphdmE6NjIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5EaXJlY3RFeGVjdXRvci5leGVjdXRlKERpcmVjdEV4ZWN1dG9yLmphdmE6MzApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5leGVjdXRlTGlzdGVuZXIoQWJzdHJhY3RGdXR1cmUuamF2YToxMTQzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuY29tcGxldGUoQWJzdHJhY3RGdXR1cmUuamF2YTo5NjMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5zZXQoQWJzdHJhY3RGdXR1cmUuamF2YTo3MzEpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLnV0aWwuQ2FsbGFibGVGdXR1cmUucnVuKENhbGxhYmxlRnV0dXJlLmphdmE6NjIpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci50aHJlYWQuVGhyZWFkVHJhY2tlcnMkVGhyZWFkVHJhY2tpbmdSdW5uYWJsZS5ydW4oVGhyZWFkVHJhY2tlcnMuamF2YToxMjYpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkVHJhY2VDb250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KFRyYWNlQ29udGV4dC5qYXZhOjQ1NSlcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnNlcnZlci5Db21tb25Nb2R1bGUkQ29udGV4dENhcnJ5aW5nRXhlY3V0b3JTZXJ2aWNlJDEucnVuSW5Db250ZXh0KENvbW1vbk1vZHVsZS5qYXZhOjg0Nilcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRUcmFjZUNvbnRleHRSdW5uYWJsZSQxLnJ1bihUcmFjZUNvbnRleHQuamF2YTo0NjIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkQWJzdHJhY3RUcmFjZUNvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKFRyYWNlQ29udGV4dC5qYXZhOjMyMSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRBYnN0cmFjdFRyYWNlQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChUcmFjZUNvbnRleHQuamF2YTozMTMpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkVHJhY2VDb250ZXh0UnVubmFibGUucnVuKFRyYWNlQ29udGV4dC5qYXZhOjQ1OSlcblx0YXQgY29tLmdvb2dsZS5nc2UuaW50ZXJuYWwuRGlzcGF0Y2hRdWV1ZUltcGwkV29ya2VyVGhyZWFkLnJ1bihEaXNwYXRjaFF1ZXVlSW1wbC5qYXZhOjQwMylcbiJ9XSwiY29kZSI6NDI5LCJtZXNzYWdlIjoiVGhlIHByb2plY3QgZXhjZWVkZWQgdGhlIHJhdGUgbGltaXQgZm9yIGNyZWF0aW5nIGFuZCBkZWxldGluZyBidWNrZXRzLiJ9fQ=="
+ }
+ },
+ {
+ "ID": "7aaeb5b6064014cf",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0010?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "0c824b79369ca5b0582093808bcfc251/4932805084536460094;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0010?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 429,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0"
+ ],
+ "Content-Length": [
+ "12085"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:49 GMT"
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:25:49 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051446000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrce189:4322,/bns/yr/borg/yr/bns/blobstore2/bitpusher/74.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=TcysW7VS0LrhBIS3nfgL"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/74.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/74:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWWhLRWRJS21GUEgxdEtyUnZ6LTVHcEpFV2I3OTF6d2FCanpvT0REdnVuTmhHVVBINWJHX1BHc1ljQ2JIS0hpR1QtR1ZSOHdaTlZqMFJQdml6U2NZUnRQUWg3QkdWU1UzbXNkXzNJSERFRUFoQVVXU3ZQZHNMSmZocVBubWZlZUgtb3pCMEtxQ3hFRTBob2FQbTRqQmlvMXVidF9WSlVuZmVvcl9sZkhCLTMxWkpsNENCQ1dIRXVRQ1EwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Upload-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UoHEannxoQgJHDWnyc3VdxrvGoBWcWYnpGbLyOcR9hKEOc4ujSkrKiQTv7WEwa595fMdZxHTDEZDX9WhbXdhMYvhS465w"
+ ]
+ },
+ "Body": "eyJlcnJvciI6eyJlcnJvcnMiOlt7ImRvbWFpbiI6InVzYWdlTGltaXRzIiwicmVhc29uIjoicmF0ZUxpbWl0RXhjZWVkZWQiLCJtZXNzYWdlIjoiVGhlIHByb2plY3QgZXhjZWVkZWQgdGhlIHJhdGUgbGltaXQgZm9yIGNyZWF0aW5nIGFuZCBkZWxldGluZyBidWNrZXRzLiIsImRlYnVnSW5mbyI6ImNvbS5nb29nbGUubmV0LnJwYzMuUnBjRXhjZXB0aW9uOiBjbG91ZC5iaWdzdG9yZS5SZXNwb25zZUNvZGUuRXJyb3JDb2RlOjpQUk9KRUNUX0JVQ0tFVF9PUF9SQVRFX1RPT19ISUdIOiBEZWxldGluZyBidWNrZXRzIHRvbyBxdWlja2x5LCBwbGVhc2Ugc2xvdyBkb3duXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRvUnBjM0V4Y2VwdGlvbihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjEzNSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5idWNrZXRzLkRlbGV0ZUJ1Y2tldC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoRGVsZXRlQnVja2V0LmphdmE6NzEpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYnVja2V0cy5EZWxldGVCdWNrZXQuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKERlbGV0ZUJ1Y2tldC5qYXZhOjIzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmZyYW1ld29yay5SZXF1ZXN0SGFuZGxlci5oYW5kbGUoUmVxdWVzdEhhbmRsZXIuamF2YToyOTQpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uQnVja2V0c0RlbGVnYXRvci5kZWxldGUoQnVja2V0c0RlbGVnYXRvci5qYXZhOjExNSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uUnBjUmVjZWl2ZXIubGFtYmRhJHByb2Nlc3NSZXF1ZXN0QXN5bmMkNChScGNSZWNlaXZlci5qYXZhOjIwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uQXN5bmNFeGVjdXRvci5sYW1iZGEkc3VibWl0JDAoQXN5bmNFeGVjdXRvci5qYXZhOjI3Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KENvbnRleHRSdW5uYWJsZS5qYXZhOjUwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZSQxLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozOSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NzIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozNilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRXhlY3V0b3JzJFJ1bm5hYmxlQWRhcHRlci5jYWxsKEV4ZWN1dG9ycy5qYXZhOjUxMSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRnV0dXJlVGFzay5ydW4oRnV0dXJlVGFzay5qYXZhOjI2Nilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yLnJ1bldvcmtlcihUaHJlYWRQb29sRXhlY3V0b3IuamF2YToxMTQ5KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IkV29ya2VyLnJ1bihUaHJlYWRQb29sRXhlY3V0b3IuamF2YTo2MjQpXG5cdGF0IGphdmEubGFuZy5UaHJlYWQucnVuKFRocmVhZC5qYXZhOjc0OClcbkNhdXNlZCBieTogY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb246IERlbGV0aW5nIGJ1Y2tldHMgdG9vIHF1aWNrbHksIHBsZWFzZSBzbG93IGRvd25cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MjkwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAxKVxuXHQuLi4gMTcgbW9yZVxuXG5jb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS5GYXVsdDogSW1tdXRhYmxlRXJyb3JEZWZpbml0aW9ue2Jhc2U9VE9PX01BTllfUkVRVUVTVFMsIGNhdGVnb3J5PVFVT1RBX0VSUk9SLCBjYXVzZT1udWxsLCBkZWJ1Z0luZm89Y29tLmdvb2dsZS5uZXQucnBjMy5ScGNFeGNlcHRpb246IGNsb3VkLmJpZ3N0b3JlLlJlc3BvbnNlQ29kZS5FcnJvckNvZGU6OlBST0pFQ1RfQlVDS0VUX09QX1JBVEVfVE9PX0hJR0g6IERlbGV0aW5nIGJ1Y2tldHMgdG9vIHF1aWNrbHksIHBsZWFzZSBzbG93IGRvd25cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udG9ScGMzRXhjZXB0aW9uKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MTM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmJ1Y2tldHMuRGVsZXRlQnVja2V0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChEZWxldGVCdWNrZXQuamF2YTo3MSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5idWNrZXRzLkRlbGV0ZUJ1Y2tldC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoRGVsZXRlQnVja2V0LmphdmE6MjMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5CdWNrZXRzRGVsZWdhdG9yLmRlbGV0ZShCdWNrZXRzRGVsZWdhdG9yLmphdmE6MTE1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5ScGNSZWNlaXZlci5sYW1iZGEkcHJvY2Vzc1JlcXVlc3RBc3luYyQ0KFJwY1JlY2VpdmVyLmphdmE6MjAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5Bc3luY0V4ZWN1dG9yLmxhbWJkYSRzdWJtaXQkMChBc3luY0V4ZWN1dG9yLmphdmE6MjcyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoQ29udGV4dFJ1bm5hYmxlLmphdmE6NTApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlJDEucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM5KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo3Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5FeGVjdXRvcnMkUnVubmFibGVBZGFwdGVyLmNhbGwoRXhlY3V0b3JzLmphdmE6NTExKVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5GdXR1cmVUYXNrLnJ1bihGdXR1cmVUYXNrLmphdmE6MjY2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IucnVuV29ya2VyKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjExNDkpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvciRXb3JrZXIucnVuKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjYyNClcblx0YXQgamF2YS5sYW5nLlRocmVhZC5ydW4oVGhyZWFkLmphdmE6NzQ4KVxuQ2F1c2VkIGJ5OiBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbjogRGVsZXRpbmcgYnVja2V0cyB0b28gcXVpY2tseSwgcGxlYXNlIHNsb3cgZG93blxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxNyBtb3JlXG4sIGRvbWFpbj11c2FnZUxpbWl0cywgZXh0ZW5kZWRIZWxwPW51bGwsIGh0dHBIZWFkZXJzPXt9LCBodHRwU3RhdHVzPXRvb01hbnlSZXF1ZXN0cywgaW50ZXJuYWxSZWFzb249UmVhc29ue2FyZ3VtZW50cz17fSwgY2F1c2U9bnVsbCwgY29kZT1jbG91ZC5iaWdzdG9yZS5hcGkuQmlnc3RvcmVFcnJvckRvbWFpbi5DTElFTlRfUVVPVEFfRVhDRUVERUQsIGNyZWF0ZWRCeUJhY2tlbmQ9dHJ1ZSwgZGVidWdNZXNzYWdlPWNvbS5nb29nbGUubmV0LnJwYzMuUnBjRXhjZXB0aW9uOiBjbG91ZC5iaWdzdG9yZS5SZXNwb25zZUNvZGUuRXJyb3JDb2RlOjpQUk9KRUNUX0JVQ0tFVF9PUF9SQVRFX1RPT19ISUdIOiBEZWxldGluZyBidWNrZXRzIHRvbyBxdWlja2x5LCBwbGVhc2Ugc2xvdyBkb3duXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRvUnBjM0V4Y2VwdGlvbihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjEzNSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5idWNrZXRzLkRlbGV0ZUJ1Y2tldC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoRGVsZXRlQnVja2V0LmphdmE6NzEpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYnVja2V0cy5EZWxldGVCdWNrZXQuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKERlbGV0ZUJ1Y2tldC5qYXZhOjIzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmZyYW1ld29yay5SZXF1ZXN0SGFuZGxlci5oYW5kbGUoUmVxdWVzdEhhbmRsZXIuamF2YToyOTQpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uQnVja2V0c0RlbGVnYXRvci5kZWxldGUoQnVja2V0c0RlbGVnYXRvci5qYXZhOjExNSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uUnBjUmVjZWl2ZXIubGFtYmRhJHByb2Nlc3NSZXF1ZXN0QXN5bmMkNChScGNSZWNlaXZlci5qYXZhOjIwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uQXN5bmNFeGVjdXRvci5sYW1iZGEkc3VibWl0JDAoQXN5bmNFeGVjdXRvci5qYXZhOjI3Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KENvbnRleHRSdW5uYWJsZS5qYXZhOjUwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZSQxLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozOSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NzIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozNilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRXhlY3V0b3JzJFJ1bm5hYmxlQWRhcHRlci5jYWxsKEV4ZWN1dG9ycy5qYXZhOjUxMSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRnV0dXJlVGFzay5ydW4oRnV0dXJlVGFzay5qYXZhOjI2Nilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yLnJ1bldvcmtlcihUaHJlYWRQb29sRXhlY3V0b3IuamF2YToxMTQ5KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IkV29ya2VyLnJ1bihUaHJlYWRQb29sRXhlY3V0b3IuamF2YTo2MjQpXG5cdGF0IGphdmEubGFuZy5UaHJlYWQucnVuKFRocmVhZC5qYXZhOjc0OClcbkNhdXNlZCBieTogY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb246IERlbGV0aW5nIGJ1Y2tldHMgdG9vIHF1aWNrbHksIHBsZWFzZSBzbG93IGRvd25cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MjkwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAxKVxuXHQuLi4gMTcgbW9yZVxuLCBlcnJvclByb3RvQ29kZT1DTElFTlRfUVVPVEFfRVhDRUVERUQsIGVycm9yUHJvdG9Eb21haW49Y2xvdWQuYmlnc3RvcmUuYXBpLkJpZ3N0b3JlRXJyb3JEb21haW4sIGZpbHRlcmVkTWVzc2FnZT1udWxsLCBsb2NhdGlvbj1lbnRpdHkucmVzb3VyY2VfaWQubmFtZSwgbWVzc2FnZT1UaGUgcHJvamVjdCBleGNlZWRlZCB0aGUgcmF0ZSBsaW1pdCBmb3IgY3JlYXRpbmcgYW5kIGRlbGV0aW5nIGJ1Y2tldHMuLCB1bm5hbWVkQXJndW1lbnRzPVtdfSwgbG9jYXRpb249ZW50aXR5LnJlc291cmNlX2lkLm5hbWUsIG1lc3NhZ2U9VGhlIHByb2plY3QgZXhjZWVkZWQgdGhlIHJhdGUgbGltaXQgZm9yIGNyZWF0aW5nIGFuZCBkZWxldGluZyBidWNrZXRzLiwgcmVhc29uPXJhdGVMaW1pdEV4Y2VlZGVkLCBycGNDb2RlPTQyOX0gVGhlIHByb2plY3QgZXhjZWVkZWQgdGhlIHJhdGUgbGltaXQgZm9yIGNyZWF0aW5nIGFuZCBkZWxldGluZyBidWNrZXRzLjogY29tLmdvb2dsZS5uZXQucnBjMy5ScGNFeGNlcHRpb246IGNsb3VkLmJpZ3N0b3JlLlJlc3BvbnNlQ29kZS5FcnJvckNvZGU6OlBST0pFQ1RfQlVDS0VUX09QX1JBVEVfVE9PX0hJR0g6IERlbGV0aW5nIGJ1Y2tldHMgdG9vIHF1aWNrbHksIHBsZWFzZSBzbG93IGRvd25cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udG9ScGMzRXhjZXB0aW9uKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MTM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmJ1Y2tldHMuRGVsZXRlQnVja2V0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChEZWxldGVCdWNrZXQuamF2YTo3MSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5idWNrZXRzLkRlbGV0ZUJ1Y2tldC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoRGVsZXRlQnVja2V0LmphdmE6MjMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5CdWNrZXRzRGVsZWdhdG9yLmRlbGV0ZShCdWNrZXRzRGVsZWdhdG9yLmphdmE6MTE1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5ScGNSZWNlaXZlci5sYW1iZGEkcHJvY2Vzc1JlcXVlc3RBc3luYyQ0KFJwY1JlY2VpdmVyLmphdmE6MjAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5Bc3luY0V4ZWN1dG9yLmxhbWJkYSRzdWJtaXQkMChBc3luY0V4ZWN1dG9yLmphdmE6MjcyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoQ29udGV4dFJ1bm5hYmxlLmphdmE6NTApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlJDEucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM5KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo3Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5FeGVjdXRvcnMkUnVubmFibGVBZGFwdGVyLmNhbGwoRXhlY3V0b3JzLmphdmE6NTExKVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5GdXR1cmVUYXNrLnJ1bihGdXR1cmVUYXNrLmphdmE6MjY2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IucnVuV29ya2VyKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjExNDkpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvciRXb3JrZXIucnVuKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjYyNClcblx0YXQgamF2YS5sYW5nLlRocmVhZC5ydW4oVGhyZWFkLmphdmE6NzQ4KVxuQ2F1c2VkIGJ5OiBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbjogRGVsZXRpbmcgYnVja2V0cyB0b28gcXVpY2tseSwgcGxlYXNlIHNsb3cgZG93blxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxNyBtb3JlXG5cblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUuRXJyb3JDb2xsZWN0b3IudG9GYXVsdChFcnJvckNvbGxlY3Rvci5qYXZhOjU0KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIucmVzdC5hZGFwdGVyLnJvc3kuUm9zeUVycm9yQ29udmVydGVyLnRvRmF1bHQoUm9zeUVycm9yQ29udmVydGVyLmphdmE6NjcpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5yZXN0LmFkYXB0ZXIucm9zeS5Sb3N5SGFuZGxlciQyLmNhbGwoUm9zeUhhbmRsZXIuamF2YToyNTgpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5yZXN0LmFkYXB0ZXIucm9zeS5Sb3N5SGFuZGxlciQyLmNhbGwoUm9zeUhhbmRsZXIuamF2YToyMzgpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLnV0aWwuQ2FsbGFibGVGdXR1cmUucnVuKENhbGxhYmxlRnV0dXJlLmphdmE6NjIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5EaXJlY3RFeGVjdXRvci5leGVjdXRlKERpcmVjdEV4ZWN1dG9yLmphdmE6MzApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5leGVjdXRlTGlzdGVuZXIoQWJzdHJhY3RGdXR1cmUuamF2YToxMTQzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuY29tcGxldGUoQWJzdHJhY3RGdXR1cmUuamF2YTo5NjMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5zZXQoQWJzdHJhY3RGdXR1cmUuamF2YTo3MzEpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLnV0aWwuQ2FsbGFibGVGdXR1cmUucnVuKENhbGxhYmxlRnV0dXJlLmphdmE6NjIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5EaXJlY3RFeGVjdXRvci5leGVjdXRlKERpcmVjdEV4ZWN1dG9yLmphdmE6MzApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5leGVjdXRlTGlzdGVuZXIoQWJzdHJhY3RGdXR1cmUuamF2YToxMTQzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuY29tcGxldGUoQWJzdHJhY3RGdXR1cmUuamF2YTo5NjMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5zZXQoQWJzdHJhY3RGdXR1cmUuamF2YTo3MzEpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLnV0aWwuQ2FsbGFibGVGdXR1cmUucnVuKENhbGxhYmxlRnV0dXJlLmphdmE6NjIpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci50aHJlYWQuVGhyZWFkVHJhY2tlcnMkVGhyZWFkVHJhY2tpbmdSdW5uYWJsZS5ydW4oVGhyZWFkVHJhY2tlcnMuamF2YToxMjYpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkVHJhY2VDb250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KFRyYWNlQ29udGV4dC5qYXZhOjQ1NSlcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnNlcnZlci5Db21tb25Nb2R1bGUkQ29udGV4dENhcnJ5aW5nRXhlY3V0b3JTZXJ2aWNlJDEucnVuSW5Db250ZXh0KENvbW1vbk1vZHVsZS5qYXZhOjg0Nilcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRUcmFjZUNvbnRleHRSdW5uYWJsZSQxLnJ1bihUcmFjZUNvbnRleHQuamF2YTo0NjIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkQWJzdHJhY3RUcmFjZUNvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKFRyYWNlQ29udGV4dC5qYXZhOjMyMSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRBYnN0cmFjdFRyYWNlQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChUcmFjZUNvbnRleHQuamF2YTozMTMpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkVHJhY2VDb250ZXh0UnVubmFibGUucnVuKFRyYWNlQ29udGV4dC5qYXZhOjQ1OSlcblx0YXQgY29tLmdvb2dsZS5nc2UuaW50ZXJuYWwuRGlzcGF0Y2hRdWV1ZUltcGwkV29ya2VyVGhyZWFkLnJ1bihEaXNwYXRjaFF1ZXVlSW1wbC5qYXZhOjQwMylcbiJ9XSwiY29kZSI6NDI5LCJtZXNzYWdlIjoiVGhlIHByb2plY3QgZXhjZWVkZWQgdGhlIHJhdGUgbGltaXQgZm9yIGNyZWF0aW5nIGFuZCBkZWxldGluZyBidWNrZXRzLiJ9fQ=="
+ }
+ },
+ {
+ "ID": "2ebbcc95335f4f93",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0010?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "0c824b79369ca5b0582093808bcfc251/5763898544205833613;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0010?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 429,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0"
+ ],
+ "Content-Length": [
+ "12085"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:49 GMT"
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:25:49 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051446000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrp62:4379,/bns/yv/borg/yv/bns/blobstore2/bitpusher/357.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=TcysW7_eK5CDgQS0t7uoDw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/357.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/357:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWWhLRWRJS21GUEgxdEtyUnZ6LTVHcEpFV2I3OTF6d2FCanpvT0REdnVuTmhHVVBINWJHX1BHc1ljQ2JIS0hpR1QtR1ZSOHdaTlZqMFJQdml6U2NZUnRQUWg3QkdWU1UzbXNkXzNJSERFRUFoQVVXU3ZQZHNMSmZocVBubWZlZUgtb3pCMEtxQ3hFRTBob2FQbTRqQmlvMXVidF9WSlVuZmVvcl9sZkhCLTMxWkpsNENCQ1dIRXVRQ1EwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Upload-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UrregfVY1sg5Sp_yURvbA5_SFSGMdDtgIbhnq8lhUf0vZbfw7xFwy8ew6Z2q7pHEKyfkuLasT2ZtE7GUr7X6j8CPGtb_g"
+ ]
+ },
+ "Body": "eyJlcnJvciI6eyJlcnJvcnMiOlt7ImRvbWFpbiI6InVzYWdlTGltaXRzIiwicmVhc29uIjoicmF0ZUxpbWl0RXhjZWVkZWQiLCJtZXNzYWdlIjoiVGhlIHByb2plY3QgZXhjZWVkZWQgdGhlIHJhdGUgbGltaXQgZm9yIGNyZWF0aW5nIGFuZCBkZWxldGluZyBidWNrZXRzLiIsImRlYnVnSW5mbyI6ImNvbS5nb29nbGUubmV0LnJwYzMuUnBjRXhjZXB0aW9uOiBjbG91ZC5iaWdzdG9yZS5SZXNwb25zZUNvZGUuRXJyb3JDb2RlOjpQUk9KRUNUX0JVQ0tFVF9PUF9SQVRFX1RPT19ISUdIOiBEZWxldGluZyBidWNrZXRzIHRvbyBxdWlja2x5LCBwbGVhc2Ugc2xvdyBkb3duXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRvUnBjM0V4Y2VwdGlvbihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjEzNSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5idWNrZXRzLkRlbGV0ZUJ1Y2tldC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoRGVsZXRlQnVja2V0LmphdmE6NzEpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYnVja2V0cy5EZWxldGVCdWNrZXQuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKERlbGV0ZUJ1Y2tldC5qYXZhOjIzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmZyYW1ld29yay5SZXF1ZXN0SGFuZGxlci5oYW5kbGUoUmVxdWVzdEhhbmRsZXIuamF2YToyOTQpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uQnVja2V0c0RlbGVnYXRvci5kZWxldGUoQnVja2V0c0RlbGVnYXRvci5qYXZhOjExNSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uUnBjUmVjZWl2ZXIubGFtYmRhJHByb2Nlc3NSZXF1ZXN0QXN5bmMkNChScGNSZWNlaXZlci5qYXZhOjIwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uQXN5bmNFeGVjdXRvci5sYW1iZGEkc3VibWl0JDAoQXN5bmNFeGVjdXRvci5qYXZhOjI3Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KENvbnRleHRSdW5uYWJsZS5qYXZhOjUwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZSQxLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozOSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NzIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozNilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRXhlY3V0b3JzJFJ1bm5hYmxlQWRhcHRlci5jYWxsKEV4ZWN1dG9ycy5qYXZhOjUxMSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRnV0dXJlVGFzay5ydW4oRnV0dXJlVGFzay5qYXZhOjI2Nilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yLnJ1bldvcmtlcihUaHJlYWRQb29sRXhlY3V0b3IuamF2YToxMTQ5KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IkV29ya2VyLnJ1bihUaHJlYWRQb29sRXhlY3V0b3IuamF2YTo2MjQpXG5cdGF0IGphdmEubGFuZy5UaHJlYWQucnVuKFRocmVhZC5qYXZhOjc0OClcbkNhdXNlZCBieTogY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb246IERlbGV0aW5nIGJ1Y2tldHMgdG9vIHF1aWNrbHksIHBsZWFzZSBzbG93IGRvd25cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MjkwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAxKVxuXHQuLi4gMTcgbW9yZVxuXG5jb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS5GYXVsdDogSW1tdXRhYmxlRXJyb3JEZWZpbml0aW9ue2Jhc2U9VE9PX01BTllfUkVRVUVTVFMsIGNhdGVnb3J5PVFVT1RBX0VSUk9SLCBjYXVzZT1udWxsLCBkZWJ1Z0luZm89Y29tLmdvb2dsZS5uZXQucnBjMy5ScGNFeGNlcHRpb246IGNsb3VkLmJpZ3N0b3JlLlJlc3BvbnNlQ29kZS5FcnJvckNvZGU6OlBST0pFQ1RfQlVDS0VUX09QX1JBVEVfVE9PX0hJR0g6IERlbGV0aW5nIGJ1Y2tldHMgdG9vIHF1aWNrbHksIHBsZWFzZSBzbG93IGRvd25cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udG9ScGMzRXhjZXB0aW9uKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MTM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmJ1Y2tldHMuRGVsZXRlQnVja2V0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChEZWxldGVCdWNrZXQuamF2YTo3MSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5idWNrZXRzLkRlbGV0ZUJ1Y2tldC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoRGVsZXRlQnVja2V0LmphdmE6MjMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5CdWNrZXRzRGVsZWdhdG9yLmRlbGV0ZShCdWNrZXRzRGVsZWdhdG9yLmphdmE6MTE1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5ScGNSZWNlaXZlci5sYW1iZGEkcHJvY2Vzc1JlcXVlc3RBc3luYyQ0KFJwY1JlY2VpdmVyLmphdmE6MjAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5Bc3luY0V4ZWN1dG9yLmxhbWJkYSRzdWJtaXQkMChBc3luY0V4ZWN1dG9yLmphdmE6MjcyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoQ29udGV4dFJ1bm5hYmxlLmphdmE6NTApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlJDEucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM5KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo3Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5FeGVjdXRvcnMkUnVubmFibGVBZGFwdGVyLmNhbGwoRXhlY3V0b3JzLmphdmE6NTExKVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5GdXR1cmVUYXNrLnJ1bihGdXR1cmVUYXNrLmphdmE6MjY2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IucnVuV29ya2VyKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjExNDkpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvciRXb3JrZXIucnVuKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjYyNClcblx0YXQgamF2YS5sYW5nLlRocmVhZC5ydW4oVGhyZWFkLmphdmE6NzQ4KVxuQ2F1c2VkIGJ5OiBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbjogRGVsZXRpbmcgYnVja2V0cyB0b28gcXVpY2tseSwgcGxlYXNlIHNsb3cgZG93blxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxNyBtb3JlXG4sIGRvbWFpbj11c2FnZUxpbWl0cywgZXh0ZW5kZWRIZWxwPW51bGwsIGh0dHBIZWFkZXJzPXt9LCBodHRwU3RhdHVzPXRvb01hbnlSZXF1ZXN0cywgaW50ZXJuYWxSZWFzb249UmVhc29ue2FyZ3VtZW50cz17fSwgY2F1c2U9bnVsbCwgY29kZT1jbG91ZC5iaWdzdG9yZS5hcGkuQmlnc3RvcmVFcnJvckRvbWFpbi5DTElFTlRfUVVPVEFfRVhDRUVERUQsIGNyZWF0ZWRCeUJhY2tlbmQ9dHJ1ZSwgZGVidWdNZXNzYWdlPWNvbS5nb29nbGUubmV0LnJwYzMuUnBjRXhjZXB0aW9uOiBjbG91ZC5iaWdzdG9yZS5SZXNwb25zZUNvZGUuRXJyb3JDb2RlOjpQUk9KRUNUX0JVQ0tFVF9PUF9SQVRFX1RPT19ISUdIOiBEZWxldGluZyBidWNrZXRzIHRvbyBxdWlja2x5LCBwbGVhc2Ugc2xvdyBkb3duXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRvUnBjM0V4Y2VwdGlvbihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjEzNSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5idWNrZXRzLkRlbGV0ZUJ1Y2tldC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoRGVsZXRlQnVja2V0LmphdmE6NzEpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYnVja2V0cy5EZWxldGVCdWNrZXQuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKERlbGV0ZUJ1Y2tldC5qYXZhOjIzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmZyYW1ld29yay5SZXF1ZXN0SGFuZGxlci5oYW5kbGUoUmVxdWVzdEhhbmRsZXIuamF2YToyOTQpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uQnVja2V0c0RlbGVnYXRvci5kZWxldGUoQnVja2V0c0RlbGVnYXRvci5qYXZhOjExNSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uUnBjUmVjZWl2ZXIubGFtYmRhJHByb2Nlc3NSZXF1ZXN0QXN5bmMkNChScGNSZWNlaXZlci5qYXZhOjIwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uQXN5bmNFeGVjdXRvci5sYW1iZGEkc3VibWl0JDAoQXN5bmNFeGVjdXRvci5qYXZhOjI3Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KENvbnRleHRSdW5uYWJsZS5qYXZhOjUwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZSQxLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozOSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NzIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozNilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRXhlY3V0b3JzJFJ1bm5hYmxlQWRhcHRlci5jYWxsKEV4ZWN1dG9ycy5qYXZhOjUxMSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRnV0dXJlVGFzay5ydW4oRnV0dXJlVGFzay5qYXZhOjI2Nilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yLnJ1bldvcmtlcihUaHJlYWRQb29sRXhlY3V0b3IuamF2YToxMTQ5KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IkV29ya2VyLnJ1bihUaHJlYWRQb29sRXhlY3V0b3IuamF2YTo2MjQpXG5cdGF0IGphdmEubGFuZy5UaHJlYWQucnVuKFRocmVhZC5qYXZhOjc0OClcbkNhdXNlZCBieTogY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb246IERlbGV0aW5nIGJ1Y2tldHMgdG9vIHF1aWNrbHksIHBsZWFzZSBzbG93IGRvd25cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MjkwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAxKVxuXHQuLi4gMTcgbW9yZVxuLCBlcnJvclByb3RvQ29kZT1DTElFTlRfUVVPVEFfRVhDRUVERUQsIGVycm9yUHJvdG9Eb21haW49Y2xvdWQuYmlnc3RvcmUuYXBpLkJpZ3N0b3JlRXJyb3JEb21haW4sIGZpbHRlcmVkTWVzc2FnZT1udWxsLCBsb2NhdGlvbj1lbnRpdHkucmVzb3VyY2VfaWQubmFtZSwgbWVzc2FnZT1UaGUgcHJvamVjdCBleGNlZWRlZCB0aGUgcmF0ZSBsaW1pdCBmb3IgY3JlYXRpbmcgYW5kIGRlbGV0aW5nIGJ1Y2tldHMuLCB1bm5hbWVkQXJndW1lbnRzPVtdfSwgbG9jYXRpb249ZW50aXR5LnJlc291cmNlX2lkLm5hbWUsIG1lc3NhZ2U9VGhlIHByb2plY3QgZXhjZWVkZWQgdGhlIHJhdGUgbGltaXQgZm9yIGNyZWF0aW5nIGFuZCBkZWxldGluZyBidWNrZXRzLiwgcmVhc29uPXJhdGVMaW1pdEV4Y2VlZGVkLCBycGNDb2RlPTQyOX0gVGhlIHByb2plY3QgZXhjZWVkZWQgdGhlIHJhdGUgbGltaXQgZm9yIGNyZWF0aW5nIGFuZCBkZWxldGluZyBidWNrZXRzLjogY29tLmdvb2dsZS5uZXQucnBjMy5ScGNFeGNlcHRpb246IGNsb3VkLmJpZ3N0b3JlLlJlc3BvbnNlQ29kZS5FcnJvckNvZGU6OlBST0pFQ1RfQlVDS0VUX09QX1JBVEVfVE9PX0hJR0g6IERlbGV0aW5nIGJ1Y2tldHMgdG9vIHF1aWNrbHksIHBsZWFzZSBzbG93IGRvd25cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udG9ScGMzRXhjZXB0aW9uKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MTM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmJ1Y2tldHMuRGVsZXRlQnVja2V0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChEZWxldGVCdWNrZXQuamF2YTo3MSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5idWNrZXRzLkRlbGV0ZUJ1Y2tldC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoRGVsZXRlQnVja2V0LmphdmE6MjMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5CdWNrZXRzRGVsZWdhdG9yLmRlbGV0ZShCdWNrZXRzRGVsZWdhdG9yLmphdmE6MTE1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5ScGNSZWNlaXZlci5sYW1iZGEkcHJvY2Vzc1JlcXVlc3RBc3luYyQ0KFJwY1JlY2VpdmVyLmphdmE6MjAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5Bc3luY0V4ZWN1dG9yLmxhbWJkYSRzdWJtaXQkMChBc3luY0V4ZWN1dG9yLmphdmE6MjcyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoQ29udGV4dFJ1bm5hYmxlLmphdmE6NTApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlJDEucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM5KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo3Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5FeGVjdXRvcnMkUnVubmFibGVBZGFwdGVyLmNhbGwoRXhlY3V0b3JzLmphdmE6NTExKVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5GdXR1cmVUYXNrLnJ1bihGdXR1cmVUYXNrLmphdmE6MjY2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IucnVuV29ya2VyKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjExNDkpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvciRXb3JrZXIucnVuKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjYyNClcblx0YXQgamF2YS5sYW5nLlRocmVhZC5ydW4oVGhyZWFkLmphdmE6NzQ4KVxuQ2F1c2VkIGJ5OiBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbjogRGVsZXRpbmcgYnVja2V0cyB0b28gcXVpY2tseSwgcGxlYXNlIHNsb3cgZG93blxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxNyBtb3JlXG5cblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUuRXJyb3JDb2xsZWN0b3IudG9GYXVsdChFcnJvckNvbGxlY3Rvci5qYXZhOjU0KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIucmVzdC5hZGFwdGVyLnJvc3kuUm9zeUVycm9yQ29udmVydGVyLnRvRmF1bHQoUm9zeUVycm9yQ29udmVydGVyLmphdmE6NjcpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5yZXN0LmFkYXB0ZXIucm9zeS5Sb3N5SGFuZGxlciQyLmNhbGwoUm9zeUhhbmRsZXIuamF2YToyNTgpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5yZXN0LmFkYXB0ZXIucm9zeS5Sb3N5SGFuZGxlciQyLmNhbGwoUm9zeUhhbmRsZXIuamF2YToyMzgpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLnV0aWwuQ2FsbGFibGVGdXR1cmUucnVuKENhbGxhYmxlRnV0dXJlLmphdmE6NjIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5EaXJlY3RFeGVjdXRvci5leGVjdXRlKERpcmVjdEV4ZWN1dG9yLmphdmE6MzApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5leGVjdXRlTGlzdGVuZXIoQWJzdHJhY3RGdXR1cmUuamF2YToxMTQzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuY29tcGxldGUoQWJzdHJhY3RGdXR1cmUuamF2YTo5NjMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5zZXQoQWJzdHJhY3RGdXR1cmUuamF2YTo3MzEpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLnV0aWwuQ2FsbGFibGVGdXR1cmUucnVuKENhbGxhYmxlRnV0dXJlLmphdmE6NjIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5EaXJlY3RFeGVjdXRvci5leGVjdXRlKERpcmVjdEV4ZWN1dG9yLmphdmE6MzApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5leGVjdXRlTGlzdGVuZXIoQWJzdHJhY3RGdXR1cmUuamF2YToxMTQzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuY29tcGxldGUoQWJzdHJhY3RGdXR1cmUuamF2YTo5NjMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5zZXQoQWJzdHJhY3RGdXR1cmUuamF2YTo3MzEpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLnV0aWwuQ2FsbGFibGVGdXR1cmUucnVuKENhbGxhYmxlRnV0dXJlLmphdmE6NjIpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci50aHJlYWQuVGhyZWFkVHJhY2tlcnMkVGhyZWFkVHJhY2tpbmdSdW5uYWJsZS5ydW4oVGhyZWFkVHJhY2tlcnMuamF2YToxMjYpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkVHJhY2VDb250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KFRyYWNlQ29udGV4dC5qYXZhOjQ1NSlcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnNlcnZlci5Db21tb25Nb2R1bGUkQ29udGV4dENhcnJ5aW5nRXhlY3V0b3JTZXJ2aWNlJDEucnVuSW5Db250ZXh0KENvbW1vbk1vZHVsZS5qYXZhOjg0Nilcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRUcmFjZUNvbnRleHRSdW5uYWJsZSQxLnJ1bihUcmFjZUNvbnRleHQuamF2YTo0NjIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkQWJzdHJhY3RUcmFjZUNvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKFRyYWNlQ29udGV4dC5qYXZhOjMyMSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRBYnN0cmFjdFRyYWNlQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChUcmFjZUNvbnRleHQuamF2YTozMTMpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkVHJhY2VDb250ZXh0UnVubmFibGUucnVuKFRyYWNlQ29udGV4dC5qYXZhOjQ1OSlcblx0YXQgY29tLmdvb2dsZS5nc2UuaW50ZXJuYWwuRGlzcGF0Y2hRdWV1ZUltcGwkV29ya2VyVGhyZWFkLnJ1bihEaXNwYXRjaFF1ZXVlSW1wbC5qYXZhOjQwMylcbiJ9XSwiY29kZSI6NDI5LCJtZXNzYWdlIjoiVGhlIHByb2plY3QgZXhjZWVkZWQgdGhlIHJhdGUgbGltaXQgZm9yIGNyZWF0aW5nIGFuZCBkZWxldGluZyBidWNrZXRzLiJ9fQ=="
+ }
+ },
+ {
+ "ID": "3edc73005530733b",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0010?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "0c824b79369ca5b0582093808bcfc251/6522935513627031772;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0010?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 204,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "0"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:53 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051445000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vntt133:4318,/bns/yw/borg/yw/bns/blobstore2/bitpusher/157.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=UMysW7elKYLnN5zigqgK"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yw/borg/yw/bns/blobstore2/bitpusher/157.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yw/borg/yw/bns/blobstore2/bitpusher/157:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWWhLRWRJS21GUEgxdEtyUnZ6LTVHcEpFV2I3OTF6d2FCanpvT0REdnVuTmhHVVBINWJHX1BHc1ljQ2JIS0hpR1QtR1ZSOHdaTlZqMFJQdml6U2NZUnRQUWg3QkdWU1UzbXNkXzNJSERFRUFoQVVXU3ZQZHNMSmZocVBubWZlZUgtb3pCMEtxQ3hFRTBob2FQbTRqQmlvMXVidF9WSlVuZmVvcl9sZkhCLTMxWkpsNENCQ1dIRXVRQ1EwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UocdzltEwu8I8TD_NoAYID4E9DjuZ0ms_uu-qjIUWzE5LhuXYKS0lxfzfKyBPrns-r3ZIMU10abKbPF0wAd25p04JqFXw"
+ ]
+ },
+ "Body": ""
+ }
+ },
+ {
+ "ID": "16fa5da19588dcb2",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/storage/v1/b?alt=json\u0026prettyPrint=false\u0026project=dulcet-port-762",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "103"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "f223250479f9326d3120a77d446cfcc0/8113347417694182779;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b?alt=json\u0026prettyPrint=false\u0026project=dulcet-port-762"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJuYW1lIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDExIiwicmV0ZW50aW9uUG9saWN5Ijp7InJldGVudGlvblBlcmlvZCI6IjYwIn19Cg=="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "512"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:53 GMT"
+ ],
+ "Etag": [
+ "CAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051453000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vri14:4058,/bns/yr/borg/yr/bns/blobstore2/bitpusher/56.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=UcysW8mmEIu-4QSu3Jz4Aw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/56.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/56:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWkdVeUFHMkhLRHc5UlRMb3BORW9Rb2xrMjQ2NGItSkRZcnRkVjRCV21pUlNvVVY2Q2w3WTlJTk1FZWFKY2FnRlFZc0ZHcVpmbU84dUgxMG5aYl9IWnIzTkhKMFJOQjJEUWhEVnlMQ0JaaVNlQlJHZUhtWDlpRGN2OE9iaEppdVBmbG93Y3NEbWtObF9lSzRaVUNrVmd4Nm5QRmhJak1JSUtKYkpLbnBqN2pCMEkwcnE2TmxKRlAtWmswBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UrobIhiXco9A_-oMp2VoLDQLC5201S_4RyjRRZxpMTx2Zv8ZQIy5Nit2onYj9_d72nRNL9xdxtJRI-TI2FXlJEbhkAzwg"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxMSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxMSIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTEiLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjU6NTMuNzY5WiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI1OjUzLjc2OVoiLCJtZXRhZ2VuZXJhdGlvbiI6IjEiLCJsb2NhdGlvbiI6IlVTIiwicmV0ZW50aW9uUG9saWN5Ijp7InJldGVudGlvblBlcmlvZCI6IjYwIiwiZWZmZWN0aXZlVGltZSI6IjIwMTgtMDktMjdUMTI6MjU6NTMuNzY5WiJ9LCJzdG9yYWdlQ2xhc3MiOiJTVEFOREFSRCIsImV0YWciOiJDQUU9In0="
+ }
+ },
+ {
+ "ID": "fde3f1916684ed66",
+ "Request": {
+ "Method": "PATCH",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0011?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "47"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "0d879cc229c3bee2bb0b0a9783868213/9703759321744556826;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0011?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJyZXRlbnRpb25Qb2xpY3kiOnsicmV0ZW50aW9uUGVyaW9kIjoiMzYwMCJ9fQo="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "2441"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:55 GMT"
+ ],
+ "Etag": [
+ "CAI="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051454000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vnno9:4384,/bns/yw/borg/yw/bns/blobstore2/bitpusher/150.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=UcysW-6JOsPJhASY15bgDQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yw/borg/yw/bns/blobstore2/bitpusher/150.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yw/borg/yw/bns/blobstore2/bitpusher/150:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATpxChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4CtK4wESxgF5YTI5LmMuRW93QkpRWkdVeUFHMkhLRHc5UlRMb3BORW9Rb2xrMjQ2NGItSkRZcnRkVjRCV21pUlNvVVY2Q2w3WTlJTk1FZWFKY2FnRlFZc0ZHcVpmbU84dUgxMG5aYl9IWnIzTkhKMFJOQjJEUWhEVnlMQ0JaaVNlQlJHZUhtWDlpRGN2OE9iaEppdVBmbG93Y3NEbWtObF9lSzRaVUNrVmd4Nm5QRmhJak1JSUtKYkpLbnBqN2pCMEkwcnE2TmxKRlAtWmswBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UqgSqPtAP9ja5GplqzD5idak2DxVIHfikqXTwLl-RQfR82NbOjWTMMCHClKja8qnc59jKReVtM0g_SaSDptgLgpVxWGOg"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxMSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxMSIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTEiLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjU6NTMuNzY5WiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI1OjU1LjIzOVoiLCJtZXRhZ2VuZXJhdGlvbiI6IjIiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxMS9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxMS9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTEiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBST0ifSx7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxMS9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTEvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxMSIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDQUk9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTEvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDExL2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTEiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNBST0ifV0sImRlZmF1bHRPYmplY3RBY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBST0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0FJPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0FJPSJ9XSwib3duZXIiOnsiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUifSwibG9jYXRpb24iOiJVUyIsInJldGVudGlvblBvbGljeSI6eyJyZXRlbnRpb25QZXJpb2QiOiIzNjAwIiwiZWZmZWN0aXZlVGltZSI6IjIwMTgtMDktMjdUMTI6MjU6NTMuNzY5WiJ9LCJzdG9yYWdlQ2xhc3MiOiJTVEFOREFSRCIsImV0YWciOiJDQUk9In0="
+ }
+ },
+ {
+ "ID": "8a91697bbe3e6511",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0011?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "6db55bdaeee6d1b5348ac0cb62d8c887/11294171221516871864;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0011?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0, must-revalidate, no-transform"
+ ],
+ "Content-Length": [
+ "2441"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:55 GMT"
+ ],
+ "Etag": [
+ "CAI="
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:25:55 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051453000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vnz126:4460,/bns/yx/borg/yx/bns/blobstore2/bitpusher/39.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=U8ysW63uHMbUzwLGrZrQAw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yx/borg/yx/bns/blobstore2/bitpusher/39.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yx/borg/yx/bns/blobstore2/bitpusher/39:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRWkdVeUFHMkhLRHc5UlRMb3BORW9Rb2xrMjQ2NGItSkRZcnRkVjRCV21pUlNvVVY2Q2w3WTlJTk1FZWFKY2FnRlFZc0ZHcVpmbU84dUgxMG5aYl9IWnIzTkhKMFJOQjJEUWhEVnlMQ0JaaVNlQlJHZUhtWDlpRGN2OE9iaEppdVBmbG93Y3NEbWtObF9lSzRaVUNrVmd4Nm5QRmhJak1JSUtKYkpLbnBqN2pCMEkwcnE2TmxKRlAtWmswBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UqjdbmLX5yJrLPaS36C6KBnXWtkd3J95Z_ftw6bzTcSkCNgUwj3IpOgLOOTh5eH2ltPmePXC_XyuZZsyce_xjfVTGXMmQ"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxMSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxMSIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTEiLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjU6NTMuNzY5WiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI1OjU1LjIzOVoiLCJtZXRhZ2VuZXJhdGlvbiI6IjIiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxMS9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxMS9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTEiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBST0ifSx7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxMS9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTEvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxMSIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDQUk9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTEvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDExL2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTEiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNBST0ifV0sImRlZmF1bHRPYmplY3RBY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBST0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0FJPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0FJPSJ9XSwib3duZXIiOnsiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUifSwibG9jYXRpb24iOiJVUyIsInJldGVudGlvblBvbGljeSI6eyJyZXRlbnRpb25QZXJpb2QiOiIzNjAwIiwiZWZmZWN0aXZlVGltZSI6IjIwMTgtMDktMjdUMTI6MjU6NTMuNzY5WiJ9LCJzdG9yYWdlQ2xhc3MiOiJTVEFOREFSRCIsImV0YWciOiJDQUk9In0="
+ }
+ },
+ {
+ "ID": "9bbed24b50a1eaa1",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/storage/v1/b?alt=json\u0026prettyPrint=false\u0026project=dulcet-port-762",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "103"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "802d3dc20f903c593a444cdd814956c7/12884300555390651991;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b?alt=json\u0026prettyPrint=false\u0026project=dulcet-port-762"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJuYW1lIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDEyIiwicmV0ZW50aW9uUG9saWN5Ijp7InJldGVudGlvblBlcmlvZCI6IjYwIn19Cg=="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "512"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:56 GMT"
+ ],
+ "Etag": [
+ "CAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051453000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vruw21:4201,/bns/yv/borg/yv/bns/blobstore2/bitpusher/50.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=U8ysW5q4MpHLswb4lL2QAw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/50.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/50:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWkdVeUFHMkhLRHc5UlRMb3BORW9Rb2xrMjQ2NGItSkRZcnRkVjRCV21pUlNvVVY2Q2w3WTlJTk1FZWFKY2FnRlFZc0ZHcVpmbU84dUgxMG5aYl9IWnIzTkhKMFJOQjJEUWhEVnlMQ0JaaVNlQlJHZUhtWDlpRGN2OE9iaEppdVBmbG93Y3NEbWtObF9lSzRaVUNrVmd4Nm5QRmhJak1JSUtKYkpLbnBqN2pCMEkwcnE2TmxKRlAtWmswBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UoXG9bPCZjg8Y-JYI_mKdqxDfcvxy1T1PEOnEOwqO3hTQsieNFGouIFTCWTs_WPwVLYtb44oe_VICNWurm3S0GPUXvizw"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxMiIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxMiIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTIiLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjU6NTYuMzg0WiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI1OjU2LjM4NFoiLCJtZXRhZ2VuZXJhdGlvbiI6IjEiLCJsb2NhdGlvbiI6IlVTIiwicmV0ZW50aW9uUG9saWN5Ijp7InJldGVudGlvblBlcmlvZCI6IjYwIiwiZWZmZWN0aXZlVGltZSI6IjIwMTgtMDktMjdUMTI6MjU6NTYuMzg0WiJ9LCJzdG9yYWdlQ2xhc3MiOiJTVEFOREFSRCIsImV0YWciOiJDQUU9In0="
+ }
+ },
+ {
+ "ID": "f1c21ab6b25294f4",
+ "Request": {
+ "Method": "PATCH",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0012?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "47"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "4048de951dc5ccf83e71e2ffdece3a3e/14474712459457803254;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0012?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJyZXRlbnRpb25Qb2xpY3kiOnsicmV0ZW50aW9uUGVyaW9kIjoiMzYwMCJ9fQo="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "2441"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:58 GMT"
+ ],
+ "Etag": [
+ "CAI="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051454000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vnlf2:4485,/bns/yx/borg/yx/bns/blobstore2/bitpusher/94.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=VMysW6uqJcngzgL4h4rADw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yx/borg/yx/bns/blobstore2/bitpusher/94.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yx/borg/yx/bns/blobstore2/bitpusher/94:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATpxChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4CtK4wESxgF5YTI5LmMuRW93QkpRWkdVeUFHMkhLRHc5UlRMb3BORW9Rb2xrMjQ2NGItSkRZcnRkVjRCV21pUlNvVVY2Q2w3WTlJTk1FZWFKY2FnRlFZc0ZHcVpmbU84dUgxMG5aYl9IWnIzTkhKMFJOQjJEUWhEVnlMQ0JaaVNlQlJHZUhtWDlpRGN2OE9iaEppdVBmbG93Y3NEbWtObF9lSzRaVUNrVmd4Nm5QRmhJak1JSUtKYkpLbnBqN2pCMEkwcnE2TmxKRlAtWmswBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UoMFwI7mcS4cWtpbLK42cpnqw0kSanMUXAFgllAzXYjMAP7pqhOjWKPzKeGP889Mcw9U3Y-M7fNZ0e7QNmm7i_4IaLWvQ"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxMiIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxMiIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTIiLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjU6NTYuMzg0WiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI1OjU4LjI1N1oiLCJtZXRhZ2VuZXJhdGlvbiI6IjIiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxMi9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxMi9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTIiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBST0ifSx7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxMi9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTIvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxMiIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDQUk9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTIvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDEyL2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTIiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNBST0ifV0sImRlZmF1bHRPYmplY3RBY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBST0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0FJPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0FJPSJ9XSwib3duZXIiOnsiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUifSwibG9jYXRpb24iOiJVUyIsInJldGVudGlvblBvbGljeSI6eyJyZXRlbnRpb25QZXJpb2QiOiIzNjAwIiwiZWZmZWN0aXZlVGltZSI6IjIwMTgtMDktMjdUMTI6MjU6NTYuMzg0WiJ9LCJzdG9yYWdlQ2xhc3MiOiJTVEFOREFSRCIsImV0YWciOiJDQUk9In0="
+ }
+ },
+ {
+ "ID": "6f5d255f0d88f21b",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0012?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "1c795c1024bc55ef42d27faffed977f3/16065124363508242836;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0012?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0, must-revalidate, no-transform"
+ ],
+ "Content-Length": [
+ "2441"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:58 GMT"
+ ],
+ "Etag": [
+ "CAI="
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:25:58 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051458000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrbq123:4158,/bns/yv/borg/yv/bns/blobstore2/bitpusher/295.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=VsysW6TRHIjeggTPoo6QAg"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/295.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/295:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRWkdVeUFHMkhLRHc5UlRMb3BORW9Rb2xrMjQ2NGItSkRZcnRkVjRCV21pUlNvVVY2Q2w3WTlJTk1FZWFKY2FnRlFZc0ZHcVpmbU84dUgxMG5aYl9IWnIzTkhKMFJOQjJEUWhEVnlMQ0JaaVNlQlJHZUhtWDlpRGN2OE9iaEppdVBmbG93Y3NEbWtObF9lSzRaVUNrVmd4Nm5QRmhJak1JSUtKYkpLbnBqN2pCMEkwcnE2TmxKRlAtWmswBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UoPL5yIP9ZEqMYOFdRS_FrN6uAVgJDcH82ZdNWFTiRzrpzphlRzFY7M7_qfGxNAhJodJCRNpjkt0TmohT1V5v8okMD72A"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxMiIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxMiIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTIiLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjU6NTYuMzg0WiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI1OjU4LjI1N1oiLCJtZXRhZ2VuZXJhdGlvbiI6IjIiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxMi9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxMi9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTIiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBST0ifSx7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxMi9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTIvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxMiIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDQUk9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTIvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDEyL2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTIiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNBST0ifV0sImRlZmF1bHRPYmplY3RBY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBST0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0FJPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0FJPSJ9XSwib3duZXIiOnsiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUifSwibG9jYXRpb24iOiJVUyIsInJldGVudGlvblBvbGljeSI6eyJyZXRlbnRpb25QZXJpb2QiOiIzNjAwIiwiZWZmZWN0aXZlVGltZSI6IjIwMTgtMDktMjdUMTI6MjU6NTYuMzg0WiJ9LCJzdG9yYWdlQ2xhc3MiOiJTVEFOREFSRCIsImV0YWciOiJDQUk9In0="
+ }
+ },
+ {
+ "ID": "4b64fc29d8731a8f",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/storage/v1/b?alt=json\u0026prettyPrint=false\u0026project=dulcet-port-762",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "103"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "64bbece284f2952cd259b93aee5a9e73/17583198298072448563;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b?alt=json\u0026prettyPrint=false\u0026project=dulcet-port-762"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJuYW1lIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDEzIiwicmV0ZW50aW9uUG9saWN5Ijp7InJldGVudGlvblBlcmlvZCI6IjYwIn19Cg=="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "512"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:25:59 GMT"
+ ],
+ "Etag": [
+ "CAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051453000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vryy20:4108,/bns/yv/borg/yv/bns/blobstore2/bitpusher/37.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=VsysW_SiNsz5gASdporABw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/37.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/37:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWkdVeUFHMkhLRHc5UlRMb3BORW9Rb2xrMjQ2NGItSkRZcnRkVjRCV21pUlNvVVY2Q2w3WTlJTk1FZWFKY2FnRlFZc0ZHcVpmbU84dUgxMG5aYl9IWnIzTkhKMFJOQjJEUWhEVnlMQ0JaaVNlQlJHZUhtWDlpRGN2OE9iaEppdVBmbG93Y3NEbWtObF9lSzRaVUNrVmd4Nm5QRmhJak1JSUtKYkpLbnBqN2pCMEkwcnE2TmxKRlAtWmswBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UpqMbhbjEYwtx_QsZjoA3HbE40bhjEQzZU2TbptRTES7Bq3MHuojyXP0eKhY3Y9VCIhn8spjA4y4fSsdshX9umGMl1fe2uK8yNasoLTBPqcv6DyUuE"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxMyIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxMyIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTMiLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjU6NTkuNTA4WiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI1OjU5LjUwOFoiLCJtZXRhZ2VuZXJhdGlvbiI6IjEiLCJsb2NhdGlvbiI6IlVTIiwicmV0ZW50aW9uUG9saWN5Ijp7InJldGVudGlvblBlcmlvZCI6IjYwIiwiZWZmZWN0aXZlVGltZSI6IjIwMTgtMDktMjdUMTI6MjU6NTkuNTA4WiJ9LCJzdG9yYWdlQ2xhc3MiOiJTVEFOREFSRCIsImV0YWciOiJDQUU9In0="
+ }
+ },
+ {
+ "ID": "496195d1abcde418",
+ "Request": {
+ "Method": "PATCH",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0013?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "25"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "697aa538323c65d1011f2f6844cd5763/727147603389981906;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0013?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJyZXRlbnRpb25Qb2xpY3kiOm51bGx9Cg=="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "2353"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:01 GMT"
+ ],
+ "Etag": [
+ "CAI="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051454000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vnew15:4140,/bns/yx/borg/yx/bns/blobstore2/bitpusher/83.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=V8ysW8rRLsW1zALZhJywDw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yx/borg/yx/bns/blobstore2/bitpusher/83.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yx/borg/yx/bns/blobstore2/bitpusher/83:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATpxChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4CtK4wESxgF5YTI5LmMuRW93QkpRWkdVeUFHMkhLRHc5UlRMb3BORW9Rb2xrMjQ2NGItSkRZcnRkVjRCV21pUlNvVVY2Q2w3WTlJTk1FZWFKY2FnRlFZc0ZHcVpmbU84dUgxMG5aYl9IWnIzTkhKMFJOQjJEUWhEVnlMQ0JaaVNlQlJHZUhtWDlpRGN2OE9iaEppdVBmbG93Y3NEbWtObF9lSzRaVUNrVmd4Nm5QRmhJak1JSUtKYkpLbnBqN2pCMEkwcnE2TmxKRlAtWmswBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UrbY7boJBe2XoPiqZsTc01Uxq6nqiB2OXZBh1o6oSng7jBQL9mpCi5qkBcck0oI_DAJTDbBjDuflfdVXyA2hLXAl70_FA"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxMyIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxMyIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTMiLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjU6NTkuNTA4WiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI2OjAwLjgyM1oiLCJtZXRhZ2VuZXJhdGlvbiI6IjIiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxMy9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxMy9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTMiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBST0ifSx7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxMy9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTMvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxMyIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDQUk9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTMvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDEzL2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTMiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNBST0ifV0sImRlZmF1bHRPYmplY3RBY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBST0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0FJPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0FJPSJ9XSwib3duZXIiOnsiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUifSwibG9jYXRpb24iOiJVUyIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwiZXRhZyI6IkNBST0ifQ=="
+ }
+ },
+ {
+ "ID": "0b8bf573cd2107c4",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0013?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "d9d2b7dcaa66aaabfa2864d56c5d3a72/2317558407962347888;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0013?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0, must-revalidate, no-transform"
+ ],
+ "Content-Length": [
+ "2353"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:01 GMT"
+ ],
+ "Etag": [
+ "CAI="
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:26:01 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051453000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vnhu9:4289,/bns/yx/borg/yx/bns/blobstore2/bitpusher/102.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=WcysW4T4AszpzgLY0KnIDg"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yx/borg/yx/bns/blobstore2/bitpusher/102.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yx/borg/yx/bns/blobstore2/bitpusher/102:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRWkdVeUFHMkhLRHc5UlRMb3BORW9Rb2xrMjQ2NGItSkRZcnRkVjRCV21pUlNvVVY2Q2w3WTlJTk1FZWFKY2FnRlFZc0ZHcVpmbU84dUgxMG5aYl9IWnIzTkhKMFJOQjJEUWhEVnlMQ0JaaVNlQlJHZUhtWDlpRGN2OE9iaEppdVBmbG93Y3NEbWtObF9lSzRaVUNrVmd4Nm5QRmhJak1JSUtKYkpLbnBqN2pCMEkwcnE2TmxKRlAtWmswBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UrbRCrtu0mTZRDhZrFXk7VrictqM0zKI1U8DoFpKO28cynd5QzxKB5J7XCMWYbXrJca3OalA-IIX45CGsetEVGp4qZISg"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxMyIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxMyIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTMiLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjU6NTkuNTA4WiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI2OjAwLjgyM1oiLCJtZXRhZ2VuZXJhdGlvbiI6IjIiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxMy9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxMy9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTMiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBST0ifSx7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxMy9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTMvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxMyIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDQUk9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTMvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDEzL2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTMiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNBST0ifV0sImRlZmF1bHRPYmplY3RBY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBST0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0FJPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0FJPSJ9XSwib3duZXIiOnsiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUifSwibG9jYXRpb24iOiJVUyIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwiZXRhZyI6IkNBST0ifQ=="
+ }
+ },
+ {
+ "ID": "a7c95422a2471394",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/storage/v1/b?alt=json\u0026prettyPrint=false\u0026project=dulcet-port-762",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "103"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "0e89c35a6de9f58ec66d48975c54b4f9/3907970307717820175;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b?alt=json\u0026prettyPrint=false\u0026project=dulcet-port-762"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJuYW1lIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDE0IiwicmV0ZW50aW9uUG9saWN5Ijp7InJldGVudGlvblBlcmlvZCI6IjYwIn19Cg=="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "512"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:02 GMT"
+ ],
+ "Etag": [
+ "CAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051453000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrdh9:4228,/bns/yv/borg/yv/bns/blobstore2/bitpusher/304.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=WcysW63cGcSqgQSHvaiACQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/304.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/304:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWkdVeUFHMkhLRHc5UlRMb3BORW9Rb2xrMjQ2NGItSkRZcnRkVjRCV21pUlNvVVY2Q2w3WTlJTk1FZWFKY2FnRlFZc0ZHcVpmbU84dUgxMG5aYl9IWnIzTkhKMFJOQjJEUWhEVnlMQ0JaaVNlQlJHZUhtWDlpRGN2OE9iaEppdVBmbG93Y3NEbWtObF9lSzRaVUNrVmd4Nm5QRmhJak1JSUtKYkpLbnBqN2pCMEkwcnE2TmxKRlAtWmswBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UpP8VkKvEDcF-JqT0gT3fvzqoizXGbFNONJWx8R5oaqlSM0Q0uc5ken0aSOiix0NPrauvWu1QRiwbreckiadEfVgtHnVg"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxNCIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxNCIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTQiLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjY6MDEuODgxWiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI2OjAxLjg4MVoiLCJtZXRhZ2VuZXJhdGlvbiI6IjEiLCJsb2NhdGlvbiI6IlVTIiwicmV0ZW50aW9uUG9saWN5Ijp7InJldGVudGlvblBlcmlvZCI6IjYwIiwiZWZmZWN0aXZlVGltZSI6IjIwMTgtMDktMjdUMTI6MjY6MDEuODgxWiJ9LCJzdG9yYWdlQ2xhc3MiOiJTVEFOREFSRCIsImV0YWciOiJDQUU9In0="
+ }
+ },
+ {
+ "ID": "325d0ff065c04d4e",
+ "Request": {
+ "Method": "PATCH",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0014?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "25"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "51fd4d8c082df8e4d506278eb1ca823b/5498100741103228078;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0014?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJyZXRlbnRpb25Qb2xpY3kiOm51bGx9Cg=="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "2353"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:03 GMT"
+ ],
+ "Etag": [
+ "CAI="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051462000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrba123:4470,/bns/yv/borg/yv/bns/blobstore2/bitpusher/259.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=WsysW7KWC8mngASFkp7wAw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/259.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/259:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATpxChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4CtK4wESxgF5YTI5LmMuRW93QkpRWkdVeUFHMkhLRHc5UlRMb3BORW9Rb2xrMjQ2NGItSkRZcnRkVjRCV21pUlNvVVY2Q2w3WTlJTk1FZWFKY2FnRlFZc0ZHcVpmbU84dUgxMG5aYl9IWnIzTkhKMFJOQjJEUWhEVnlMQ0JaaVNlQlJHZUhtWDlpRGN2OE9iaEppdVBmbG93Y3NEbWtObF9lSzRaVUNrVmd4Nm5QRmhJak1JSUtKYkpLbnBqN2pCMEkwcnE2TmxKRlAtWmswBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UqJUrTAXY29C_wmpxbjt01tQ4m9VTBeUypKlJzX15UwDuSJe5hsBBynDQsl5a16PpiVFdBz0u-Vf-X5ZRRt209TtmIHKw"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxNCIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxNCIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTQiLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjY6MDEuODgxWiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI2OjAzLjUyMFoiLCJtZXRhZ2VuZXJhdGlvbiI6IjIiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxNC9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxNC9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTQiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBST0ifSx7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxNC9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTQvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxNCIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDQUk9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTQvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDE0L2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTQiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNBST0ifV0sImRlZmF1bHRPYmplY3RBY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBST0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0FJPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0FJPSJ9XSwib3duZXIiOnsiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUifSwibG9jYXRpb24iOiJVUyIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwiZXRhZyI6IkNBST0ifQ=="
+ }
+ },
+ {
+ "ID": "cca326efdc436d37",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0014?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "4ab7fb4514357f83b302152b924fb136/7088512645153667660;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0014?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0, must-revalidate, no-transform"
+ ],
+ "Content-Length": [
+ "2353"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:03 GMT"
+ ],
+ "Etag": [
+ "CAI="
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:26:03 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051458000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrnn4:4418,/bns/yv/borg/yv/bns/blobstore2/bitpusher/270.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=W8ysW5i6LIykNvW7uMAB"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/270.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/270:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRWkdVeUFHMkhLRHc5UlRMb3BORW9Rb2xrMjQ2NGItSkRZcnRkVjRCV21pUlNvVVY2Q2w3WTlJTk1FZWFKY2FnRlFZc0ZHcVpmbU84dUgxMG5aYl9IWnIzTkhKMFJOQjJEUWhEVnlMQ0JaaVNlQlJHZUhtWDlpRGN2OE9iaEppdVBmbG93Y3NEbWtObF9lSzRaVUNrVmd4Nm5QRmhJak1JSUtKYkpLbnBqN2pCMEkwcnE2TmxKRlAtWmswBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UpbKUoJzMFO7uO-VveC3KwrCtOcCOHRDrLKCkq-DsuFXnTJrCWiiMgqfkbFYrmOP-ubGDpLSrMWmRKLmSXBxP8Gry44mA"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxNCIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxNCIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTQiLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjY6MDEuODgxWiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI2OjAzLjUyMFoiLCJtZXRhZ2VuZXJhdGlvbiI6IjIiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxNC9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxNC9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTQiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBST0ifSx7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxNC9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTQvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxNCIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDQUk9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTQvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDE0L2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTQiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNBST0ifV0sImRlZmF1bHRPYmplY3RBY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBST0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0FJPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0FJPSJ9XSwib3duZXIiOnsiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUifSwibG9jYXRpb24iOiJVUyIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwiZXRhZyI6IkNBST0ifQ=="
+ }
+ },
+ {
+ "ID": "63c01600827f77b3",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/storage/v1/b?alt=json\u0026prettyPrint=false\u0026project=dulcet-port-762",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "103"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "c9bb61a9fd1b4ae9f5981ca5df957f93/8678924544925917163;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b?alt=json\u0026prettyPrint=false\u0026project=dulcet-port-762"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJuYW1lIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDE1IiwicmV0ZW50aW9uUG9saWN5Ijp7InJldGVudGlvblBlcmlvZCI6IjYwIn19Cg=="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "512"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:04 GMT"
+ ],
+ "Etag": [
+ "CAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051453000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrud24:4012,/bns/yv/borg/yv/bns/blobstore2/bitpusher/387.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=XMysW89vy6KCBKOFl_AD"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/387.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/387:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWkdVeUFHMkhLRHc5UlRMb3BORW9Rb2xrMjQ2NGItSkRZcnRkVjRCV21pUlNvVVY2Q2w3WTlJTk1FZWFKY2FnRlFZc0ZHcVpmbU84dUgxMG5aYl9IWnIzTkhKMFJOQjJEUWhEVnlMQ0JaaVNlQlJHZUhtWDlpRGN2OE9iaEppdVBmbG93Y3NEbWtObF9lSzRaVUNrVmd4Nm5QRmhJak1JSUtKYkpLbnBqN2pCMEkwcnE2TmxKRlAtWmswBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UrUsJUBq_XX9ztZulVTMu3salJ5JDRcpfmZ0mmdN70LnnzyOiN2Y8ICZBiw2LZ5ahaPBX2P3IaVz8keKoWCNgAX7TenNA"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxNSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxNSIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTUiLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjY6MDQuNDU0WiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI2OjA0LjQ1NFoiLCJtZXRhZ2VuZXJhdGlvbiI6IjEiLCJsb2NhdGlvbiI6IlVTIiwicmV0ZW50aW9uUG9saWN5Ijp7InJldGVudGlvblBlcmlvZCI6IjYwIiwiZWZmZWN0aXZlVGltZSI6IjIwMTgtMDktMjdUMTI6MjY6MDQuNDU0WiJ9LCJzdG9yYWdlQ2xhc3MiOiJTVEFOREFSRCIsImV0YWciOiJDQUU9In0="
+ }
+ },
+ {
+ "ID": "768bc98442297830",
+ "Request": {
+ "Method": "PATCH",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0015?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "3"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "71269e6dd6eb30c6c2d4b40e6b4d950f/10269053878799697290;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0015?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "e30K"
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "2439"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:06 GMT"
+ ],
+ "Etag": [
+ "CAI="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051462000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrni16:4226,/bns/yv/borg/yv/bns/blobstore2/bitpusher/221.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=XMysW-W9LM_kgwSjmoe4DQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/221.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/221:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATpxChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4CtK4wESxgF5YTI5LmMuRW93QkpRWkdVeUFHMkhLRHc5UlRMb3BORW9Rb2xrMjQ2NGItSkRZcnRkVjRCV21pUlNvVVY2Q2w3WTlJTk1FZWFKY2FnRlFZc0ZHcVpmbU84dUgxMG5aYl9IWnIzTkhKMFJOQjJEUWhEVnlMQ0JaaVNlQlJHZUhtWDlpRGN2OE9iaEppdVBmbG93Y3NEbWtObF9lSzRaVUNrVmd4Nm5QRmhJak1JSUtKYkpLbnBqN2pCMEkwcnE2TmxKRlAtWmswBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Uox4G0BhHPrZfc-b4hSe5pLsjUItbWWUixSn0GyQ5oUgO_Pp74soedZ0zi0uAJ23USfmwKxzzrdNmWS5mGPrSA7xMDoWg"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxNSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxNSIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTUiLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjY6MDQuNDU0WiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI2OjA2LjAzM1oiLCJtZXRhZ2VuZXJhdGlvbiI6IjIiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxNS9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxNS9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTUiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBST0ifSx7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxNS9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTUvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxNSIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDQUk9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTUvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDE1L2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTUiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNBST0ifV0sImRlZmF1bHRPYmplY3RBY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBST0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0FJPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0FJPSJ9XSwib3duZXIiOnsiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUifSwibG9jYXRpb24iOiJVUyIsInJldGVudGlvblBvbGljeSI6eyJyZXRlbnRpb25QZXJpb2QiOiI2MCIsImVmZmVjdGl2ZVRpbWUiOiIyMDE4LTA5LTI3VDEyOjI2OjA0LjQ1NFoifSwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJldGFnIjoiQ0FJPSJ9"
+ }
+ },
+ {
+ "ID": "cdd3f2848c873bb4",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0015?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "c16176bddcc21b2c6d2882ce5fd06ae1/11859465782866913832;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0015?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0, must-revalidate, no-transform"
+ ],
+ "Content-Length": [
+ "2439"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:06 GMT"
+ ],
+ "Etag": [
+ "CAI="
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:26:06 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051458000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrqs12:4337,/bns/yw/borg/yw/bns/blobstore2/bitpusher/196.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=XsysW8nRDtayN7DNhPAN"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yw/borg/yw/bns/blobstore2/bitpusher/196.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yw/borg/yw/bns/blobstore2/bitpusher/196:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRWkdVeUFHMkhLRHc5UlRMb3BORW9Rb2xrMjQ2NGItSkRZcnRkVjRCV21pUlNvVVY2Q2w3WTlJTk1FZWFKY2FnRlFZc0ZHcVpmbU84dUgxMG5aYl9IWnIzTkhKMFJOQjJEUWhEVnlMQ0JaaVNlQlJHZUhtWDlpRGN2OE9iaEppdVBmbG93Y3NEbWtObF9lSzRaVUNrVmd4Nm5QRmhJak1JSUtKYkpLbnBqN2pCMEkwcnE2TmxKRlAtWmswBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Uov7rSAsXMYIGR6Ss96xbFjQgp0NIncfsGrPyYJrNeooyiPImTTAN4_Bc7mxhhFQAajgNguI2PRkTggi9Gg2ILtEGzpXg"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxNSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxNSIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTUiLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjY6MDQuNDU0WiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI2OjA2LjAzM1oiLCJtZXRhZ2VuZXJhdGlvbiI6IjIiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxNS9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxNS9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTUiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBST0ifSx7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxNS9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTUvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxNSIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDQUk9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTUvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDE1L2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTUiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNBST0ifV0sImRlZmF1bHRPYmplY3RBY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBST0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0FJPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0FJPSJ9XSwib3duZXIiOnsiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUifSwibG9jYXRpb24iOiJVUyIsInJldGVudGlvblBvbGljeSI6eyJyZXRlbnRpb25QZXJpb2QiOiI2MCIsImVmZmVjdGl2ZVRpbWUiOiIyMDE4LTA5LTI3VDEyOjI2OjA0LjQ1NFoifSwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJldGFnIjoiQ0FJPSJ9"
+ }
+ },
+ {
+ "ID": "186f1f73a6d920af",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0015?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "455235aa4f1ed37b4bb469c1d623fc80/13449877686917288135;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0015?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 204,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "0"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:07 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051466000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vnf65:4298,/bns/yx/borg/yx/bns/blobstore2/bitpusher/73.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=XsysW8DKJce6zwLWnrjACQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yx/borg/yx/bns/blobstore2/bitpusher/73.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yx/borg/yx/bns/blobstore2/bitpusher/73:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWkdVeUFHMkhLRHc5UlRMb3BORW9Rb2xrMjQ2NGItSkRZcnRkVjRCV21pUlNvVVY2Q2w3WTlJTk1FZWFKY2FnRlFZc0ZHcVpmbU84dUgxMG5aYl9IWnIzTkhKMFJOQjJEUWhEVnlMQ0JaaVNlQlJHZUhtWDlpRGN2OE9iaEppdVBmbG93Y3NEbWtObF9lSzRaVUNrVmd4Nm5QRmhJak1JSUtKYkpLbnBqN2pCMEkwcnE2TmxKRlAtWmswBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UrUvGh7bHpgmVxRKfm-xKQepbBeSGbWt50TgXOFRbNlv_XSDoVmBBQYQXpkmZw0TUnXHNvfkDQnr9mVvq1aWtZ4ug8lsA"
+ ]
+ },
+ "Body": ""
+ }
+ },
+ {
+ "ID": "dfd8fbe545d7bee6",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0014?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "07a05ef320720f3b509ec54f162283bb/15040289586689602917;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0014?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 204,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "0"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:07 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051453000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrqi15:4037,/bns/yr/borg/yr/bns/blobstore2/bitpusher/28.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=X8ysW9iWBKiWkATJhbDgBQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/28.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/28:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWkdVeUFHMkhLRHc5UlRMb3BORW9Rb2xrMjQ2NGItSkRZcnRkVjRCV21pUlNvVVY2Q2w3WTlJTk1FZWFKY2FnRlFZc0ZHcVpmbU84dUgxMG5aYl9IWnIzTkhKMFJOQjJEUWhEVnlMQ0JaaVNlQlJHZUhtWDlpRGN2OE9iaEppdVBmbG93Y3NEbWtObF9lSzRaVUNrVmd4Nm5QRmhJak1JSUtKYkpLbnBqN2pCMEkwcnE2TmxKRlAtWmswBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UobaiYoUYiX5ZJvU-OYpl1FY5F9nfQiJXeWBYxdo-WvOnvz5aVbrblbXtwUnAzgH0UyM3mc2drAZddD0clThFqqJP61Gw"
+ ]
+ },
+ "Body": ""
+ }
+ },
+ {
+ "ID": "012e95579c6845fb",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0013?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "dbcd5340924fe39a15e8e32ab27745fe/16630420020058233604;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0013?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 204,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "0"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:07 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051453000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrfw24:4041,/bns/yr/borg/yr/bns/blobstore2/bitpusher/53.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=X8ysW4fcHcX4kAOu3LKIDg"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/53.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/53:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWkdVeUFHMkhLRHc5UlRMb3BORW9Rb2xrMjQ2NGItSkRZcnRkVjRCV21pUlNvVVY2Q2w3WTlJTk1FZWFKY2FnRlFZc0ZHcVpmbU84dUgxMG5aYl9IWnIzTkhKMFJOQjJEUWhEVnlMQ0JaaVNlQlJHZUhtWDlpRGN2OE9iaEppdVBmbG93Y3NEbWtObF9lSzRaVUNrVmd4Nm5QRmhJak1JSUtKYkpLbnBqN2pCMEkwcnE2TmxKRlAtWmswBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UoSbsEMlGkIsvaXr6x6MfACr66APL8lwZSivf3_cryiFk4Vt_8ap4MIFxSDS0CMex25ggALxCfJNIKispqIj9qd5FgM-A"
+ ]
+ },
+ "Body": ""
+ }
+ },
+ {
+ "ID": "62966b136cf0b529",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0012?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "07fa936444fbf30801717d2d264883c6/18220830824630534307;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0012?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 204,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "0"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:08 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051453000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrt3:4124,/bns/yr/borg/yr/bns/blobstore2/bitpusher/96.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=X8ysW__bOsihkATs_LGgCw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/96.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/96:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWkdVeUFHMkhLRHc5UlRMb3BORW9Rb2xrMjQ2NGItSkRZcnRkVjRCV21pUlNvVVY2Q2w3WTlJTk1FZWFKY2FnRlFZc0ZHcVpmbU84dUgxMG5aYl9IWnIzTkhKMFJOQjJEUWhEVnlMQ0JaaVNlQlJHZUhtWDlpRGN2OE9iaEppdVBmbG93Y3NEbWtObF9lSzRaVUNrVmd4Nm5QRmhJak1JSUtKYkpLbnBqN2pCMEkwcnE2TmxKRlAtWmswBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Uqy0RkP5XEsHo3lOvqW35li0Pw0z3juzlb9FvypLY_302_58O6U-mg6Vjn-cJpHJSjkmbIjP8-g5V1n-2CZ9S3yvkbq_g"
+ ]
+ },
+ "Body": ""
+ }
+ },
+ {
+ "ID": "308931080dfea4b9",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0011?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "81a10a84360b6edf4533bd4f550bb0d0/1364780125653231169;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0011?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 204,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "0"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:08 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051453000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrjl65:4261,/bns/yv/borg/yv/bns/blobstore2/bitpusher/211.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=YMysW_22G8fWgwSThbvoBw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/211.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/211:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWkdVeUFHMkhLRHc5UlRMb3BORW9Rb2xrMjQ2NGItSkRZcnRkVjRCV21pUlNvVVY2Q2w3WTlJTk1FZWFKY2FnRlFZc0ZHcVpmbU84dUgxMG5aYl9IWnIzTkhKMFJOQjJEUWhEVnlMQ0JaaVNlQlJHZUhtWDlpRGN2OE9iaEppdVBmbG93Y3NEbWtObF9lSzRaVUNrVmd4Nm5QRmhJak1JSUtKYkpLbnBqN2pCMEkwcnE2TmxKRlAtWmswBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UqIieaMhbydFRqWbKPS5MmBE4LNbvLVhM6e9eGRbbgl0_hso2ahTxY4gWLqyahE89LsT91qfndHkp9Fzq-5NPhltIEdrA"
+ ]
+ },
+ "Body": ""
+ }
+ },
+ {
+ "ID": "d1beb37dcd83aa6a",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/storage/v1/b?alt=json\u0026prettyPrint=false\u0026project=dulcet-port-762",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "106"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "64af50f9fd3c73200370a81b5f0883c8/2883135535194082272;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b?alt=json\u0026prettyPrint=false\u0026project=dulcet-port-762"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJuYW1lIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDE2IiwicmV0ZW50aW9uUG9saWN5Ijp7InJldGVudGlvblBlcmlvZCI6IjkwMDAwIn19Cg=="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "515"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:09 GMT"
+ ],
+ "Etag": [
+ "CAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051468000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrlq86:4154,/bns/yv/borg/yv/bns/blobstore2/bitpusher/301.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=YMysW5HAOMaPgQTXw4nIBw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/301.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/301:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRYTVGNmlfNzNkdVJhUVRFQXNzZUdCeEdGWld0bm9pVHl0TGhyNW1FY0hyQTF4eDJEXzNxS2cwUGxYVTJhZC1kOHl3dE9jMUVrNzZmVXdFU2J1TlpoVE9NWThoaEhzNlRjUTl1dHRwNHZZRmJBODdBX05uZ1BwNWIxRHdNR1NQUXV2XzdySWxFZjFtQTVRRUMyZThES1VqcHotcmFtNFJMc01MR2x0aVdrTFQzNlNXLVNZMFhjVlpFVG8wBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Urvb0freP0GJIhCc7eyV_aUlJDKx3W0kq2q99OI4-jWaBAzkU-aGnP6QsWrmOiP-EMxe0DtGBtgqrud-qgZepmxpx3PNw"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxNiIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxNiIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTYiLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjY6MDkuNDg3WiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI2OjA5LjQ4N1oiLCJtZXRhZ2VuZXJhdGlvbiI6IjEiLCJsb2NhdGlvbiI6IlVTIiwicmV0ZW50aW9uUG9saWN5Ijp7InJldGVudGlvblBlcmlvZCI6IjkwMDAwIiwiZWZmZWN0aXZlVGltZSI6IjIwMTgtMDktMjdUMTI6MjY6MDkuNDg3WiJ9LCJzdG9yYWdlQ2xhc3MiOiJTVEFOREFSRCIsImV0YWciOiJDQUU9In0="
+ }
+ },
+ {
+ "ID": "5a146f91846e2f4b",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0016/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Type": [
+ "multipart/related; boundary=4a385c57e7c68fe2d07ad9d19a8e1f50a9b104c1e57d1387629dc32ad0d9"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "9c6200e4526c02cb8c8b5c77883e179c/3714228999141580335;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0016/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "LS00YTM4NWM1N2U3YzY4ZmUyZDA3YWQ5ZDE5YThlMWY1MGE5YjEwNGMxZTU3ZDEzODc2MjlkYzMyYWQwZDkNCkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vanNvbg0KDQp7ImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxNiIsImNhY2hlQ29udHJvbCI6InB1YmxpYywgbWF4LWFnZT02MCIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbiIsIm5hbWUiOiJzb21lLW9iamVjdCJ9Cg0KLS00YTM4NWM1N2U3YzY4ZmUyZDA3YWQ5ZDE5YThlMWY1MGE5YjEwNGMxZTU3ZDEzODc2MjlkYzMyYWQwZDkNCkNvbnRlbnQtVHlwZTogdGV4dC9wbGFpbg0KDQpoZWxsbyB3b3JsZA0KLS00YTM4NWM1N2U3YzY4ZmUyZDA3YWQ5ZDE5YThlMWY1MGE5YjEwNGMxZTU3ZDEzODc2MjlkYzMyYWQwZDktLQ0K"
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3408"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:10 GMT"
+ ],
+ "Etag": [
+ "CLajk42X290CEAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051468000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrt186:4143,/bns/yr/borg/yr/bns/blobstore2/bitpusher/63.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=YcysW47OMJKQkATCvaHwDg"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/63.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/63:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRYTVGNmlfNzNkdVJhUVRFQXNzZUdCeEdGWld0bm9pVHl0TGhyNW1FY0hyQTF4eDJEXzNxS2cwUGxYVTJhZC1kOHl3dE9jMUVrNzZmVXdFU2J1TlpoVE9NWThoaEhzNlRjUTl1dHRwNHZZRmJBODdBX05uZ1BwNWIxRHdNR1NQUXV2XzdySWxFZjFtQTVRRUMyZThES1VqcHotcmFtNFJMc01MR2x0aVdrTFQzNlNXLVNZMFhjVlpFVG8wBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_single_post_uploads"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Uq0lNITSEEX9MB17Og399j1oxQXjkF757LQ9dGaEIJ--anuY0cz52Whpi7vpIyV9kVIH-zuGiEZgxw-UCK-JEjurFLsOQ"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxNi9zb21lLW9iamVjdC8xNTM4MDUxMTcwMTYxMDc4Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDE2L28vc29tZS1vYmplY3QiLCJuYW1lIjoic29tZS1vYmplY3QiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTYiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE3MDE2MTA3OCIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbiIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNjoxMC4xNjBaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjY6MTAuMTYwWiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI2OjEwLjE2MFoiLCJzaXplIjoiMTEiLCJtZDVIYXNoIjoiWHJZN3UrQWU3dENUeXlLN2oxck53dz09IiwibWVkaWFMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vZG93bmxvYWQvc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxNi9vL3NvbWUtb2JqZWN0P2dlbmVyYXRpb249MTUzODA1MTE3MDE2MTA3OCZhbHQ9bWVkaWEiLCJjYWNoZUNvbnRyb2wiOiJwdWJsaWMsIG1heC1hZ2U9NjAiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxNi9zb21lLW9iamVjdC8xNTM4MDUxMTcwMTYxMDc4L3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDE2L28vc29tZS1vYmplY3QvYWNsL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDE2Iiwib2JqZWN0Ijoic29tZS1vYmplY3QiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE3MDE2MTA3OCIsImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6Im93bmVycyJ9LCJldGFnIjoiQ0xhams0MlgyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDE2L3NvbWUtb2JqZWN0LzE1MzgwNTExNzAxNjEwNzgvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDE2L28vc29tZS1vYmplY3QvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxNiIsIm9iamVjdCI6InNvbWUtb2JqZWN0IiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTExNzAxNjEwNzgiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0xhams0MlgyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDE2L3NvbWUtb2JqZWN0LzE1MzgwNTExNzAxNjEwNzgvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDE2L28vc29tZS1vYmplY3QvYWNsL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxNiIsIm9iamVjdCI6InNvbWUtb2JqZWN0IiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTExNzAxNjEwNzgiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNMYWprNDJYMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxNi9zb21lLW9iamVjdC8xNTM4MDUxMTcwMTYxMDc4L3VzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTYvby9zb21lLW9iamVjdC9hY2wvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxNiIsIm9iamVjdCI6InNvbWUtb2JqZWN0IiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTExNzAxNjEwNzgiLCJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwicm9sZSI6Ik9XTkVSIiwiZW1haWwiOiIzNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImV0YWciOiJDTGFqazQyWDI5MENFQUU9In1dLCJvd25lciI6eyJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIn0sImNyYzMyYyI6InlaUmxxZz09IiwiZXRhZyI6IkNMYWprNDJYMjkwQ0VBRT0iLCJyZXRlbnRpb25FeHBpcmF0aW9uVGltZSI6IjIwMTgtMDktMjhUMTM6MjY6MTAuMTYwWiJ9"
+ }
+ },
+ {
+ "ID": "fc16f5c7b8a77052",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0016/o/some-object?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "6b5663749bf8ab9ea1692229808a7b22/4473265968562712959;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0016/o/some-object?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 403,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0"
+ ],
+ "Content-Length": [
+ "13776"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:10 GMT"
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:26:10 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051468000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrjd27:4293,/bns/yw/borg/yw/bns/blobstore2/bitpusher/115.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=YsysW6CPGI-jhQTSyrfwDA"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yw/borg/yw/bns/blobstore2/bitpusher/115.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yw/borg/yw/bns/blobstore2/bitpusher/115:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRYTVGNmlfNzNkdVJhUVRFQXNzZUdCeEdGWld0bm9pVHl0TGhyNW1FY0hyQTF4eDJEXzNxS2cwUGxYVTJhZC1kOHl3dE9jMUVrNzZmVXdFU2J1TlpoVE9NWThoaEhzNlRjUTl1dHRwNHZZRmJBODdBX05uZ1BwNWIxRHdNR1NQUXV2XzdySWxFZjFtQTVRRUMyZThES1VqcHotcmFtNFJMc01MR2x0aVdrTFQzNlNXLVNZMFhjVlpFVG8wBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Upload-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Uo_qg4-mUkzGfnA4DihWnTigVKTnnU-Rezw6vz2A3xHWZpDnrOUkw3-hDkcOOGydPq1y_TLcMAeYRtwAOGjU3FmE4YFig"
+ ]
+ },
+ "Body": "eyJlcnJvciI6eyJlcnJvcnMiOlt7ImRvbWFpbiI6Imdsb2JhbCIsInJlYXNvbiI6ImZvcmJpZGRlbiIsIm1lc3NhZ2UiOiJPYmplY3QgJ2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxNi9zb21lLW9iamVjdCcgaXMgc3ViamVjdCB0byBidWNrZXQncyByZXRlbnRpb24gcG9saWN5IGFuZCBjYW5ub3QgYmUgZGVsZXRlZCwgb3ZlcndyaXR0ZW4gb3IgYXJjaGl2ZWQgdW50aWwgMjAxOC0wOS0yOFQwNjoyNjoxMC4xNjA5Mjg0NDYtMDc6MDAiLCJkZWJ1Z0luZm8iOiJjb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6UkVURU5USU9OX1BPTElDWV9OT1RfTUVUOiBPYmplY3QgJ2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxNi9zb21lLW9iamVjdCcgaXMgc3ViamVjdCB0byBidWNrZXQncyByZXRlbnRpb24gcG9saWN5IGFuZCBjYW5ub3QgYmUgZGVsZXRlZCwgb3ZlcndyaXR0ZW4gb3IgYXJjaGl2ZWQgdW50aWwgMjAxOC0wOS0yOFQwNjoyNjoxMC4xNjA5Mjg0NDYtMDc6MDBcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udG9ScGMzRXhjZXB0aW9uKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MTM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuRGVsZXRlT2JqZWN0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChEZWxldGVPYmplY3QuamF2YTo3Nylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5vYmplY3RzLkRlbGV0ZU9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoRGVsZXRlT2JqZWN0LmphdmE6MjMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5PYmplY3RzRGVsZWdhdG9yLmRlbGV0ZShPYmplY3RzRGVsZWdhdG9yLmphdmE6MTEzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5ScGNSZWNlaXZlci5sYW1iZGEkcHJvY2Vzc1JlcXVlc3RBc3luYyQ0KFJwY1JlY2VpdmVyLmphdmE6MjAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5Bc3luY0V4ZWN1dG9yLmxhbWJkYSRzdWJtaXQkMChBc3luY0V4ZWN1dG9yLmphdmE6MjcyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoQ29udGV4dFJ1bm5hYmxlLmphdmE6NTApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlJDEucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM5KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo3Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5FeGVjdXRvcnMkUnVubmFibGVBZGFwdGVyLmNhbGwoRXhlY3V0b3JzLmphdmE6NTExKVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5GdXR1cmVUYXNrLnJ1bihGdXR1cmVUYXNrLmphdmE6MjY2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IucnVuV29ya2VyKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjExNDkpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvciRXb3JrZXIucnVuKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjYyNClcblx0YXQgamF2YS5sYW5nLlRocmVhZC5ydW4oVGhyZWFkLmphdmE6NzQ4KVxuQ2F1c2VkIGJ5OiBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbjogT2JqZWN0ICdnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTYvc29tZS1vYmplY3QnIGlzIHN1YmplY3QgdG8gYnVja2V0J3MgcmV0ZW50aW9uIHBvbGljeSBhbmQgY2Fubm90IGJlIGRlbGV0ZWQsIG92ZXJ3cml0dGVuIG9yIGFyY2hpdmVkIHVudGlsIDIwMTgtMDktMjhUMDY6MjY6MTAuMTYwOTI4NDQ2LTA3OjAwXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93T25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjI5MClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMSlcblx0Li4uIDE3IG1vcmVcblxuY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUuRmF1bHQ6IEltbXV0YWJsZUVycm9yRGVmaW5pdGlvbntiYXNlPUZPUkJJRERFTiwgY2F0ZWdvcnk9VVNFUl9FUlJPUiwgY2F1c2U9bnVsbCwgZGVidWdJbmZvPWNvbS5nb29nbGUubmV0LnJwYzMuUnBjRXhjZXB0aW9uOiBjbG91ZC5iaWdzdG9yZS5SZXNwb25zZUNvZGUuRXJyb3JDb2RlOjpSRVRFTlRJT05fUE9MSUNZX05PVF9NRVQ6IE9iamVjdCAnZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDE2L3NvbWUtb2JqZWN0JyBpcyBzdWJqZWN0IHRvIGJ1Y2tldCdzIHJldGVudGlvbiBwb2xpY3kgYW5kIGNhbm5vdCBiZSBkZWxldGVkLCBvdmVyd3JpdHRlbiBvciBhcmNoaXZlZCB1bnRpbCAyMDE4LTA5LTI4VDA2OjI2OjEwLjE2MDkyODQ0Ni0wNzowMFxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5EZWxldGVPYmplY3QuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKERlbGV0ZU9iamVjdC5qYXZhOjc3KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuRGVsZXRlT2JqZWN0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChEZWxldGVPYmplY3QuamF2YToyMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLk9iamVjdHNEZWxlZ2F0b3IuZGVsZXRlKE9iamVjdHNEZWxlZ2F0b3IuamF2YToxMTMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBPYmplY3QgJ2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxNi9zb21lLW9iamVjdCcgaXMgc3ViamVjdCB0byBidWNrZXQncyByZXRlbnRpb24gcG9saWN5IGFuZCBjYW5ub3QgYmUgZGVsZXRlZCwgb3ZlcndyaXR0ZW4gb3IgYXJjaGl2ZWQgdW50aWwgMjAxOC0wOS0yOFQwNjoyNjoxMC4xNjA5Mjg0NDYtMDc6MDBcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MjkwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAxKVxuXHQuLi4gMTcgbW9yZVxuLCBkb21haW49Z2xvYmFsLCBleHRlbmRlZEhlbHA9bnVsbCwgaHR0cEhlYWRlcnM9e30sIGh0dHBTdGF0dXM9Zm9yYmlkZGVuLCBpbnRlcm5hbFJlYXNvbj1SZWFzb257YXJndW1lbnRzPXt9LCBjYXVzZT1udWxsLCBjb2RlPWdkYXRhLkNvcmVFcnJvckRvbWFpbi5GT1JCSURERU4sIGNyZWF0ZWRCeUJhY2tlbmQ9dHJ1ZSwgZGVidWdNZXNzYWdlPWNvbS5nb29nbGUubmV0LnJwYzMuUnBjRXhjZXB0aW9uOiBjbG91ZC5iaWdzdG9yZS5SZXNwb25zZUNvZGUuRXJyb3JDb2RlOjpSRVRFTlRJT05fUE9MSUNZX05PVF9NRVQ6IE9iamVjdCAnZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDE2L3NvbWUtb2JqZWN0JyBpcyBzdWJqZWN0IHRvIGJ1Y2tldCdzIHJldGVudGlvbiBwb2xpY3kgYW5kIGNhbm5vdCBiZSBkZWxldGVkLCBvdmVyd3JpdHRlbiBvciBhcmNoaXZlZCB1bnRpbCAyMDE4LTA5LTI4VDA2OjI2OjEwLjE2MDkyODQ0Ni0wNzowMFxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5EZWxldGVPYmplY3QuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKERlbGV0ZU9iamVjdC5qYXZhOjc3KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuRGVsZXRlT2JqZWN0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChEZWxldGVPYmplY3QuamF2YToyMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLk9iamVjdHNEZWxlZ2F0b3IuZGVsZXRlKE9iamVjdHNEZWxlZ2F0b3IuamF2YToxMTMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBPYmplY3QgJ2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxNi9zb21lLW9iamVjdCcgaXMgc3ViamVjdCB0byBidWNrZXQncyByZXRlbnRpb24gcG9saWN5IGFuZCBjYW5ub3QgYmUgZGVsZXRlZCwgb3ZlcndyaXR0ZW4gb3IgYXJjaGl2ZWQgdW50aWwgMjAxOC0wOS0yOFQwNjoyNjoxMC4xNjA5Mjg0NDYtMDc6MDBcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MjkwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAxKVxuXHQuLi4gMTcgbW9yZVxuLCBlcnJvclByb3RvQ29kZT1GT1JCSURERU4sIGVycm9yUHJvdG9Eb21haW49Z2RhdGEuQ29yZUVycm9yRG9tYWluLCBmaWx0ZXJlZE1lc3NhZ2U9bnVsbCwgbG9jYXRpb249bnVsbCwgbWVzc2FnZT1PYmplY3QgJ2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxNi9zb21lLW9iamVjdCcgaXMgc3ViamVjdCB0byBidWNrZXQncyByZXRlbnRpb24gcG9saWN5IGFuZCBjYW5ub3QgYmUgZGVsZXRlZCwgb3ZlcndyaXR0ZW4gb3IgYXJjaGl2ZWQgdW50aWwgMjAxOC0wOS0yOFQwNjoyNjoxMC4xNjA5Mjg0NDYtMDc6MDAsIHVubmFtZWRBcmd1bWVudHM9W119LCBsb2NhdGlvbj1udWxsLCBtZXNzYWdlPU9iamVjdCAnZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDE2L3NvbWUtb2JqZWN0JyBpcyBzdWJqZWN0IHRvIGJ1Y2tldCdzIHJldGVudGlvbiBwb2xpY3kgYW5kIGNhbm5vdCBiZSBkZWxldGVkLCBvdmVyd3JpdHRlbiBvciBhcmNoaXZlZCB1bnRpbCAyMDE4LTA5LTI4VDA2OjI2OjEwLjE2MDkyODQ0Ni0wNzowMCwgcmVhc29uPWZvcmJpZGRlbiwgcnBjQ29kZT00MDN9IE9iamVjdCAnZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDE2L3NvbWUtb2JqZWN0JyBpcyBzdWJqZWN0IHRvIGJ1Y2tldCdzIHJldGVudGlvbiBwb2xpY3kgYW5kIGNhbm5vdCBiZSBkZWxldGVkLCBvdmVyd3JpdHRlbiBvciBhcmNoaXZlZCB1bnRpbCAyMDE4LTA5LTI4VDA2OjI2OjEwLjE2MDkyODQ0Ni0wNzowMDogY29tLmdvb2dsZS5uZXQucnBjMy5ScGNFeGNlcHRpb246IGNsb3VkLmJpZ3N0b3JlLlJlc3BvbnNlQ29kZS5FcnJvckNvZGU6OlJFVEVOVElPTl9QT0xJQ1lfTk9UX01FVDogT2JqZWN0ICdnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTYvc29tZS1vYmplY3QnIGlzIHN1YmplY3QgdG8gYnVja2V0J3MgcmV0ZW50aW9uIHBvbGljeSBhbmQgY2Fubm90IGJlIGRlbGV0ZWQsIG92ZXJ3cml0dGVuIG9yIGFyY2hpdmVkIHVudGlsIDIwMTgtMDktMjhUMDY6MjY6MTAuMTYwOTI4NDQ2LTA3OjAwXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRvUnBjM0V4Y2VwdGlvbihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjEzNSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5vYmplY3RzLkRlbGV0ZU9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoRGVsZXRlT2JqZWN0LmphdmE6NzcpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5EZWxldGVPYmplY3QuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKERlbGV0ZU9iamVjdC5qYXZhOjIzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmZyYW1ld29yay5SZXF1ZXN0SGFuZGxlci5oYW5kbGUoUmVxdWVzdEhhbmRsZXIuamF2YToyOTQpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uT2JqZWN0c0RlbGVnYXRvci5kZWxldGUoT2JqZWN0c0RlbGVnYXRvci5qYXZhOjExMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uUnBjUmVjZWl2ZXIubGFtYmRhJHByb2Nlc3NSZXF1ZXN0QXN5bmMkNChScGNSZWNlaXZlci5qYXZhOjIwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uQXN5bmNFeGVjdXRvci5sYW1iZGEkc3VibWl0JDAoQXN5bmNFeGVjdXRvci5qYXZhOjI3Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KENvbnRleHRSdW5uYWJsZS5qYXZhOjUwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZSQxLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozOSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NzIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozNilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRXhlY3V0b3JzJFJ1bm5hYmxlQWRhcHRlci5jYWxsKEV4ZWN1dG9ycy5qYXZhOjUxMSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRnV0dXJlVGFzay5ydW4oRnV0dXJlVGFzay5qYXZhOjI2Nilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yLnJ1bldvcmtlcihUaHJlYWRQb29sRXhlY3V0b3IuamF2YToxMTQ5KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IkV29ya2VyLnJ1bihUaHJlYWRQb29sRXhlY3V0b3IuamF2YTo2MjQpXG5cdGF0IGphdmEubGFuZy5UaHJlYWQucnVuKFRocmVhZC5qYXZhOjc0OClcbkNhdXNlZCBieTogY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb246IE9iamVjdCAnZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDE2L3NvbWUtb2JqZWN0JyBpcyBzdWJqZWN0IHRvIGJ1Y2tldCdzIHJldGVudGlvbiBwb2xpY3kgYW5kIGNhbm5vdCBiZSBkZWxldGVkLCBvdmVyd3JpdHRlbiBvciBhcmNoaXZlZCB1bnRpbCAyMDE4LTA5LTI4VDA2OjI2OjEwLjE2MDkyODQ0Ni0wNzowMFxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxNyBtb3JlXG5cblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUuRXJyb3JDb2xsZWN0b3IudG9GYXVsdChFcnJvckNvbGxlY3Rvci5qYXZhOjU0KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIucmVzdC5hZGFwdGVyLnJvc3kuUm9zeUVycm9yQ29udmVydGVyLnRvRmF1bHQoUm9zeUVycm9yQ29udmVydGVyLmphdmE6NjcpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5yZXN0LmFkYXB0ZXIucm9zeS5Sb3N5SGFuZGxlciQyLmNhbGwoUm9zeUhhbmRsZXIuamF2YToyNTgpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5yZXN0LmFkYXB0ZXIucm9zeS5Sb3N5SGFuZGxlciQyLmNhbGwoUm9zeUhhbmRsZXIuamF2YToyMzgpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLnV0aWwuQ2FsbGFibGVGdXR1cmUucnVuKENhbGxhYmxlRnV0dXJlLmphdmE6NjIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5EaXJlY3RFeGVjdXRvci5leGVjdXRlKERpcmVjdEV4ZWN1dG9yLmphdmE6MzApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5leGVjdXRlTGlzdGVuZXIoQWJzdHJhY3RGdXR1cmUuamF2YToxMTQzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuY29tcGxldGUoQWJzdHJhY3RGdXR1cmUuamF2YTo5NjMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5zZXQoQWJzdHJhY3RGdXR1cmUuamF2YTo3MzEpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLnV0aWwuQ2FsbGFibGVGdXR1cmUucnVuKENhbGxhYmxlRnV0dXJlLmphdmE6NjIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5EaXJlY3RFeGVjdXRvci5leGVjdXRlKERpcmVjdEV4ZWN1dG9yLmphdmE6MzApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5leGVjdXRlTGlzdGVuZXIoQWJzdHJhY3RGdXR1cmUuamF2YToxMTQzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuY29tcGxldGUoQWJzdHJhY3RGdXR1cmUuamF2YTo5NjMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5zZXQoQWJzdHJhY3RGdXR1cmUuamF2YTo3MzEpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLnV0aWwuQ2FsbGFibGVGdXR1cmUucnVuKENhbGxhYmxlRnV0dXJlLmphdmE6NjIpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci50aHJlYWQuVGhyZWFkVHJhY2tlcnMkVGhyZWFkVHJhY2tpbmdSdW5uYWJsZS5ydW4oVGhyZWFkVHJhY2tlcnMuamF2YToxMjYpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkVHJhY2VDb250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KFRyYWNlQ29udGV4dC5qYXZhOjQ1NSlcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnNlcnZlci5Db21tb25Nb2R1bGUkQ29udGV4dENhcnJ5aW5nRXhlY3V0b3JTZXJ2aWNlJDEucnVuSW5Db250ZXh0KENvbW1vbk1vZHVsZS5qYXZhOjg0Nilcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRUcmFjZUNvbnRleHRSdW5uYWJsZSQxLnJ1bihUcmFjZUNvbnRleHQuamF2YTo0NjIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkQWJzdHJhY3RUcmFjZUNvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKFRyYWNlQ29udGV4dC5qYXZhOjMyMSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRBYnN0cmFjdFRyYWNlQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChUcmFjZUNvbnRleHQuamF2YTozMTMpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkVHJhY2VDb250ZXh0UnVubmFibGUucnVuKFRyYWNlQ29udGV4dC5qYXZhOjQ1OSlcblx0YXQgY29tLmdvb2dsZS5nc2UuaW50ZXJuYWwuRGlzcGF0Y2hRdWV1ZUltcGwkV29ya2VyVGhyZWFkLnJ1bihEaXNwYXRjaFF1ZXVlSW1wbC5qYXZhOjQwMylcbiJ9XSwiY29kZSI6NDAzLCJtZXNzYWdlIjoiT2JqZWN0ICdnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTYvc29tZS1vYmplY3QnIGlzIHN1YmplY3QgdG8gYnVja2V0J3MgcmV0ZW50aW9uIHBvbGljeSBhbmQgY2Fubm90IGJlIGRlbGV0ZWQsIG92ZXJ3cml0dGVuIG9yIGFyY2hpdmVkIHVudGlsIDIwMTgtMDktMjhUMDY6MjY6MTAuMTYwOTI4NDQ2LTA3OjAwIn19"
+ }
+ },
+ {
+ "ID": "605f8d1dd95809c7",
+ "Request": {
+ "Method": "PATCH",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0016?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "25"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "45a524594262aa1f959d45c5f0261799/6063677872629929501;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0016?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJyZXRlbnRpb25Qb2xpY3kiOm51bGx9Cg=="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "2353"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:12 GMT"
+ ],
+ "Etag": [
+ "CAI="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051471000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrjl65:4261,/bns/yw/borg/yw/bns/blobstore2/bitpusher/84.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=YsysW6jRKIXMhgTk56f4BQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yw/borg/yw/bns/blobstore2/bitpusher/84.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yw/borg/yw/bns/blobstore2/bitpusher/84:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATpxChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4CtK4wESxgF5YTI5LmMuRW93QkpRYTVGNmlfNzNkdVJhUVRFQXNzZUdCeEdGWld0bm9pVHl0TGhyNW1FY0hyQTF4eDJEXzNxS2cwUGxYVTJhZC1kOHl3dE9jMUVrNzZmVXdFU2J1TlpoVE9NWThoaEhzNlRjUTl1dHRwNHZZRmJBODdBX05uZ1BwNWIxRHdNR1NQUXV2XzdySWxFZjFtQTVRRUMyZThES1VqcHotcmFtNFJMc01MR2x0aVdrTFQzNlNXLVNZMFhjVlpFVG8wBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Uoc4h8amQZalCX5R_TWKyE24jbt0D3VpYBvdcCaXM00UzRTu3Uk2OZ8JSITvj7Ihu8hWdeClLqSaL_ppYtUpu5tGHa0Dg"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxNiIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxNiIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTYiLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjY6MDkuNDg3WiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI2OjEyLjExOFoiLCJtZXRhZ2VuZXJhdGlvbiI6IjIiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxNi9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxNi9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTYiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBST0ifSx7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxNi9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTYvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxNiIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDQUk9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTYvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDE2L2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTYiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNBST0ifV0sImRlZmF1bHRPYmplY3RBY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBST0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0FJPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0FJPSJ9XSwib3duZXIiOnsiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUifSwibG9jYXRpb24iOiJVUyIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwiZXRhZyI6IkNBST0ifQ=="
+ }
+ },
+ {
+ "ID": "47475e76832941e9",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0016/o/some-object?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "ffa1323060cacbec2111b53f746f3400/6894771332282460525;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0016/o/some-object?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 204,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "0"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:12 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051468000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrhr16:4228,/bns/yv/borg/yv/bns/blobstore2/bitpusher/266.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=ZMysW5-wGpCcNsOPmzA"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/266.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/266:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRYTVGNmlfNzNkdVJhUVRFQXNzZUdCeEdGWld0bm9pVHl0TGhyNW1FY0hyQTF4eDJEXzNxS2cwUGxYVTJhZC1kOHl3dE9jMUVrNzZmVXdFU2J1TlpoVE9NWThoaEhzNlRjUTl1dHRwNHZZRmJBODdBX05uZ1BwNWIxRHdNR1NQUXV2XzdySWxFZjFtQTVRRUMyZThES1VqcHotcmFtNFJMc01MR2x0aVdrTFQzNlNXLVNZMFhjVlpFVG8wBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UpZOvNJJ_u3XkC7z73EahCGO3GCWFD-dAlxsw3J2U8j_6n3KGm4-dI8loxdemHGBCvsyaPf2VS5jesxH8IblmKbUB7dWQ"
+ ]
+ },
+ "Body": ""
+ }
+ },
+ {
+ "ID": "f15f5d67c9f184d5",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0016?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "800ead8e859d24c198485164290457c1/8485182136854826507;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0016?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 204,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "0"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:13 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051472000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vnab126:4314,/bns/yx/borg/yx/bns/blobstore2/bitpusher/8.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=ZMysW8T8MsyAzQKYkrHgAw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yx/borg/yx/bns/blobstore2/bitpusher/8.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yx/borg/yx/bns/blobstore2/bitpusher/8:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRYTVGNmlfNzNkdVJhUVRFQXNzZUdCeEdGWld0bm9pVHl0TGhyNW1FY0hyQTF4eDJEXzNxS2cwUGxYVTJhZC1kOHl3dE9jMUVrNzZmVXdFU2J1TlpoVE9NWThoaEhzNlRjUTl1dHRwNHZZRmJBODdBX05uZ1BwNWIxRHdNR1NQUXV2XzdySWxFZjFtQTVRRUMyZThES1VqcHotcmFtNFJMc01MR2x0aVdrTFQzNlNXLVNZMFhjVlpFVG8wBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UrxN_lEa5gdh4ZryppZ3tgdyGfuXwgtkZUYTAJ28QIFZaJmgFdh7RTwJ2pzxdYDYVKrl1tX4Z8HjuMsKBnwyB7UDIUD8A"
+ ]
+ },
+ "Body": ""
+ }
+ },
+ {
+ "ID": "d1099de2d74ac1d9",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/storage/v1/b?alt=json\u0026prettyPrint=false\u0026project=dulcet-port-762",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "106"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "d073a04f3dfd6da876848e5ad6f763ca/10075594040905200810;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b?alt=json\u0026prettyPrint=false\u0026project=dulcet-port-762"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJuYW1lIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDE3IiwicmV0ZW50aW9uUG9saWN5Ijp7InJldGVudGlvblBlcmlvZCI6IjkwMDAwIn19Cg=="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "515"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:14 GMT"
+ ],
+ "Etag": [
+ "CAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051473000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vnao18:4369,/bns/yx/borg/yx/bns/blobstore2/bitpusher/108.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=ZcysW4jUEYHGzALUubuoBg"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yx/borg/yx/bns/blobstore2/bitpusher/108.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yx/borg/yx/bns/blobstore2/bitpusher/108:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRYkNVTHJoYzlVZGhJQ1l3YzNNQjVKQU8wRzBJZjBPb3FOYk5IMEpoZlphYzBaTkNzR2RCR1hCYV9LcDFYeEZ1aWlOSVo3WFhZM2I0azlnS1lSZWZscEtNNlpDclNKTGhad0RuLWxKR3pUNEFULVU0RV9xa01MQ1dRallrTDFUeTBSOTFJV2M3MzQtYWs5ZlhjdF9BbmtLMVlMbEFHRFFhMGgtRXdCM0VsOW1La29ibG1UZHZCZ0VKaXcwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UpPbyGbVtM7oj8m_VpH2LDSEgA3a9Y1xJv-Uyzm9pbwLkO2oGHAtjaP132v8oabe0lkhVZhbYCUYJwzfb2M46NBOJQU_Q"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxNyIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxNyIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTciLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjY6MTMuODg3WiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI2OjEzLjg4N1oiLCJtZXRhZ2VuZXJhdGlvbiI6IjEiLCJsb2NhdGlvbiI6IlVTIiwicmV0ZW50aW9uUG9saWN5Ijp7InJldGVudGlvblBlcmlvZCI6IjkwMDAwIiwiZWZmZWN0aXZlVGltZSI6IjIwMTgtMDktMjdUMTI6MjY6MTMuODg3WiJ9LCJzdG9yYWdlQ2xhc3MiOiJTVEFOREFSRCIsImV0YWciOiJDQUU9In0="
+ }
+ },
+ {
+ "ID": "a939f9cc6dba5113",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0017?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "9733eddf476bb62db1d4cd2544bb7770/11666005940677450057;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0017?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0, must-revalidate, no-transform"
+ ],
+ "Content-Length": [
+ "2442"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:14 GMT"
+ ],
+ "Etag": [
+ "CAE="
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:26:14 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051474000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrlb12:4251,/bns/yv/borg/yv/bns/blobstore2/bitpusher/43.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=ZsysW9jpBoOegwTq3L2ADw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/43.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/43:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRYkNVTHJoYzlVZGhJQ1l3YzNNQjVKQU8wRzBJZjBPb3FOYk5IMEpoZlphYzBaTkNzR2RCR1hCYV9LcDFYeEZ1aWlOSVo3WFhZM2I0azlnS1lSZWZscEtNNlpDclNKTGhad0RuLWxKR3pUNEFULVU0RV9xa01MQ1dRallrTDFUeTBSOTFJV2M3MzQtYWs5ZlhjdF9BbmtLMVlMbEFHRFFhMGgtRXdCM0VsOW1La29ibG1UZHZCZ0VKaXcwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UrZ01-y1806-liZzg1Zc4EJgkrGX9gYB6aX_TDs2Zm-j1iUC6AD7poaLO05U5iAiWwcAUDxfQNuWV9Vcq6MDGim36ClVA"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxNyIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxNyIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTciLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjY6MTMuODg3WiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI2OjEzLjg4N1oiLCJtZXRhZ2VuZXJhdGlvbiI6IjEiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxNy9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxNy9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTciLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxNy9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTcvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxNyIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDQUU9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTcvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDE3L2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTciLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNBRT0ifV0sImRlZmF1bHRPYmplY3RBY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0FFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0FFPSJ9XSwib3duZXIiOnsiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUifSwibG9jYXRpb24iOiJVUyIsInJldGVudGlvblBvbGljeSI6eyJyZXRlbnRpb25QZXJpb2QiOiI5MDAwMCIsImVmZmVjdGl2ZVRpbWUiOiIyMDE4LTA5LTI3VDEyOjI2OjEzLjg4N1oifSwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJldGFnIjoiQ0FFPSJ9"
+ }
+ },
+ {
+ "ID": "7e76ac1d23c04912",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0017/lockRetentionPolicy?alt=json\u0026ifMetagenerationMatch=1\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "0"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "8fe2407fd7131d02df69a56f109f8645/12425042910098648216;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0017/lockRetentionPolicy?alt=json\u0026ifMetagenerationMatch=1\u0026prettyPrint=false"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "579"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:16 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051473000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vnnk15:4485,/bns/yx/borg/yx/bns/blobstore2/bitpusher/113.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=ZsysW_6JGcP9zALA9KDoCQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yx/borg/yx/bns/blobstore2/bitpusher/113.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yx/borg/yx/bns/blobstore2/bitpusher/113:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRYkNVTHJoYzlVZGhJQ1l3YzNNQjVKQU8wRzBJZjBPb3FOYk5IMEpoZlphYzBaTkNzR2RCR1hCYV9LcDFYeEZ1aWlOSVo3WFhZM2I0azlnS1lSZWZscEtNNlpDclNKTGhad0RuLWxKR3pUNEFULVU0RV9xa01MQ1dRallrTDFUeTBSOTFJV2M3MzQtYWs5ZlhjdF9BbmtLMVlMbEFHRFFhMGgtRXdCM0VsOW1La29ibG1UZHZCZ0VKaXcwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UoMQSqHqmJkvz8xDacwxPwyaIVrIlIsEdjNKzPZAvOHXU4sJVbyiBesmbpc5gIpL9KBQYa4AMYhYCo5u-LFPQ0y_vAVZg"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxNyIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxNyIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTciLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjY6MTMuODg3WiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI2OjE1LjkzNloiLCJtZXRhZ2VuZXJhdGlvbiI6IjIiLCJvd25lciI6eyJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSJ9LCJsb2NhdGlvbiI6IlVTIiwicmV0ZW50aW9uUG9saWN5Ijp7InJldGVudGlvblBlcmlvZCI6IjkwMDAwIiwiZWZmZWN0aXZlVGltZSI6IjIwMTgtMDktMjdUMTI6MjY6MTMuODg3WiIsImlzTG9ja2VkIjp0cnVlfSwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJldGFnIjoiQ0FJPSJ9"
+ }
+ },
+ {
+ "ID": "8e8e90b1f311e0c0",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0017?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "fe36332fb369320ee3dd205b0abd8788/14015454814165799223;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0017?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0, must-revalidate, no-transform"
+ ],
+ "Content-Length": [
+ "2458"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:16 GMT"
+ ],
+ "Etag": [
+ "CAI="
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:26:16 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051474000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrtg25:4215,/bns/yr/borg/yr/bns/blobstore2/bitpusher/19.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=aMysW-GeCcXtkAPp7qJg"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/19.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/19:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRYkNVTHJoYzlVZGhJQ1l3YzNNQjVKQU8wRzBJZjBPb3FOYk5IMEpoZlphYzBaTkNzR2RCR1hCYV9LcDFYeEZ1aWlOSVo3WFhZM2I0azlnS1lSZWZscEtNNlpDclNKTGhad0RuLWxKR3pUNEFULVU0RV9xa01MQ1dRallrTDFUeTBSOTFJV2M3MzQtYWs5ZlhjdF9BbmtLMVlMbEFHRFFhMGgtRXdCM0VsOW1La29ibG1UZHZCZ0VKaXcwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Uq8KJ3zwGSpR8HjTO4SFtb08TdIZrIEj9oG7XdimkQAiSDBWdUHlWYI1_2NgFVVXV67OFPEutBQarF5JHYd86SUCglkPA"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxNyIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxNyIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTciLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjY6MTMuODg3WiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI2OjE1LjkzNloiLCJtZXRhZ2VuZXJhdGlvbiI6IjIiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxNy9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxNy9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTciLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBST0ifSx7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxNy9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTcvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxNyIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDQUk9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTcvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDE3L2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTciLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNBST0ifV0sImRlZmF1bHRPYmplY3RBY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBST0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0FJPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0FJPSJ9XSwib3duZXIiOnsiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUifSwibG9jYXRpb24iOiJVUyIsInJldGVudGlvblBvbGljeSI6eyJyZXRlbnRpb25QZXJpb2QiOiI5MDAwMCIsImVmZmVjdGl2ZVRpbWUiOiIyMDE4LTA5LTI3VDEyOjI2OjEzLjg4N1oiLCJpc0xvY2tlZCI6dHJ1ZX0sInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwiZXRhZyI6IkNBST0ifQ=="
+ }
+ },
+ {
+ "ID": "e070e3b1fc8b6e0b",
+ "Request": {
+ "Method": "PATCH",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0017?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "47"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "83e4b5789f8577482f1a8df237d6382c/15605584148039645141;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0017?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJyZXRlbnRpb25Qb2xpY3kiOnsicmV0ZW50aW9uUGVyaW9kIjoiMzYwMCJ9fQo="
+ },
+ "Response": {
+ "StatusCode": 403,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Content-Length": [
+ "13262"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:17 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051476000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrqe25:4313,/bns/yv/borg/yv/bns/blobstore2/bitpusher/358.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=aMysW7WpG8SCgQTU6r3QDw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/358.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/358:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATpxChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4CtK4wESxgF5YTI5LmMuRW93QkpRYkNVTHJoYzlVZGhJQ1l3YzNNQjVKQU8wRzBJZjBPb3FOYk5IMEpoZlphYzBaTkNzR2RCR1hCYV9LcDFYeEZ1aWlOSVo3WFhZM2I0azlnS1lSZWZscEtNNlpDclNKTGhad0RuLWxKR3pUNEFULVU0RV9xa01MQ1dRallrTDFUeTBSOTFJV2M3MzQtYWs5ZlhjdF9BbmtLMVlMbEFHRFFhMGgtRXdCM0VsOW1La29ibG1UZHZCZ0VKaXcwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Upload-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UqBd-ZobK3AR5YXeKm28RfOfm_Lp9v4Baz5VA9TTyBtqKBlN-MkFvHcwI9Cwjn9yLgZjc1YCEa1iXmaVLszE1_inCuh8w"
+ ]
+ },
+ "Body": "eyJlcnJvciI6eyJlcnJvcnMiOlt7ImRvbWFpbiI6Imdsb2JhbCIsInJlYXNvbiI6ImZvcmJpZGRlbiIsIm1lc3NhZ2UiOiJDYW5ub3QgcmVkdWNlIHJldGVudGlvbiBkdXJhdGlvbiBvZiBhIGxvY2tlZCBSZXRlbnRpb24gUG9saWN5IGZvciBidWNrZXQgJ2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxNycuIiwiZGVidWdJbmZvIjoiY29tLmdvb2dsZS5uZXQucnBjMy5ScGNFeGNlcHRpb246IGNsb3VkLmJpZ3N0b3JlLlJlc3BvbnNlQ29kZS5FcnJvckNvZGU6OkFDQ0VTU19ERU5JRUQ6IENhbm5vdCByZWR1Y2UgcmV0ZW50aW9uIGR1cmF0aW9uIG9mIGEgbG9ja2VkIFJldGVudGlvbiBQb2xpY3kgZm9yIGJ1Y2tldCAnZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDE3Jy5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udG9ScGMzRXhjZXB0aW9uKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MTM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmJ1Y2tldHMuVXBkYXRlQW5kUGF0Y2hCdWNrZXQudXBkYXRlQnVja2V0KFVwZGF0ZUFuZFBhdGNoQnVja2V0LmphdmE6MTIxKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmJ1Y2tldHMuVXBkYXRlQnVja2V0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChVcGRhdGVCdWNrZXQuamF2YTo3OClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5idWNrZXRzLlVwZGF0ZUJ1Y2tldC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoVXBkYXRlQnVja2V0LmphdmE6MTgpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5CdWNrZXRzRGVsZWdhdG9yLnVwZGF0ZShCdWNrZXRzRGVsZWdhdG9yLmphdmE6MTAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5ScGNSZWNlaXZlci5sYW1iZGEkcHJvY2Vzc1JlcXVlc3RBc3luYyQ0KFJwY1JlY2VpdmVyLmphdmE6MjAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5Bc3luY0V4ZWN1dG9yLmxhbWJkYSRzdWJtaXQkMChBc3luY0V4ZWN1dG9yLmphdmE6MjcyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoQ29udGV4dFJ1bm5hYmxlLmphdmE6NTApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlJDEucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM5KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo3Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5FeGVjdXRvcnMkUnVubmFibGVBZGFwdGVyLmNhbGwoRXhlY3V0b3JzLmphdmE6NTExKVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5GdXR1cmVUYXNrLnJ1bihGdXR1cmVUYXNrLmphdmE6MjY2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IucnVuV29ya2VyKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjExNDkpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvciRXb3JrZXIucnVuKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjYyNClcblx0YXQgamF2YS5sYW5nLlRocmVhZC5ydW4oVGhyZWFkLmphdmE6NzQ4KVxuQ2F1c2VkIGJ5OiBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbjogQ2Fubm90IHJlZHVjZSByZXRlbnRpb24gZHVyYXRpb24gb2YgYSBsb2NrZWQgUmV0ZW50aW9uIFBvbGljeSBmb3IgYnVja2V0ICdnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTcnLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxOCBtb3JlXG5cbmNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLkZhdWx0OiBJbW11dGFibGVFcnJvckRlZmluaXRpb257YmFzZT1GT1JCSURERU4sIGNhdGVnb3J5PVVTRVJfRVJST1IsIGNhdXNlPW51bGwsIGRlYnVnSW5mbz1jb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6QUNDRVNTX0RFTklFRDogQ2Fubm90IHJlZHVjZSByZXRlbnRpb24gZHVyYXRpb24gb2YgYSBsb2NrZWQgUmV0ZW50aW9uIFBvbGljeSBmb3IgYnVja2V0ICdnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTcnLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYnVja2V0cy5VcGRhdGVBbmRQYXRjaEJ1Y2tldC51cGRhdGVCdWNrZXQoVXBkYXRlQW5kUGF0Y2hCdWNrZXQuamF2YToxMjEpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYnVja2V0cy5VcGRhdGVCdWNrZXQuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKFVwZGF0ZUJ1Y2tldC5qYXZhOjc4KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmJ1Y2tldHMuVXBkYXRlQnVja2V0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChVcGRhdGVCdWNrZXQuamF2YToxOClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLkJ1Y2tldHNEZWxlZ2F0b3IudXBkYXRlKEJ1Y2tldHNEZWxlZ2F0b3IuamF2YToxMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBDYW5ub3QgcmVkdWNlIHJldGVudGlvbiBkdXJhdGlvbiBvZiBhIGxvY2tlZCBSZXRlbnRpb24gUG9saWN5IGZvciBidWNrZXQgJ2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxNycuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93T25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjI5MClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMSlcblx0Li4uIDE4IG1vcmVcbiwgZG9tYWluPWdsb2JhbCwgZXh0ZW5kZWRIZWxwPW51bGwsIGh0dHBIZWFkZXJzPXt9LCBodHRwU3RhdHVzPWZvcmJpZGRlbiwgaW50ZXJuYWxSZWFzb249UmVhc29ue2FyZ3VtZW50cz17fSwgY2F1c2U9bnVsbCwgY29kZT1nZGF0YS5Db3JlRXJyb3JEb21haW4uRk9SQklEREVOLCBjcmVhdGVkQnlCYWNrZW5kPXRydWUsIGRlYnVnTWVzc2FnZT1jb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6QUNDRVNTX0RFTklFRDogQ2Fubm90IHJlZHVjZSByZXRlbnRpb24gZHVyYXRpb24gb2YgYSBsb2NrZWQgUmV0ZW50aW9uIFBvbGljeSBmb3IgYnVja2V0ICdnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTcnLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYnVja2V0cy5VcGRhdGVBbmRQYXRjaEJ1Y2tldC51cGRhdGVCdWNrZXQoVXBkYXRlQW5kUGF0Y2hCdWNrZXQuamF2YToxMjEpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYnVja2V0cy5VcGRhdGVCdWNrZXQuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKFVwZGF0ZUJ1Y2tldC5qYXZhOjc4KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmJ1Y2tldHMuVXBkYXRlQnVja2V0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChVcGRhdGVCdWNrZXQuamF2YToxOClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLkJ1Y2tldHNEZWxlZ2F0b3IudXBkYXRlKEJ1Y2tldHNEZWxlZ2F0b3IuamF2YToxMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBDYW5ub3QgcmVkdWNlIHJldGVudGlvbiBkdXJhdGlvbiBvZiBhIGxvY2tlZCBSZXRlbnRpb24gUG9saWN5IGZvciBidWNrZXQgJ2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxNycuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93T25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjI5MClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMSlcblx0Li4uIDE4IG1vcmVcbiwgZXJyb3JQcm90b0NvZGU9Rk9SQklEREVOLCBlcnJvclByb3RvRG9tYWluPWdkYXRhLkNvcmVFcnJvckRvbWFpbiwgZmlsdGVyZWRNZXNzYWdlPW51bGwsIGxvY2F0aW9uPW51bGwsIG1lc3NhZ2U9Q2Fubm90IHJlZHVjZSByZXRlbnRpb24gZHVyYXRpb24gb2YgYSBsb2NrZWQgUmV0ZW50aW9uIFBvbGljeSBmb3IgYnVja2V0ICdnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTcnLiwgdW5uYW1lZEFyZ3VtZW50cz1bXX0sIGxvY2F0aW9uPW51bGwsIG1lc3NhZ2U9Q2Fubm90IHJlZHVjZSByZXRlbnRpb24gZHVyYXRpb24gb2YgYSBsb2NrZWQgUmV0ZW50aW9uIFBvbGljeSBmb3IgYnVja2V0ICdnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTcnLiwgcmVhc29uPWZvcmJpZGRlbiwgcnBjQ29kZT00MDN9IENhbm5vdCByZWR1Y2UgcmV0ZW50aW9uIGR1cmF0aW9uIG9mIGEgbG9ja2VkIFJldGVudGlvbiBQb2xpY3kgZm9yIGJ1Y2tldCAnZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDE3Jy46IGNvbS5nb29nbGUubmV0LnJwYzMuUnBjRXhjZXB0aW9uOiBjbG91ZC5iaWdzdG9yZS5SZXNwb25zZUNvZGUuRXJyb3JDb2RlOjpBQ0NFU1NfREVOSUVEOiBDYW5ub3QgcmVkdWNlIHJldGVudGlvbiBkdXJhdGlvbiBvZiBhIGxvY2tlZCBSZXRlbnRpb24gUG9saWN5IGZvciBidWNrZXQgJ2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxNycuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRvUnBjM0V4Y2VwdGlvbihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjEzNSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5idWNrZXRzLlVwZGF0ZUFuZFBhdGNoQnVja2V0LnVwZGF0ZUJ1Y2tldChVcGRhdGVBbmRQYXRjaEJ1Y2tldC5qYXZhOjEyMSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5idWNrZXRzLlVwZGF0ZUJ1Y2tldC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoVXBkYXRlQnVja2V0LmphdmE6NzgpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYnVja2V0cy5VcGRhdGVCdWNrZXQuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKFVwZGF0ZUJ1Y2tldC5qYXZhOjE4KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmZyYW1ld29yay5SZXF1ZXN0SGFuZGxlci5oYW5kbGUoUmVxdWVzdEhhbmRsZXIuamF2YToyOTQpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uQnVja2V0c0RlbGVnYXRvci51cGRhdGUoQnVja2V0c0RlbGVnYXRvci5qYXZhOjEwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uUnBjUmVjZWl2ZXIubGFtYmRhJHByb2Nlc3NSZXF1ZXN0QXN5bmMkNChScGNSZWNlaXZlci5qYXZhOjIwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uQXN5bmNFeGVjdXRvci5sYW1iZGEkc3VibWl0JDAoQXN5bmNFeGVjdXRvci5qYXZhOjI3Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KENvbnRleHRSdW5uYWJsZS5qYXZhOjUwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZSQxLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozOSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NzIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozNilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRXhlY3V0b3JzJFJ1bm5hYmxlQWRhcHRlci5jYWxsKEV4ZWN1dG9ycy5qYXZhOjUxMSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRnV0dXJlVGFzay5ydW4oRnV0dXJlVGFzay5qYXZhOjI2Nilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yLnJ1bldvcmtlcihUaHJlYWRQb29sRXhlY3V0b3IuamF2YToxMTQ5KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IkV29ya2VyLnJ1bihUaHJlYWRQb29sRXhlY3V0b3IuamF2YTo2MjQpXG5cdGF0IGphdmEubGFuZy5UaHJlYWQucnVuKFRocmVhZC5qYXZhOjc0OClcbkNhdXNlZCBieTogY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb246IENhbm5vdCByZWR1Y2UgcmV0ZW50aW9uIGR1cmF0aW9uIG9mIGEgbG9ja2VkIFJldGVudGlvbiBQb2xpY3kgZm9yIGJ1Y2tldCAnZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDE3Jy5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MjkwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAxKVxuXHQuLi4gMTggbW9yZVxuXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLkVycm9yQ29sbGVjdG9yLnRvRmF1bHQoRXJyb3JDb2xsZWN0b3IuamF2YTo1NClcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnJlc3QuYWRhcHRlci5yb3N5LlJvc3lFcnJvckNvbnZlcnRlci50b0ZhdWx0KFJvc3lFcnJvckNvbnZlcnRlci5qYXZhOjY3KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIucmVzdC5hZGFwdGVyLnJvc3kuUm9zeUhhbmRsZXIkMi5jYWxsKFJvc3lIYW5kbGVyLmphdmE6MjU4KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIucmVzdC5hZGFwdGVyLnJvc3kuUm9zeUhhbmRsZXIkMi5jYWxsKFJvc3lIYW5kbGVyLmphdmE6MjM4KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS51dGlsLkNhbGxhYmxlRnV0dXJlLnJ1bihDYWxsYWJsZUZ1dHVyZS5qYXZhOjYyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuRGlyZWN0RXhlY3V0b3IuZXhlY3V0ZShEaXJlY3RFeGVjdXRvci5qYXZhOjMwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuZXhlY3V0ZUxpc3RlbmVyKEFic3RyYWN0RnV0dXJlLmphdmE6MTE0Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmNvbXBsZXRlKEFic3RyYWN0RnV0dXJlLmphdmE6OTYzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuc2V0KEFic3RyYWN0RnV0dXJlLmphdmE6NzMxKVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS51dGlsLkNhbGxhYmxlRnV0dXJlLnJ1bihDYWxsYWJsZUZ1dHVyZS5qYXZhOjYyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuRGlyZWN0RXhlY3V0b3IuZXhlY3V0ZShEaXJlY3RFeGVjdXRvci5qYXZhOjMwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuZXhlY3V0ZUxpc3RlbmVyKEFic3RyYWN0RnV0dXJlLmphdmE6MTE0Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmNvbXBsZXRlKEFic3RyYWN0RnV0dXJlLmphdmE6OTYzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuc2V0KEFic3RyYWN0RnV0dXJlLmphdmE6NzMxKVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS51dGlsLkNhbGxhYmxlRnV0dXJlLnJ1bihDYWxsYWJsZUZ1dHVyZS5qYXZhOjYyKVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIudGhyZWFkLlRocmVhZFRyYWNrZXJzJFRocmVhZFRyYWNraW5nUnVubmFibGUucnVuKFRocmVhZFRyYWNrZXJzLmphdmE6MTI2KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JFRyYWNlQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChUcmFjZUNvbnRleHQuamF2YTo0NTUpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5zZXJ2ZXIuQ29tbW9uTW9kdWxlJENvbnRleHRDYXJyeWluZ0V4ZWN1dG9yU2VydmljZSQxLnJ1bkluQ29udGV4dChDb21tb25Nb2R1bGUuamF2YTo4NDYpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkVHJhY2VDb250ZXh0UnVubmFibGUkMS5ydW4oVHJhY2VDb250ZXh0LmphdmE6NDYyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JEFic3RyYWN0VHJhY2VDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihUcmFjZUNvbnRleHQuamF2YTozMjEpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkQWJzdHJhY3RUcmFjZUNvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoVHJhY2VDb250ZXh0LmphdmE6MzEzKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JFRyYWNlQ29udGV4dFJ1bm5hYmxlLnJ1bihUcmFjZUNvbnRleHQuamF2YTo0NTkpXG5cdGF0IGNvbS5nb29nbGUuZ3NlLmludGVybmFsLkRpc3BhdGNoUXVldWVJbXBsJFdvcmtlclRocmVhZC5ydW4oRGlzcGF0Y2hRdWV1ZUltcGwuamF2YTo0MDMpXG4ifV0sImNvZGUiOjQwMywibWVzc2FnZSI6IkNhbm5vdCByZWR1Y2UgcmV0ZW50aW9uIGR1cmF0aW9uIG9mIGEgbG9ja2VkIFJldGVudGlvbiBQb2xpY3kgZm9yIGJ1Y2tldCAnZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDE3Jy4ifX0="
+ }
+ },
+ {
+ "ID": "e047cc4d51eb7a0b",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/storage/v1/b?alt=json\u0026prettyPrint=false\u0026project=dulcet-port-762",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "106"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "659c9077010b672bd0c19fc8b2a97534/17195996047811894388;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b?alt=json\u0026prettyPrint=false\u0026project=dulcet-port-762"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJuYW1lIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDE4IiwicmV0ZW50aW9uUG9saWN5Ijp7InJldGVudGlvblBlcmlvZCI6IjkwMDAwIn19Cg=="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "515"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:18 GMT"
+ ],
+ "Etag": [
+ "CAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051477000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vnel1:4152,/bns/yx/borg/yx/bns/blobstore2/bitpusher/100.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=acysW_7mMMrpzgLno6zgCQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yx/borg/yx/bns/blobstore2/bitpusher/100.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yx/borg/yx/bns/blobstore2/bitpusher/100:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWkdjdEt2SlhWQm5yQUtJOTBLMVdES19JU2FRSFdleUZlcEpXeVdXLWpxZzQ0cHVUbEtVdzlsX1gwUHg4UzZEM3dsck9SNFZ1OW5GRkR3TlItd0xIdWRWSGU2b2VEVDZNdnhZdm5xV0VWQVN6djl1YW5lYVlacFZuSm9jZkV2TDV4R0NycEt5UGZLX2VQNTNvMlEyUlgwRGMxal8xRDQtSDlEMWNqTV8wTlRoZlFOYzRseEFKYnhRb0EwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UowgkIx9NAooO2nrcRcCMxbenJDY1cuQTBJ9cG6ivuhp_2AhgfZRoIGVOcXBlkej0lSskPz8aTvaEQk_l1S4S8SYVZ1bA"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxOCIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxOCIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTgiLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjY6MTguMjU5WiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI2OjE4LjI1OVoiLCJtZXRhZ2VuZXJhdGlvbiI6IjEiLCJsb2NhdGlvbiI6IlVTIiwicmV0ZW50aW9uUG9saWN5Ijp7InJldGVudGlvblBlcmlvZCI6IjkwMDAwIiwiZWZmZWN0aXZlVGltZSI6IjIwMTgtMDktMjdUMTI6MjY6MTguMjU5WiJ9LCJzdG9yYWdlQ2xhc3MiOiJTVEFOREFSRCIsImV0YWciOiJDQUU9In0="
+ }
+ },
+ {
+ "ID": "e1e8b0731cfcad02",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0018/lockRetentionPolicy?alt=json\u0026ifMetagenerationMatch=0\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "0"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "23661918021938212e5b727fa88cefdb/17955033017233092547;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0018/lockRetentionPolicy?alt=json\u0026ifMetagenerationMatch=0\u0026prettyPrint=false"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 412,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Content-Length": [
+ "12047"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:19 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051478000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrqn25:4154,/bns/yv/borg/yv/bns/blobstore2/bitpusher/374.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=asysW93pIY3yggSq27_4CQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/374.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/374:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWkdjdEt2SlhWQm5yQUtJOTBLMVdES19JU2FRSFdleUZlcEpXeVdXLWpxZzQ0cHVUbEtVdzlsX1gwUHg4UzZEM3dsck9SNFZ1OW5GRkR3TlItd0xIdWRWSGU2b2VEVDZNdnhZdm5xV0VWQVN6djl1YW5lYVlacFZuSm9jZkV2TDV4R0NycEt5UGZLX2VQNTNvMlEyUlgwRGMxal8xRDQtSDlEMWNqTV8wTlRoZlFOYzRseEFKYnhRb0EwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Upload-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UqER26joR5Zr10uFvGr04GcG4fwKz3reu5PWUfJhto9NHp7X0WIF6R6tqywEUrgQtORtgykSYov_L6b3N_o4QRDOAFBqA"
+ ]
+ },
+ "Body": "eyJlcnJvciI6eyJlcnJvcnMiOlt7ImRvbWFpbiI6Imdsb2JhbCIsInJlYXNvbiI6ImNvbmRpdGlvbk5vdE1ldCIsIm1lc3NhZ2UiOiJQcmVjb25kaXRpb24gRmFpbGVkIiwibG9jYXRpb25UeXBlIjoiaGVhZGVyIiwibG9jYXRpb24iOiJJZi1NYXRjaCIsImRlYnVnSW5mbyI6ImNvbS5nb29nbGUubmV0LnJwYzMuUnBjRXhjZXB0aW9uOiBjbG91ZC5iaWdzdG9yZS5SZXNwb25zZUNvZGUuRXJyb3JDb2RlOjpJTkNPUlJFQ1RfTUVUQV9HRU5FUkFUSU9OX1NQRUNJRklFRDogZXhwZWN0ZWQgQnVja2V0TWV0YWRhdGEubWV0YWRhdGFfZ2VuZXJhdGlvbjogMCBhY3R1YWw6IDFcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udG9ScGMzRXhjZXB0aW9uKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MTM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmJ1Y2tldHMuTG9ja1JldGVudGlvblBvbGljeS5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoTG9ja1JldGVudGlvblBvbGljeS5qYXZhOjIxMilcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5idWNrZXRzLkxvY2tSZXRlbnRpb25Qb2xpY3kuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKExvY2tSZXRlbnRpb25Qb2xpY3kuamF2YTo1OSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLkJ1Y2tldHNEZWxlZ2F0b3IubG9ja1JldGVudGlvblBvbGljeShCdWNrZXRzRGVsZWdhdG9yLmphdmE6MTA5KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5ScGNSZWNlaXZlci5sYW1iZGEkcHJvY2Vzc1JlcXVlc3RBc3luYyQ0KFJwY1JlY2VpdmVyLmphdmE6MjAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5Bc3luY0V4ZWN1dG9yLmxhbWJkYSRzdWJtaXQkMChBc3luY0V4ZWN1dG9yLmphdmE6MjcyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoQ29udGV4dFJ1bm5hYmxlLmphdmE6NTApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlJDEucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM5KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo3Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5FeGVjdXRvcnMkUnVubmFibGVBZGFwdGVyLmNhbGwoRXhlY3V0b3JzLmphdmE6NTExKVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5GdXR1cmVUYXNrLnJ1bihGdXR1cmVUYXNrLmphdmE6MjY2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IucnVuV29ya2VyKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjExNDkpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvciRXb3JrZXIucnVuKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjYyNClcblx0YXQgamF2YS5sYW5nLlRocmVhZC5ydW4oVGhyZWFkLmphdmE6NzQ4KVxuQ2F1c2VkIGJ5OiBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbjogZXhwZWN0ZWQgQnVja2V0TWV0YWRhdGEubWV0YWRhdGFfZ2VuZXJhdGlvbjogMCBhY3R1YWw6IDFcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MjkzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAxKVxuXHQuLi4gMTcgbW9yZVxuXG5jb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS5GYXVsdDogSW1tdXRhYmxlRXJyb3JEZWZpbml0aW9ue2Jhc2U9UFJFQ09ORElUSU9OX0ZBSUxFRCwgY2F0ZWdvcnk9VVNFUl9FUlJPUiwgY2F1c2U9bnVsbCwgZGVidWdJbmZvPWNvbS5nb29nbGUubmV0LnJwYzMuUnBjRXhjZXB0aW9uOiBjbG91ZC5iaWdzdG9yZS5SZXNwb25zZUNvZGUuRXJyb3JDb2RlOjpJTkNPUlJFQ1RfTUVUQV9HRU5FUkFUSU9OX1NQRUNJRklFRDogZXhwZWN0ZWQgQnVja2V0TWV0YWRhdGEubWV0YWRhdGFfZ2VuZXJhdGlvbjogMCBhY3R1YWw6IDFcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udG9ScGMzRXhjZXB0aW9uKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MTM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmJ1Y2tldHMuTG9ja1JldGVudGlvblBvbGljeS5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoTG9ja1JldGVudGlvblBvbGljeS5qYXZhOjIxMilcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5idWNrZXRzLkxvY2tSZXRlbnRpb25Qb2xpY3kuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKExvY2tSZXRlbnRpb25Qb2xpY3kuamF2YTo1OSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLkJ1Y2tldHNEZWxlZ2F0b3IubG9ja1JldGVudGlvblBvbGljeShCdWNrZXRzRGVsZWdhdG9yLmphdmE6MTA5KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5ScGNSZWNlaXZlci5sYW1iZGEkcHJvY2Vzc1JlcXVlc3RBc3luYyQ0KFJwY1JlY2VpdmVyLmphdmE6MjAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5Bc3luY0V4ZWN1dG9yLmxhbWJkYSRzdWJtaXQkMChBc3luY0V4ZWN1dG9yLmphdmE6MjcyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoQ29udGV4dFJ1bm5hYmxlLmphdmE6NTApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlJDEucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM5KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo3Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5FeGVjdXRvcnMkUnVubmFibGVBZGFwdGVyLmNhbGwoRXhlY3V0b3JzLmphdmE6NTExKVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5GdXR1cmVUYXNrLnJ1bihGdXR1cmVUYXNrLmphdmE6MjY2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IucnVuV29ya2VyKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjExNDkpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvciRXb3JrZXIucnVuKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjYyNClcblx0YXQgamF2YS5sYW5nLlRocmVhZC5ydW4oVGhyZWFkLmphdmE6NzQ4KVxuQ2F1c2VkIGJ5OiBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbjogZXhwZWN0ZWQgQnVja2V0TWV0YWRhdGEubWV0YWRhdGFfZ2VuZXJhdGlvbjogMCBhY3R1YWw6IDFcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MjkzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAxKVxuXHQuLi4gMTcgbW9yZVxuLCBkb21haW49Z2xvYmFsLCBleHRlbmRlZEhlbHA9bnVsbCwgaHR0cEhlYWRlcnM9e30sIGh0dHBTdGF0dXM9cHJlY29uZGl0aW9uRmFpbGVkLCBpbnRlcm5hbFJlYXNvbj1SZWFzb257YXJndW1lbnRzPXt9LCBjYXVzZT1udWxsLCBjb2RlPWdkYXRhLkNvcmVFcnJvckRvbWFpbi5DT05ESVRJT05fTk9UX01FVCwgY3JlYXRlZEJ5QmFja2VuZD10cnVlLCBkZWJ1Z01lc3NhZ2U9Y29tLmdvb2dsZS5uZXQucnBjMy5ScGNFeGNlcHRpb246IGNsb3VkLmJpZ3N0b3JlLlJlc3BvbnNlQ29kZS5FcnJvckNvZGU6OklOQ09SUkVDVF9NRVRBX0dFTkVSQVRJT05fU1BFQ0lGSUVEOiBleHBlY3RlZCBCdWNrZXRNZXRhZGF0YS5tZXRhZGF0YV9nZW5lcmF0aW9uOiAwIGFjdHVhbDogMVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYnVja2V0cy5Mb2NrUmV0ZW50aW9uUG9saWN5LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChMb2NrUmV0ZW50aW9uUG9saWN5LmphdmE6MjEyKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmJ1Y2tldHMuTG9ja1JldGVudGlvblBvbGljeS5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoTG9ja1JldGVudGlvblBvbGljeS5qYXZhOjU5KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmZyYW1ld29yay5SZXF1ZXN0SGFuZGxlci5oYW5kbGUoUmVxdWVzdEhhbmRsZXIuamF2YToyOTQpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uQnVja2V0c0RlbGVnYXRvci5sb2NrUmV0ZW50aW9uUG9saWN5KEJ1Y2tldHNEZWxlZ2F0b3IuamF2YToxMDkpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBleHBlY3RlZCBCdWNrZXRNZXRhZGF0YS5tZXRhZGF0YV9nZW5lcmF0aW9uOiAwIGFjdHVhbDogMVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxNyBtb3JlXG4sIGVycm9yUHJvdG9Db2RlPUNPTkRJVElPTl9OT1RfTUVULCBlcnJvclByb3RvRG9tYWluPWdkYXRhLkNvcmVFcnJvckRvbWFpbiwgZmlsdGVyZWRNZXNzYWdlPW51bGwsIGxvY2F0aW9uPW51bGwsIG1lc3NhZ2U9bnVsbCwgdW5uYW1lZEFyZ3VtZW50cz1bXX0sIGxvY2F0aW9uPWhlYWRlcnMuSWYtTWF0Y2gsIG1lc3NhZ2U9UHJlY29uZGl0aW9uIEZhaWxlZCwgcmVhc29uPWNvbmRpdGlvbk5vdE1ldCwgcnBjQ29kZT00MTJ9IFByZWNvbmRpdGlvbiBGYWlsZWQ6IGNvbS5nb29nbGUubmV0LnJwYzMuUnBjRXhjZXB0aW9uOiBjbG91ZC5iaWdzdG9yZS5SZXNwb25zZUNvZGUuRXJyb3JDb2RlOjpJTkNPUlJFQ1RfTUVUQV9HRU5FUkFUSU9OX1NQRUNJRklFRDogZXhwZWN0ZWQgQnVja2V0TWV0YWRhdGEubWV0YWRhdGFfZ2VuZXJhdGlvbjogMCBhY3R1YWw6IDFcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udG9ScGMzRXhjZXB0aW9uKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MTM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmJ1Y2tldHMuTG9ja1JldGVudGlvblBvbGljeS5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoTG9ja1JldGVudGlvblBvbGljeS5qYXZhOjIxMilcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5idWNrZXRzLkxvY2tSZXRlbnRpb25Qb2xpY3kuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKExvY2tSZXRlbnRpb25Qb2xpY3kuamF2YTo1OSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLkJ1Y2tldHNEZWxlZ2F0b3IubG9ja1JldGVudGlvblBvbGljeShCdWNrZXRzRGVsZWdhdG9yLmphdmE6MTA5KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5ScGNSZWNlaXZlci5sYW1iZGEkcHJvY2Vzc1JlcXVlc3RBc3luYyQ0KFJwY1JlY2VpdmVyLmphdmE6MjAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5Bc3luY0V4ZWN1dG9yLmxhbWJkYSRzdWJtaXQkMChBc3luY0V4ZWN1dG9yLmphdmE6MjcyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoQ29udGV4dFJ1bm5hYmxlLmphdmE6NTApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlJDEucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM5KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo3Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5FeGVjdXRvcnMkUnVubmFibGVBZGFwdGVyLmNhbGwoRXhlY3V0b3JzLmphdmE6NTExKVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5GdXR1cmVUYXNrLnJ1bihGdXR1cmVUYXNrLmphdmE6MjY2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IucnVuV29ya2VyKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjExNDkpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvciRXb3JrZXIucnVuKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjYyNClcblx0YXQgamF2YS5sYW5nLlRocmVhZC5ydW4oVGhyZWFkLmphdmE6NzQ4KVxuQ2F1c2VkIGJ5OiBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbjogZXhwZWN0ZWQgQnVja2V0TWV0YWRhdGEubWV0YWRhdGFfZ2VuZXJhdGlvbjogMCBhY3R1YWw6IDFcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MjkzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAxKVxuXHQuLi4gMTcgbW9yZVxuXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLkVycm9yQ29sbGVjdG9yLnRvRmF1bHQoRXJyb3JDb2xsZWN0b3IuamF2YTo1NClcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnJlc3QuYWRhcHRlci5yb3N5LlJvc3lFcnJvckNvbnZlcnRlci50b0ZhdWx0KFJvc3lFcnJvckNvbnZlcnRlci5qYXZhOjY3KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIucmVzdC5hZGFwdGVyLnJvc3kuUm9zeUhhbmRsZXIkMi5jYWxsKFJvc3lIYW5kbGVyLmphdmE6MjU4KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIucmVzdC5hZGFwdGVyLnJvc3kuUm9zeUhhbmRsZXIkMi5jYWxsKFJvc3lIYW5kbGVyLmphdmE6MjM4KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS51dGlsLkNhbGxhYmxlRnV0dXJlLnJ1bihDYWxsYWJsZUZ1dHVyZS5qYXZhOjYyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuRGlyZWN0RXhlY3V0b3IuZXhlY3V0ZShEaXJlY3RFeGVjdXRvci5qYXZhOjMwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuZXhlY3V0ZUxpc3RlbmVyKEFic3RyYWN0RnV0dXJlLmphdmE6MTE0Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmNvbXBsZXRlKEFic3RyYWN0RnV0dXJlLmphdmE6OTYzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuc2V0KEFic3RyYWN0RnV0dXJlLmphdmE6NzMxKVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS51dGlsLkNhbGxhYmxlRnV0dXJlLnJ1bihDYWxsYWJsZUZ1dHVyZS5qYXZhOjYyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuRGlyZWN0RXhlY3V0b3IuZXhlY3V0ZShEaXJlY3RFeGVjdXRvci5qYXZhOjMwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuZXhlY3V0ZUxpc3RlbmVyKEFic3RyYWN0RnV0dXJlLmphdmE6MTE0Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmNvbXBsZXRlKEFic3RyYWN0RnV0dXJlLmphdmE6OTYzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuc2V0KEFic3RyYWN0RnV0dXJlLmphdmE6NzMxKVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS51dGlsLkNhbGxhYmxlRnV0dXJlLnJ1bihDYWxsYWJsZUZ1dHVyZS5qYXZhOjYyKVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIudGhyZWFkLlRocmVhZFRyYWNrZXJzJFRocmVhZFRyYWNraW5nUnVubmFibGUucnVuKFRocmVhZFRyYWNrZXJzLmphdmE6MTI2KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JFRyYWNlQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChUcmFjZUNvbnRleHQuamF2YTo0NTUpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5zZXJ2ZXIuQ29tbW9uTW9kdWxlJENvbnRleHRDYXJyeWluZ0V4ZWN1dG9yU2VydmljZSQxLnJ1bkluQ29udGV4dChDb21tb25Nb2R1bGUuamF2YTo4NDYpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkVHJhY2VDb250ZXh0UnVubmFibGUkMS5ydW4oVHJhY2VDb250ZXh0LmphdmE6NDYyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JEFic3RyYWN0VHJhY2VDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihUcmFjZUNvbnRleHQuamF2YTozMjEpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkQWJzdHJhY3RUcmFjZUNvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoVHJhY2VDb250ZXh0LmphdmE6MzEzKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JFRyYWNlQ29udGV4dFJ1bm5hYmxlLnJ1bihUcmFjZUNvbnRleHQuamF2YTo0NTkpXG5cdGF0IGNvbS5nb29nbGUuZ3NlLmludGVybmFsLkRpc3BhdGNoUXVldWVJbXBsJFdvcmtlclRocmVhZC5ydW4oRGlzcGF0Y2hRdWV1ZUltcGwuamF2YTo0MDMpXG4ifV0sImNvZGUiOjQxMiwibWVzc2FnZSI6IlByZWNvbmRpdGlvbiBGYWlsZWQifX0="
+ }
+ },
+ {
+ "ID": "26ad03b13cb9a440",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026kmsKeyName=projects%2Fdulcet-port-762%2Flocations%2Fus%2FkeyRings%2Fgo-integration-test%2FcryptoKeys%2Fkey1\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Type": [
+ "multipart/related; boundary=0c3a1ebded0d74462865e396c868acafbb701f15d2e7922cd62ec5885fe3"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "2183dfe9a0824db0099ffe40c5204242/339945353129427475;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026kmsKeyName=projects%2Fdulcet-port-762%2Flocations%2Fus%2FkeyRings%2Fgo-integration-test%2FcryptoKeys%2Fkey1\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "LS0wYzNhMWViZGVkMGQ3NDQ2Mjg2NWUzOTZjODY4YWNhZmJiNzAxZjE1ZDJlNzkyMmNkNjJlYzU4ODVmZTMNCkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vanNvbg0KDQp7ImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm5hbWUiOiJrbXMifQoNCi0tMGMzYTFlYmRlZDBkNzQ0NjI4NjVlMzk2Yzg2OGFjYWZiYjcwMWYxNWQyZTc5MjJjZDYyZWM1ODg1ZmUzDQpDb250ZW50LVR5cGU6IHRleHQvcGxhaW47IGNoYXJzZXQ9dXRmLTgNCg0KbXkgc2VjcmV0DQotLTBjM2ExZWJkZWQwZDc0NDYyODY1ZTM5NmM4NjhhY2FmYmI3MDFmMTVkMmU3OTIyY2Q2MmVjNTg4NWZlMy0tDQo="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3323"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:21 GMT"
+ ],
+ "Etag": [
+ "CIHswZKX290CEAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051480000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vnbu6:4207,/bns/yx/borg/yx/bns/blobstore2/bitpusher/115.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=bMysW-i0A4igzALuzLGYBQ"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yx/borg/yx/bns/blobstore2/bitpusher/115.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yx/borg/yx/bns/blobstore2/bitpusher/115:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWm1PRlpHcGk5RmhEek1fZDZaWW5nT2k1RTVURThhLXdxeDhkTnNrcVMyNVJkeURqQnQ0MVRlWnZtbjJLRHBEVm5yZUlsNTN0clJYXzFGNkpfMU5OS1ZRZlEzY0M5WTkwSHhZb1hGc09JbTgtUkRPYThhcUVFWnFrdkpjOGw2WmQyMzFhRmliVmwyQVVoeHFzQkdvOFJKTXZ2QTc1M29vT1BCanZJQTR0VEZ6bXVzbTEyU2lVU0xveWMwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_single_post_uploads"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UqwEUvAdhjjtCpa7cDpQOh4WraTFmvAU6477TEva-lYmRo41fu1ekaVjDSKM95VeLFE5gmOhJ-9s9IlFQMUgNT59m5Amw"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9rbXMvMTUzODA1MTE4MTQwOTc5MyIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2ttcyIsIm5hbWUiOiJrbXMiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE4MTQwOTc5MyIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOCIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNjoyMS40MDlaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjY6MjEuNDA5WiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI2OjIxLjQwOVoiLCJzaXplIjoiOSIsIm1kNUhhc2giOiJBQVBRUzQ2VHJuTVlucWlLQWJhZ3RRPT0iLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28va21zP2dlbmVyYXRpb249MTUzODA1MTE4MTQwOTc5MyZhbHQ9bWVkaWEiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9rbXMvMTUzODA1MTE4MTQwOTc5My9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2ttcy9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJrbXMiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE4MTQwOTc5MyIsImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6Im93bmVycyJ9LCJldGFnIjoiQ0lIc3daS1gyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2ttcy8xNTM4MDUxMTgxNDA5NzkzL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2ttcy9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0Ijoia21zIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTExODE0MDk3OTMiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0lIc3daS1gyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2ttcy8xNTM4MDUxMTgxNDA5NzkzL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2ttcy9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0Ijoia21zIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTExODE0MDk3OTMiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNJSHN3WktYMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9rbXMvMTUzODA1MTE4MTQwOTc5My91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28va21zL2FjbC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0Ijoia21zIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTExODE0MDk3OTMiLCJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwicm9sZSI6Ik9XTkVSIiwiZW1haWwiOiIzNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImV0YWciOiJDSUhzd1pLWDI5MENFQUU9In1dLCJvd25lciI6eyJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIn0sImNyYzMyYyI6IlVJNzg1QT09IiwiZXRhZyI6IkNJSHN3WktYMjkwQ0VBRT0iLCJrbXNLZXlOYW1lIjoicHJvamVjdHMvZHVsY2V0LXBvcnQtNzYyL2xvY2F0aW9ucy91cy9rZXlSaW5ncy9nby1pbnRlZ3JhdGlvbi10ZXN0L2NyeXB0b0tleXMva2V5MS9jcnlwdG9LZXlWZXJzaW9ucy8xIn0="
+ }
+ },
+ {
+ "ID": "83ecf58d8ae08666",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://storage.googleapis.com/go-integration-test-20180927-44630911863640-0001/kms",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "Go-http-client/1.1"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "fb8cda3f34c8118f6c49a1fee026ffb5/1930075786514900913;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "storage.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://storage.googleapis.com/go-integration-test-20180927-44630911863640-0001/kms"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Accept-Ranges": [
+ "bytes"
+ ],
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "9"
+ ],
+ "Content-Type": [
+ "text/plain; charset=utf-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:21 GMT"
+ ],
+ "Etag": [
+ "\"-CIHswZKX290CEAE=\""
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Last-Modified": [
+ "Thu, 27 Sep 2018 12:26:21 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "X-Goog-Encryption-Kms-Key-Name": [
+ "projects/dulcet-port-762/locations/us/keyRings/go-integration-test/cryptoKeys/key1/cryptoKeyVersions/1"
+ ],
+ "X-Goog-Expiration": [
+ "Sat, 27 Oct 2018 12:26:21 GMT"
+ ],
+ "X-Goog-Generation": [
+ "1538051181409793"
+ ],
+ "X-Goog-Hash": [
+ "crc32c=UI785A==",
+ "md5=AAPQS46TrnMYnqiKAbagtQ=="
+ ],
+ "X-Goog-Metageneration": [
+ "1"
+ ],
+ "X-Goog-Storage-Class": [
+ "STANDARD"
+ ],
+ "X-Goog-Stored-Content-Encoding": [
+ "identity"
+ ],
+ "X-Goog-Stored-Content-Length": [
+ "9"
+ ],
+ "X-Google-Backends": [
+ "/bns/xh/borg/xh/bns/cloud-storage/prod-cloud-storage-frontend.frontend/35,/bns/xh/borg/xh/bns/blobstore2/bitpusher/2.scotty,aclgag19:443"
+ ],
+ "X-Google-Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=bcysW7fsII6kswbkhYKoAQ"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "aclgag19:443,/bns/xh/borg/xh/bns/blobstore2/bitpusher/2.scotty,aclgag19:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/xh/borg/xh/bns/blobstore2/bitpusher/2:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBJ"
+ ],
+ "X-Google-Storage-Location": [
+ "US"
+ ],
+ "X-Guploader-Customer": [
+ "cloud-storage"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UoP-scCUQfp-FabC2kCJED0zZhTBx6qp7seKgu7IvwEPJru7voz-I4aRKXb5ZENMkXDurafjLwyzJdkcT6YgXmAtL3Eiw"
+ ]
+ },
+ "Body": "bXkgc2VjcmV0"
+ }
+ },
+ {
+ "ID": "107c5ecc1982bc8a",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/kms?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "9ecd0d79a117a2848bed84654246265a/3520487690565274960;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/kms?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3323"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:22 GMT"
+ ],
+ "Etag": [
+ "CIHswZKX290CEAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051481000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrp62:4379,/bns/yw/borg/yw/bns/blobstore2/bitpusher/191.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=bcysW-GxNtW_hATnsKm4BA"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yw/borg/yw/bns/blobstore2/bitpusher/191.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yw/borg/yw/bns/blobstore2/bitpusher/191:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRWm1PRlpHcGk5RmhEek1fZDZaWW5nT2k1RTVURThhLXdxeDhkTnNrcVMyNVJkeURqQnQ0MVRlWnZtbjJLRHBEVm5yZUlsNTN0clJYXzFGNkpfMU5OS1ZRZlEzY0M5WTkwSHhZb1hGc09JbTgtUkRPYThhcUVFWnFrdkpjOGw2WmQyMzFhRmliVmwyQVVoeHFzQkdvOFJKTXZ2QTc1M29vT1BCanZJQTR0VEZ6bXVzbTEyU2lVU0xveWMwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UpVIJ58Vc6OdRzCeCdWcfDPryC9SxGM8vlaBeyGyfjN8QT009BeR4KdR8ZxmXI_VCiiob9ZCk7DrgkQl5muzJ9PTDit8Q"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9rbXMvMTUzODA1MTE4MTQwOTc5MyIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2ttcyIsIm5hbWUiOiJrbXMiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE4MTQwOTc5MyIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOCIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNjoyMS40MDlaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjY6MjEuNDA5WiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI2OjIxLjQwOVoiLCJzaXplIjoiOSIsIm1kNUhhc2giOiJBQVBRUzQ2VHJuTVlucWlLQWJhZ3RRPT0iLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28va21zP2dlbmVyYXRpb249MTUzODA1MTE4MTQwOTc5MyZhbHQ9bWVkaWEiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9rbXMvMTUzODA1MTE4MTQwOTc5My9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2ttcy9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJrbXMiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE4MTQwOTc5MyIsImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6Im93bmVycyJ9LCJldGFnIjoiQ0lIc3daS1gyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2ttcy8xNTM4MDUxMTgxNDA5NzkzL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2ttcy9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0Ijoia21zIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTExODE0MDk3OTMiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0lIc3daS1gyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2ttcy8xNTM4MDUxMTgxNDA5NzkzL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2ttcy9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0Ijoia21zIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTExODE0MDk3OTMiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNJSHN3WktYMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9rbXMvMTUzODA1MTE4MTQwOTc5My91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28va21zL2FjbC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0Ijoia21zIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTExODE0MDk3OTMiLCJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwicm9sZSI6Ik9XTkVSIiwiZW1haWwiOiIzNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImV0YWciOiJDSUhzd1pLWDI5MENFQUU9In1dLCJvd25lciI6eyJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIn0sImNyYzMyYyI6IlVJNzg1QT09IiwiZXRhZyI6IkNJSHN3WktYMjkwQ0VBRT0iLCJrbXNLZXlOYW1lIjoicHJvamVjdHMvZHVsY2V0LXBvcnQtNzYyL2xvY2F0aW9ucy91cy9rZXlSaW5ncy9nby1pbnRlZ3JhdGlvbi10ZXN0L2NyeXB0b0tleXMva2V5MS9jcnlwdG9LZXlWZXJzaW9ucy8xIn0="
+ }
+ },
+ {
+ "ID": "13fbc80fb1aa6b47",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/kms?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "97f99806cd482d3aed9f661961a2e0f0/4279806126373314719;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/kms?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 204,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "0"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:22 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051482000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrvj9:4122,/bns/yv/borg/yv/bns/blobstore2/bitpusher/296.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=bsysW-vuAcu0gASSk5bYAQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/296.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/296:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWm1PRlpHcGk5RmhEek1fZDZaWW5nT2k1RTVURThhLXdxeDhkTnNrcVMyNVJkeURqQnQ0MVRlWnZtbjJLRHBEVm5yZUlsNTN0clJYXzFGNkpfMU5OS1ZRZlEzY0M5WTkwSHhZb1hGc09JbTgtUkRPYThhcUVFWnFrdkpjOGw2WmQyMzFhRmliVmwyQVVoeHFzQkdvOFJKTXZ2QTc1M29vT1BCanZJQTR0VEZ6bXVzbTEyU2lVU0xveWMwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UpDftfZWHfmZJAilgwtUbtPOsOPMq-dwRcjfSZJEri1v0W1v-HfuBBevxJ6rYv06LgT2JjjUsb5K7ntra9HTFiz6ya_kQ"
+ ]
+ },
+ "Body": ""
+ }
+ },
+ {
+ "ID": "b8cb55f73f268a09",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Type": [
+ "multipart/related; boundary=cd07c217ad1b4040d04177ecdd1c792ad8cf91b4aa87c7fa4f72f9042bb1"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "856c112fe406a0bd419f15f0ec95f1ca/5110898490842739438;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ],
+ "X-Goog-Encryption-Algorithm": [
+ "AES256"
+ ],
+ "X-Goog-Encryption-Key": [
+ "REDACTED"
+ ],
+ "X-Goog-Encryption-Key-Sha256": [
+ "Io4lnOPU+EThO0X0nq7mNEXB1rWxZsBI4L37pBmyfDc="
+ ]
+ },
+ "Body": "LS1jZDA3YzIxN2FkMWI0MDQwZDA0MTc3ZWNkZDFjNzkyYWQ4Y2Y5MWI0YWE4N2M3ZmE0ZjcyZjkwNDJiYjENCkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vanNvbg0KDQp7ImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsImNhY2hlQ29udHJvbCI6InB1YmxpYywgbWF4LWFnZT02MCIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbiIsIm5hbWUiOiJjc2VrIn0KDQotLWNkMDdjMjE3YWQxYjQwNDBkMDQxNzdlY2RkMWM3OTJhZDhjZjkxYjRhYTg3YzdmYTRmNzJmOTA0MmJiMQ0KQ29udGVudC1UeXBlOiB0ZXh0L3BsYWluDQoNCm15IHNlY3JldA0KLS1jZDA3YzIxN2FkMWI0MDQwZDA0MTc3ZWNkZDFjNzkyYWQ4Y2Y5MWI0YWE4N2M3ZmE0ZjcyZjkwNDJiYjEtLQ0K"
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3355"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:22 GMT"
+ ],
+ "Etag": [
+ "CJD7+ZKX290CEAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051480000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vnap189:4365,/bns/yx/borg/yx/bns/blobstore2/bitpusher/28.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=bsysW--PDpLlzAKvsrHYBA"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yx/borg/yx/bns/blobstore2/bitpusher/28.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yx/borg/yx/bns/blobstore2/bitpusher/28:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWm1PRlpHcGk5RmhEek1fZDZaWW5nT2k1RTVURThhLXdxeDhkTnNrcVMyNVJkeURqQnQ0MVRlWnZtbjJLRHBEVm5yZUlsNTN0clJYXzFGNkpfMU5OS1ZRZlEzY0M5WTkwSHhZb1hGc09JbTgtUkRPYThhcUVFWnFrdkpjOGw2WmQyMzFhRmliVmwyQVVoeHFzQkdvOFJKTXZ2QTc1M29vT1BCanZJQTR0VEZ6bXVzbTEyU2lVU0xveWMwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_single_post_uploads"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Ur4Us7KxtRF9-lVKK2FUYH_EXFpHY-EaaO0VIwmldcOC2ISoEAfhjWxLUcaaaKqVyW2WeyswAJ3b1so1p7VHGutspR5jA"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jc2VrLzE1MzgwNTExODIzMjkyMzIiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9jc2VrIiwibmFtZSI6ImNzZWsiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE4MjMyOTIzMiIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbiIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNjoyMi4zMjhaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjY6MjIuMzI4WiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI2OjIyLjMyOFoiLCJzaXplIjoiOSIsIm1kNUhhc2giOiJBQVBRUzQ2VHJuTVlucWlLQWJhZ3RRPT0iLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vY3Nlaz9nZW5lcmF0aW9uPTE1MzgwNTExODIzMjkyMzImYWx0PW1lZGlhIiwiY2FjaGVDb250cm9sIjoicHVibGljLCBtYXgtYWdlPTYwIiwiYWNsIjpbeyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvY3Nlay8xNTM4MDUxMTgyMzI5MjMyL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vY3Nlay9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJjc2VrIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTExODIzMjkyMzIiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNKRDcrWktYMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jc2VrLzE1MzgwNTExODIzMjkyMzIvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vY3Nlay9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiY3NlayIsImdlbmVyYXRpb24iOiIxNTM4MDUxMTgyMzI5MjMyIiwiZW50aXR5IjoicHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6ImVkaXRvcnMifSwiZXRhZyI6IkNKRDcrWktYMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jc2VrLzE1MzgwNTExODIzMjkyMzIvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vY3Nlay9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiY3NlayIsImdlbmVyYXRpb24iOiIxNTM4MDUxMTgyMzI5MjMyIiwiZW50aXR5IjoicHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6IlJFQURFUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJ2aWV3ZXJzIn0sImV0YWciOiJDSkQ3K1pLWDI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvY3Nlay8xNTM4MDUxMTgyMzI5MjMyL3VzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9jc2VrL2FjbC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiY3NlayIsImdlbmVyYXRpb24iOiIxNTM4MDUxMTgyMzI5MjMyIiwiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInJvbGUiOiJPV05FUiIsImVtYWlsIjoiMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJldGFnIjoiQ0pENytaS1gyOTBDRUFFPSJ9XSwib3duZXIiOnsiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSJ9LCJjcmMzMmMiOiJVSTc4NUE9PSIsImV0YWciOiJDSkQ3K1pLWDI5MENFQUU9IiwiY3VzdG9tZXJFbmNyeXB0aW9uIjp7ImVuY3J5cHRpb25BbGdvcml0aG0iOiJBRVMyNTYiLCJrZXlTaGEyNTYiOiJJbzRsbk9QVStFVGhPMFgwbnE3bU5FWEIxcld4WnNCSTRMMzdwQm15ZkRjPSJ9fQ=="
+ }
+ },
+ {
+ "ID": "d3abeec5c28d5532",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/csek/rewriteTo/b/go-integration-test-20180927-44630911863640-0001/o/cmek?alt=json\u0026destinationKmsKeyName=projects%2Fdulcet-port-762%2Flocations%2Fus%2FkeyRings%2Fgo-integration-test%2FcryptoKeys%2Fkey1\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "3"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "33a94b645ecf5e03ba14b10348949d2e/6701310394893113485;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/csek/rewriteTo/b/go-integration-test-20180927-44630911863640-0001/o/cmek?alt=json\u0026destinationKmsKeyName=projects%2Fdulcet-port-762%2Flocations%2Fus%2FkeyRings%2Fgo-integration-test%2FcryptoKeys%2Fkey1\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ],
+ "X-Goog-Copy-Source-Encryption-Algorithm": [
+ "AES256"
+ ],
+ "X-Goog-Copy-Source-Encryption-Key": [
+ "REDACTED"
+ ],
+ "X-Goog-Copy-Source-Encryption-Key-Sha256": [
+ "Io4lnOPU+EThO0X0nq7mNEXB1rWxZsBI4L37pBmyfDc="
+ ]
+ },
+ "Body": "e30K"
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3461"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:22 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051482000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrdz77:4028,/bns/yv/borg/yv/bns/blobstore2/bitpusher/82.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=bsysW4aoIoOlgASf-Jco"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/82.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/82:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp0ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4StK4wESxgF5YTI5LmMuRW93QkpRWm1PRlpHcGk5RmhEek1fZDZaWW5nT2k1RTVURThhLXdxeDhkTnNrcVMyNVJkeURqQnQ0MVRlWnZtbjJLRHBEVm5yZUlsNTN0clJYXzFGNkpfMU5OS1ZRZlEzY0M5WTkwSHhZb1hGc09JbTgtUkRPYThhcUVFWnFrdkpjOGw2WmQyMzFhRmliVmwyQVVoeHFzQkdvOFJKTXZ2QTc1M29vT1BCanZJQTR0VEZ6bXVzbTEyU2lVU0xveWMwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Up-GIJ-hr4O1BXwGcOo0ufD5O5Cck3nZrSYqNqSDYS3I25lPDsq81Qdf83Kt3O7zYafFwVdpGLlHrPgdWFPsYxU-dQMWw"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNyZXdyaXRlUmVzcG9uc2UiLCJ0b3RhbEJ5dGVzUmV3cml0dGVuIjoiOSIsIm9iamVjdFNpemUiOiI5IiwiZG9uZSI6dHJ1ZSwicmVzb3VyY2UiOnsia2luZCI6InN0b3JhZ2Ujb2JqZWN0IiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvY21lay8xNTM4MDUxMTgyODgwMjY2Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vY21layIsIm5hbWUiOiJjbWVrIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTExODI4ODAyNjYiLCJtZXRhZ2VuZXJhdGlvbiI6IjEiLCJjb250ZW50VHlwZSI6InRleHQvcGxhaW4iLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjY6MjIuODgwWiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI2OjIyLjg4MFoiLCJzdG9yYWdlQ2xhc3MiOiJTVEFOREFSRCIsInRpbWVTdG9yYWdlQ2xhc3NVcGRhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNjoyMi44ODBaIiwic2l6ZSI6IjkiLCJtZDVIYXNoIjoiQUFQUVM0NlRybk1ZbnFpS0FiYWd0UT09IiwibWVkaWFMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vZG93bmxvYWQvc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2NtZWs/Z2VuZXJhdGlvbj0xNTM4MDUxMTgyODgwMjY2JmFsdD1tZWRpYSIsImNhY2hlQ29udHJvbCI6InB1YmxpYywgbWF4LWFnZT02MCIsImFjbCI6W3sia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2NtZWsvMTUzODA1MTE4Mjg4MDI2Ni9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2NtZWsvYWNsL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiY21layIsImdlbmVyYXRpb24iOiIxNTM4MDUxMTgyODgwMjY2IiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDSXJNbTVPWDI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvY21lay8xNTM4MDUxMTgyODgwMjY2L3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2NtZWsvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6ImNtZWsiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE4Mjg4MDI2NiIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDSXJNbTVPWDI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvY21lay8xNTM4MDUxMTgyODgwMjY2L3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2NtZWsvYWNsL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6ImNtZWsiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE4Mjg4MDI2NiIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0lyTW01T1gyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2NtZWsvMTUzODA1MTE4Mjg4MDI2Ni91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vY21lay9hY2wvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6ImNtZWsiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE4Mjg4MDI2NiIsImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJyb2xlIjoiT1dORVIiLCJlbWFpbCI6IjM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiZXRhZyI6IkNJck1tNU9YMjkwQ0VBRT0ifV0sIm93bmVyIjp7ImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20ifSwiY3JjMzJjIjoiVUk3ODVBPT0iLCJldGFnIjoiQ0lyTW01T1gyOTBDRUFFPSIsImttc0tleU5hbWUiOiJwcm9qZWN0cy9kdWxjZXQtcG9ydC03NjIvbG9jYXRpb25zL3VzL2tleVJpbmdzL2dvLWludGVncmF0aW9uLXRlc3QvY3J5cHRvS2V5cy9rZXkxL2NyeXB0b0tleVZlcnNpb25zLzEifX0="
+ }
+ },
+ {
+ "ID": "b97ea7cb09758872",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://storage.googleapis.com/go-integration-test-20180927-44630911863640-0001/cmek",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "Go-http-client/1.1"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "dd30b0cbb65a6fc65281b1c38c359d6f/8219384333752220972;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "storage.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://storage.googleapis.com/go-integration-test-20180927-44630911863640-0001/cmek"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Accept-Ranges": [
+ "bytes"
+ ],
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "9"
+ ],
+ "Content-Type": [
+ "text/plain"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:23 GMT"
+ ],
+ "Etag": [
+ "\"-CIrMm5OX290CEAE=\""
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Last-Modified": [
+ "Thu, 27 Sep 2018 12:26:22 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "X-Goog-Encryption-Kms-Key-Name": [
+ "projects/dulcet-port-762/locations/us/keyRings/go-integration-test/cryptoKeys/key1/cryptoKeyVersions/1"
+ ],
+ "X-Goog-Expiration": [
+ "Sat, 27 Oct 2018 12:26:22 GMT"
+ ],
+ "X-Goog-Generation": [
+ "1538051182880266"
+ ],
+ "X-Goog-Hash": [
+ "crc32c=UI785A==",
+ "md5=AAPQS46TrnMYnqiKAbagtQ=="
+ ],
+ "X-Goog-Metageneration": [
+ "1"
+ ],
+ "X-Goog-Storage-Class": [
+ "STANDARD"
+ ],
+ "X-Goog-Stored-Content-Encoding": [
+ "identity"
+ ],
+ "X-Goog-Stored-Content-Length": [
+ "9"
+ ],
+ "X-Google-Backends": [
+ "/bns/xh/borg/xh/bns/cloud-storage/prod-cloud-storage-frontend.frontend/37,/bns/xh/borg/xh/bns/blobstore2/bitpusher/64.scotty,aclgag19:443"
+ ],
+ "X-Google-Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=b8ysW-0KwqazBrKogYgO"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "aclgag19:443,/bns/xh/borg/xh/bns/blobstore2/bitpusher/64.scotty,aclgag19:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/xh/borg/xh/bns/blobstore2/bitpusher/64:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBJ"
+ ],
+ "X-Google-Storage-Location": [
+ "US"
+ ],
+ "X-Guploader-Customer": [
+ "cloud-storage"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UpEYPjNylJw_x0HSlaYlHnG5ObFsMfVkmtpR5B5UuLAgVHHvkN1Mlj7d84jSdO5r9VR20TYFanxN-HpkmO08bEr5XYNbQ"
+ ]
+ },
+ "Body": "bXkgc2VjcmV0"
+ }
+ },
+ {
+ "ID": "7470c09fdaf73fca",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/cmek?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "4412449cb3de7d4e1ea446fc09b69389/9809796233507759050;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/cmek?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3360"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:23 GMT"
+ ],
+ "Etag": [
+ "CIrMm5OX290CEAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051481000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrjl65:4261,/bns/yw/borg/yw/bns/blobstore2/bitpusher/195.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=b8ysW9C1DtTDhgTjyLO4CA"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yw/borg/yw/bns/blobstore2/bitpusher/195.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yw/borg/yw/bns/blobstore2/bitpusher/195:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRWm1PRlpHcGk5RmhEek1fZDZaWW5nT2k1RTVURThhLXdxeDhkTnNrcVMyNVJkeURqQnQ0MVRlWnZtbjJLRHBEVm5yZUlsNTN0clJYXzFGNkpfMU5OS1ZRZlEzY0M5WTkwSHhZb1hGc09JbTgtUkRPYThhcUVFWnFrdkpjOGw2WmQyMzFhRmliVmwyQVVoeHFzQkdvOFJKTXZ2QTc1M29vT1BCanZJQTR0VEZ6bXVzbTEyU2lVU0xveWMwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UrqAbn5AuAiZxxcaDtDRpw3gqzV-tqipVeKhMqY5BHMNNGkTvc_PIactpOG0D99x0BfLS383RIBwfCxQMc_39vIffe6oA"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jbWVrLzE1MzgwNTExODI4ODAyNjYiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9jbWVrIiwibmFtZSI6ImNtZWsiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE4Mjg4MDI2NiIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbiIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNjoyMi44ODBaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjY6MjIuODgwWiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI2OjIyLjg4MFoiLCJzaXplIjoiOSIsIm1kNUhhc2giOiJBQVBRUzQ2VHJuTVlucWlLQWJhZ3RRPT0iLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vY21laz9nZW5lcmF0aW9uPTE1MzgwNTExODI4ODAyNjYmYWx0PW1lZGlhIiwiY2FjaGVDb250cm9sIjoicHVibGljLCBtYXgtYWdlPTYwIiwiYWNsIjpbeyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvY21lay8xNTM4MDUxMTgyODgwMjY2L3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vY21lay9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJjbWVrIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTExODI4ODAyNjYiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNJck1tNU9YMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jbWVrLzE1MzgwNTExODI4ODAyNjYvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vY21lay9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiY21layIsImdlbmVyYXRpb24iOiIxNTM4MDUxMTgyODgwMjY2IiwiZW50aXR5IjoicHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6ImVkaXRvcnMifSwiZXRhZyI6IkNJck1tNU9YMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jbWVrLzE1MzgwNTExODI4ODAyNjYvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vY21lay9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiY21layIsImdlbmVyYXRpb24iOiIxNTM4MDUxMTgyODgwMjY2IiwiZW50aXR5IjoicHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6IlJFQURFUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJ2aWV3ZXJzIn0sImV0YWciOiJDSXJNbTVPWDI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvY21lay8xNTM4MDUxMTgyODgwMjY2L3VzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9jbWVrL2FjbC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiY21layIsImdlbmVyYXRpb24iOiIxNTM4MDUxMTgyODgwMjY2IiwiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInJvbGUiOiJPV05FUiIsImVtYWlsIjoiMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJldGFnIjoiQ0lyTW01T1gyOTBDRUFFPSJ9XSwib3duZXIiOnsiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSJ9LCJjcmMzMmMiOiJVSTc4NUE9PSIsImV0YWciOiJDSXJNbTVPWDI5MENFQUU9Iiwia21zS2V5TmFtZSI6InByb2plY3RzL2R1bGNldC1wb3J0LTc2Mi9sb2NhdGlvbnMvdXMva2V5UmluZ3MvZ28taW50ZWdyYXRpb24tdGVzdC9jcnlwdG9LZXlzL2tleTEvY3J5cHRvS2V5VmVyc2lvbnMvMSJ9"
+ }
+ },
+ {
+ "ID": "79abcb8c4c7c4a93",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/csek?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "0551ce04083a90c2f936914acf102ade/10640889697471968538;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/csek?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 204,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "0"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:23 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051482000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrpa10:4240,/bns/yw/borg/yw/bns/blobstore2/bitpusher/26.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=b8ysW-XJFYrahQTRl7aoCQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yw/borg/yw/bns/blobstore2/bitpusher/26.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yw/borg/yw/bns/blobstore2/bitpusher/26:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWm1PRlpHcGk5RmhEek1fZDZaWW5nT2k1RTVURThhLXdxeDhkTnNrcVMyNVJkeURqQnQ0MVRlWnZtbjJLRHBEVm5yZUlsNTN0clJYXzFGNkpfMU5OS1ZRZlEzY0M5WTkwSHhZb1hGc09JbTgtUkRPYThhcUVFWnFrdkpjOGw2WmQyMzFhRmliVmwyQVVoeHFzQkdvOFJKTXZ2QTc1M29vT1BCanZJQTR0VEZ6bXVzbTEyU2lVU0xveWMwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UqxmCHZ6nG_fv9txvIgPWT-btTH3CklFSONa4gIntCV80jUBLdhvwLvPbL4S2_Wxe7VeI81G89Dv2wOLxd6nd6nfS9_vA"
+ ]
+ },
+ "Body": ""
+ }
+ },
+ {
+ "ID": "bfc9cf8ca6d60100",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/cmek?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "20625a94d307387d3dd25631634e914f/11400208137574910057;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/cmek?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 204,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "0"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:23 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051482000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrch186:4050,/bns/yv/borg/yv/bns/blobstore2/bitpusher/289.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=b8ysW7H-IIb-gQTynLpY"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/289.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/289:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWm1PRlpHcGk5RmhEek1fZDZaWW5nT2k1RTVURThhLXdxeDhkTnNrcVMyNVJkeURqQnQ0MVRlWnZtbjJLRHBEVm5yZUlsNTN0clJYXzFGNkpfMU5OS1ZRZlEzY0M5WTkwSHhZb1hGc09JbTgtUkRPYThhcUVFWnFrdkpjOGw2WmQyMzFhRmliVmwyQVVoeHFzQkdvOFJKTXZ2QTc1M29vT1BCanZJQTR0VEZ6bXVzbTEyU2lVU0xveWMwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UpID_zLKj3Thx28dlgiIatppY3nHmPVtxZsDwGTNfapqMcGaQdejUos_3Y7IqGs0bgkSdqKF1By7cJITT6l3yIeFeTocQ"
+ ]
+ },
+ "Body": ""
+ }
+ },
+ {
+ "ID": "e95d94c243928a86",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/storage/v1/b?alt=json\u0026prettyPrint=false\u0026project=dulcet-port-762",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "196"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "26eda56d11fa90f3369f3d16e097cb4a/12990618942130433544;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b?alt=json\u0026prettyPrint=false\u0026project=dulcet-port-762"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJlbmNyeXB0aW9uIjp7ImRlZmF1bHRLbXNLZXlOYW1lIjoicHJvamVjdHMvZHVsY2V0LXBvcnQtNzYyL2xvY2F0aW9ucy91cy9rZXlSaW5ncy9nby1pbnRlZ3JhdGlvbi10ZXN0L2NyeXB0b0tleXMva2V5MSJ9LCJsb2NhdGlvbiI6IlVTIiwibmFtZSI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxOSJ9Cg=="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "546"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:24 GMT"
+ ],
+ "Etag": [
+ "CAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051482000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrvs3:4021,/bns/yw/borg/yw/bns/blobstore2/bitpusher/192.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=b8ysW63yK4eqhQTHrbmIBw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yw/borg/yw/bns/blobstore2/bitpusher/192.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yw/borg/yw/bns/blobstore2/bitpusher/192:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWm1PRlpHcGk5RmhEek1fZDZaWW5nT2k1RTVURThhLXdxeDhkTnNrcVMyNVJkeURqQnQ0MVRlWnZtbjJLRHBEVm5yZUlsNTN0clJYXzFGNkpfMU5OS1ZRZlEzY0M5WTkwSHhZb1hGc09JbTgtUkRPYThhcUVFWnFrdkpjOGw2WmQyMzFhRmliVmwyQVVoeHFzQkdvOFJKTXZ2QTc1M29vT1BCanZJQTR0VEZ6bXVzbTEyU2lVU0xveWMwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UotNfKtVqKNn8cMC1eOIsB9ICtRV_iouKvDLT910PuKBmI8ITvotlxU93Y2PkHDOt8Q_U6jOmAWK-YWwvrmdto7Q7Bn1w"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxOSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxOSIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTkiLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjY6MjQuMTU2WiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI2OjI0LjE1NloiLCJtZXRhZ2VuZXJhdGlvbiI6IjEiLCJlbmNyeXB0aW9uIjp7ImRlZmF1bHRLbXNLZXlOYW1lIjoicHJvamVjdHMvZHVsY2V0LXBvcnQtNzYyL2xvY2F0aW9ucy91cy9rZXlSaW5ncy9nby1pbnRlZ3JhdGlvbi10ZXN0L2NyeXB0b0tleXMva2V5MSJ9LCJsb2NhdGlvbiI6IlVTIiwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJldGFnIjoiQ0FFPSJ9"
+ }
+ },
+ {
+ "ID": "20ba6d16efe589ea",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0019?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "5788138dee7e452edf25cc2804838019/14580749371221005222;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0019?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0, must-revalidate, no-transform"
+ ],
+ "Content-Length": [
+ "2473"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:24 GMT"
+ ],
+ "Etag": [
+ "CAE="
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:26:24 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051484000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vndt66:4404,/bns/yx/borg/yx/bns/blobstore2/bitpusher/131.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=cMysW--wF8a5zALhwpn4Ag"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yx/borg/yx/bns/blobstore2/bitpusher/131.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yx/borg/yx/bns/blobstore2/bitpusher/131:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRWm1PRlpHcGk5RmhEek1fZDZaWW5nT2k1RTVURThhLXdxeDhkTnNrcVMyNVJkeURqQnQ0MVRlWnZtbjJLRHBEVm5yZUlsNTN0clJYXzFGNkpfMU5OS1ZRZlEzY0M5WTkwSHhZb1hGc09JbTgtUkRPYThhcUVFWnFrdkpjOGw2WmQyMzFhRmliVmwyQVVoeHFzQkdvOFJKTXZ2QTc1M29vT1BCanZJQTR0VEZ6bXVzbTEyU2lVU0xveWMwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UoFlZwaiTWES3oc5jmTNwSMGBjBKeRObUKKMPiM0vcvToX1cVnGImNDiXBmo4xbYBE-yRM4_mBGxRl16aJv7ji_xVVoJg"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxOSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxOSIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTkiLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjY6MjQuMTU2WiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI2OjI0LjE1NloiLCJtZXRhZ2VuZXJhdGlvbiI6IjEiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxOS9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxOS9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTkiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxOS9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTkvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxOSIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDQUU9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTkvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDE5L2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTkiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNBRT0ifV0sImRlZmF1bHRPYmplY3RBY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0FFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0FFPSJ9XSwiZW5jcnlwdGlvbiI6eyJkZWZhdWx0S21zS2V5TmFtZSI6InByb2plY3RzL2R1bGNldC1wb3J0LTc2Mi9sb2NhdGlvbnMvdXMva2V5UmluZ3MvZ28taW50ZWdyYXRpb24tdGVzdC9jcnlwdG9LZXlzL2tleTEifSwib3duZXIiOnsiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUifSwibG9jYXRpb24iOiJVUyIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwiZXRhZyI6IkNBRT0ifQ=="
+ }
+ },
+ {
+ "ID": "98d4d0396aa532db",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0019/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Type": [
+ "multipart/related; boundary=0183510b9204e3050d5dc85bb81ef02775f84a265d260d4e05220590dcd1"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "f1ca850acbb001abd943c3dc4b11d15c/15412124305850181366;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0019/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "LS0wMTgzNTEwYjkyMDRlMzA1MGQ1ZGM4NWJiODFlZjAyNzc1Zjg0YTI2NWQyNjBkNGUwNTIyMDU5MGRjZDENCkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vanNvbg0KDQp7ImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxOSIsIm5hbWUiOiJrbXMifQoNCi0tMDE4MzUxMGI5MjA0ZTMwNTBkNWRjODViYjgxZWYwMjc3NWY4NGEyNjVkMjYwZDRlMDUyMjA1OTBkY2QxDQpDb250ZW50LVR5cGU6IHRleHQvcGxhaW47IGNoYXJzZXQ9dXRmLTgNCg0KbXkgc2VjcmV0DQotLTAxODM1MTBiOTIwNGUzMDUwZDVkYzg1YmI4MWVmMDI3NzVmODRhMjY1ZDI2MGQ0ZTA1MjIwNTkwZGNkMS0tDQo="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3323"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:26 GMT"
+ ],
+ "Etag": [
+ "CJyE6ZSX290CEAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051482000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrl7:4233,/bns/yr/borg/yr/bns/blobstore2/bitpusher/41.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=cMysW8CILMy9kASo-IzwBQ"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/41.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/41:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWm1PRlpHcGk5RmhEek1fZDZaWW5nT2k1RTVURThhLXdxeDhkTnNrcVMyNVJkeURqQnQ0MVRlWnZtbjJLRHBEVm5yZUlsNTN0clJYXzFGNkpfMU5OS1ZRZlEzY0M5WTkwSHhZb1hGc09JbTgtUkRPYThhcUVFWnFrdkpjOGw2WmQyMzFhRmliVmwyQVVoeHFzQkdvOFJKTXZ2QTc1M29vT1BCanZJQTR0VEZ6bXVzbTEyU2lVU0xveWMwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_single_post_uploads"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Uo6QGRGmaNNuOiWVDAgdtuLslGQeZy-98D7XTNvT-KZreR-QMUmyGGG3KX-ZiREC1U4y2-ieiHWGgOaBkdl4bOc6g9lxw"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxOS9rbXMvMTUzODA1MTE4NjI0NjE3MiIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxOS9vL2ttcyIsIm5hbWUiOiJrbXMiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTkiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE4NjI0NjE3MiIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOCIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNjoyNi4yNDVaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjY6MjYuMjQ1WiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI2OjI2LjI0NVoiLCJzaXplIjoiOSIsIm1kNUhhc2giOiJBQVBRUzQ2VHJuTVlucWlLQWJhZ3RRPT0iLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDE5L28va21zP2dlbmVyYXRpb249MTUzODA1MTE4NjI0NjE3MiZhbHQ9bWVkaWEiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxOS9rbXMvMTUzODA1MTE4NjI0NjE3Mi9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxOS9vL2ttcy9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTkiLCJvYmplY3QiOiJrbXMiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE4NjI0NjE3MiIsImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6Im93bmVycyJ9LCJldGFnIjoiQ0p5RTZaU1gyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDE5L2ttcy8xNTM4MDUxMTg2MjQ2MTcyL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxOS9vL2ttcy9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDE5Iiwib2JqZWN0Ijoia21zIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTExODYyNDYxNzIiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0p5RTZaU1gyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDE5L2ttcy8xNTM4MDUxMTg2MjQ2MTcyL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxOS9vL2ttcy9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDE5Iiwib2JqZWN0Ijoia21zIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTExODYyNDYxNzIiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNKeUU2WlNYMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxOS9rbXMvMTUzODA1MTE4NjI0NjE3Mi91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDE5L28va21zL2FjbC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDE5Iiwib2JqZWN0Ijoia21zIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTExODYyNDYxNzIiLCJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwicm9sZSI6Ik9XTkVSIiwiZW1haWwiOiIzNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImV0YWciOiJDSnlFNlpTWDI5MENFQUU9In1dLCJvd25lciI6eyJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIn0sImNyYzMyYyI6IlVJNzg1QT09IiwiZXRhZyI6IkNKeUU2WlNYMjkwQ0VBRT0iLCJrbXNLZXlOYW1lIjoicHJvamVjdHMvZHVsY2V0LXBvcnQtNzYyL2xvY2F0aW9ucy91cy9rZXlSaW5ncy9nby1pbnRlZ3JhdGlvbi10ZXN0L2NyeXB0b0tleXMva2V5MS9jcnlwdG9LZXlWZXJzaW9ucy8xIn0="
+ }
+ },
+ {
+ "ID": "9f8cf00a4303c7e8",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://storage.googleapis.com/go-integration-test-20180927-44630911863640-0019/kms",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "Go-http-client/1.1"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "84569a2d9db1db62fa4d579148c78171/17002254739235654548;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "storage.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://storage.googleapis.com/go-integration-test-20180927-44630911863640-0019/kms"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Accept-Ranges": [
+ "bytes"
+ ],
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "9"
+ ],
+ "Content-Type": [
+ "text/plain; charset=utf-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:26 GMT"
+ ],
+ "Etag": [
+ "\"-CJyE6ZSX290CEAE=\""
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Last-Modified": [
+ "Thu, 27 Sep 2018 12:26:26 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "X-Goog-Encryption-Kms-Key-Name": [
+ "projects/dulcet-port-762/locations/us/keyRings/go-integration-test/cryptoKeys/key1/cryptoKeyVersions/1"
+ ],
+ "X-Goog-Generation": [
+ "1538051186246172"
+ ],
+ "X-Goog-Hash": [
+ "crc32c=UI785A==",
+ "md5=AAPQS46TrnMYnqiKAbagtQ=="
+ ],
+ "X-Goog-Metageneration": [
+ "1"
+ ],
+ "X-Goog-Storage-Class": [
+ "STANDARD"
+ ],
+ "X-Goog-Stored-Content-Encoding": [
+ "identity"
+ ],
+ "X-Goog-Stored-Content-Length": [
+ "9"
+ ],
+ "X-Google-Backends": [
+ "/bns/xh/borg/xh/bns/cloud-storage/prod-cloud-storage-frontend.frontend/28,/bns/xh/borg/xh/bns/blobstore2/bitpusher/50.scotty,aclgag19:443"
+ ],
+ "X-Google-Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=csysW9mnFoKiswbHo7-QAQ"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "aclgag19:443,/bns/xh/borg/xh/bns/blobstore2/bitpusher/50.scotty,aclgag19:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/xh/borg/xh/bns/blobstore2/bitpusher/50:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBJ"
+ ],
+ "X-Google-Storage-Location": [
+ "US"
+ ],
+ "X-Guploader-Customer": [
+ "cloud-storage"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Uq1-XQ2yh2yq4HD7w8uf-OE1shhofPPQuAKmp-qC5da9s0m1AN7uTNKx0tIrF9-MyTIt7td30r9K5tTyLuqRzWNHMxFwQ"
+ ]
+ },
+ "Body": "bXkgc2VjcmV0"
+ }
+ },
+ {
+ "ID": "a485ba435ca28523",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0019/o/kms?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "7830534cfb711b081d08eba0b65cf2a9/74147550026887475;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0019/o/kms?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3323"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:27 GMT"
+ ],
+ "Etag": [
+ "CJyE6ZSX290CEAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051481000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrsw12:4100,/bns/yr/borg/yr/bns/blobstore2/bitpusher/77.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=csysW_vKIo-ZkAT23pHoBg"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/77.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/77:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRWm1PRlpHcGk5RmhEek1fZDZaWW5nT2k1RTVURThhLXdxeDhkTnNrcVMyNVJkeURqQnQ0MVRlWnZtbjJLRHBEVm5yZUlsNTN0clJYXzFGNkpfMU5OS1ZRZlEzY0M5WTkwSHhZb1hGc09JbTgtUkRPYThhcUVFWnFrdkpjOGw2WmQyMzFhRmliVmwyQVVoeHFzQkdvOFJKTXZ2QTc1M29vT1BCanZJQTR0VEZ6bXVzbTEyU2lVU0xveWMwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UpT4qsGMeiKmm3SkoiWZwAbBHcGKtofVYo_STTBdjDahuf4BQEGdwFN6zz_j2-uhr3VZgULq_8JuBgsgZAQQPSwIK19OA"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxOS9rbXMvMTUzODA1MTE4NjI0NjE3MiIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxOS9vL2ttcyIsIm5hbWUiOiJrbXMiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTkiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE4NjI0NjE3MiIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOCIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNjoyNi4yNDVaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjY6MjYuMjQ1WiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI2OjI2LjI0NVoiLCJzaXplIjoiOSIsIm1kNUhhc2giOiJBQVBRUzQ2VHJuTVlucWlLQWJhZ3RRPT0iLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDE5L28va21zP2dlbmVyYXRpb249MTUzODA1MTE4NjI0NjE3MiZhbHQ9bWVkaWEiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxOS9rbXMvMTUzODA1MTE4NjI0NjE3Mi9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxOS9vL2ttcy9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTkiLCJvYmplY3QiOiJrbXMiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE4NjI0NjE3MiIsImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6Im93bmVycyJ9LCJldGFnIjoiQ0p5RTZaU1gyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDE5L2ttcy8xNTM4MDUxMTg2MjQ2MTcyL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxOS9vL2ttcy9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDE5Iiwib2JqZWN0Ijoia21zIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTExODYyNDYxNzIiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0p5RTZaU1gyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDE5L2ttcy8xNTM4MDUxMTg2MjQ2MTcyL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxOS9vL2ttcy9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDE5Iiwib2JqZWN0Ijoia21zIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTExODYyNDYxNzIiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNKeUU2WlNYMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxOS9rbXMvMTUzODA1MTE4NjI0NjE3Mi91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDE5L28va21zL2FjbC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDE5Iiwib2JqZWN0Ijoia21zIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTExODYyNDYxNzIiLCJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwicm9sZSI6Ik9XTkVSIiwiZW1haWwiOiIzNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImV0YWciOiJDSnlFNlpTWDI5MENFQUU9In1dLCJvd25lciI6eyJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIn0sImNyYzMyYyI6IlVJNzg1QT09IiwiZXRhZyI6IkNKeUU2WlNYMjkwQ0VBRT0iLCJrbXNLZXlOYW1lIjoicHJvamVjdHMvZHVsY2V0LXBvcnQtNzYyL2xvY2F0aW9ucy91cy9rZXlSaW5ncy9nby1pbnRlZ3JhdGlvbi10ZXN0L2NyeXB0b0tleXMva2V5MS9jcnlwdG9LZXlWZXJzaW9ucy8xIn0="
+ }
+ },
+ {
+ "ID": "7d9bd0c6e55e46e5",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0019/o/kms?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "d215618fb2f9dcd133d16a7384b7d353/905241013974385794;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0019/o/kms?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 204,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "0"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:28 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051480000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vnbd134:4063,/bns/yx/borg/yx/bns/blobstore2/bitpusher/105.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=c8ysW8HfNIbjzAKq95zACQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yx/borg/yx/bns/blobstore2/bitpusher/105.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yx/borg/yx/bns/blobstore2/bitpusher/105:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWm1PRlpHcGk5RmhEek1fZDZaWW5nT2k1RTVURThhLXdxeDhkTnNrcVMyNVJkeURqQnQ0MVRlWnZtbjJLRHBEVm5yZUlsNTN0clJYXzFGNkpfMU5OS1ZRZlEzY0M5WTkwSHhZb1hGc09JbTgtUkRPYThhcUVFWnFrdkpjOGw2WmQyMzFhRmliVmwyQVVoeHFzQkdvOFJKTXZ2QTc1M29vT1BCanZJQTR0VEZ6bXVzbTEyU2lVU0xveWMwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UpAexQip8Gz7qHe9IjghL0m9p9kYsvUUOwykqCu4RqDkKXhu6scrgPhzVL1QmWWMZD5L8-ZEXNcUylqtd4on6SutBZ4RA"
+ ]
+ },
+ "Body": ""
+ }
+ },
+ {
+ "ID": "c47642fa5db3bd5e",
+ "Request": {
+ "Method": "PATCH",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0019?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "122"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "fbfc712b5c1899fd4ca63ee52e6ab532/2495651814251784481;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0019?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJlbmNyeXB0aW9uIjp7ImRlZmF1bHRLbXNLZXlOYW1lIjoicHJvamVjdHMvZHVsY2V0LXBvcnQtNzYyL2xvY2F0aW9ucy91cy9rZXlSaW5ncy9nby1pbnRlZ3JhdGlvbi10ZXN0L2NyeXB0b0tleXMva2V5MiJ9fQo="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "2473"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:29 GMT"
+ ],
+ "Etag": [
+ "CAI="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051488000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vncd127:4456,/bns/yx/borg/yx/bns/blobstore2/bitpusher/98.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=dMysW5vaC5C5zwK1qK7ABg"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yx/borg/yx/bns/blobstore2/bitpusher/98.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yx/borg/yx/bns/blobstore2/bitpusher/98:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATpxChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4CtK4wESxgF5YTI5LmMuRW93QkpRWm1PRlpHcGk5RmhEek1fZDZaWW5nT2k1RTVURThhLXdxeDhkTnNrcVMyNVJkeURqQnQ0MVRlWnZtbjJLRHBEVm5yZUlsNTN0clJYXzFGNkpfMU5OS1ZRZlEzY0M5WTkwSHhZb1hGc09JbTgtUkRPYThhcUVFWnFrdkpjOGw2WmQyMzFhRmliVmwyQVVoeHFzQkdvOFJKTXZ2QTc1M29vT1BCanZJQTR0VEZ6bXVzbTEyU2lVU0xveWMwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Uo4X9EhCcRBlaJH_pVouWM2j23zb0mheEAPSKeXBBJwCJRwCNMRaw6tJxmnLuktTi66gi6vWF93hfao8LTicVMfjoUWgA"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxOSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxOSIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTkiLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjY6MjQuMTU2WiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI2OjI5LjQyM1oiLCJtZXRhZ2VuZXJhdGlvbiI6IjIiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxOS9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxOS9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTkiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBST0ifSx7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxOS9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTkvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxOSIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDQUk9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTkvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDE5L2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTkiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNBST0ifV0sImRlZmF1bHRPYmplY3RBY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBST0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0FJPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0FJPSJ9XSwiZW5jcnlwdGlvbiI6eyJkZWZhdWx0S21zS2V5TmFtZSI6InByb2plY3RzL2R1bGNldC1wb3J0LTc2Mi9sb2NhdGlvbnMvdXMva2V5UmluZ3MvZ28taW50ZWdyYXRpb24tdGVzdC9jcnlwdG9LZXlzL2tleTIifSwib3duZXIiOnsiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUifSwibG9jYXRpb24iOiJVUyIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwiZXRhZyI6IkNBST0ifQ=="
+ }
+ },
+ {
+ "ID": "7f62069aba528822",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0019?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "c002ca593e602630ded6a19c2b134689/4086063718302158784;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0019?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0, must-revalidate, no-transform"
+ ],
+ "Content-Length": [
+ "2473"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:29 GMT"
+ ],
+ "Etag": [
+ "CAI="
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:26:29 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051481000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrlm79:4339,/bns/yv/borg/yv/bns/blobstore2/bitpusher/192.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=dcysW8jIJsHMggTy3YG4Bw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/192.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/192:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRWm1PRlpHcGk5RmhEek1fZDZaWW5nT2k1RTVURThhLXdxeDhkTnNrcVMyNVJkeURqQnQ0MVRlWnZtbjJLRHBEVm5yZUlsNTN0clJYXzFGNkpfMU5OS1ZRZlEzY0M5WTkwSHhZb1hGc09JbTgtUkRPYThhcUVFWnFrdkpjOGw2WmQyMzFhRmliVmwyQVVoeHFzQkdvOFJKTXZ2QTc1M29vT1BCanZJQTR0VEZ6bXVzbTEyU2lVU0xveWMwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UqkNX11AQYP3N2kiMuxoq73fzNO7Bi0pJMhX1c_mLQ42QXGDO_A43-c1RBddVMXKxeMwfQhiRGF86B-ooIMrZpXs1MmVw"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxOSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxOSIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTkiLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjY6MjQuMTU2WiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI2OjI5LjQyM1oiLCJtZXRhZ2VuZXJhdGlvbiI6IjIiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxOS9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxOS9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTkiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBST0ifSx7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxOS9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTkvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxOSIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDQUk9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTkvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDE5L2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTkiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNBST0ifV0sImRlZmF1bHRPYmplY3RBY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBST0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0FJPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0FJPSJ9XSwiZW5jcnlwdGlvbiI6eyJkZWZhdWx0S21zS2V5TmFtZSI6InByb2plY3RzL2R1bGNldC1wb3J0LTc2Mi9sb2NhdGlvbnMvdXMva2V5UmluZ3MvZ28taW50ZWdyYXRpb24tdGVzdC9jcnlwdG9LZXlzL2tleTIifSwib3duZXIiOnsiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUifSwibG9jYXRpb24iOiJVUyIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwiZXRhZyI6IkNBST0ifQ=="
+ }
+ },
+ {
+ "ID": "fa6f06c5ad8064e4",
+ "Request": {
+ "Method": "PATCH",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0019?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "20"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "130a425fc5abcea3f3c5283a84daaac0/5676475622369375326;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0019?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJlbmNyeXB0aW9uIjpudWxsfQo="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "2353"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:31 GMT"
+ ],
+ "Etag": [
+ "CAM="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051490000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrv189:4445,/bns/yr/borg/yr/bns/blobstore2/bitpusher/106.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=dcysW-mJONHokAPIiaDwDw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/106.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/106:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATpxChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4CtK4wESxgF5YTI5LmMuRW93QkpRWm1PRlpHcGk5RmhEek1fZDZaWW5nT2k1RTVURThhLXdxeDhkTnNrcVMyNVJkeURqQnQ0MVRlWnZtbjJLRHBEVm5yZUlsNTN0clJYXzFGNkpfMU5OS1ZRZlEzY0M5WTkwSHhZb1hGc09JbTgtUkRPYThhcUVFWnFrdkpjOGw2WmQyMzFhRmliVmwyQVVoeHFzQkdvOFJKTXZ2QTc1M29vT1BCanZJQTR0VEZ6bXVzbTEyU2lVU0xveWMwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UojIFggaWZN6hEXoEkYo4ICef8Y8G2QPP99gaRwO_31pyKn2XSpn1KMBY5Ha9TGzntD2rjuSpxTPCpF9icPZ4U5RDR_2Q"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxOSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxOSIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTkiLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjY6MjQuMTU2WiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI2OjMxLjE1OFoiLCJtZXRhZ2VuZXJhdGlvbiI6IjMiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxOS9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxOS9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTkiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBTT0ifSx7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxOS9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTkvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxOSIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDQU09In0seyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTkvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDE5L2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTkiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNBTT0ifV0sImRlZmF1bHRPYmplY3RBY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBTT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0FNPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0FNPSJ9XSwib3duZXIiOnsiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUifSwibG9jYXRpb24iOiJVUyIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwiZXRhZyI6IkNBTT0ifQ=="
+ }
+ },
+ {
+ "ID": "4cb5a8bb09514dcd",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0019?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "49bf774f40da9c6ccd6aaac6b1f8fb6d/7266606051459881469;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0019?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 204,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "0"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:31 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051482000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrhj86:4129,/bns/yv/borg/yv/bns/blobstore2/bitpusher/227.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=d8ysW_DxFsTDswat-Z-oBg"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/227.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/227:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWm1PRlpHcGk5RmhEek1fZDZaWW5nT2k1RTVURThhLXdxeDhkTnNrcVMyNVJkeURqQnQ0MVRlWnZtbjJLRHBEVm5yZUlsNTN0clJYXzFGNkpfMU5OS1ZRZlEzY0M5WTkwSHhZb1hGc09JbTgtUkRPYThhcUVFWnFrdkpjOGw2WmQyMzFhRmliVmwyQVVoeHFzQkdvOFJKTXZ2QTc1M29vT1BCanZJQTR0VEZ6bXVzbTEyU2lVU0xveWMwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Up1rQ-BgoD09ndH8GWMMzS2Zhmn0QjIDIJukp6NieOesT9EvuTS0RwbBIPpMlVgQEhFAKxVMNUp4VJAYaWQ7swQezWs0A"
+ ]
+ },
+ "Body": ""
+ }
+ },
+ {
+ "ID": "891d7683ffefdda3",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/storage/v1/b?alt=json\u0026predefinedAcl=authenticatedRead\u0026predefinedDefaultObjectAcl=publicRead\u0026prettyPrint=false\u0026project=dulcet-port-762",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "60"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "cb6b62d23ca6eb2db0c7e01be1b9bb97/8857017955510321051;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b?alt=json\u0026predefinedAcl=authenticatedRead\u0026predefinedDefaultObjectAcl=publicRead\u0026prettyPrint=false\u0026project=dulcet-port-762"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJuYW1lIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDIwIn0K"
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "1404"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:32 GMT"
+ ],
+ "Etag": [
+ "CAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051491000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vnam67:4028,/bns/yx/borg/yx/bns/blobstore2/bitpusher/78.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=d8ysW8yrPKSGzQLC47eoAQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yx/borg/yx/bns/blobstore2/bitpusher/78.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yx/borg/yx/bns/blobstore2/bitpusher/78:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWnhJX2MxZzUwRGhIUUYyaHZ3SXljdlJ1SEdtaEZZb3ZldVcwLVZDMUdOcjdRck83TTFuWXp0MklvWnJfaXBRTFlpNUplM1RyZ29mSUJJLXRFcnpkVlR2dzJsTGVlQWdJS1lmQ01WejJrT1pTWFo4Vk9FT3pzMHhVVExreDdiU2NtaWg3Ung5NXFVeEsxYjdwbkxQSGJ0RGhHOEhfTFZvUWhGT1pseWNwZ0E3NlZZODlSY3RiNHVLRGcwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UqMpuPJgLpZv1oExTs4Xg16mQfhfIKXonUO9BJXMHQsuGF4dTdsbigEov8h0t91zJU8pmxlW3jj0JTLD7rnnfatR3lPrg"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAyMCIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAyMCIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMjAiLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjY6MzIuNDU2WiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI2OjMyLjQ1NloiLCJtZXRhZ2VuZXJhdGlvbiI6IjEiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAyMC9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAyMC9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMjAiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAyMC9hbGxBdXRoZW50aWNhdGVkVXNlcnMiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMjAvYWNsL2FsbEF1dGhlbnRpY2F0ZWRVc2VycyIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAyMCIsImVudGl0eSI6ImFsbEF1dGhlbnRpY2F0ZWRVc2VycyIsInJvbGUiOiJSRUFERVIiLCJldGFnIjoiQ0FFPSJ9XSwiZGVmYXVsdE9iamVjdEFjbCI6W3sia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImVudGl0eSI6ImFsbFVzZXJzIiwicm9sZSI6IlJFQURFUiIsImV0YWciOiJDQUU9In1dLCJvd25lciI6eyJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSJ9LCJsb2NhdGlvbiI6IlVTIiwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJldGFnIjoiQ0FFPSJ9"
+ }
+ },
+ {
+ "ID": "b49c1e9a0f83e151",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0020?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "0d60ab1455023a58da860c5a8382cd3f/10447428760082621498;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0020?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0, must-revalidate, no-transform"
+ ],
+ "Content-Length": [
+ "1404"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:33 GMT"
+ ],
+ "Etag": [
+ "CAE="
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:26:33 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051492000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrp184:4188,/bns/yr/borg/yr/bns/blobstore2/bitpusher/105.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=eMysW7aDLZCMkATtpaSoDA"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/105.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/105:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRWnhJX2MxZzUwRGhIUUYyaHZ3SXljdlJ1SEdtaEZZb3ZldVcwLVZDMUdOcjdRck83TTFuWXp0MklvWnJfaXBRTFlpNUplM1RyZ29mSUJJLXRFcnpkVlR2dzJsTGVlQWdJS1lmQ01WejJrT1pTWFo4Vk9FT3pzMHhVVExreDdiU2NtaWg3Ung5NXFVeEsxYjdwbkxQSGJ0RGhHOEhfTFZvUWhGT1pseWNwZ0E3NlZZODlSY3RiNHVLRGcwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Urqu3mcHdMmoSo-FZwYHnjUt-4JoFJC40fJlB6GgRNe3MJSsnCfflBb4Fn7MRFozkTM0lJVdby67cEnsWc_pzlvRBjCew"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAyMCIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAyMCIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMjAiLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjY6MzIuNDU2WiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI2OjMyLjQ1NloiLCJtZXRhZ2VuZXJhdGlvbiI6IjEiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAyMC9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAyMC9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMjAiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAyMC9hbGxBdXRoZW50aWNhdGVkVXNlcnMiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMjAvYWNsL2FsbEF1dGhlbnRpY2F0ZWRVc2VycyIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAyMCIsImVudGl0eSI6ImFsbEF1dGhlbnRpY2F0ZWRVc2VycyIsInJvbGUiOiJSRUFERVIiLCJldGFnIjoiQ0FFPSJ9XSwiZGVmYXVsdE9iamVjdEFjbCI6W3sia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImVudGl0eSI6ImFsbFVzZXJzIiwicm9sZSI6IlJFQURFUiIsImV0YWciOiJDQUU9In1dLCJvd25lciI6eyJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSJ9LCJsb2NhdGlvbiI6IlVTIiwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJldGFnIjoiQ0FFPSJ9"
+ }
+ },
+ {
+ "ID": "87a9188ffc1f950f",
+ "Request": {
+ "Method": "PATCH",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0020?alt=json\u0026predefinedAcl=private\u0026predefinedDefaultObjectAcl=authenticatedRead\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "33"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "949ae0c5485ef5fba888d9ee9e3ece82/11965502694630050521;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0020?alt=json\u0026predefinedAcl=private\u0026predefinedDefaultObjectAcl=authenticatedRead\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJhY2wiOltdLCJkZWZhdWx0T2JqZWN0QWNsIjpbXX0K"
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "1049"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:34 GMT"
+ ],
+ "Etag": [
+ "CAI="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051493000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrna23:4440,/bns/yw/borg/yw/bns/blobstore2/bitpusher/181.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=ecysW7XYAdPkhATNoabIDw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yw/borg/yw/bns/blobstore2/bitpusher/181.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yw/borg/yw/bns/blobstore2/bitpusher/181:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATpxChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4CtK4wESxgF5YTI5LmMuRW93QkpRWnhJX2MxZzUwRGhIUUYyaHZ3SXljdlJ1SEdtaEZZb3ZldVcwLVZDMUdOcjdRck83TTFuWXp0MklvWnJfaXBRTFlpNUplM1RyZ29mSUJJLXRFcnpkVlR2dzJsTGVlQWdJS1lmQ01WejJrT1pTWFo4Vk9FT3pzMHhVVExreDdiU2NtaWg3Ung5NXFVeEsxYjdwbkxQSGJ0RGhHOEhfTFZvUWhGT1pseWNwZ0E3NlZZODlSY3RiNHVLRGcwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UpZpSJIhVMhoHzAya137K-3ICxB3mv_44utwUUjjgeN6udkUR5RE-QVvopzq8Es4nhaQ3ZLEx2u6y7TcbaBjwRy5LAqqQ"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAyMCIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAyMCIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMjAiLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjY6MzIuNDU2WiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI2OjM0LjU0M1oiLCJtZXRhZ2VuZXJhdGlvbiI6IjIiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAyMC9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAyMC9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMjAiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBST0ifV0sImRlZmF1bHRPYmplY3RBY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJhbGxBdXRoZW50aWNhdGVkVXNlcnMiLCJyb2xlIjoiUkVBREVSIiwiZXRhZyI6IkNBST0ifV0sIm93bmVyIjp7ImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1In0sImxvY2F0aW9uIjoiVVMiLCJzdG9yYWdlQ2xhc3MiOiJTVEFOREFSRCIsImV0YWciOiJDQUk9In0="
+ }
+ },
+ {
+ "ID": "e4a3dd503180735b",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0020/o?alt=json\u0026predefinedAcl=authenticatedRead\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Type": [
+ "multipart/related; boundary=beb0c8923f1906fc1d6a5d8d3bc17f536531b44ab40d3d9fc8efb9fb7f72"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "23efe85846102ea586924024a1100570/12796877629259291944;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0020/o?alt=json\u0026predefinedAcl=authenticatedRead\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "LS1iZWIwYzg5MjNmMTkwNmZjMWQ2YTVkOGQzYmMxN2Y1MzY1MzFiNDRhYjQwZDNkOWZjOGVmYjlmYjdmNzINCkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vanNvbg0KDQp7ImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAyMCIsIm5hbWUiOiJwcml2YXRlIn0KDQotLWJlYjBjODkyM2YxOTA2ZmMxZDZhNWQ4ZDNiYzE3ZjUzNjUzMWI0NGFiNDBkM2Q5ZmM4ZWZiOWZiN2Y3Mg0KQ29udGVudC1UeXBlOiB0ZXh0L3BsYWluOyBjaGFyc2V0PXV0Zi04DQoNCmhlbGxvDQotLWJlYjBjODkyM2YxOTA2ZmMxZDZhNWQ4ZDNiYzE3ZjUzNjUzMWI0NGFiNDBkM2Q5ZmM4ZWZiOWZiN2Y3Mi0tDQo="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "2100"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:35 GMT"
+ ],
+ "Etag": [
+ "COekh5mX290CEAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051494000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vryy5:4338,/bns/yw/borg/yw/bns/blobstore2/bitpusher/209.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=esysW57EMM2dhQTpyo-oDQ"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yw/borg/yw/bns/blobstore2/bitpusher/209.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yw/borg/yw/bns/blobstore2/bitpusher/209:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWnhJX2MxZzUwRGhIUUYyaHZ3SXljdlJ1SEdtaEZZb3ZldVcwLVZDMUdOcjdRck83TTFuWXp0MklvWnJfaXBRTFlpNUplM1RyZ29mSUJJLXRFcnpkVlR2dzJsTGVlQWdJS1lmQ01WejJrT1pTWFo4Vk9FT3pzMHhVVExreDdiU2NtaWg3Ung5NXFVeEsxYjdwbkxQSGJ0RGhHOEhfTFZvUWhGT1pseWNwZ0E3NlZZODlSY3RiNHVLRGcwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_single_post_uploads"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UpCtq9CUGSgrynMd2mh8SOMhrLN0tJva6vaDC8MLugZf43ohkNU0tMfnT9LrjH9cN9nhdnM3SZuopEE2PwjqP0eRagjRg"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAyMC9wcml2YXRlLzE1MzgwNTExOTUxMzA0NzEiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMjAvby9wcml2YXRlIiwibmFtZSI6InByaXZhdGUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMjAiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE5NTEzMDQ3MSIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOCIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNjozNS4xMzBaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjY6MzUuMTMwWiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI2OjM1LjEzMFoiLCJzaXplIjoiNSIsIm1kNUhhc2giOiJYVUZBS3J4TEtuYTVjWjJSRUJmRmtnPT0iLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDIwL28vcHJpdmF0ZT9nZW5lcmF0aW9uPTE1MzgwNTExOTUxMzA0NzEmYWx0PW1lZGlhIiwiYWNsIjpbeyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMjAvcHJpdmF0ZS8xNTM4MDUxMTk1MTMwNDcxL3VzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMjAvby9wcml2YXRlL2FjbC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDIwIiwib2JqZWN0IjoicHJpdmF0ZSIsImdlbmVyYXRpb24iOiIxNTM4MDUxMTk1MTMwNDcxIiwiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInJvbGUiOiJPV05FUiIsImVtYWlsIjoiMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJldGFnIjoiQ09la2g1bVgyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDIwL3ByaXZhdGUvMTUzODA1MTE5NTEzMDQ3MS9hbGxBdXRoZW50aWNhdGVkVXNlcnMiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMjAvby9wcml2YXRlL2FjbC9hbGxBdXRoZW50aWNhdGVkVXNlcnMiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMjAiLCJvYmplY3QiOiJwcml2YXRlIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTExOTUxMzA0NzEiLCJlbnRpdHkiOiJhbGxBdXRoZW50aWNhdGVkVXNlcnMiLCJyb2xlIjoiUkVBREVSIiwiZXRhZyI6IkNPZWtoNW1YMjkwQ0VBRT0ifV0sIm93bmVyIjp7ImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20ifSwiY3JjMzJjIjoibW5HN1RBPT0iLCJldGFnIjoiQ09la2g1bVgyOTBDRUFFPSJ9"
+ }
+ },
+ {
+ "ID": "58df35897052bee4",
+ "Request": {
+ "Method": "PATCH",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0020/o/private?alt=json\u0026predefinedAcl=private\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "62"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "24397f66feee409b62926787352017ec/14387289533326443207;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0020/o/private?alt=json\u0026predefinedAcl=private\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMjAifQo="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "1634"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:35 GMT"
+ ],
+ "Etag": [
+ "COekh5mX290CEAI="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051493000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrjo80:4463,/bns/yv/borg/yv/bns/blobstore2/bitpusher/13.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=e8ysW4LvDtCuggSokbuwAQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/13.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/13:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATpxChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4CtK4wESxgF5YTI5LmMuRW93QkpRWnhJX2MxZzUwRGhIUUYyaHZ3SXljdlJ1SEdtaEZZb3ZldVcwLVZDMUdOcjdRck83TTFuWXp0MklvWnJfaXBRTFlpNUplM1RyZ29mSUJJLXRFcnpkVlR2dzJsTGVlQWdJS1lmQ01WejJrT1pTWFo4Vk9FT3pzMHhVVExreDdiU2NtaWg3Ung5NXFVeEsxYjdwbkxQSGJ0RGhHOEhfTFZvUWhGT1pseWNwZ0E3NlZZODlSY3RiNHVLRGcwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Up9VN6AT4MFmZg0IARYnDCGfAGvkNhL2qzxtqOu4JFgUXJ_Q9kA4PKAlsvszTSqw4rljl00PRjory0QRWzbLupw8M06nA"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAyMC9wcml2YXRlLzE1MzgwNTExOTUxMzA0NzEiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMjAvby9wcml2YXRlIiwibmFtZSI6InByaXZhdGUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMjAiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE5NTEzMDQ3MSIsIm1ldGFnZW5lcmF0aW9uIjoiMiIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOCIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNjozNS4xMzBaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjY6MzUuMzM0WiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI2OjM1LjEzMFoiLCJzaXplIjoiNSIsIm1kNUhhc2giOiJYVUZBS3J4TEtuYTVjWjJSRUJmRmtnPT0iLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDIwL28vcHJpdmF0ZT9nZW5lcmF0aW9uPTE1MzgwNTExOTUxMzA0NzEmYWx0PW1lZGlhIiwiYWNsIjpbeyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMjAvcHJpdmF0ZS8xNTM4MDUxMTk1MTMwNDcxL3VzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMjAvby9wcml2YXRlL2FjbC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDIwIiwib2JqZWN0IjoicHJpdmF0ZSIsImdlbmVyYXRpb24iOiIxNTM4MDUxMTk1MTMwNDcxIiwiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInJvbGUiOiJPV05FUiIsImVtYWlsIjoiMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJldGFnIjoiQ09la2g1bVgyOTBDRUFJPSJ9XSwib3duZXIiOnsiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSJ9LCJjcmMzMmMiOiJtbkc3VEE9PSIsImV0YWciOiJDT2VraDVtWDI5MENFQUk9In0="
+ }
+ },
+ {
+ "ID": "6c8b9234e260aec0",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0020/o/private/rewriteTo/b/go-integration-test-20180927-44630911863640-0020/o/dst?alt=json\u0026destinationPredefinedAcl=publicRead\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "3"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "e84540708abd3927db61182f95c94954/15977419966695139429;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0020/o/private/rewriteTo/b/go-integration-test-20180927-44630911863640-0020/o/dst?alt=json\u0026destinationPredefinedAcl=publicRead\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "e30K"
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "2122"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:35 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051495000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrqv16:4123,/bns/yv/borg/yv/bns/blobstore2/bitpusher/135.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=e8ysW8aOG4iRNq7qqOgL"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/135.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/135:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp0ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4StK4wESxgF5YTI5LmMuRW93QkpRWnhJX2MxZzUwRGhIUUYyaHZ3SXljdlJ1SEdtaEZZb3ZldVcwLVZDMUdOcjdRck83TTFuWXp0MklvWnJfaXBRTFlpNUplM1RyZ29mSUJJLXRFcnpkVlR2dzJsTGVlQWdJS1lmQ01WejJrT1pTWFo4Vk9FT3pzMHhVVExreDdiU2NtaWg3Ung5NXFVeEsxYjdwbkxQSGJ0RGhHOEhfTFZvUWhGT1pseWNwZ0E3NlZZODlSY3RiNHVLRGcwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UoGz2UN6X_ehowCDfc4UzRfzOOABUIOku0QYLlq2xV_D-ZSoyXFGiI0r2Ze0jbdiZtGxNtE0ZDopU4i4_VfctaYdcfLUw"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNyZXdyaXRlUmVzcG9uc2UiLCJ0b3RhbEJ5dGVzUmV3cml0dGVuIjoiNSIsIm9iamVjdFNpemUiOiI1IiwiZG9uZSI6dHJ1ZSwicmVzb3VyY2UiOnsia2luZCI6InN0b3JhZ2Ujb2JqZWN0IiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMjAvZHN0LzE1MzgwNTExOTU4MjAwMDMiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMjAvby9kc3QiLCJuYW1lIjoiZHN0IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDIwIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTExOTU4MjAwMDMiLCJtZXRhZ2VuZXJhdGlvbiI6IjEiLCJjb250ZW50VHlwZSI6InRleHQvcGxhaW47IGNoYXJzZXQ9dXRmLTgiLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjY6MzUuODE4WiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI2OjM1LjgxOFoiLCJzdG9yYWdlQ2xhc3MiOiJTVEFOREFSRCIsInRpbWVTdG9yYWdlQ2xhc3NVcGRhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNjozNS44MThaIiwic2l6ZSI6IjUiLCJtZDVIYXNoIjoiWFVGQUtyeExLbmE1Y1oyUkVCZkZrZz09IiwibWVkaWFMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vZG93bmxvYWQvc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAyMC9vL2RzdD9nZW5lcmF0aW9uPTE1MzgwNTExOTU4MjAwMDMmYWx0PW1lZGlhIiwiYWNsIjpbeyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMjAvZHN0LzE1MzgwNTExOTU4MjAwMDMvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAyMC9vL2RzdC9hY2wvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAyMCIsIm9iamVjdCI6ImRzdCIsImdlbmVyYXRpb24iOiIxNTM4MDUxMTk1ODIwMDAzIiwiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInJvbGUiOiJPV05FUiIsImVtYWlsIjoiMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJldGFnIjoiQ09PdnNabVgyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDIwL2RzdC8xNTM4MDUxMTk1ODIwMDAzL2FsbFVzZXJzIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDIwL28vZHN0L2FjbC9hbGxVc2VycyIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAyMCIsIm9iamVjdCI6ImRzdCIsImdlbmVyYXRpb24iOiIxNTM4MDUxMTk1ODIwMDAzIiwiZW50aXR5IjoiYWxsVXNlcnMiLCJyb2xlIjoiUkVBREVSIiwiZXRhZyI6IkNPT3ZzWm1YMjkwQ0VBRT0ifV0sIm93bmVyIjp7ImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20ifSwiY3JjMzJjIjoibW5HN1RBPT0iLCJldGFnIjoiQ09PdnNabVgyOTBDRUFFPSJ9fQ=="
+ }
+ },
+ {
+ "ID": "bdf3d7c64ba82e03",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0020/o/comp/compose?alt=json\u0026destinationPredefinedAcl=authenticatedRead\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Length": [
+ "130"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "55fba242302f069c8de08a55a63b312f/17567830766972538116;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0020/o/comp/compose?alt=json\u0026destinationPredefinedAcl=authenticatedRead\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "eyJkZXN0aW5hdGlvbiI6eyJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMjAifSwic291cmNlT2JqZWN0cyI6W3sibmFtZSI6InByaXZhdGUifSx7Im5hbWUiOiJkc3QifV19Cg=="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "2011"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:36 GMT"
+ ],
+ "Etag": [
+ "CKiF2JmX290CEAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051495000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrbe87:4071,/bns/yv/borg/yv/bns/blobstore2/bitpusher/178.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=e8ysW6n9O8TIggSEmZeoDA"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/178.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/178:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp0ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4StK4wESxgF5YTI5LmMuRW93QkpRWnhJX2MxZzUwRGhIUUYyaHZ3SXljdlJ1SEdtaEZZb3ZldVcwLVZDMUdOcjdRck83TTFuWXp0MklvWnJfaXBRTFlpNUplM1RyZ29mSUJJLXRFcnpkVlR2dzJsTGVlQWdJS1lmQ01WejJrT1pTWFo4Vk9FT3pzMHhVVExreDdiU2NtaWg3Ung5NXFVeEsxYjdwbkxQSGJ0RGhHOEhfTFZvUWhGT1pseWNwZ0E3NlZZODlSY3RiNHVLRGcwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UoVcr8Vwk5n96yY0XwCEwzrkQvuCRGOYIkL4sTNjvaL0NlweMw8cCjbLfz-73ZEPbE8s7m5oNJ6KhRMMLKJ8eR_29Msng"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAyMC9jb21wLzE1MzgwNTExOTY0NTM1NDQiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMjAvby9jb21wIiwibmFtZSI6ImNvbXAiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMjAiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE5NjQ1MzU0NCIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNjozNi40NTJaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjY6MzYuNDUyWiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI2OjM2LjQ1MloiLCJzaXplIjoiMTAiLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDIwL28vY29tcD9nZW5lcmF0aW9uPTE1MzgwNTExOTY0NTM1NDQmYWx0PW1lZGlhIiwiYWNsIjpbeyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMjAvY29tcC8xNTM4MDUxMTk2NDUzNTQ0L3VzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMjAvby9jb21wL2FjbC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDIwIiwib2JqZWN0IjoiY29tcCIsImdlbmVyYXRpb24iOiIxNTM4MDUxMTk2NDUzNTQ0IiwiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInJvbGUiOiJPV05FUiIsImVtYWlsIjoiMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJldGFnIjoiQ0tpRjJKbVgyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDIwL2NvbXAvMTUzODA1MTE5NjQ1MzU0NC9hbGxBdXRoZW50aWNhdGVkVXNlcnMiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMjAvby9jb21wL2FjbC9hbGxBdXRoZW50aWNhdGVkVXNlcnMiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMjAiLCJvYmplY3QiOiJjb21wIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTExOTY0NTM1NDQiLCJlbnRpdHkiOiJhbGxBdXRoZW50aWNhdGVkVXNlcnMiLCJyb2xlIjoiUkVBREVSIiwiZXRhZyI6IkNLaUYySm1YMjkwQ0VBRT0ifV0sIm93bmVyIjp7ImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20ifSwiY3JjMzJjIjoiL1JDT2dnPT0iLCJjb21wb25lbnRDb3VudCI6MiwiZXRhZyI6IkNLaUYySm1YMjkwQ0VBRT0ifQ=="
+ }
+ },
+ {
+ "ID": "ee7bc5d7208c190c",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0020/o/comp?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "4a2194905ad1cf3d334d917f83e28255/18326867736393736275;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0020/o/comp?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 204,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "0"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:37 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051496000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrvq22:4011,/bns/yr/borg/yr/bns/blobstore2/bitpusher/69.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=fMysW-3oJ8zx4QSiqbCQCw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/69.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/69:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWnhJX2MxZzUwRGhIUUYyaHZ3SXljdlJ1SEdtaEZZb3ZldVcwLVZDMUdOcjdRck83TTFuWXp0MklvWnJfaXBRTFlpNUplM1RyZ29mSUJJLXRFcnpkVlR2dzJsTGVlQWdJS1lmQ01WejJrT1pTWFo4Vk9FT3pzMHhVVExreDdiU2NtaWg3Ung5NXFVeEsxYjdwbkxQSGJ0RGhHOEhfTFZvUWhGT1pseWNwZ0E3NlZZODlSY3RiNHVLRGcwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UpG9-TyHzYXAb1ytjOQjqEQ98fTCU_yZe5G-HK1SELnmk4DQ2EcgdFJoM4mSUTB1yro5RqktWxmw0pNnLiUyBC25Ba60g"
+ ]
+ },
+ "Body": ""
+ }
+ },
+ {
+ "ID": "ac3f89ec4e04e3c1",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0020/o/dst?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "d86b6c05e8c204b9a0f81a62b0ff1215/711780072290071459;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0020/o/dst?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 204,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "0"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:37 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051496000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrud20:4007,/bns/yv/borg/yv/bns/blobstore2/bitpusher/259.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=fcysW8_OBsmngASFkp7wAw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/259.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/259:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWnhJX2MxZzUwRGhIUUYyaHZ3SXljdlJ1SEdtaEZZb3ZldVcwLVZDMUdOcjdRck83TTFuWXp0MklvWnJfaXBRTFlpNUplM1RyZ29mSUJJLXRFcnpkVlR2dzJsTGVlQWdJS1lmQ01WejJrT1pTWFo4Vk9FT3pzMHhVVExreDdiU2NtaWg3Ung5NXFVeEsxYjdwbkxQSGJ0RGhHOEhfTFZvUWhGT1pseWNwZ0E3NlZZODlSY3RiNHVLRGcwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UqEiJiMnVBV_g1vn1HPeT4lJx2pAGupW_0ewE6RCPuEs6LX1kKVZPChhF6uNXfd6B-zq41gJBEXqWV3n_C2rVbwOdxQZA"
+ ]
+ },
+ "Body": ""
+ }
+ },
+ {
+ "ID": "624ebe45009cda5b",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0020/o/private?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "93b0a271a6a576c37c4b73fa976c4598/1470817041728046578;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0020/o/private?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 204,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "0"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:37 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051491000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vnep66:4228,/bns/yx/borg/yx/bns/blobstore2/bitpusher/121.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=fcysW-m_H8uRzgLBuZuAAQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yx/borg/yx/bns/blobstore2/bitpusher/121.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yx/borg/yx/bns/blobstore2/bitpusher/121:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWnhJX2MxZzUwRGhIUUYyaHZ3SXljdlJ1SEdtaEZZb3ZldVcwLVZDMUdOcjdRck83TTFuWXp0MklvWnJfaXBRTFlpNUplM1RyZ29mSUJJLXRFcnpkVlR2dzJsTGVlQWdJS1lmQ01WejJrT1pTWFo4Vk9FT3pzMHhVVExreDdiU2NtaWg3Ung5NXFVeEsxYjdwbkxQSGJ0RGhHOEhfTFZvUWhGT1pseWNwZ0E3NlZZODlSY3RiNHVLRGcwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UrMCxb5W9i5rriC3v0MUc9h8Xj4pD83_CNEbRKtAEPOBu0xByvZFQkU2cY3omAUSed_AUo69GRSfyfOfQWZvfpYx1dTYw"
+ ]
+ },
+ "Body": ""
+ }
+ },
+ {
+ "ID": "96fe3135b84e9748",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0020?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "7be9885fc654f5342511b3e446928915/3061228945778420625;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0020?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 204,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "0"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:38 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051496000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrdp9:4227,/bns/yr/borg/yr/bns/blobstore2/bitpusher/0.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=fcysW9y4OMSxkATZ74bIAQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yr/borg/yr/bns/blobstore2/bitpusher/0.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yr/borg/yr/bns/blobstore2/bitpusher/0:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWnhJX2MxZzUwRGhIUUYyaHZ3SXljdlJ1SEdtaEZZb3ZldVcwLVZDMUdOcjdRck83TTFuWXp0MklvWnJfaXBRTFlpNUplM1RyZ29mSUJJLXRFcnpkVlR2dzJsTGVlQWdJS1lmQ01WejJrT1pTWFo4Vk9FT3pzMHhVVExreDdiU2NtaWg3Ung5NXFVeEsxYjdwbkxQSGJ0RGhHOEhfTFZvUWhGT1pseWNwZ0E3NlZZODlSY3RiNHVLRGcwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Upkthb5ilb0PmvZb8U4V94kTAXT3MGBM_IgyGfzK-IJ6cNMLC5-5iXDx9bVq8L2RsI3oWQofGLNRTSEyGisE1QS9Od1uA"
+ ]
+ },
+ "Body": ""
+ }
+ },
+ {
+ "ID": "ef843a316e292cac",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/projects/dulcet-port-762/serviceAccount?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "d7dda37113a0d839d93dfd3c96e9240d/3820265915199618784;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/projects/dulcet-port-762/serviceAccount?alt=json\u0026prettyPrint=false"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0, must-revalidate, no-transform"
+ ],
+ "Content-Length": [
+ "115"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:38 GMT"
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:26:38 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051498000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vraf24:4012,/bns/yv/borg/yv/bns/blobstore2/bitpusher/164.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=fsysW_33GJCAgwTX26HYCw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/164.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/164:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRYjRBUXFsa3NIcFl6R0t5SlVsbnU0blE5Y0RGNkp6TDRMRmNFaFpMbTNYekFTUmhVUXQtQzgtN3FQcjhsMERLd0NWM09Mck1iR1lhZG0xZnFESVlSaFR3MzloN1Y0U1JocVZDdmM2eGJ2ZjZhVzcwSlhQU0JjdVVQRzVpMEJIMVdQcGZOR0NiakY1X19QcXBpb3lsWEJVaTFGa0l6TVRZWEk5bVk2N01kSG8wOENVOGN2N3hQenRsa1UwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Ur0HKrUa4R5Mq8Ygoy8TSuogTipVuQD81bwHIZhbVtOKm3ynxpsPT0CFMujvH7hOyRMdQOUJnJU12fFAqF8yrNatJVHFg"
+ ]
+ },
+ "Body": "eyJlbWFpbF9hZGRyZXNzIjoic2VydmljZS0zNjYzOTkzMzE0NUBncy1wcm9qZWN0LWFjY291bnRzLmlhbS5nc2VydmljZWFjY291bnQuY29tIiwia2luZCI6InN0b3JhZ2Ujc2VydmljZUFjY291bnQifQ=="
+ }
+ },
+ {
+ "ID": "87b1562f89ba920e",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Type": [
+ "multipart/related; boundary=127503253f4275a1da1367a0477ce4d95e90d1d7751cb3524fb96f55940e"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "5c407b38ad9b734e406b6679785ea219/4651640845550735407;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "LS0xMjc1MDMyNTNmNDI3NWExZGExMzY3YTA0NzdjZTRkOTVlOTBkMWQ3NzUxY2IzNTI0ZmI5NmY1NTk0MGUNCkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vanNvbg0KDQp7ImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsImNhY2hlQ29udHJvbCI6InB1YmxpYywgbWF4LWFnZT02MCIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbiIsIm5hbWUiOiJzb21lLW9iamVjdCJ9Cg0KLS0xMjc1MDMyNTNmNDI3NWExZGExMzY3YTA0NzdjZTRkOTVlOTBkMWQ3NzUxY2IzNTI0ZmI5NmY1NTk0MGUNCkNvbnRlbnQtVHlwZTogdGV4dC9wbGFpbg0KDQpJco8tJMbRB9F7evlHCJTVDQotLTEyNzUwMzI1M2Y0Mjc1YTFkYTEzNjdhMDQ3N2NlNGQ5NWU5MGQxZDc3NTFjYjM1MjRmYjk2ZjU1OTQwZS0tDQo="
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3355"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:39 GMT"
+ ],
+ "Etag": [
+ "CMXE9pqX290CEAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051498000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrqm23:4413,/bns/yv/borg/yv/bns/blobstore2/bitpusher/243.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=fsysW9qAOoGngASMt5uwAw"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yv/borg/yv/bns/blobstore2/bitpusher/243.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yv/borg/yv/bns/blobstore2/bitpusher/243:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRYjRBUXFsa3NIcFl6R0t5SlVsbnU0blE5Y0RGNkp6TDRMRmNFaFpMbTNYekFTUmhVUXQtQzgtN3FQcjhsMERLd0NWM09Mck1iR1lhZG0xZnFESVlSaFR3MzloN1Y0U1JocVZDdmM2eGJ2ZjZhVzcwSlhQU0JjdVVQRzVpMEJIMVdQcGZOR0NiakY1X19QcXBpb3lsWEJVaTFGa0l6TVRZWEk5bVk2N01kSG8wOENVOGN2N3hQenRsa1UwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_single_post_uploads"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UoZH9z6DQLmLB3hszbJhku2WP75wvFdtWB0fK58doI-vthHIkizLLlhv9R7fh6RktiLx1xK60xmYuZySlA3JW_n9MbA8Q"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9zb21lLW9iamVjdC8xNTM4MDUxMTk5MDUwMzA5Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vc29tZS1vYmplY3QiLCJuYW1lIjoic29tZS1vYmplY3QiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE5OTA1MDMwOSIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbiIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNjozOS4wNTBaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjY6MzkuMDUwWiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI2OjM5LjA1MFoiLCJzaXplIjoiMTYiLCJtZDVIYXNoIjoicUUrc2Iva3BhNXRXaGVidWVmdkFOdz09IiwibWVkaWFMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vZG93bmxvYWQvc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL3NvbWUtb2JqZWN0P2dlbmVyYXRpb249MTUzODA1MTE5OTA1MDMwOSZhbHQ9bWVkaWEiLCJjYWNoZUNvbnRyb2wiOiJwdWJsaWMsIG1heC1hZ2U9NjAiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9zb21lLW9iamVjdC8xNTM4MDUxMTk5MDUwMzA5L3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vc29tZS1vYmplY3QvYWNsL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0Ijoic29tZS1vYmplY3QiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE5OTA1MDMwOSIsImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6Im93bmVycyJ9LCJldGFnIjoiQ01YRTlwcVgyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL3NvbWUtb2JqZWN0LzE1MzgwNTExOTkwNTAzMDkvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vc29tZS1vYmplY3QvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6InNvbWUtb2JqZWN0IiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTExOTkwNTAzMDkiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ01YRTlwcVgyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL3NvbWUtb2JqZWN0LzE1MzgwNTExOTkwNTAzMDkvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vc29tZS1vYmplY3QvYWNsL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6InNvbWUtb2JqZWN0IiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTExOTkwNTAzMDkiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNNWEU5cHFYMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9zb21lLW9iamVjdC8xNTM4MDUxMTk5MDUwMzA5L3VzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9zb21lLW9iamVjdC9hY2wvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6InNvbWUtb2JqZWN0IiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTExOTkwNTAzMDkiLCJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwicm9sZSI6Ik9XTkVSIiwiZW1haWwiOiIzNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImV0YWciOiJDTVhFOXBxWDI5MENFQUU9In1dLCJvd25lciI6eyJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIn0sImNyYzMyYyI6IlNqenVxUT09IiwiZXRhZyI6IkNNWEU5cHFYMjkwQ0VBRT0ifQ=="
+ }
+ },
+ {
+ "ID": "9ecb01da3bca46d8",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://storage.googleapis.com/go-integration-test-20180927-44630911863640-0001/some-object",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "Go-http-client/1.1"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "0cf8cc62e6088f206796f89f84a766d2/6241771278919366350;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "storage.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://storage.googleapis.com/go-integration-test-20180927-44630911863640-0001/some-object"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Accept-Ranges": [
+ "bytes"
+ ],
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "public, max-age=60"
+ ],
+ "Content-Length": [
+ "16"
+ ],
+ "Content-Type": [
+ "text/plain"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:39 GMT"
+ ],
+ "Etag": [
+ "\"a84fac6ff9296b9b5685e6ee79fbc037\""
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:27:39 GMT"
+ ],
+ "Last-Modified": [
+ "Thu, 27 Sep 2018 12:26:39 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "X-Goog-Expiration": [
+ "Sat, 27 Oct 2018 12:26:39 GMT"
+ ],
+ "X-Goog-Generation": [
+ "1538051199050309"
+ ],
+ "X-Goog-Hash": [
+ "crc32c=SjzuqQ==",
+ "md5=qE+sb/kpa5tWhebuefvANw=="
+ ],
+ "X-Goog-Metageneration": [
+ "1"
+ ],
+ "X-Goog-Storage-Class": [
+ "STANDARD"
+ ],
+ "X-Goog-Stored-Content-Encoding": [
+ "identity"
+ ],
+ "X-Goog-Stored-Content-Length": [
+ "16"
+ ],
+ "X-Google-Backends": [
+ "/bns/xh/borg/xh/bns/cloud-storage/prod-cloud-storage-frontend.frontend/12,/bns/xh/borg/xh/bns/blobstore2/bitpusher/66.scotty,aclgag19:443"
+ ],
+ "X-Google-Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=f8ysW4nqEcqtswbr-bqwBw"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "aclgag19:443,/bns/xh/borg/xh/bns/blobstore2/bitpusher/66.scotty,aclgag19:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/xh/borg/xh/bns/blobstore2/bitpusher/66:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBJ"
+ ],
+ "X-Google-Storage-Location": [
+ "US"
+ ],
+ "X-Guploader-Customer": [
+ "cloud-storage"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Urw8zsXd0aII9-Dy-sOtg9P7YKZhi_9stUTywmNGoP55deaXNxwKNlKoSuPRmN7ABkk_PN3mBo56AbtnHHgMznZSZtzMQ"
+ ]
+ },
+ "Body": "SXKPLSTG0QfRe3r5RwiU1Q=="
+ }
+ },
+ {
+ "ID": "72b17314bb7de6e2",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/some-object?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "e27bc4849f7b3e65585a7b7f7eb80649/7832182083491666797;o=0"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/some-object?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3355"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:39 GMT"
+ ],
+ "Etag": [
+ "CMXE9pqX290CEAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051498000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrdz77:4028,/bns/yw/borg/yw/bns/blobstore2/bitpusher/20.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=f8ysW7_lGIfjhASigr7ACQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yw/borg/yw/bns/blobstore2/bitpusher/20.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yw/borg/yw/bns/blobstore2/bitpusher/20:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRYjRBUXFsa3NIcFl6R0t5SlVsbnU0blE5Y0RGNkp6TDRMRmNFaFpMbTNYekFTUmhVUXQtQzgtN3FQcjhsMERLd0NWM09Mck1iR1lhZG0xZnFESVlSaFR3MzloN1Y0U1JocVZDdmM2eGJ2ZjZhVzcwSlhQU0JjdVVQRzVpMEJIMVdQcGZOR0NiakY1X19QcXBpb3lsWEJVaTFGa0l6TVRZWEk5bVk2N01kSG8wOENVOGN2N3hQenRsa1UwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Uoa6lNJOwaCeO8CbNnMDeuNJhaMQUSmgIPPeM5txvHbfy-amN-3jbSuXejgrSadZ3_EKFxfGfJNssxhrZahoqwOU3msTQ"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9zb21lLW9iamVjdC8xNTM4MDUxMTk5MDUwMzA5Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vc29tZS1vYmplY3QiLCJuYW1lIjoic29tZS1vYmplY3QiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE5OTA1MDMwOSIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbiIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNjozOS4wNTBaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjY6MzkuMDUwWiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI2OjM5LjA1MFoiLCJzaXplIjoiMTYiLCJtZDVIYXNoIjoicUUrc2Iva3BhNXRXaGVidWVmdkFOdz09IiwibWVkaWFMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vZG93bmxvYWQvc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL3NvbWUtb2JqZWN0P2dlbmVyYXRpb249MTUzODA1MTE5OTA1MDMwOSZhbHQ9bWVkaWEiLCJjYWNoZUNvbnRyb2wiOiJwdWJsaWMsIG1heC1hZ2U9NjAiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9zb21lLW9iamVjdC8xNTM4MDUxMTk5MDUwMzA5L3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vc29tZS1vYmplY3QvYWNsL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0Ijoic29tZS1vYmplY3QiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE5OTA1MDMwOSIsImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6Im93bmVycyJ9LCJldGFnIjoiQ01YRTlwcVgyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL3NvbWUtb2JqZWN0LzE1MzgwNTExOTkwNTAzMDkvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vc29tZS1vYmplY3QvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6InNvbWUtb2JqZWN0IiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTExOTkwNTAzMDkiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ01YRTlwcVgyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL3NvbWUtb2JqZWN0LzE1MzgwNTExOTkwNTAzMDkvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vc29tZS1vYmplY3QvYWNsL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6InNvbWUtb2JqZWN0IiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTExOTkwNTAzMDkiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNNWEU5cHFYMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9zb21lLW9iamVjdC8xNTM4MDUxMTk5MDUwMzA5L3VzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9zb21lLW9iamVjdC9hY2wvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6InNvbWUtb2JqZWN0IiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTExOTkwNTAzMDkiLCJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwicm9sZSI6Ik9XTkVSIiwiZW1haWwiOiIzNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImV0YWciOiJDTVhFOXBxWDI5MENFQUU9In1dLCJvd25lciI6eyJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIn0sImNyYzMyYyI6IlNqenVxUT09IiwiZXRhZyI6IkNNWEU5cHFYMjkwQ0VBRT0ifQ=="
+ }
+ },
+ {
+ "ID": "e6fb407ff0ea1619",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "1986dc56b619cf38e2e1dff7ba63e222/11772042856735554041;o=1"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0, must-revalidate, no-transform"
+ ],
+ "Content-Length": [
+ "2493"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:39 GMT"
+ ],
+ "Etag": [
+ "CAw="
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:26:39 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051499000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vnbq5:4467,/bns/yx/borg/yx/bns/blobstore2/bitpusher/109.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=f8ysW6G1IsOSzALqioPQCw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yx/borg/yx/bns/blobstore2/bitpusher/109.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yx/borg/yx/bns/blobstore2/bitpusher/109:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRWWM5QnpDbzAwZl9ZcWt3RGJLV21iQWhrMXlzd1pUM0N2aVZrcjlNV2FJWWFTcDhXenE5WlVKR2wzVzVQTHNLSFgtRVdicUtncHF4ZzdPbDhpbWVQYXRXRHloVXgxVHhycVZ5R2xtNDNiaTlEZ3BrSGRKWlEtLUVVbndMVXZDSDFsQTIwcDMxMDVwZ3FhcEZhZG5RUFhGYklKTUtsVmRjVE5xaENqRG9UZmdXdXBYcFAyWjNRdlFpbjgwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Ur8lmXsqw9klo3KfTUQKj8SjhLcx5JNfMtlnIfw2b27a3bJzG3Ax2xD9Iqe5ZefCvdfTGStaoPjJlW1JwF-bcyRTqhLEQ"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjM6NTIuMzU1WiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI1OjIxLjYyNFoiLCJtZXRhZ2VuZXJhdGlvbiI6IjEyIiwiYWNsIjpbeyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2FjbC9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0F3PSJ9LHsia2luZCI6InN0b3JhZ2UjYnVja2V0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2FjbC9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6Im93bmVycyJ9LCJldGFnIjoiQ0F3PSJ9LHsia2luZCI6InN0b3JhZ2UjYnVja2V0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwiZW50aXR5IjoicHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6IlJFQURFUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJ2aWV3ZXJzIn0sImV0YWciOiJDQXc9In1dLCJkZWZhdWx0T2JqZWN0QWNsIjpbeyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDQXc9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiZW50aXR5IjoicHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6ImVkaXRvcnMifSwiZXRhZyI6IkNBdz0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNBdz0ifV0sIm93bmVyIjp7ImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1In0sImxvY2F0aW9uIjoiVVMiLCJ2ZXJzaW9uaW5nIjp7ImVuYWJsZWQiOmZhbHNlfSwibGlmZWN5Y2xlIjp7InJ1bGUiOlt7ImFjdGlvbiI6eyJ0eXBlIjoiRGVsZXRlIn0sImNvbmRpdGlvbiI6eyJhZ2UiOjMwfX1dfSwibGFiZWxzIjp7Im5ldyI6Im5ldyIsImwxIjoidjIifSwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJldGFnIjoiQ0F3PSJ9"
+ }
+ },
+ {
+ "ID": "d9fdf9def0ae992e",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0021?alt=json\u0026prettyPrint=false\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "4d4193baef0cea67da822685e135bc86/3998359321505832337;o=1"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0021?alt=json\u0026prettyPrint=false\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 404,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0"
+ ],
+ "Content-Length": [
+ "11693"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:39 GMT"
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:26:39 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051499000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrsp13:4212,/bns/yw/borg/yw/bns/blobstore2/bitpusher/30.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=f8ysW4GkMtWuN-TzuZgK"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yw/borg/yw/bns/blobstore2/bitpusher/30.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yw/borg/yw/bns/blobstore2/bitpusher/30:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRWWM5QnpDbzAwZl9ZcWt3RGJLV21iQWhrMXlzd1pUM0N2aVZrcjlNV2FJWWFTcDhXenE5WlVKR2wzVzVQTHNLSFgtRVdicUtncHF4ZzdPbDhpbWVQYXRXRHloVXgxVHhycVZ5R2xtNDNiaTlEZ3BrSGRKWlEtLUVVbndMVXZDSDFsQTIwcDMxMDVwZ3FhcEZhZG5RUFhGYklKTUtsVmRjVE5xaENqRG9UZmdXdXBYcFAyWjNRdlFpbjgwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Upload-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UoYHqfe9AEz4PqkjcQ8M4PtgG-XYjPzfLqyI_Rwy4j7jrKbFuXHoq_Us0tLKDQaHkdo_OdAFahJfqPTmHZlLIyCWoTjJQ"
+ ]
+ },
+ "Body": "eyJlcnJvciI6eyJlcnJvcnMiOlt7ImRvbWFpbiI6Imdsb2JhbCIsInJlYXNvbiI6Im5vdEZvdW5kIiwibWVzc2FnZSI6Ik5vdCBGb3VuZCIsImRlYnVnSW5mbyI6ImNvbS5nb29nbGUubmV0LnJwYzMuUnBjRXhjZXB0aW9uOiBjbG91ZC5iaWdzdG9yZS5SZXNwb25zZUNvZGUuRXJyb3JDb2RlOjpCVUNLRVRfTk9UX0ZPVU5EOiBObyBzdWNoIGJ1Y2tldDogZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDIxXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRvUnBjM0V4Y2VwdGlvbihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjEzNSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5idWNrZXRzLkdldEJ1Y2tldC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoR2V0QnVja2V0LmphdmE6OTkpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYnVja2V0cy5HZXRCdWNrZXQuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKEdldEJ1Y2tldC5qYXZhOjMxKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmZyYW1ld29yay5SZXF1ZXN0SGFuZGxlci5oYW5kbGUoUmVxdWVzdEhhbmRsZXIuamF2YToyOTQpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uQnVja2V0c0RlbGVnYXRvci5nZXQoQnVja2V0c0RlbGVnYXRvci5qYXZhOjgzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5ScGNSZWNlaXZlci5sYW1iZGEkcHJvY2Vzc1JlcXVlc3RBc3luYyQ0KFJwY1JlY2VpdmVyLmphdmE6MjAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5Bc3luY0V4ZWN1dG9yLmxhbWJkYSRzdWJtaXQkMChBc3luY0V4ZWN1dG9yLmphdmE6MjcyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoQ29udGV4dFJ1bm5hYmxlLmphdmE6NTApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlJDEucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM5KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo3Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5FeGVjdXRvcnMkUnVubmFibGVBZGFwdGVyLmNhbGwoRXhlY3V0b3JzLmphdmE6NTExKVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5GdXR1cmVUYXNrLnJ1bihGdXR1cmVUYXNrLmphdmE6MjY2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IucnVuV29ya2VyKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjExNDkpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvciRXb3JrZXIucnVuKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjYyNClcblx0YXQgamF2YS5sYW5nLlRocmVhZC5ydW4oVGhyZWFkLmphdmE6NzQ4KVxuQ2F1c2VkIGJ5OiBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbjogTm8gc3VjaCBidWNrZXQ6IGdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAyMVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxNyBtb3JlXG5cbmNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLkZhdWx0OiBJbW11dGFibGVFcnJvckRlZmluaXRpb257YmFzZT1OT1RfRk9VTkQsIGNhdGVnb3J5PVVTRVJfRVJST1IsIGNhdXNlPW51bGwsIGRlYnVnSW5mbz1jb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6QlVDS0VUX05PVF9GT1VORDogTm8gc3VjaCBidWNrZXQ6IGdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAyMVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMuYnVja2V0cy5HZXRCdWNrZXQuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKEdldEJ1Y2tldC5qYXZhOjk5KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmJ1Y2tldHMuR2V0QnVja2V0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChHZXRCdWNrZXQuamF2YTozMSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLkJ1Y2tldHNEZWxlZ2F0b3IuZ2V0KEJ1Y2tldHNEZWxlZ2F0b3IuamF2YTo4Mylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uUnBjUmVjZWl2ZXIubGFtYmRhJHByb2Nlc3NSZXF1ZXN0QXN5bmMkNChScGNSZWNlaXZlci5qYXZhOjIwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uQXN5bmNFeGVjdXRvci5sYW1iZGEkc3VibWl0JDAoQXN5bmNFeGVjdXRvci5qYXZhOjI3Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KENvbnRleHRSdW5uYWJsZS5qYXZhOjUwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZSQxLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozOSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NzIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozNilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRXhlY3V0b3JzJFJ1bm5hYmxlQWRhcHRlci5jYWxsKEV4ZWN1dG9ycy5qYXZhOjUxMSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRnV0dXJlVGFzay5ydW4oRnV0dXJlVGFzay5qYXZhOjI2Nilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yLnJ1bldvcmtlcihUaHJlYWRQb29sRXhlY3V0b3IuamF2YToxMTQ5KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IkV29ya2VyLnJ1bihUaHJlYWRQb29sRXhlY3V0b3IuamF2YTo2MjQpXG5cdGF0IGphdmEubGFuZy5UaHJlYWQucnVuKFRocmVhZC5qYXZhOjc0OClcbkNhdXNlZCBieTogY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb246IE5vIHN1Y2ggYnVja2V0OiBnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMjFcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MjkzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAxKVxuXHQuLi4gMTcgbW9yZVxuLCBkb21haW49Z2xvYmFsLCBleHRlbmRlZEhlbHA9bnVsbCwgaHR0cEhlYWRlcnM9e30sIGh0dHBTdGF0dXM9bm90Rm91bmQsIGludGVybmFsUmVhc29uPVJlYXNvbnthcmd1bWVudHM9e30sIGNhdXNlPW51bGwsIGNvZGU9Z2RhdGEuQ29yZUVycm9yRG9tYWluLk5PVF9GT1VORCwgY3JlYXRlZEJ5QmFja2VuZD10cnVlLCBkZWJ1Z01lc3NhZ2U9Y29tLmdvb2dsZS5uZXQucnBjMy5ScGNFeGNlcHRpb246IGNsb3VkLmJpZ3N0b3JlLlJlc3BvbnNlQ29kZS5FcnJvckNvZGU6OkJVQ0tFVF9OT1RfRk9VTkQ6IE5vIHN1Y2ggYnVja2V0OiBnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMjFcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udG9ScGMzRXhjZXB0aW9uKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MTM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmJ1Y2tldHMuR2V0QnVja2V0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChHZXRCdWNrZXQuamF2YTo5OSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5idWNrZXRzLkdldEJ1Y2tldC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoR2V0QnVja2V0LmphdmE6MzEpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5CdWNrZXRzRGVsZWdhdG9yLmdldChCdWNrZXRzRGVsZWdhdG9yLmphdmE6ODMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBObyBzdWNoIGJ1Y2tldDogZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDIxXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93T25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjI5Mylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMSlcblx0Li4uIDE3IG1vcmVcbiwgZXJyb3JQcm90b0NvZGU9Tk9UX0ZPVU5ELCBlcnJvclByb3RvRG9tYWluPWdkYXRhLkNvcmVFcnJvckRvbWFpbiwgZmlsdGVyZWRNZXNzYWdlPW51bGwsIGxvY2F0aW9uPWVudGl0eS5yZXNvdXJjZV9pZC5uYW1lLCBtZXNzYWdlPW51bGwsIHVubmFtZWRBcmd1bWVudHM9W119LCBsb2NhdGlvbj1lbnRpdHkucmVzb3VyY2VfaWQubmFtZSwgbWVzc2FnZT1Ob3QgRm91bmQsIHJlYXNvbj1ub3RGb3VuZCwgcnBjQ29kZT00MDR9IE5vdCBGb3VuZDogY29tLmdvb2dsZS5uZXQucnBjMy5ScGNFeGNlcHRpb246IGNsb3VkLmJpZ3N0b3JlLlJlc3BvbnNlQ29kZS5FcnJvckNvZGU6OkJVQ0tFVF9OT1RfRk9VTkQ6IE5vIHN1Y2ggYnVja2V0OiBnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMjFcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udG9ScGMzRXhjZXB0aW9uKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MTM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLmJ1Y2tldHMuR2V0QnVja2V0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChHZXRCdWNrZXQuamF2YTo5OSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5idWNrZXRzLkdldEJ1Y2tldC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoR2V0QnVja2V0LmphdmE6MzEpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5CdWNrZXRzRGVsZWdhdG9yLmdldChCdWNrZXRzRGVsZWdhdG9yLmphdmE6ODMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBObyBzdWNoIGJ1Y2tldDogZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDIxXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93T25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjI5Mylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMSlcblx0Li4uIDE3IG1vcmVcblxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS5FcnJvckNvbGxlY3Rvci50b0ZhdWx0KEVycm9yQ29sbGVjdG9yLmphdmE6NTQpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5yZXN0LmFkYXB0ZXIucm9zeS5Sb3N5RXJyb3JDb252ZXJ0ZXIudG9GYXVsdChSb3N5RXJyb3JDb252ZXJ0ZXIuamF2YTo2Nylcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnJlc3QuYWRhcHRlci5yb3N5LlJvc3lIYW5kbGVyJDIuY2FsbChSb3N5SGFuZGxlci5qYXZhOjI1OClcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnJlc3QuYWRhcHRlci5yb3N5LlJvc3lIYW5kbGVyJDIuY2FsbChSb3N5SGFuZGxlci5qYXZhOjIzOClcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkRpcmVjdEV4ZWN1dG9yLmV4ZWN1dGUoRGlyZWN0RXhlY3V0b3IuamF2YTozMClcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmV4ZWN1dGVMaXN0ZW5lcihBYnN0cmFjdEZ1dHVyZS5qYXZhOjExNDMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5jb21wbGV0ZShBYnN0cmFjdEZ1dHVyZS5qYXZhOjk2Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLnNldChBYnN0cmFjdEZ1dHVyZS5qYXZhOjczMSlcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkRpcmVjdEV4ZWN1dG9yLmV4ZWN1dGUoRGlyZWN0RXhlY3V0b3IuamF2YTozMClcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmV4ZWN1dGVMaXN0ZW5lcihBYnN0cmFjdEZ1dHVyZS5qYXZhOjExNDMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5jb21wbGV0ZShBYnN0cmFjdEZ1dHVyZS5qYXZhOjk2Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLnNldChBYnN0cmFjdEZ1dHVyZS5qYXZhOjczMSlcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUudXRpbC5DYWxsYWJsZUZ1dHVyZS5ydW4oQ2FsbGFibGVGdXR1cmUuamF2YTo2Milcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnRocmVhZC5UaHJlYWRUcmFja2VycyRUaHJlYWRUcmFja2luZ1J1bm5hYmxlLnJ1bihUaHJlYWRUcmFja2Vycy5qYXZhOjEyNilcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRUcmFjZUNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoVHJhY2VDb250ZXh0LmphdmE6NDU1KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuc2VydmVyLkNvbW1vbk1vZHVsZSRDb250ZXh0Q2FycnlpbmdFeGVjdXRvclNlcnZpY2UkMS5ydW5JbkNvbnRleHQoQ29tbW9uTW9kdWxlLmphdmE6ODQ2KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JFRyYWNlQ29udGV4dFJ1bm5hYmxlJDEucnVuKFRyYWNlQ29udGV4dC5qYXZhOjQ2Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRBYnN0cmFjdFRyYWNlQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoVHJhY2VDb250ZXh0LmphdmE6MzIxKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JEFic3RyYWN0VHJhY2VDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KFRyYWNlQ29udGV4dC5qYXZhOjMxMylcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRUcmFjZUNvbnRleHRSdW5uYWJsZS5ydW4oVHJhY2VDb250ZXh0LmphdmE6NDU5KVxuXHRhdCBjb20uZ29vZ2xlLmdzZS5pbnRlcm5hbC5EaXNwYXRjaFF1ZXVlSW1wbCRXb3JrZXJUaHJlYWQucnVuKERpc3BhdGNoUXVldWVJbXBsLmphdmE6NDAzKVxuIn1dLCJjb2RlIjo0MDQsIm1lc3NhZ2UiOiJOb3QgRm91bmQifX0="
+ }
+ },
+ {
+ "ID": "f2edea2e972018e1",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://storage.googleapis.com/storage-library-test-bucket/Caf%C3%A9",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "Go-http-client/1.1"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "933e44fa78b6b0ed72a1c7d4bd460266/4757677761608773856;o=1"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "storage.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://storage.googleapis.com/storage-library-test-bucket/Caf%C3%A9"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Accept-Ranges": [
+ "bytes"
+ ],
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "public, max-age=3600"
+ ],
+ "Content-Length": [
+ "20"
+ ],
+ "Content-Type": [
+ "text/plain"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:39 GMT"
+ ],
+ "Etag": [
+ "\"ade43306cb39336d630e101af5fb51b4\""
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 13:26:39 GMT"
+ ],
+ "Last-Modified": [
+ "Fri, 24 Mar 2017 20:04:38 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "X-Goog-Generation": [
+ "1490385878535828"
+ ],
+ "X-Goog-Hash": [
+ "crc32c=fN3yZg==",
+ "md5=reQzBss5M21jDhAa9ftRtA=="
+ ],
+ "X-Goog-Metageneration": [
+ "2"
+ ],
+ "X-Goog-Storage-Class": [
+ "MULTI_REGIONAL"
+ ],
+ "X-Goog-Stored-Content-Encoding": [
+ "identity"
+ ],
+ "X-Goog-Stored-Content-Length": [
+ "20"
+ ],
+ "X-Google-Backends": [
+ "/bns/xh/borg/xh/bns/cloud-storage/prod-cloud-storage-frontend.frontend/37,/bns/xh/borg/xh/bns/blobstore2/bitpusher/49.scotty,aclgag19:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=f8ysW_rAMoSiswb5o6qIAQ"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "149776848335"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "aclgag19:443,/bns/xh/borg/xh/bns/blobstore2/bitpusher/49.scotty,aclgag19:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/xh/borg/xh/bns/blobstore2/bitpusher/49:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBJ"
+ ],
+ "X-Google-Storage-Location": [
+ "US"
+ ],
+ "X-Guploader-Customer": [
+ "cloud-storage"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UpJdKvPm3TxMimdp11GJCNz-S3qlr68hTz4f2s27QxYCMrVkbVDSRKeUhg-Btf2ddXmVwaNQ0sXdnkh6Vgfww7XD6j0ww"
+ ]
+ },
+ "Body": "Tm9ybWFsaXphdGlvbiBGb3JtIEM="
+ }
+ },
+ {
+ "ID": "a29c391e37458245",
+ "Request": {
+ "Method": "POST",
+ "URL": "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "Content-Type": [
+ "multipart/related; boundary=ae8294b34cb6487dfa4fea0f258df1ec078489b2ede5ab6f6bac3a2ac7f7"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "109c8ce598490c80bd07e57ab2feb0f2/5588771225556271919;o=1"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/upload/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026prettyPrint=false\u0026projection=full\u0026uploadType=multipart"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": "LS1hZTgyOTRiMzRjYjY0ODdkZmE0ZmVhMGYyNThkZjFlYzA3ODQ4OWIyZWRlNWFiNmY2YmFjM2EyYWM3ZjcNCkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vanNvbg0KDQp7ImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm5hbWUiOiJ6ZXJvIn0KDQotLWFlODI5NGIzNGNiNjQ4N2RmYTRmZWEwZjI1OGRmMWVjMDc4NDg5YjJlZGU1YWI2ZjZiYWMzYTJhYzdmNw0KQ29udGVudC1UeXBlOiB0ZXh0L3BsYWluOyBjaGFyc2V0PXV0Zi04DQoNCg0KLS1hZTgyOTRiMzRjYjY0ODdkZmE0ZmVhMGYyNThkZjFlYzA3ODQ4OWIyZWRlNWFiNmY2YmFjM2EyYWM3ZjctLQ0K"
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "3221"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:40 GMT"
+ ],
+ "Etag": [
+ "CPzzsJuX290CEAE="
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051499000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vrks2:4058,/bns/yw/borg/yw/bns/blobstore2/bitpusher/85.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=f8ysW7vPN8j0hQSdnoHgBg"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "yxfg3-v6:443,/bns/yw/borg/yw/bns/blobstore2/bitpusher/85.scotty,yxfg3-v6:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yw/borg/yw/bns/blobstore2/bitpusher/85:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWWM5QnpDbzAwZl9ZcWt3RGJLV21iQWhrMXlzd1pUM0N2aVZrcjlNV2FJWWFTcDhXenE5WlVKR2wzVzVQTHNLSFgtRVdicUtncHF4ZzdPbDhpbWVQYXRXRHloVXgxVHhycVZ5R2xtNDNiaTlEZ3BrSGRKWlEtLUVVbndMVXZDSDFsQTIwcDMxMDVwZ3FhcEZhZG5RUFhGYklKTUtsVmRjVE5xaENqRG9UZmdXdXBYcFAyWjNRdlFpbjgwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_single_post_uploads"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UprL6_ZKFBbAa3bmTkv0s56mho6CPzO6zIAoHGZ_upPgJFAGrHfSXKPmjgB17shyHdAD2SvQz7t6nCfVMo65tybQC7OiQ"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS96ZXJvLzE1MzgwNTEyMDAwMDY2NTIiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby96ZXJvIiwibmFtZSI6Inplcm8iLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTIwMDAwNjY1MiIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOCIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNjo0MC4wMDVaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjY6NDAuMDA1WiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI2OjQwLjAwNVoiLCJzaXplIjoiMCIsIm1kNUhhc2giOiIxQjJNMlk4QXNnVHBnQW1ZN1BoQ2ZnPT0iLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vemVybz9nZW5lcmF0aW9uPTE1MzgwNTEyMDAwMDY2NTImYWx0PW1lZGlhIiwiYWNsIjpbeyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvemVyby8xNTM4MDUxMjAwMDA2NjUyL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vemVyby9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJ6ZXJvIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEyMDAwMDY2NTIiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNQenpzSnVYMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS96ZXJvLzE1MzgwNTEyMDAwMDY2NTIvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vemVyby9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiemVybyIsImdlbmVyYXRpb24iOiIxNTM4MDUxMjAwMDA2NjUyIiwiZW50aXR5IjoicHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6ImVkaXRvcnMifSwiZXRhZyI6IkNQenpzSnVYMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS96ZXJvLzE1MzgwNTEyMDAwMDY2NTIvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vemVyby9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiemVybyIsImdlbmVyYXRpb24iOiIxNTM4MDUxMjAwMDA2NjUyIiwiZW50aXR5IjoicHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6IlJFQURFUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJ2aWV3ZXJzIn0sImV0YWciOiJDUHp6c0p1WDI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvemVyby8xNTM4MDUxMjAwMDA2NjUyL3VzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby96ZXJvL2FjbC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiemVybyIsImdlbmVyYXRpb24iOiIxNTM4MDUxMjAwMDA2NjUyIiwiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInJvbGUiOiJPV05FUiIsImVtYWlsIjoiMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJldGFnIjoiQ1B6enNKdVgyOTBDRUFFPSJ9XSwib3duZXIiOnsiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSJ9LCJjcmMzMmMiOiJBQUFBQUE9PSIsImV0YWciOiJDUHp6c0p1WDI5MENFQUU9In0="
+ }
+ },
+ {
+ "ID": "ad8e1b5fa8d4abd6",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0021/o?alt=json\u0026delimiter=\u0026pageToken=\u0026prefix=\u0026prettyPrint=false\u0026projection=full\u0026versions=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "72f5cb05d9cd5cf0128b6566bbb6b02f/6348089665675924863;o=1"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0021/o?alt=json\u0026delimiter=\u0026pageToken=\u0026prefix=\u0026prettyPrint=false\u0026projection=full\u0026versions=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 404,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0"
+ ],
+ "Content-Length": [
+ "11713"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:39 GMT"
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:26:39 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051499000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vlhm196:4223,/bns/yk/borg/yk/bns/blobstore2/bitpusher/511.scotty,acatlm7:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=f8ysW5aMONXuqQXr74ywDA"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "acatlm7:443,/bns/yk/borg/yk/bns/blobstore2/bitpusher/511.scotty,acatlm7:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yk/borg/yk/bns/blobstore2/bitpusher/511:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRWWM5QnpDbzAwZl9ZcWt3RGJLV21iQWhrMXlzd1pUM0N2aVZrcjlNV2FJWWFTcDhXenE5WlVKR2wzVzVQTHNLSFgtRVdicUtncHF4ZzdPbDhpbWVQYXRXRHloVXgxVHhycVZ5R2xtNDNiaTlEZ3BrSGRKWlEtLUVVbndMVXZDSDFsQTIwcDMxMDVwZ3FhcEZhZG5RUFhGYklKTUtsVmRjVE5xaENqRG9UZmdXdXBYcFAyWjNRdlFpbjgwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Upload-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UpkzYrUdFlxkZrW8EdgXtWWUKQvTAJuGymLHVTn4cPRfEREWNaVKuXwyYW4mF2y6_d3a1GoYDsx3b3TTuknUqSSfQEl_g"
+ ]
+ },
+ "Body": "eyJlcnJvciI6eyJlcnJvcnMiOlt7ImRvbWFpbiI6Imdsb2JhbCIsInJlYXNvbiI6Im5vdEZvdW5kIiwibWVzc2FnZSI6Ik5vdCBGb3VuZCIsImRlYnVnSW5mbyI6ImNvbS5nb29nbGUubmV0LnJwYzMuUnBjRXhjZXB0aW9uOiBjbG91ZC5iaWdzdG9yZS5SZXNwb25zZUNvZGUuRXJyb3JDb2RlOjpCVUNLRVRfTk9UX0ZPVU5EOiBObyBzdWNoIGJ1Y2tldDogZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDIxXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRvUnBjM0V4Y2VwdGlvbihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjEzNSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5vYmplY3RzLkxpc3RPYmplY3RzLmhhbmRsZVJlcXVlc3RSZWNlaXZlZChMaXN0T2JqZWN0cy5qYXZhOjE2MClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5vYmplY3RzLkxpc3RPYmplY3RzLmhhbmRsZVJlcXVlc3RSZWNlaXZlZChMaXN0T2JqZWN0cy5qYXZhOjM4KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmZyYW1ld29yay5SZXF1ZXN0SGFuZGxlci5oYW5kbGUoUmVxdWVzdEhhbmRsZXIuamF2YToyOTQpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uT2JqZWN0c0RlbGVnYXRvci5saXN0KE9iamVjdHNEZWxlZ2F0b3IuamF2YTo4OSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uUnBjUmVjZWl2ZXIubGFtYmRhJHByb2Nlc3NSZXF1ZXN0QXN5bmMkNChScGNSZWNlaXZlci5qYXZhOjIwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uQXN5bmNFeGVjdXRvci5sYW1iZGEkc3VibWl0JDAoQXN5bmNFeGVjdXRvci5qYXZhOjI3Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KENvbnRleHRSdW5uYWJsZS5qYXZhOjUwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZSQxLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozOSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NzIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozNilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRXhlY3V0b3JzJFJ1bm5hYmxlQWRhcHRlci5jYWxsKEV4ZWN1dG9ycy5qYXZhOjUxMSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRnV0dXJlVGFzay5ydW4oRnV0dXJlVGFzay5qYXZhOjI2Nilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yLnJ1bldvcmtlcihUaHJlYWRQb29sRXhlY3V0b3IuamF2YToxMTQ5KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IkV29ya2VyLnJ1bihUaHJlYWRQb29sRXhlY3V0b3IuamF2YTo2MjQpXG5cdGF0IGphdmEubGFuZy5UaHJlYWQucnVuKFRocmVhZC5qYXZhOjc0OClcbkNhdXNlZCBieTogY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb246IE5vIHN1Y2ggYnVja2V0OiBnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMjFcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MjkzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAxKVxuXHQuLi4gMTcgbW9yZVxuXG5jb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS5GYXVsdDogSW1tdXRhYmxlRXJyb3JEZWZpbml0aW9ue2Jhc2U9Tk9UX0ZPVU5ELCBjYXRlZ29yeT1VU0VSX0VSUk9SLCBjYXVzZT1udWxsLCBkZWJ1Z0luZm89Y29tLmdvb2dsZS5uZXQucnBjMy5ScGNFeGNlcHRpb246IGNsb3VkLmJpZ3N0b3JlLlJlc3BvbnNlQ29kZS5FcnJvckNvZGU6OkJVQ0tFVF9OT1RfRk9VTkQ6IE5vIHN1Y2ggYnVja2V0OiBnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMjFcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udG9ScGMzRXhjZXB0aW9uKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MTM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuTGlzdE9iamVjdHMuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKExpc3RPYmplY3RzLmphdmE6MTYwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuTGlzdE9iamVjdHMuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKExpc3RPYmplY3RzLmphdmE6MzgpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5PYmplY3RzRGVsZWdhdG9yLmxpc3QoT2JqZWN0c0RlbGVnYXRvci5qYXZhOjg5KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5ScGNSZWNlaXZlci5sYW1iZGEkcHJvY2Vzc1JlcXVlc3RBc3luYyQ0KFJwY1JlY2VpdmVyLmphdmE6MjAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5Bc3luY0V4ZWN1dG9yLmxhbWJkYSRzdWJtaXQkMChBc3luY0V4ZWN1dG9yLmphdmE6MjcyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoQ29udGV4dFJ1bm5hYmxlLmphdmE6NTApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlJDEucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM5KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo3Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5FeGVjdXRvcnMkUnVubmFibGVBZGFwdGVyLmNhbGwoRXhlY3V0b3JzLmphdmE6NTExKVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5GdXR1cmVUYXNrLnJ1bihGdXR1cmVUYXNrLmphdmE6MjY2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IucnVuV29ya2VyKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjExNDkpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvciRXb3JrZXIucnVuKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjYyNClcblx0YXQgamF2YS5sYW5nLlRocmVhZC5ydW4oVGhyZWFkLmphdmE6NzQ4KVxuQ2F1c2VkIGJ5OiBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbjogTm8gc3VjaCBidWNrZXQ6IGdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAyMVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxNyBtb3JlXG4sIGRvbWFpbj1nbG9iYWwsIGV4dGVuZGVkSGVscD1udWxsLCBodHRwSGVhZGVycz17fSwgaHR0cFN0YXR1cz1ub3RGb3VuZCwgaW50ZXJuYWxSZWFzb249UmVhc29ue2FyZ3VtZW50cz17fSwgY2F1c2U9bnVsbCwgY29kZT1nZGF0YS5Db3JlRXJyb3JEb21haW4uTk9UX0ZPVU5ELCBjcmVhdGVkQnlCYWNrZW5kPXRydWUsIGRlYnVnTWVzc2FnZT1jb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6QlVDS0VUX05PVF9GT1VORDogTm8gc3VjaCBidWNrZXQ6IGdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAyMVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5MaXN0T2JqZWN0cy5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoTGlzdE9iamVjdHMuamF2YToxNjApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5MaXN0T2JqZWN0cy5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoTGlzdE9iamVjdHMuamF2YTozOClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLk9iamVjdHNEZWxlZ2F0b3IubGlzdChPYmplY3RzRGVsZWdhdG9yLmphdmE6ODkpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBObyBzdWNoIGJ1Y2tldDogZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDIxXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93T25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjI5Mylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMSlcblx0Li4uIDE3IG1vcmVcbiwgZXJyb3JQcm90b0NvZGU9Tk9UX0ZPVU5ELCBlcnJvclByb3RvRG9tYWluPWdkYXRhLkNvcmVFcnJvckRvbWFpbiwgZmlsdGVyZWRNZXNzYWdlPW51bGwsIGxvY2F0aW9uPWVudGl0eS5idWNrZXQsIG1lc3NhZ2U9bnVsbCwgdW5uYW1lZEFyZ3VtZW50cz1bXX0sIGxvY2F0aW9uPWVudGl0eS5idWNrZXQsIG1lc3NhZ2U9Tm90IEZvdW5kLCByZWFzb249bm90Rm91bmQsIHJwY0NvZGU9NDA0fSBOb3QgRm91bmQ6IGNvbS5nb29nbGUubmV0LnJwYzMuUnBjRXhjZXB0aW9uOiBjbG91ZC5iaWdzdG9yZS5SZXNwb25zZUNvZGUuRXJyb3JDb2RlOjpCVUNLRVRfTk9UX0ZPVU5EOiBObyBzdWNoIGJ1Y2tldDogZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDIxXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRvUnBjM0V4Y2VwdGlvbihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjEzNSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5vYmplY3RzLkxpc3RPYmplY3RzLmhhbmRsZVJlcXVlc3RSZWNlaXZlZChMaXN0T2JqZWN0cy5qYXZhOjE2MClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5vYmplY3RzLkxpc3RPYmplY3RzLmhhbmRsZVJlcXVlc3RSZWNlaXZlZChMaXN0T2JqZWN0cy5qYXZhOjM4KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmZyYW1ld29yay5SZXF1ZXN0SGFuZGxlci5oYW5kbGUoUmVxdWVzdEhhbmRsZXIuamF2YToyOTQpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uT2JqZWN0c0RlbGVnYXRvci5saXN0KE9iamVjdHNEZWxlZ2F0b3IuamF2YTo4OSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uUnBjUmVjZWl2ZXIubGFtYmRhJHByb2Nlc3NSZXF1ZXN0QXN5bmMkNChScGNSZWNlaXZlci5qYXZhOjIwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uQXN5bmNFeGVjdXRvci5sYW1iZGEkc3VibWl0JDAoQXN5bmNFeGVjdXRvci5qYXZhOjI3Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KENvbnRleHRSdW5uYWJsZS5qYXZhOjUwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZSQxLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozOSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NzIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozNilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRXhlY3V0b3JzJFJ1bm5hYmxlQWRhcHRlci5jYWxsKEV4ZWN1dG9ycy5qYXZhOjUxMSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRnV0dXJlVGFzay5ydW4oRnV0dXJlVGFzay5qYXZhOjI2Nilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yLnJ1bldvcmtlcihUaHJlYWRQb29sRXhlY3V0b3IuamF2YToxMTQ5KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IkV29ya2VyLnJ1bihUaHJlYWRQb29sRXhlY3V0b3IuamF2YTo2MjQpXG5cdGF0IGphdmEubGFuZy5UaHJlYWQucnVuKFRocmVhZC5qYXZhOjc0OClcbkNhdXNlZCBieTogY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb246IE5vIHN1Y2ggYnVja2V0OiBnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMjFcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MjkzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAxKVxuXHQuLi4gMTcgbW9yZVxuXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLkVycm9yQ29sbGVjdG9yLnRvRmF1bHQoRXJyb3JDb2xsZWN0b3IuamF2YTo1NClcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnJlc3QuYWRhcHRlci5yb3N5LlJvc3lFcnJvckNvbnZlcnRlci50b0ZhdWx0KFJvc3lFcnJvckNvbnZlcnRlci5qYXZhOjY3KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIucmVzdC5hZGFwdGVyLnJvc3kuUm9zeUhhbmRsZXIkMi5jYWxsKFJvc3lIYW5kbGVyLmphdmE6MjU4KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIucmVzdC5hZGFwdGVyLnJvc3kuUm9zeUhhbmRsZXIkMi5jYWxsKFJvc3lIYW5kbGVyLmphdmE6MjM4KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS51dGlsLkNhbGxhYmxlRnV0dXJlLnJ1bihDYWxsYWJsZUZ1dHVyZS5qYXZhOjYyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuRGlyZWN0RXhlY3V0b3IuZXhlY3V0ZShEaXJlY3RFeGVjdXRvci5qYXZhOjMwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuZXhlY3V0ZUxpc3RlbmVyKEFic3RyYWN0RnV0dXJlLmphdmE6MTE0Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmNvbXBsZXRlKEFic3RyYWN0RnV0dXJlLmphdmE6OTYzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuc2V0KEFic3RyYWN0RnV0dXJlLmphdmE6NzMxKVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS51dGlsLkNhbGxhYmxlRnV0dXJlLnJ1bihDYWxsYWJsZUZ1dHVyZS5qYXZhOjYyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuRGlyZWN0RXhlY3V0b3IuZXhlY3V0ZShEaXJlY3RFeGVjdXRvci5qYXZhOjMwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuZXhlY3V0ZUxpc3RlbmVyKEFic3RyYWN0RnV0dXJlLmphdmE6MTE0Mylcblx0YXQgY29tLmdvb2dsZS5jb21tb24udXRpbC5jb25jdXJyZW50LkFic3RyYWN0RnV0dXJlLmNvbXBsZXRlKEFic3RyYWN0RnV0dXJlLmphdmE6OTYzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuc2V0KEFic3RyYWN0RnV0dXJlLmphdmE6NzMxKVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIuY29yZS51dGlsLkNhbGxhYmxlRnV0dXJlLnJ1bihDYWxsYWJsZUZ1dHVyZS5qYXZhOjYyKVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIudGhyZWFkLlRocmVhZFRyYWNrZXJzJFRocmVhZFRyYWNraW5nUnVubmFibGUucnVuKFRocmVhZFRyYWNrZXJzLmphdmE6MTI2KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JFRyYWNlQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChUcmFjZUNvbnRleHQuamF2YTo0NTUpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5zZXJ2ZXIuQ29tbW9uTW9kdWxlJENvbnRleHRDYXJyeWluZ0V4ZWN1dG9yU2VydmljZSQxLnJ1bkluQ29udGV4dChDb21tb25Nb2R1bGUuamF2YTo4NDYpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkVHJhY2VDb250ZXh0UnVubmFibGUkMS5ydW4oVHJhY2VDb250ZXh0LmphdmE6NDYyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JEFic3RyYWN0VHJhY2VDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihUcmFjZUNvbnRleHQuamF2YTozMjEpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkQWJzdHJhY3RUcmFjZUNvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoVHJhY2VDb250ZXh0LmphdmE6MzEzKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuVHJhY2VDb250ZXh0JFRyYWNlQ29udGV4dFJ1bm5hYmxlLnJ1bihUcmFjZUNvbnRleHQuamF2YTo0NTkpXG5cdGF0IGNvbS5nb29nbGUuZ3NlLmludGVybmFsLkRpc3BhdGNoUXVldWVJbXBsJFdvcmtlclRocmVhZC5ydW4oRGlzcGF0Y2hRdWV1ZUltcGwuamF2YTo0MDMpXG4ifV0sImNvZGUiOjQwNCwibWVzc2FnZSI6Ik5vdCBGb3VuZCJ9fQ=="
+ }
+ },
+ {
+ "ID": "66fe2a28fb424b1b",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://storage.googleapis.com/storage-library-test-bucket/Cafe%CC%81",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "Go-http-client/1.1"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "c37f321207ea898411bcb64ce8a123d9/7938218995254868765;o=1"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "storage.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://storage.googleapis.com/storage-library-test-bucket/Cafe%CC%81"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Accept-Ranges": [
+ "bytes"
+ ],
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "public, max-age=3600"
+ ],
+ "Content-Length": [
+ "20"
+ ],
+ "Content-Type": [
+ "text/plain"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:40 GMT"
+ ],
+ "Etag": [
+ "\"df597679bac7c6150429ad80a1a05680\""
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 13:26:40 GMT"
+ ],
+ "Last-Modified": [
+ "Fri, 24 Mar 2017 20:04:37 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "X-Goog-Generation": [
+ "1490385877705600"
+ ],
+ "X-Goog-Hash": [
+ "crc32c=qBeWjQ==",
+ "md5=31l2ebrHxhUEKa2AoaBWgA=="
+ ],
+ "X-Goog-Metageneration": [
+ "2"
+ ],
+ "X-Goog-Storage-Class": [
+ "MULTI_REGIONAL"
+ ],
+ "X-Goog-Stored-Content-Encoding": [
+ "identity"
+ ],
+ "X-Goog-Stored-Content-Length": [
+ "20"
+ ],
+ "X-Google-Backends": [
+ "/bns/xh/borg/xh/bns/cloud-storage/prod-cloud-storage-frontend.frontend/41,/bns/xh/borg/xh/bns/blobstore2/bitpusher/31.scotty,aclgag19:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=gMysW-n0Au2iswb0w5eIAQ"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "149776848335"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "aclgag19:443,/bns/xh/borg/xh/bns/blobstore2/bitpusher/31.scotty,aclgag19:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/xh/borg/xh/bns/blobstore2/bitpusher/31:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBJ"
+ ],
+ "X-Google-Storage-Location": [
+ "US"
+ ],
+ "X-Guploader-Customer": [
+ "cloud-storage"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UoNn1YQ-BDeQ-KRYAa-HiVMAgNHohnsb2swJwhk8j-DIFUfIxwS-uSy-ewFIj6cekOhnlt8vVrHhxZkrgZ3kftYtB2g_A"
+ ]
+ },
+ "Body": "Tm9ybWFsaXphdGlvbiBGb3JtIEQ="
+ }
+ },
+ {
+ "ID": "f235a22996dff1e9",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://storage.googleapis.com/go-integration-test-20180927-44630911863640-0001/zero",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "Go-http-client/1.1"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "5235692a62da640b886a2be6092c3a8f/9528630899322020028;o=1"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "storage.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://storage.googleapis.com/go-integration-test-20180927-44630911863640-0001/zero"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Accept-Ranges": [
+ "bytes"
+ ],
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0"
+ ],
+ "Content-Length": [
+ "0"
+ ],
+ "Content-Type": [
+ "text/plain; charset=utf-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:40 GMT"
+ ],
+ "Etag": [
+ "\"d41d8cd98f00b204e9800998ecf8427e\""
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:26:40 GMT"
+ ],
+ "Last-Modified": [
+ "Thu, 27 Sep 2018 12:26:40 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "X-Goog-Expiration": [
+ "Sat, 27 Oct 2018 12:26:40 GMT"
+ ],
+ "X-Goog-Generation": [
+ "1538051200006652"
+ ],
+ "X-Goog-Hash": [
+ "crc32c=AAAAAA==",
+ "md5=1B2M2Y8AsgTpgAmY7PhCfg=="
+ ],
+ "X-Goog-Metageneration": [
+ "1"
+ ],
+ "X-Goog-Storage-Class": [
+ "STANDARD"
+ ],
+ "X-Goog-Stored-Content-Encoding": [
+ "identity"
+ ],
+ "X-Goog-Stored-Content-Length": [
+ "0"
+ ],
+ "X-Google-Backends": [
+ "/bns/xh/borg/xh/bns/cloud-storage/prod-cloud-storage-frontend.frontend/31,/bns/xh/borg/xh/bns/blobstore2/bitpusher/54.scotty,aclgag19:443"
+ ],
+ "X-Google-Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=gMysW43ZCaagswbX74WoBA"
+ ],
+ "X-Google-Gfe-Cloud-Project-Number": [
+ "36639933145"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "aclgag19:443,/bns/xh/borg/xh/bns/blobstore2/bitpusher/54.scotty,aclgag19:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/xh/borg/xh/bns/blobstore2/bitpusher/54:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-cloud-storage"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBJ"
+ ],
+ "X-Google-Storage-Location": [
+ "US"
+ ],
+ "X-Guploader-Customer": [
+ "cloud-storage"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UpRIGEDgm48N7EzftkVrfZeWQdtHI4QTti5zdCFBt7gLd3XZDI6Ehi5VVtXA0DAnoDRx1CGBgC0W9CGOHt-JOsIkALP1g"
+ ]
+ },
+ "Body": ""
+ }
+ },
+ {
+ "ID": "7889cb6a06d14c21",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/zero?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "f59da26d669545720dc31e2a55614433/10359724363269518091;o=1"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/zero?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 204,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "0"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:40 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051500000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vnpp189:4374,/bns/yk/borg/yk/bns/blobstore2/bitpusher/765.scotty,acatlm7:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=gMysW5rFDtW4qQXQnLHQBQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "acatlm7:443,/bns/yk/borg/yk/bns/blobstore2/bitpusher/765.scotty,acatlm7:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yk/borg/yk/bns/blobstore2/bitpusher/765:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWWM5QnpDbzAwZl9ZcWt3RGJLV21iQWhrMXlzd1pUM0N2aVZrcjlNV2FJWWFTcDhXenE5WlVKR2wzVzVQTHNLSFgtRVdicUtncHF4ZzdPbDhpbWVQYXRXRHloVXgxVHhycVZ5R2xtNDNiaTlEZ3BrSGRKWlEtLUVVbndMVXZDSDFsQTIwcDMxMDVwZ3FhcEZhZG5RUFhGYklKTUtsVmRjVE5xaENqRG9UZmdXdXBYcFAyWjNRdlFpbjgwBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UqRhqqFiBwv6ALAvWPdy7FoMtfiJtc7AdZC3JrI92TgGvrnvK6IouIO2tkfGGKVxqq0SdCy6c-3RlAZqCL2DVyogJawrA"
+ ]
+ },
+ "Body": ""
+ }
+ },
+ {
+ "ID": "df180f9e03860f11",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026delimiter=\u0026pageToken=\u0026prefix=\u0026prettyPrint=false\u0026projection=full\u0026versions=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "725cdf27d3143785c971c87035f61f1a/11119042803372394075;o=1"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o?alt=json\u0026delimiter=\u0026pageToken=\u0026prefix=\u0026prettyPrint=false\u0026projection=full\u0026versions=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0, must-revalidate, no-transform"
+ ],
+ "Content-Length": [
+ "66618"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:44 GMT"
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:26:44 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051503000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vlep62:4200,/bns/yk/borg/yk/bns/blobstore2/bitpusher/689.scotty,acatlm7:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=g8ysW__dOdXZqAXus6PwCg"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "acatlm7:443,/bns/yk/borg/yk/bns/blobstore2/bitpusher/689.scotty,acatlm7:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yk/borg/yk/bns/blobstore2/bitpusher/689:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRWU94SDhBWjdSeWVHSm16OFFSZV80RWc4RjdJOUFYemxhX1lqdU1TYkM3YkFFZ2hZY3JuVmR3ckppdUNMWlQyUXNhUWFlV01xeW1EbmRlY3EySHQ5b0ZjQmtGZDA5bk9yZTl4T3Q1Q081RXpHVkNNMGxQQjdneUR4Nm9iMWJFUlZqVTJ0QTJMX0tzMnhZZkRTaEU2cFhlTlpEMzR3Z3lJbUZXQjBUTVU0eDNvLTVFVG5Wa2VpSW9rR00wBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UoqUqo_U2y3joYDko_2gxf4WCSpFiddYyWfcbCD8QiyOD-5tvBtzIAB0JiYF9KQSIvI6DqW2XH7pa1qz4qgsuEplKIO-g"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3RzIiwiaXRlbXMiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2FjbDEvMTUzODA1MTA2MzIzMTMxNyIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2FjbDEiLCJuYW1lIjoiYWNsMSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDYzMjMxMzE3IiwibWV0YWdlbmVyYXRpb24iOiIyIiwiY29udGVudFR5cGUiOiJhcHBsaWNhdGlvbi9vY3RldC1zdHJlYW0iLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MjMuMjMwWiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjI0LjQ4N1oiLCJzdG9yYWdlQ2xhc3MiOiJTVEFOREFSRCIsInRpbWVTdG9yYWdlQ2xhc3NVcGRhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDoyMy4yMzBaIiwic2l6ZSI6IjE2IiwibWQ1SGFzaCI6InpwQ0ozb3JROTV5eHZmeitRcTd2UUE9PSIsIm1lZGlhTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2Rvd25sb2FkL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9hY2wxP2dlbmVyYXRpb249MTUzODA1MTA2MzIzMTMxNyZhbHQ9bWVkaWEiLCJjYWNoZUNvbnRyb2wiOiJwdWJsaWMsIG1heC1hZ2U9NjAiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9hY2wxLzE1MzgwNTEwNjMyMzEzMTcvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9hY2wxL2FjbC9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6ImFjbDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA2MzIzMTMxNyIsImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6Im93bmVycyJ9LCJldGFnIjoiQ05YbWxOcVcyOTBDRUFJPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2FjbDEvMTUzODA1MTA2MzIzMTMxNy9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9hY2wxL2FjbC9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJhY2wxIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNjMyMzEzMTciLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ05YbWxOcVcyOTBDRUFJPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2FjbDEvMTUzODA1MTA2MzIzMTMxNy9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9hY2wxL2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJhY2wxIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNjMyMzEzMTciLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNOWG1sTnFXMjkwQ0VBST0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9hY2wxLzE1MzgwNTEwNjMyMzEzMTcvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2FjbDEvYWNsL3VzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJhY2wxIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNjMyMzEzMTciLCJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwicm9sZSI6Ik9XTkVSIiwiZW1haWwiOiIzNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImV0YWciOiJDTlhtbE5xVzI5MENFQUk9In1dLCJvd25lciI6eyJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIn0sImNyYzMyYyI6IjViL2ltZz09IiwiZXRhZyI6IkNOWG1sTnFXMjkwQ0VBST0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2FjbDIvMTUzODA1MTA2Mzk1MTQ5OSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2FjbDIiLCJuYW1lIjoiYWNsMiIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDYzOTUxNDk5IiwibWV0YWdlbmVyYXRpb24iOiIxIiwiY29udGVudFR5cGUiOiJhcHBsaWNhdGlvbi9vY3RldC1zdHJlYW0iLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MjMuOTUxWiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjIzLjk1MVoiLCJzdG9yYWdlQ2xhc3MiOiJTVEFOREFSRCIsInRpbWVTdG9yYWdlQ2xhc3NVcGRhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDoyMy45NTFaIiwic2l6ZSI6IjE2IiwibWQ1SGFzaCI6ImFtdGMwalVmWjJDRUYwR1ZmNVR6ZXc9PSIsIm1lZGlhTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2Rvd25sb2FkL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9hY2wyP2dlbmVyYXRpb249MTUzODA1MTA2Mzk1MTQ5OSZhbHQ9bWVkaWEiLCJjYWNoZUNvbnRyb2wiOiJwdWJsaWMsIG1heC1hZ2U9NjAiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9hY2wyLzE1MzgwNTEwNjM5NTE0OTkvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9hY2wyL2FjbC9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6ImFjbDIiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA2Mzk1MTQ5OSIsImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6Im93bmVycyJ9LCJldGFnIjoiQ0l2aHdOcVcyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2FjbDIvMTUzODA1MTA2Mzk1MTQ5OS9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9hY2wyL2FjbC9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJhY2wyIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNjM5NTE0OTkiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0l2aHdOcVcyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2FjbDIvMTUzODA1MTA2Mzk1MTQ5OS9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9hY2wyL2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJhY2wyIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNjM5NTE0OTkiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNJdmh3TnFXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9hY2wyLzE1MzgwNTEwNjM5NTE0OTkvZG9tYWluLWdvb2dsZS5jb20iLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9hY2wyL2FjbC9kb21haW4tZ29vZ2xlLmNvbSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6ImFjbDIiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA2Mzk1MTQ5OSIsImVudGl0eSI6ImRvbWFpbi1nb29nbGUuY29tIiwicm9sZSI6IlJFQURFUiIsImRvbWFpbiI6Imdvb2dsZS5jb20iLCJldGFnIjoiQ0l2aHdOcVcyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2FjbDIvMTUzODA1MTA2Mzk1MTQ5OS91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vYWNsMi9hY2wvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6ImFjbDIiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA2Mzk1MTQ5OSIsImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJyb2xlIjoiT1dORVIiLCJlbWFpbCI6IjM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiZXRhZyI6IkNJdmh3TnFXMjkwQ0VBRT0ifV0sIm93bmVyIjp7ImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20ifSwiY3JjMzJjIjoiWWRyanhnPT0iLCJldGFnIjoiQ0l2aHdOcVcyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0IiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvYnVja2V0SW5Db3B5QXR0cnMvMTUzODA1MTA4NDIyNDYwMCIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2J1Y2tldEluQ29weUF0dHJzIiwibmFtZSI6ImJ1Y2tldEluQ29weUF0dHJzIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwODQyMjQ2MDAiLCJtZXRhZ2VuZXJhdGlvbiI6IjEiLCJjb250ZW50VHlwZSI6InRleHQvcGxhaW47IGNoYXJzZXQ9dXRmLTgiLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6NDQuMjI0WiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjQ0LjIyNFoiLCJzdG9yYWdlQ2xhc3MiOiJTVEFOREFSRCIsInRpbWVTdG9yYWdlQ2xhc3NVcGRhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDo0NC4yMjRaIiwic2l6ZSI6IjMiLCJtZDVIYXNoIjoickwwWTIwekMrRnp0NzJWUHpNU2syQT09IiwibWVkaWFMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vZG93bmxvYWQvc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2J1Y2tldEluQ29weUF0dHJzP2dlbmVyYXRpb249MTUzODA1MTA4NDIyNDYwMCZhbHQ9bWVkaWEiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9idWNrZXRJbkNvcHlBdHRycy8xNTM4MDUxMDg0MjI0NjAwL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vYnVja2V0SW5Db3B5QXR0cnMvYWNsL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiYnVja2V0SW5Db3B5QXR0cnMiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA4NDIyNDYwMCIsImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6Im93bmVycyJ9LCJldGFnIjoiQ05pUWx1U1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2J1Y2tldEluQ29weUF0dHJzLzE1MzgwNTEwODQyMjQ2MDAvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vYnVja2V0SW5Db3B5QXR0cnMvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6ImJ1Y2tldEluQ29weUF0dHJzIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwODQyMjQ2MDAiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ05pUWx1U1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2J1Y2tldEluQ29weUF0dHJzLzE1MzgwNTEwODQyMjQ2MDAvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vYnVja2V0SW5Db3B5QXR0cnMvYWNsL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6ImJ1Y2tldEluQ29weUF0dHJzIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwODQyMjQ2MDAiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNOaVFsdVNXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9idWNrZXRJbkNvcHlBdHRycy8xNTM4MDUxMDg0MjI0NjAwL3VzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9idWNrZXRJbkNvcHlBdHRycy9hY2wvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6ImJ1Y2tldEluQ29weUF0dHJzIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwODQyMjQ2MDAiLCJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwicm9sZSI6Ik9XTkVSIiwiZW1haWwiOiIzNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImV0YWciOiJDTmlRbHVTVzI5MENFQUU9In1dLCJvd25lciI6eyJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIn0sImNyYzMyYyI6Ino4U3VIUT09IiwiZXRhZyI6IkNOaVFsdVNXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2NoZWNrc3VtLW9iamVjdC8xNTM4MDUxMDU1MzM3NTE5Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vY2hlY2tzdW0tb2JqZWN0IiwibmFtZSI6ImNoZWNrc3VtLW9iamVjdCIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDU1MzM3NTE5IiwibWV0YWdlbmVyYXRpb24iOiIxIiwiY29udGVudFR5cGUiOiJ0ZXh0L3BsYWluOyBjaGFyc2V0PXV0Zi04IiwidGltZUNyZWF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjE1LjMzN1oiLCJ1cGRhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDoxNS4zMzdaIiwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJ0aW1lU3RvcmFnZUNsYXNzVXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MTUuMzM3WiIsInNpemUiOiIxMCIsIm1kNUhhc2giOiIvRjREalRpbGNESUlWRUhuL25BUXNBPT0iLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vY2hlY2tzdW0tb2JqZWN0P2dlbmVyYXRpb249MTUzODA1MTA1NTMzNzUxOSZhbHQ9bWVkaWEiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jaGVja3N1bS1vYmplY3QvMTUzODA1MTA1NTMzNzUxOS9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2NoZWNrc3VtLW9iamVjdC9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJjaGVja3N1bS1vYmplY3QiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA1NTMzNzUxOSIsImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6Im93bmVycyJ9LCJldGFnIjoiQ0srQXM5YVcyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2NoZWNrc3VtLW9iamVjdC8xNTM4MDUxMDU1MzM3NTE5L3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2NoZWNrc3VtLW9iamVjdC9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiY2hlY2tzdW0tb2JqZWN0IiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNTUzMzc1MTkiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0srQXM5YVcyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2NoZWNrc3VtLW9iamVjdC8xNTM4MDUxMDU1MzM3NTE5L3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2NoZWNrc3VtLW9iamVjdC9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiY2hlY2tzdW0tb2JqZWN0IiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNTUzMzc1MTkiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNLK0FzOWFXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jaGVja3N1bS1vYmplY3QvMTUzODA1MTA1NTMzNzUxOS91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vY2hlY2tzdW0tb2JqZWN0L2FjbC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiY2hlY2tzdW0tb2JqZWN0IiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNTUzMzc1MTkiLCJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwicm9sZSI6Ik9XTkVSIiwiZW1haWwiOiIzNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImV0YWciOiJDSytBczlhVzI5MENFQUU9In1dLCJvd25lciI6eyJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIn0sImNyYzMyYyI6IlZzdTBnQT09IiwiZXRhZyI6IkNLK0FzOWFXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2NvbXBvc2VkMS8xNTM4MDUxMDU3Njg4MTc4Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vY29tcG9zZWQxIiwibmFtZSI6ImNvbXBvc2VkMSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDU3Njg4MTc4IiwibWV0YWdlbmVyYXRpb24iOiIxIiwidGltZUNyZWF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjE3LjY4OFoiLCJ1cGRhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDoxNy42ODhaIiwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJ0aW1lU3RvcmFnZUNsYXNzVXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MTcuNjg4WiIsInNpemUiOiI0OCIsIm1lZGlhTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2Rvd25sb2FkL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9jb21wb3NlZDE/Z2VuZXJhdGlvbj0xNTM4MDUxMDU3Njg4MTc4JmFsdD1tZWRpYSIsImFjbCI6W3sia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2NvbXBvc2VkMS8xNTM4MDUxMDU3Njg4MTc4L3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vY29tcG9zZWQxL2FjbC9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6ImNvbXBvc2VkMSIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDU3Njg4MTc4IiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDUEs4d3RlVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvY29tcG9zZWQxLzE1MzgwNTEwNTc2ODgxNzgvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vY29tcG9zZWQxL2FjbC9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJjb21wb3NlZDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA1NzY4ODE3OCIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDUEs4d3RlVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvY29tcG9zZWQxLzE1MzgwNTEwNTc2ODgxNzgvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vY29tcG9zZWQxL2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJjb21wb3NlZDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA1NzY4ODE3OCIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ1BLOHd0ZVcyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2NvbXBvc2VkMS8xNTM4MDUxMDU3Njg4MTc4L3VzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9jb21wb3NlZDEvYWNsL3VzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJjb21wb3NlZDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA1NzY4ODE3OCIsImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJyb2xlIjoiT1dORVIiLCJlbWFpbCI6IjM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiZXRhZyI6IkNQSzh3dGVXMjkwQ0VBRT0ifV0sIm93bmVyIjp7ImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20ifSwiY3JjMzJjIjoiYm9COG13PT0iLCJjb21wb25lbnRDb3VudCI6MywiZXRhZyI6IkNQSzh3dGVXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2NvbXBvc2VkMi8xNTM4MDUxMDU4MzgxNzg1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vY29tcG9zZWQyIiwibmFtZSI6ImNvbXBvc2VkMiIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDU4MzgxNzg1IiwibWV0YWdlbmVyYXRpb24iOiIxIiwiY29udGVudFR5cGUiOiJ0ZXh0L2pzb24iLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MTguMzc5WiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjE4LjM3OVoiLCJzdG9yYWdlQ2xhc3MiOiJTVEFOREFSRCIsInRpbWVTdG9yYWdlQ2xhc3NVcGRhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDoxOC4zNzlaIiwic2l6ZSI6IjQ4IiwibWVkaWFMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vZG93bmxvYWQvc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2NvbXBvc2VkMj9nZW5lcmF0aW9uPTE1MzgwNTEwNTgzODE3ODUmYWx0PW1lZGlhIiwiYWNsIjpbeyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvY29tcG9zZWQyLzE1MzgwNTEwNTgzODE3ODUvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9jb21wb3NlZDIvYWNsL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiY29tcG9zZWQyIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNTgzODE3ODUiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNObm43TmVXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jb21wb3NlZDIvMTUzODA1MTA1ODM4MTc4NS9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9jb21wb3NlZDIvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6ImNvbXBvc2VkMiIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDU4MzgxNzg1IiwiZW50aXR5IjoicHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6ImVkaXRvcnMifSwiZXRhZyI6IkNObm43TmVXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jb21wb3NlZDIvMTUzODA1MTA1ODM4MTc4NS9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9jb21wb3NlZDIvYWNsL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6ImNvbXBvc2VkMiIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDU4MzgxNzg1IiwiZW50aXR5IjoicHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6IlJFQURFUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJ2aWV3ZXJzIn0sImV0YWciOiJDTm5uN05lVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvY29tcG9zZWQyLzE1MzgwNTEwNTgzODE3ODUvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2NvbXBvc2VkMi9hY2wvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6ImNvbXBvc2VkMiIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDU4MzgxNzg1IiwiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInJvbGUiOiJPV05FUiIsImVtYWlsIjoiMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJldGFnIjoiQ05ubjdOZVcyOTBDRUFFPSJ9XSwib3duZXIiOnsiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSJ9LCJjcmMzMmMiOiJib0I4bXc9PSIsImNvbXBvbmVudENvdW50IjozLCJldGFnIjoiQ05ubjdOZVcyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0IiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvY29udGVudC8xNTM4MDUxMDc1MzMwMDQ5Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vY29udGVudCIsIm5hbWUiOiJjb250ZW50IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNzUzMzAwNDkiLCJtZXRhZ2VuZXJhdGlvbiI6IjEiLCJjb250ZW50VHlwZSI6ImltYWdlL2pwZWciLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MzUuMzI5WiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjM1LjMyOVoiLCJzdG9yYWdlQ2xhc3MiOiJTVEFOREFSRCIsInRpbWVTdG9yYWdlQ2xhc3NVcGRhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDozNS4zMjlaIiwic2l6ZSI6IjU0IiwibWQ1SGFzaCI6Ik44cDgvczlGd2RBQW5sdnIvbEVBalE9PSIsIm1lZGlhTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2Rvd25sb2FkL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9jb250ZW50P2dlbmVyYXRpb249MTUzODA1MTA3NTMzMDA0OSZhbHQ9bWVkaWEiLCJjYWNoZUNvbnRyb2wiOiJwdWJsaWMsIG1heC1hZ2U9NjAiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jb250ZW50LzE1MzgwNTEwNzUzMzAwNDkvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9jb250ZW50L2FjbC9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6ImNvbnRlbnQiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA3NTMzMDA0OSIsImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6Im93bmVycyJ9LCJldGFnIjoiQ0lHZzk5K1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2NvbnRlbnQvMTUzODA1MTA3NTMzMDA0OS9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9jb250ZW50L2FjbC9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJjb250ZW50IiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNzUzMzAwNDkiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0lHZzk5K1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2NvbnRlbnQvMTUzODA1MTA3NTMzMDA0OS9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9jb250ZW50L2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJjb250ZW50IiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNzUzMzAwNDkiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNJR2c5OStXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jb250ZW50LzE1MzgwNTEwNzUzMzAwNDkvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2NvbnRlbnQvYWNsL3VzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJjb250ZW50IiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNzUzMzAwNDkiLCJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwicm9sZSI6Ik9XTkVSIiwiZW1haWwiOiIzNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImV0YWciOiJDSUdnOTkrVzI5MENFQUU9In1dLCJvd25lciI6eyJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIn0sImNyYzMyYyI6IkdvVWJzUT09IiwiZXRhZyI6IkNJR2c5OStXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2N1c3RvbWVyLWVuY3J5cHRpb24vMTUzODA1MTA3NTk1NjQ3OSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2N1c3RvbWVyLWVuY3J5cHRpb24iLCJuYW1lIjoiY3VzdG9tZXItZW5jcnlwdGlvbiIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDc1OTU2NDc5IiwibWV0YWdlbmVyYXRpb24iOiIzIiwiY29udGVudFR5cGUiOiJ0ZXh0L3BsYWluOyBjaGFyc2V0PXV0Zi04IiwidGltZUNyZWF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjM1Ljk1NloiLCJ1cGRhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDozNi43NDdaIiwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJ0aW1lU3RvcmFnZUNsYXNzVXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MzUuOTU2WiIsInNpemUiOiIxMSIsIm1lZGlhTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2Rvd25sb2FkL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9jdXN0b21lci1lbmNyeXB0aW9uP2dlbmVyYXRpb249MTUzODA1MTA3NTk1NjQ3OSZhbHQ9bWVkaWEiLCJjb250ZW50TGFuZ3VhZ2UiOiJlbiIsImFjbCI6W3sia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2N1c3RvbWVyLWVuY3J5cHRpb24vMTUzODA1MTA3NTk1NjQ3OS9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2N1c3RvbWVyLWVuY3J5cHRpb24vYWNsL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiY3VzdG9tZXItZW5jcnlwdGlvbiIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDc1OTU2NDc5IiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDUCs5bmVDVzI5MENFQU09In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvY3VzdG9tZXItZW5jcnlwdGlvbi8xNTM4MDUxMDc1OTU2NDc5L3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2N1c3RvbWVyLWVuY3J5cHRpb24vYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6ImN1c3RvbWVyLWVuY3J5cHRpb24iLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA3NTk1NjQ3OSIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDUCs5bmVDVzI5MENFQU09In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvY3VzdG9tZXItZW5jcnlwdGlvbi8xNTM4MDUxMDc1OTU2NDc5L3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2N1c3RvbWVyLWVuY3J5cHRpb24vYWNsL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6ImN1c3RvbWVyLWVuY3J5cHRpb24iLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA3NTk1NjQ3OSIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ1ArOW5lQ1cyOTBDRUFNPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2N1c3RvbWVyLWVuY3J5cHRpb24vMTUzODA1MTA3NTk1NjQ3OS91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vY3VzdG9tZXItZW5jcnlwdGlvbi9hY2wvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6ImN1c3RvbWVyLWVuY3J5cHRpb24iLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA3NTk1NjQ3OSIsImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJyb2xlIjoiT1dORVIiLCJlbWFpbCI6IjM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiZXRhZyI6IkNQKzluZUNXMjkwQ0VBTT0ifV0sIm93bmVyIjp7ImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20ifSwiZXRhZyI6IkNQKzluZUNXMjkwQ0VBTT0iLCJjdXN0b21lckVuY3J5cHRpb24iOnsiZW5jcnlwdGlvbkFsZ29yaXRobSI6IkFFUzI1NiIsImtleVNoYTI1NiI6IkgrTG1uWGhSb2VJNlRNVzVic1Y2SHlVazZweUdjMklNYnFZYkFYQmNwczA9In19LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0IiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvY3VzdG9tZXItZW5jcnlwdGlvbi0yLzE1MzgwNTEwODEyMTU2MDciLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9jdXN0b21lci1lbmNyeXB0aW9uLTIiLCJuYW1lIjoiY3VzdG9tZXItZW5jcnlwdGlvbi0yIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwODEyMTU2MDciLCJtZXRhZ2VuZXJhdGlvbiI6IjEiLCJjb250ZW50VHlwZSI6InRleHQvcGxhaW47IGNoYXJzZXQ9dXRmLTgiLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6NDEuMjE0WiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjQxLjIxNFoiLCJzdG9yYWdlQ2xhc3MiOiJTVEFOREFSRCIsInRpbWVTdG9yYWdlQ2xhc3NVcGRhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDo0MS4yMTRaIiwic2l6ZSI6IjExIiwibWQ1SGFzaCI6Inh3V05GYTBWZFhQbWxBd3JsY0FKY2c9PSIsIm1lZGlhTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2Rvd25sb2FkL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9jdXN0b21lci1lbmNyeXB0aW9uLTI/Z2VuZXJhdGlvbj0xNTM4MDUxMDgxMjE1NjA3JmFsdD1tZWRpYSIsImNvbnRlbnRMYW5ndWFnZSI6ImVuIiwiYWNsIjpbeyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvY3VzdG9tZXItZW5jcnlwdGlvbi0yLzE1MzgwNTEwODEyMTU2MDcvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9jdXN0b21lci1lbmNyeXB0aW9uLTIvYWNsL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiY3VzdG9tZXItZW5jcnlwdGlvbi0yIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwODEyMTU2MDciLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNQZTgzdUtXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jdXN0b21lci1lbmNyeXB0aW9uLTIvMTUzODA1MTA4MTIxNTYwNy9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9jdXN0b21lci1lbmNyeXB0aW9uLTIvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6ImN1c3RvbWVyLWVuY3J5cHRpb24tMiIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDgxMjE1NjA3IiwiZW50aXR5IjoicHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6ImVkaXRvcnMifSwiZXRhZyI6IkNQZTgzdUtXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jdXN0b21lci1lbmNyeXB0aW9uLTIvMTUzODA1MTA4MTIxNTYwNy9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9jdXN0b21lci1lbmNyeXB0aW9uLTIvYWNsL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6ImN1c3RvbWVyLWVuY3J5cHRpb24tMiIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDgxMjE1NjA3IiwiZW50aXR5IjoicHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6IlJFQURFUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJ2aWV3ZXJzIn0sImV0YWciOiJDUGU4M3VLVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvY3VzdG9tZXItZW5jcnlwdGlvbi0yLzE1MzgwNTEwODEyMTU2MDcvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2N1c3RvbWVyLWVuY3J5cHRpb24tMi9hY2wvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6ImN1c3RvbWVyLWVuY3J5cHRpb24tMiIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDgxMjE1NjA3IiwiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInJvbGUiOiJPV05FUiIsImVtYWlsIjoiMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJldGFnIjoiQ1BlODN1S1cyOTBDRUFFPSJ9XSwib3duZXIiOnsiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSJ9LCJjcmMzMmMiOiJyME5Hcmc9PSIsImV0YWciOiJDUGU4M3VLVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jdXN0b21lci1lbmNyeXB0aW9uLTMvMTUzODA1MTA4MDQzNDU0NyIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2N1c3RvbWVyLWVuY3J5cHRpb24tMyIsIm5hbWUiOiJjdXN0b21lci1lbmNyeXB0aW9uLTMiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA4MDQzNDU0NyIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDo0MC40MzRaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6NDAuNDM0WiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjQwLjQzNFoiLCJzaXplIjoiMjIiLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vY3VzdG9tZXItZW5jcnlwdGlvbi0zP2dlbmVyYXRpb249MTUzODA1MTA4MDQzNDU0NyZhbHQ9bWVkaWEiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jdXN0b21lci1lbmNyeXB0aW9uLTMvMTUzODA1MTA4MDQzNDU0Ny9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2N1c3RvbWVyLWVuY3J5cHRpb24tMy9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJjdXN0b21lci1lbmNyeXB0aW9uLTMiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA4MDQzNDU0NyIsImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6Im93bmVycyJ9LCJldGFnIjoiQ1BQbXJ1S1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2N1c3RvbWVyLWVuY3J5cHRpb24tMy8xNTM4MDUxMDgwNDM0NTQ3L3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2N1c3RvbWVyLWVuY3J5cHRpb24tMy9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiY3VzdG9tZXItZW5jcnlwdGlvbi0zIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwODA0MzQ1NDciLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ1BQbXJ1S1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2N1c3RvbWVyLWVuY3J5cHRpb24tMy8xNTM4MDUxMDgwNDM0NTQ3L3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2N1c3RvbWVyLWVuY3J5cHRpb24tMy9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiY3VzdG9tZXItZW5jcnlwdGlvbi0zIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwODA0MzQ1NDciLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNQUG1ydUtXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9jdXN0b21lci1lbmNyeXB0aW9uLTMvMTUzODA1MTA4MDQzNDU0Ny91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vY3VzdG9tZXItZW5jcnlwdGlvbi0zL2FjbC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiY3VzdG9tZXItZW5jcnlwdGlvbi0zIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwODA0MzQ1NDciLCJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwicm9sZSI6Ik9XTkVSIiwiZW1haWwiOiIzNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImV0YWciOiJDUFBtcnVLVzI5MENFQUU9In1dLCJvd25lciI6eyJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIn0sImNvbXBvbmVudENvdW50IjoyLCJldGFnIjoiQ1BQbXJ1S1cyOTBDRUFFPSIsImN1c3RvbWVyRW5jcnlwdGlvbiI6eyJlbmNyeXB0aW9uQWxnb3JpdGhtIjoiQUVTMjU2Iiwia2V5U2hhMjU2IjoiSCtMbW5YaFJvZUk2VE1XNWJzVjZIeVVrNnB5R2MySU1icVliQVhCY3BzMD0ifX0seyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9nemlwLXRlc3QvMTUzODA1MTA1OTEzODUxMiIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2d6aXAtdGVzdCIsIm5hbWUiOiJnemlwLXRlc3QiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA1OTEzODUxMiIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoiYXBwbGljYXRpb24veC1nemlwIiwidGltZUNyZWF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjE5LjEzOFoiLCJ1cGRhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDoxOS4xMzhaIiwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJ0aW1lU3RvcmFnZUNsYXNzVXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MTkuMTM4WiIsInNpemUiOiIyNyIsIm1kNUhhc2giOiJPdEN3K2FSUklScUtHRkFFT2F4K3F3PT0iLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vZ3ppcC10ZXN0P2dlbmVyYXRpb249MTUzODA1MTA1OTEzODUxMiZhbHQ9bWVkaWEiLCJjb250ZW50RW5jb2RpbmciOiJnemlwIiwiYWNsIjpbeyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvZ3ppcC10ZXN0LzE1MzgwNTEwNTkxMzg1MTIvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9nemlwLXRlc3QvYWNsL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiZ3ppcC10ZXN0IiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNTkxMzg1MTIiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNORC9tdGlXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9nemlwLXRlc3QvMTUzODA1MTA1OTEzODUxMi9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9nemlwLXRlc3QvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Imd6aXAtdGVzdCIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDU5MTM4NTEyIiwiZW50aXR5IjoicHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6ImVkaXRvcnMifSwiZXRhZyI6IkNORC9tdGlXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9nemlwLXRlc3QvMTUzODA1MTA1OTEzODUxMi9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9nemlwLXRlc3QvYWNsL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Imd6aXAtdGVzdCIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDU5MTM4NTEyIiwiZW50aXR5IjoicHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6IlJFQURFUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJ2aWV3ZXJzIn0sImV0YWciOiJDTkQvbXRpVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvZ3ppcC10ZXN0LzE1MzgwNTEwNTkxMzg1MTIvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2d6aXAtdGVzdC9hY2wvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Imd6aXAtdGVzdCIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDU5MTM4NTEyIiwiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInJvbGUiOiJPV05FUiIsImVtYWlsIjoiMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJldGFnIjoiQ05EL210aVcyOTBDRUFFPSJ9XSwib3duZXIiOnsiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSJ9LCJjcmMzMmMiOiI5RGh3QkE9PSIsImV0YWciOiJDTkQvbXRpVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9oYXNoZXNPblVwbG9hZC0xLzE1MzgwNTEwODYxMjc0ODciLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9oYXNoZXNPblVwbG9hZC0xIiwibmFtZSI6Imhhc2hlc09uVXBsb2FkLTEiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA4NjEyNzQ4NyIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOCIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDo0Ni4xMjdaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6NDYuMTI3WiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjQ2LjEyN1oiLCJzaXplIjoiMjciLCJtZDVIYXNoIjoib2ZaakdsY1hQSmlHT0FmS0ZiSmwxUT09IiwibWVkaWFMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vZG93bmxvYWQvc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2hhc2hlc09uVXBsb2FkLTE/Z2VuZXJhdGlvbj0xNTM4MDUxMDg2MTI3NDg3JmFsdD1tZWRpYSIsImFjbCI6W3sia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2hhc2hlc09uVXBsb2FkLTEvMTUzODA1MTA4NjEyNzQ4Ny9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2hhc2hlc09uVXBsb2FkLTEvYWNsL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiaGFzaGVzT25VcGxvYWQtMSIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDg2MTI3NDg3IiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDUCtpaXVXVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvaGFzaGVzT25VcGxvYWQtMS8xNTM4MDUxMDg2MTI3NDg3L3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2hhc2hlc09uVXBsb2FkLTEvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Imhhc2hlc09uVXBsb2FkLTEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA4NjEyNzQ4NyIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDUCtpaXVXVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvaGFzaGVzT25VcGxvYWQtMS8xNTM4MDUxMDg2MTI3NDg3L3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL2hhc2hlc09uVXBsb2FkLTEvYWNsL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Imhhc2hlc09uVXBsb2FkLTEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA4NjEyNzQ4NyIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ1AraWl1V1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL2hhc2hlc09uVXBsb2FkLTEvMTUzODA1MTA4NjEyNzQ4Ny91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vaGFzaGVzT25VcGxvYWQtMS9hY2wvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Imhhc2hlc09uVXBsb2FkLTEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA4NjEyNzQ4NyIsImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJyb2xlIjoiT1dORVIiLCJlbWFpbCI6IjM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiZXRhZyI6IkNQK2lpdVdXMjkwQ0VBRT0ifV0sIm93bmVyIjp7ImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20ifSwiY3JjMzJjIjoiY0grQSt3PT0iLCJldGFnIjoiQ1AraWl1V1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0IiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqL3dpdGgvc2xhc2hlcy8xNTM4MDUxMDQ1NjI3MTk4Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vb2JqJTJGd2l0aCUyRnNsYXNoZXMiLCJuYW1lIjoib2JqL3dpdGgvc2xhc2hlcyIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDQ1NjI3MTk4IiwibWV0YWdlbmVyYXRpb24iOiIxIiwiY29udGVudFR5cGUiOiJ0ZXh0L3BsYWluIiwidGltZUNyZWF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjA1LjYyN1oiLCJ1cGRhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDowNS42MjdaIiwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJ0aW1lU3RvcmFnZUNsYXNzVXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MDUuNjI3WiIsInNpemUiOiIxNiIsIm1kNUhhc2giOiIrN21WbjZMVHdEblYzdGcvcENyaW93PT0iLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vb2JqJTJGd2l0aCUyRnNsYXNoZXM/Z2VuZXJhdGlvbj0xNTM4MDUxMDQ1NjI3MTk4JmFsdD1tZWRpYSIsImNhY2hlQ29udHJvbCI6InB1YmxpYywgbWF4LWFnZT02MCIsImFjbCI6W3sia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL29iai93aXRoL3NsYXNoZXMvMTUzODA1MTA0NTYyNzE5OC9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iaiUyRndpdGglMkZzbGFzaGVzL2FjbC9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Im9iai93aXRoL3NsYXNoZXMiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NTYyNzE5OCIsImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6Im93bmVycyJ9LCJldGFnIjoiQ0w2cTR0R1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL29iai93aXRoL3NsYXNoZXMvMTUzODA1MTA0NTYyNzE5OC9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9vYmolMkZ3aXRoJTJGc2xhc2hlcy9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0Ijoib2JqL3dpdGgvc2xhc2hlcyIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDQ1NjI3MTk4IiwiZW50aXR5IjoicHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6ImVkaXRvcnMifSwiZXRhZyI6IkNMNnE0dEdXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmovd2l0aC9zbGFzaGVzLzE1MzgwNTEwNDU2MjcxOTgvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vb2JqJTJGd2l0aCUyRnNsYXNoZXMvYWNsL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Im9iai93aXRoL3NsYXNoZXMiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NTYyNzE5OCIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0w2cTR0R1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL29iai93aXRoL3NsYXNoZXMvMTUzODA1MTA0NTYyNzE5OC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vb2JqJTJGd2l0aCUyRnNsYXNoZXMvYWNsL3VzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJvYmovd2l0aC9zbGFzaGVzIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNDU2MjcxOTgiLCJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwicm9sZSI6Ik9XTkVSIiwiZW1haWwiOiIzNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImV0YWciOiJDTDZxNHRHVzI5MENFQUU9In1dLCJvd25lciI6eyJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIn0sImNyYzMyYyI6ImtTc1dRZz09IiwiZXRhZyI6IkNMNnE0dEdXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL29iajEvMTUzODA1MTA0NDUzMjM2NiIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iajEiLCJuYW1lIjoib2JqMSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDQ0NTMyMzY2IiwibWV0YWdlbmVyYXRpb24iOiI0IiwidGltZUNyZWF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjA0LjUzMloiLCJ1cGRhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDoxNi4yMTBaIiwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJ0aW1lU3RvcmFnZUNsYXNzVXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MDQuNTMyWiIsInNpemUiOiIxNiIsIm1kNUhhc2giOiI3d1VGSDhtRER3SEZZcW83b2x4ZFBnPT0iLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vb2JqMT9nZW5lcmF0aW9uPTE1MzgwNTEwNDQ1MzIzNjYmYWx0PW1lZGlhIiwiY2FjaGVDb250cm9sIjoicHVibGljLCBtYXgtYWdlPTYwIiwiYWNsIjpbeyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqMS8xNTM4MDUxMDQ0NTMyMzY2L2RvbWFpbi1nb29nbGUuY29tIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vb2JqMS9hY2wvZG9tYWluLWdvb2dsZS5jb20iLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJvYmoxIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNDQ1MzIzNjYiLCJlbnRpdHkiOiJkb21haW4tZ29vZ2xlLmNvbSIsInJvbGUiOiJSRUFERVIiLCJkb21haW4iOiJnb29nbGUuY29tIiwiZXRhZyI6IkNJN0JuOUdXMjkwQ0VBUT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmoxLzE1MzgwNTEwNDQ1MzIzNjYvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iajEvYWNsL3VzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJvYmoxIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNDQ1MzIzNjYiLCJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwicm9sZSI6Ik9XTkVSIiwiZW1haWwiOiIzNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImV0YWciOiJDSTdCbjlHVzI5MENFQVE9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqMS8xNTM4MDUxMDQ0NTMyMzY2L2FsbFVzZXJzIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vb2JqMS9hY2wvYWxsVXNlcnMiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJvYmoxIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNDQ1MzIzNjYiLCJlbnRpdHkiOiJhbGxVc2VycyIsInJvbGUiOiJSRUFERVIiLCJldGFnIjoiQ0k3Qm45R1cyOTBDRUFRPSJ9XSwib3duZXIiOnsiZW50aXR5IjoidXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSJ9LCJjcmMzMmMiOiIrN1IxMWc9PSIsImV0YWciOiJDSTdCbjlHVzI5MENFQVE9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3QiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vYmoyLzE1MzgwNTEwNDUxMzI2MzEiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9vYmoyIiwibmFtZSI6Im9iajIiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NTEzMjYzMSIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImNvbnRlbnRUeXBlIjoidGV4dC9wbGFpbiIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDowNS4xMzJaIiwidXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MDUuMTMyWiIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwidGltZVN0b3JhZ2VDbGFzc1VwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjA1LjEzMloiLCJzaXplIjoiMTYiLCJtZDVIYXNoIjoiaDY0bVlxSjJPNTRqcnhHT0pOeUd4UT09IiwibWVkaWFMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vZG93bmxvYWQvc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iajI/Z2VuZXJhdGlvbj0xNTM4MDUxMDQ1MTMyNjMxJmFsdD1tZWRpYSIsImNhY2hlQ29udHJvbCI6InB1YmxpYywgbWF4LWFnZT02MCIsImFjbCI6W3sia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL29iajIvMTUzODA1MTA0NTEzMjYzMS9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iajIvYWNsL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0Ijoib2JqMiIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDQ1MTMyNjMxIiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDTmVTeE5HVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqMi8xNTM4MDUxMDQ1MTMyNjMxL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iajIvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Im9iajIiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NTEzMjYzMSIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDTmVTeE5HVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvb2JqMi8xNTM4MDUxMDQ1MTMyNjMxL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL29iajIvYWNsL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Im9iajIiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NTEzMjYzMSIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ05lU3hOR1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL29iajIvMTUzODA1MTA0NTEzMjYzMS91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vb2JqMi9hY2wvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Im9iajIiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA0NTEzMjYzMSIsImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJyb2xlIjoiT1dORVIiLCJlbWFpbCI6IjM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiZXRhZyI6IkNOZVN4TkdXMjkwQ0VBRT0ifV0sIm93bmVyIjp7ImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20ifSwiY3JjMzJjIjoiM0RLRHFnPT0iLCJldGFnIjoiQ05lU3hOR1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0IiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvcG9zYy8xNTM4MDUxMDgzMjI3NTQ3Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vcG9zYyIsIm5hbWUiOiJwb3NjIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwODMyMjc1NDciLCJtZXRhZ2VuZXJhdGlvbiI6IjEiLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6NDMuMjI1WiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjQzLjIyNVoiLCJzdG9yYWdlQ2xhc3MiOiJNVUxUSV9SRUdJT05BTCIsInRpbWVTdG9yYWdlQ2xhc3NVcGRhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDo0My4yMjVaIiwic2l6ZSI6IjMiLCJtZDVIYXNoIjoickwwWTIwekMrRnp0NzJWUHpNU2syQT09IiwibWVkaWFMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vZG93bmxvYWQvc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL3Bvc2M/Z2VuZXJhdGlvbj0xNTM4MDUxMDgzMjI3NTQ3JmFsdD1tZWRpYSIsImFjbCI6W3sia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL3Bvc2MvMTUzODA1MTA4MzIyNzU0Ny9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL3Bvc2MvYWNsL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoicG9zYyIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDgzMjI3NTQ3IiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDSnVqMmVPVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvcG9zYy8xNTM4MDUxMDgzMjI3NTQ3L3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL3Bvc2MvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6InBvc2MiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA4MzIyNzU0NyIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDSnVqMmVPVzI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvcG9zYy8xNTM4MDUxMDgzMjI3NTQ3L3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL3Bvc2MvYWNsL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6InBvc2MiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA4MzIyNzU0NyIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0p1ajJlT1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL3Bvc2MvMTUzODA1MTA4MzIyNzU0Ny91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vcG9zYy9hY2wvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6InBvc2MiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA4MzIyNzU0NyIsImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJyb2xlIjoiT1dORVIiLCJlbWFpbCI6IjM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiZXRhZyI6IkNKdWoyZU9XMjkwQ0VBRT0ifV0sIm93bmVyIjp7ImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20ifSwiY3JjMzJjIjoiejhTdUhRPT0iLCJldGFnIjoiQ0p1ajJlT1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0IiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvcG9zYzIvMTUzODA1MTA4MzcyNzU2MyIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL3Bvc2MyIiwibmFtZSI6InBvc2MyIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwODM3Mjc1NjMiLCJtZXRhZ2VuZXJhdGlvbiI6IjEiLCJjb250ZW50VHlwZSI6InRleHQvcGxhaW47IGNoYXJzZXQ9dXRmLTgiLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6NDMuNzI3WiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjQzLjcyN1oiLCJzdG9yYWdlQ2xhc3MiOiJNVUxUSV9SRUdJT05BTCIsInRpbWVTdG9yYWdlQ2xhc3NVcGRhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDo0My43MjdaIiwic2l6ZSI6IjMiLCJtZDVIYXNoIjoiOVdHcTl1OEw4VTFDQ0x0R3BNeXpyUT09IiwibWVkaWFMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vZG93bmxvYWQvc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL3Bvc2MyP2dlbmVyYXRpb249MTUzODA1MTA4MzcyNzU2MyZhbHQ9bWVkaWEiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9wb3NjMi8xNTM4MDUxMDgzNzI3NTYzL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vcG9zYzIvYWNsL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoicG9zYzIiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA4MzcyNzU2MyIsImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6Im93bmVycyJ9LCJldGFnIjoiQ012bDkrT1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL3Bvc2MyLzE1MzgwNTEwODM3Mjc1NjMvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vcG9zYzIvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6InBvc2MyIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwODM3Mjc1NjMiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ012bDkrT1cyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL3Bvc2MyLzE1MzgwNTEwODM3Mjc1NjMvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vcG9zYzIvYWNsL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6InBvc2MyIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwODM3Mjc1NjMiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNNdmw5K09XMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9wb3NjMi8xNTM4MDUxMDgzNzI3NTYzL3VzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9wb3NjMi9hY2wvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6InBvc2MyIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwODM3Mjc1NjMiLCJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwicm9sZSI6Ik9XTkVSIiwiZW1haWwiOiIzNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImV0YWciOiJDTXZsOStPVzI5MENFQUU9In1dLCJvd25lciI6eyJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIn0sImNyYzMyYyI6IjE3cUFCUT09IiwiZXRhZyI6IkNNdmw5K09XMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL3NpZ25lZFVSTC8xNTM4MDUxMDYwMTI4MzI0Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vc2lnbmVkVVJMIiwibmFtZSI6InNpZ25lZFVSTCIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsImdlbmVyYXRpb24iOiIxNTM4MDUxMDYwMTI4MzI0IiwibWV0YWdlbmVyYXRpb24iOiIxIiwiY29udGVudFR5cGUiOiJ0ZXh0L3BsYWluIiwidGltZUNyZWF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjIwLjEyOFoiLCJ1cGRhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDoyMC4xMjhaIiwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJ0aW1lU3RvcmFnZUNsYXNzVXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MjAuMTI4WiIsInNpemUiOiIyOSIsIm1kNUhhc2giOiJKeXh2Z3dtOW4yTXNyR1RNUGJNZVlBPT0iLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vc2lnbmVkVVJMP2dlbmVyYXRpb249MTUzODA1MTA2MDEyODMyNCZhbHQ9bWVkaWEiLCJjYWNoZUNvbnRyb2wiOiJwdWJsaWMsIG1heC1hZ2U9NjAiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9zaWduZWRVUkwvMTUzODA1MTA2MDEyODMyNC9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL3NpZ25lZFVSTC9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJzaWduZWRVUkwiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA2MDEyODMyNCIsImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6Im93bmVycyJ9LCJldGFnIjoiQ01TMDE5aVcyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL3NpZ25lZFVSTC8xNTM4MDUxMDYwMTI4MzI0L3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL3NpZ25lZFVSTC9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0Ijoic2lnbmVkVVJMIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNjAxMjgzMjQiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ01TMDE5aVcyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL3NpZ25lZFVSTC8xNTM4MDUxMDYwMTI4MzI0L3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL3NpZ25lZFVSTC9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0Ijoic2lnbmVkVVJMIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNjAxMjgzMjQiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNNUzAxOWlXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9zaWduZWRVUkwvMTUzODA1MTA2MDEyODMyNC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vc2lnbmVkVVJML2FjbC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0Ijoic2lnbmVkVVJMIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNjAxMjgzMjQiLCJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwicm9sZSI6Ik9XTkVSIiwiZW1haWwiOiIzNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImV0YWciOiJDTVMwMTlpVzI5MENFQUU9In1dLCJvd25lciI6eyJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIn0sImNyYzMyYyI6IlpUcUFMdz09IiwiZXRhZyI6IkNNUzAxOWlXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL3NvbWUtb2JqZWN0LzE1MzgwNTExOTkwNTAzMDkiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9zb21lLW9iamVjdCIsIm5hbWUiOiJzb21lLW9iamVjdCIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsImdlbmVyYXRpb24iOiIxNTM4MDUxMTk5MDUwMzA5IiwibWV0YWdlbmVyYXRpb24iOiIxIiwiY29udGVudFR5cGUiOiJ0ZXh0L3BsYWluIiwidGltZUNyZWF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI2OjM5LjA1MFoiLCJ1cGRhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNjozOS4wNTBaIiwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJ0aW1lU3RvcmFnZUNsYXNzVXBkYXRlZCI6IjIwMTgtMDktMjdUMTI6MjY6MzkuMDUwWiIsInNpemUiOiIxNiIsIm1kNUhhc2giOiJxRStzYi9rcGE1dFdoZWJ1ZWZ2QU53PT0iLCJtZWRpYUxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9kb3dubG9hZC9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vc29tZS1vYmplY3Q/Z2VuZXJhdGlvbj0xNTM4MDUxMTk5MDUwMzA5JmFsdD1tZWRpYSIsImNhY2hlQ29udHJvbCI6InB1YmxpYywgbWF4LWFnZT02MCIsImFjbCI6W3sia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL3NvbWUtb2JqZWN0LzE1MzgwNTExOTkwNTAzMDkvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9zb21lLW9iamVjdC9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEiLCJvYmplY3QiOiJzb21lLW9iamVjdCIsImdlbmVyYXRpb24iOiIxNTM4MDUxMTk5MDUwMzA5IiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDTVhFOXBxWDI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvc29tZS1vYmplY3QvMTUzODA1MTE5OTA1MDMwOS9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9zb21lLW9iamVjdC9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0Ijoic29tZS1vYmplY3QiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE5OTA1MDMwOSIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDTVhFOXBxWDI5MENFQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvc29tZS1vYmplY3QvMTUzODA1MTE5OTA1MDMwOS9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby9zb21lLW9iamVjdC9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0Ijoic29tZS1vYmplY3QiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE5OTA1MDMwOSIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ01YRTlwcVgyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL3NvbWUtb2JqZWN0LzE1MzgwNTExOTkwNTAzMDkvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL3NvbWUtb2JqZWN0L2FjbC91c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0Ijoic29tZS1vYmplY3QiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTE5OTA1MDMwOSIsImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJyb2xlIjoiT1dORVIiLCJlbWFpbCI6IjM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwiZXRhZyI6IkNNWEU5cHFYMjkwQ0VBRT0ifV0sIm93bmVyIjp7ImVudGl0eSI6InVzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20ifSwiY3JjMzJjIjoiU2p6dXFRPT0iLCJldGFnIjoiQ01YRTlwcVgyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0IiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvemVyby1vYmplY3QvMTUzODA1MTA1NTkzNjc1OCIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL3plcm8tb2JqZWN0IiwibmFtZSI6Inplcm8tb2JqZWN0IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNTU5MzY3NTgiLCJtZXRhZ2VuZXJhdGlvbiI6IjEiLCJjb250ZW50VHlwZSI6InRleHQvcGxhaW47IGNoYXJzZXQ9dXRmLTgiLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjQ6MTUuOTM2WiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI0OjE1LjkzNloiLCJzdG9yYWdlQ2xhc3MiOiJTVEFOREFSRCIsInRpbWVTdG9yYWdlQ2xhc3NVcGRhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNDoxNS45MzZaIiwic2l6ZSI6IjAiLCJtZDVIYXNoIjoiMUIyTTJZOEFzZ1RwZ0FtWTdQaENmZz09IiwibWVkaWFMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vZG93bmxvYWQvc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS9vL3plcm8tb2JqZWN0P2dlbmVyYXRpb249MTUzODA1MTA1NTkzNjc1OCZhbHQ9bWVkaWEiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS96ZXJvLW9iamVjdC8xNTM4MDUxMDU1OTM2NzU4L3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vemVyby1vYmplY3QvYWNsL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxIiwib2JqZWN0IjoiemVyby1vYmplY3QiLCJnZW5lcmF0aW9uIjoiMTUzODA1MTA1NTkzNjc1OCIsImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6Im93bmVycyJ9LCJldGFnIjoiQ1BiSjE5YVcyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL3plcm8tb2JqZWN0LzE1MzgwNTEwNTU5MzY3NTgvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vemVyby1vYmplY3QvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Inplcm8tb2JqZWN0IiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNTU5MzY3NTgiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ1BiSjE5YVcyOTBDRUFFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL3plcm8tb2JqZWN0LzE1MzgwNTEwNTU5MzY3NTgvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDAxL28vemVyby1vYmplY3QvYWNsL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Inplcm8tb2JqZWN0IiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNTU5MzY3NTgiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNQYkoxOWFXMjkwQ0VBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMS96ZXJvLW9iamVjdC8xNTM4MDUxMDU1OTM2NzU4L3VzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMDEvby96ZXJvLW9iamVjdC9hY2wvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAwMSIsIm9iamVjdCI6Inplcm8tb2JqZWN0IiwiZ2VuZXJhdGlvbiI6IjE1MzgwNTEwNTU5MzY3NTgiLCJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwicm9sZSI6Ik9XTkVSIiwiZW1haWwiOiIzNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImV0YWciOiJDUGJKMTlhVzI5MENFQUU9In1dLCJvd25lciI6eyJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIn0sImNyYzMyYyI6IkFBQUFBQT09IiwiZXRhZyI6IkNQYkoxOWFXMjkwQ0VBRT0ifV19"
+ }
+ },
+ {
+ "ID": "08c4d10dd8332635",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/acl1?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "ef2d1528b634a8d513b51fceb3755dea/11950136267319892394;o=1"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/acl1?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 204,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "0"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:44 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051504000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vlfr201:4123,/bns/yk/borg/yk/bns/blobstore2/bitpusher/609.scotty,acatlm7:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=hMysW_jTEYe3qwWuxrnABQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "acatlm7:443,/bns/yk/borg/yk/bns/blobstore2/bitpusher/609.scotty,acatlm7:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yk/borg/yk/bns/blobstore2/bitpusher/609:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWU94SDhBWjdSeWVHSm16OFFSZV80RWc4RjdJOUFYemxhX1lqdU1TYkM3YkFFZ2hZY3JuVmR3ckppdUNMWlQyUXNhUWFlV01xeW1EbmRlY3EySHQ5b0ZjQmtGZDA5bk9yZTl4T3Q1Q081RXpHVkNNMGxQQjdneUR4Nm9iMWJFUlZqVTJ0QTJMX0tzMnhZZkRTaEU2cFhlTlpEMzR3Z3lJbUZXQjBUTVU0eDNvLTVFVG5Wa2VpSW9rR00wBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UpnXVUzckGzeWmCJAkfLe_4VfTkxJKwgFhdiaJ84f8BaD2BDM47uUHfASQw4_Gwd8tn3PSepx1i50ZVi-d9RDB_WFs8CQ"
+ ]
+ },
+ "Body": ""
+ }
+ },
+ {
+ "ID": "012e6a47fa7c11ad",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/acl2?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "aeab4ffc00ee146e9159e2cbc6697ce1/12709173232462965753;o=1"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/acl2?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 204,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "0"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:44 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051504000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vng123:4144,/bns/yk/borg/yk/bns/blobstore2/bitpusher/207.scotty,acatlm7:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=hMysW67MHsKSqQXUr52wAg"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "acatlm7:443,/bns/yk/borg/yk/bns/blobstore2/bitpusher/207.scotty,acatlm7:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yk/borg/yk/bns/blobstore2/bitpusher/207:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWU94SDhBWjdSeWVHSm16OFFSZV80RWc4RjdJOUFYemxhX1lqdU1TYkM3YkFFZ2hZY3JuVmR3ckppdUNMWlQyUXNhUWFlV01xeW1EbmRlY3EySHQ5b0ZjQmtGZDA5bk9yZTl4T3Q1Q081RXpHVkNNMGxQQjdneUR4Nm9iMWJFUlZqVTJ0QTJMX0tzMnhZZkRTaEU2cFhlTlpEMzR3Z3lJbUZXQjBUTVU0eDNvLTVFVG5Wa2VpSW9rR00wBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UqOT6HMXjKjXaR-65FBDE3UzG9tfq6NN2JjBBJuMvPQraW28CciOFm0f43SI6e59nQIaHqVrWusyu7mAQiVQQ9WMlc8sw"
+ ]
+ },
+ "Body": ""
+ }
+ },
+ {
+ "ID": "9d37776ab422369f",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/bucketInCopyAttrs?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "b2f4772b497824d6fa08ec90d4b4ab2e/13540548167092207176;o=1"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/bucketInCopyAttrs?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 204,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "0"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:44 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051504000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vlkj7:4437,/bns/yk/borg/yk/bns/blobstore2/bitpusher/265.scotty,acatlm7:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=hMysW5nFL46LqgWQiJGICA"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "acatlm7:443,/bns/yk/borg/yk/bns/blobstore2/bitpusher/265.scotty,acatlm7:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yk/borg/yk/bns/blobstore2/bitpusher/265:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWU94SDhBWjdSeWVHSm16OFFSZV80RWc4RjdJOUFYemxhX1lqdU1TYkM3YkFFZ2hZY3JuVmR3ckppdUNMWlQyUXNhUWFlV01xeW1EbmRlY3EySHQ5b0ZjQmtGZDA5bk9yZTl4T3Q1Q081RXpHVkNNMGxQQjdneUR4Nm9iMWJFUlZqVTJ0QTJMX0tzMnhZZkRTaEU2cFhlTlpEMzR3Z3lJbUZXQjBUTVU0eDNvLTVFVG5Wa2VpSW9rR00wBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UqOqguDZoaoQuyhQZEqdT9gRvXfCOukU_s4IADMOeCthLyOz0ci8DeVKHiqdniCR2p0rFHU8lxtz2gq4GPJZakjC4cqig"
+ ]
+ },
+ "Body": ""
+ }
+ },
+ {
+ "ID": "f058e292b3ecbcdc",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/checksum-object?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "1d4b9606de321abb0c58127db449aa56/14299585136513339800;o=1"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/checksum-object?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 204,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "0"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:45 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051504000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vlgh81:4169,/bns/yk/borg/yk/bns/blobstore2/bitpusher/302.scotty,acatlm7:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=hMysW5OOPIrCqgWgjKzoBg"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "acatlm7:443,/bns/yk/borg/yk/bns/blobstore2/bitpusher/302.scotty,acatlm7:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yk/borg/yk/bns/blobstore2/bitpusher/302:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWU94SDhBWjdSeWVHSm16OFFSZV80RWc4RjdJOUFYemxhX1lqdU1TYkM3YkFFZ2hZY3JuVmR3ckppdUNMWlQyUXNhUWFlV01xeW1EbmRlY3EySHQ5b0ZjQmtGZDA5bk9yZTl4T3Q1Q081RXpHVkNNMGxQQjdneUR4Nm9iMWJFUlZqVTJ0QTJMX0tzMnhZZkRTaEU2cFhlTlpEMzR3Z3lJbUZXQjBUTVU0eDNvLTVFVG5Wa2VpSW9rR00wBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UptxT1bViawpoJzHTVTvKP4Xx1ZcSifkPhGPbzjvhW7hG9ugAgdOyI9uKaB4KOIMXAClmE6pHIqBaPUpEgvsppsHpWhzA"
+ ]
+ },
+ "Body": ""
+ }
+ },
+ {
+ "ID": "28115bbb2e191827",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/composed1?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "325c4987a34e0f0960b4194b3230753a/15130958971647730919;o=1"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/composed1?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 204,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "0"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:45 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051504000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vlaw129:4170,/bns/yk/borg/yk/bns/blobstore2/bitpusher/77.scotty,acatlm7:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=hcysW6GBIYTIqwWCqZ-YCg"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "acatlm7:443,/bns/yk/borg/yk/bns/blobstore2/bitpusher/77.scotty,acatlm7:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yk/borg/yk/bns/blobstore2/bitpusher/77:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWU94SDhBWjdSeWVHSm16OFFSZV80RWc4RjdJOUFYemxhX1lqdU1TYkM3YkFFZ2hZY3JuVmR3ckppdUNMWlQyUXNhUWFlV01xeW1EbmRlY3EySHQ5b0ZjQmtGZDA5bk9yZTl4T3Q1Q081RXpHVkNNMGxQQjdneUR4Nm9iMWJFUlZqVTJ0QTJMX0tzMnhZZkRTaEU2cFhlTlpEMzR3Z3lJbUZXQjBUTVU0eDNvLTVFVG5Wa2VpSW9rR00wBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Uq0IVEL0SX1tuKSBfKN5LKIj2zQZOeGRwK-vpSIa3Vz-jS_eaEWoR4kkvEpSHSwhkeASKZvvNxYij4YxB7TTQ7M0wU9Sg"
+ ]
+ },
+ "Body": ""
+ }
+ },
+ {
+ "ID": "b9135729814675aa",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/composed2?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "478ff7b82b02acc614fbd7491cc26138/15889995941085705782;o=1"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/composed2?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 204,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "0"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:45 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051504000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vnfg189:4335,/bns/yk/borg/yk/bns/blobstore2/bitpusher/210.scotty,acatlm7:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=hcysW9WbLImgqQW5iZ2IAw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "acatlm7:443,/bns/yk/borg/yk/bns/blobstore2/bitpusher/210.scotty,acatlm7:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yk/borg/yk/bns/blobstore2/bitpusher/210:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWU94SDhBWjdSeWVHSm16OFFSZV80RWc4RjdJOUFYemxhX1lqdU1TYkM3YkFFZ2hZY3JuVmR3ckppdUNMWlQyUXNhUWFlV01xeW1EbmRlY3EySHQ5b0ZjQmtGZDA5bk9yZTl4T3Q1Q081RXpHVkNNMGxQQjdneUR4Nm9iMWJFUlZqVTJ0QTJMX0tzMnhZZkRTaEU2cFhlTlpEMzR3Z3lJbUZXQjBUTVU0eDNvLTVFVG5Wa2VpSW9rR00wBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Up-GoXthTSv9bQ8EW2L_8OW8tcawoqd1dzbe5qE803XVsaMvhysX7AEki0vYm_b_PUp4UQo6nAJty3tzw3sJKs-CkVqZg"
+ ]
+ },
+ "Body": ""
+ }
+ },
+ {
+ "ID": "a70f6efc7b66aebd",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/content?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "f2138a3bfdb3ca1270a29175c89434a9/16649032910506838406;o=1"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/content?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 204,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "0"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:46 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051504000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vlfx126:4091,/bns/yk/borg/yk/bns/blobstore2/bitpusher/143.scotty,acatlm7:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=hcysW5HGN9aaqQXtlL7gBw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "acatlm7:443,/bns/yk/borg/yk/bns/blobstore2/bitpusher/143.scotty,acatlm7:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yk/borg/yk/bns/blobstore2/bitpusher/143:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWU94SDhBWjdSeWVHSm16OFFSZV80RWc4RjdJOUFYemxhX1lqdU1TYkM3YkFFZ2hZY3JuVmR3ckppdUNMWlQyUXNhUWFlV01xeW1EbmRlY3EySHQ5b0ZjQmtGZDA5bk9yZTl4T3Q1Q081RXpHVkNNMGxQQjdneUR4Nm9iMWJFUlZqVTJ0QTJMX0tzMnhZZkRTaEU2cFhlTlpEMzR3Z3lJbUZXQjBUTVU0eDNvLTVFVG5Wa2VpSW9rR00wBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UqLRuDWRCZeM1EVDaQWKPgK7oGyYAhiawyTnUmvHL8adw-5x6bDRd4BAtsgEdd6dwTjGcM31JC_PVuxFXk2Gbmi-LgZPg"
+ ]
+ },
+ "Body": ""
+ }
+ },
+ {
+ "ID": "8e3c63694062e50d",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/customer-encryption?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "0563889f56ec7e8a3d4ba57f5eff7ec8/17480407845136080085;o=1"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/customer-encryption?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 204,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "0"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:46 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051504000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vnfl3:4248,/bns/yk/borg/yk/bns/blobstore2/bitpusher/112.scotty,acatlm7:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=hsysW6a5IMHIqgXnhp64Cg"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "acatlm7:443,/bns/yk/borg/yk/bns/blobstore2/bitpusher/112.scotty,acatlm7:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yk/borg/yk/bns/blobstore2/bitpusher/112:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWU94SDhBWjdSeWVHSm16OFFSZV80RWc4RjdJOUFYemxhX1lqdU1TYkM3YkFFZ2hZY3JuVmR3ckppdUNMWlQyUXNhUWFlV01xeW1EbmRlY3EySHQ5b0ZjQmtGZDA5bk9yZTl4T3Q1Q081RXpHVkNNMGxQQjdneUR4Nm9iMWJFUlZqVTJ0QTJMX0tzMnhZZkRTaEU2cFhlTlpEMzR3Z3lJbUZXQjBUTVU0eDNvLTVFVG5Wa2VpSW9rR00wBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UpQNMs15b2ZK6X_5MihXwZgEjLo6T05WbTr2n0z8XAU1_M6PFj_TGFOvcH2xA8v51X5rXwMMgOa8Zlnciiw5XoNA0wLzw"
+ ]
+ },
+ "Body": ""
+ }
+ },
+ {
+ "ID": "e77e746365ee07f6",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/customer-encryption-2?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "ce94342b388282a0f8a232cd262deb24/18239444810262376228;o=1"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/customer-encryption-2?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 204,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "0"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:46 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051504000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vnme21:4136,/bns/yk/borg/yk/bns/blobstore2/bitpusher/346.scotty,acatlm7:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=hsysW6OaMYbdqQWr3LygCA"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "acatlm7:443,/bns/yk/borg/yk/bns/blobstore2/bitpusher/346.scotty,acatlm7:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yk/borg/yk/bns/blobstore2/bitpusher/346:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWU94SDhBWjdSeWVHSm16OFFSZV80RWc4RjdJOUFYemxhX1lqdU1TYkM3YkFFZ2hZY3JuVmR3ckppdUNMWlQyUXNhUWFlV01xeW1EbmRlY3EySHQ5b0ZjQmtGZDA5bk9yZTl4T3Q1Q081RXpHVkNNMGxQQjdneUR4Nm9iMWJFUlZqVTJ0QTJMX0tzMnhZZkRTaEU2cFhlTlpEMzR3Z3lJbUZXQjBUTVU0eDNvLTVFVG5Wa2VpSW9rR00wBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Up7RfFw6uxIJDsqLp2OQTL_fS4D5Cc7UeUw4mfGwhtlWhLKTB-dm5O4V4A2TwN9GDbHkUTbBK973X78OUzH-R3oGR63mw"
+ ]
+ },
+ "Body": ""
+ }
+ },
+ {
+ "ID": "031605bbb573c6df",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/customer-encryption-3?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "1f633c49c4dc1cf5e4c915a12098d132/624075675493745012;o=1"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/customer-encryption-3?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 204,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "0"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:47 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051504000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vngr8:4458,/bns/yk/borg/yk/bns/blobstore2/bitpusher/776.scotty,acatlm7:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=hsysW6vkPMWPqwWHh7rQCw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "acatlm7:443,/bns/yk/borg/yk/bns/blobstore2/bitpusher/776.scotty,acatlm7:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yk/borg/yk/bns/blobstore2/bitpusher/776:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWU94SDhBWjdSeWVHSm16OFFSZV80RWc4RjdJOUFYemxhX1lqdU1TYkM3YkFFZ2hZY3JuVmR3ckppdUNMWlQyUXNhUWFlV01xeW1EbmRlY3EySHQ5b0ZjQmtGZDA5bk9yZTl4T3Q1Q081RXpHVkNNMGxQQjdneUR4Nm9iMWJFUlZqVTJ0QTJMX0tzMnhZZkRTaEU2cFhlTlpEMzR3Z3lJbUZXQjBUTVU0eDNvLTVFVG5Wa2VpSW9rR00wBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UoK6XiFtLYFGaYtU7nXDjnLYgspLnsp33G7h02rm5oxCRPiKztJAxnaptk1DdxcsgtRWFDpspDibInpfJSmyNate7NAdA"
+ ]
+ },
+ "Body": ""
+ }
+ },
+ {
+ "ID": "a439009eb3aa1c46",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/gzip-test?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "873200505d2f90a7a10b789742172930/1383394115596686531;o=1"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/gzip-test?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 204,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "0"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:47 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051504000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vnfl3:4248,/bns/yk/borg/yk/bns/blobstore2/bitpusher/415.scotty,acatlm7:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=h8ysW-3XC4aaqgWynrWACA"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "acatlm7:443,/bns/yk/borg/yk/bns/blobstore2/bitpusher/415.scotty,acatlm7:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yk/borg/yk/bns/blobstore2/bitpusher/415:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWU94SDhBWjdSeWVHSm16OFFSZV80RWc4RjdJOUFYemxhX1lqdU1TYkM3YkFFZ2hZY3JuVmR3ckppdUNMWlQyUXNhUWFlV01xeW1EbmRlY3EySHQ5b0ZjQmtGZDA5bk9yZTl4T3Q1Q081RXpHVkNNMGxQQjdneUR4Nm9iMWJFUlZqVTJ0QTJMX0tzMnhZZkRTaEU2cFhlTlpEMzR3Z3lJbUZXQjBUTVU0eDNvLTVFVG5Wa2VpSW9rR00wBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UrAL3qpc0XLK8xxxACBMn1fQsJ6CVsY_8Nz09Yy-uCdBU96K6ItuF_EzyJaBR9VqVAxYzetcGXWdykqY22ex6Rd7t-WnA"
+ ]
+ },
+ "Body": ""
+ }
+ },
+ {
+ "ID": "442cd738948405a8",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/hashesOnUpload-1?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "b37363c18ed7c1f3a242d8100c37474d/2214487579544184594;o=1"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/hashesOnUpload-1?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 204,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "0"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:47 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051504000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vnbf187:4310,/bns/yk/borg/yk/bns/blobstore2/bitpusher/120.scotty,acatlm7:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=h8ysW7KrF8a9qQX1-5gQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "acatlm7:443,/bns/yk/borg/yk/bns/blobstore2/bitpusher/120.scotty,acatlm7:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yk/borg/yk/bns/blobstore2/bitpusher/120:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWU94SDhBWjdSeWVHSm16OFFSZV80RWc4RjdJOUFYemxhX1lqdU1TYkM3YkFFZ2hZY3JuVmR3ckppdUNMWlQyUXNhUWFlV01xeW1EbmRlY3EySHQ5b0ZjQmtGZDA5bk9yZTl4T3Q1Q081RXpHVkNNMGxQQjdneUR4Nm9iMWJFUlZqVTJ0QTJMX0tzMnhZZkRTaEU2cFhlTlpEMzR3Z3lJbUZXQjBUTVU0eDNvLTVFVG5Wa2VpSW9rR00wBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UrnZGU805pyZDr-jWUChiJ7PauljYSRc1qu3luwzs4sK1YhEeNuc4z23xWBHQUdf9xnFLxlcYF8y9Mp1J-ZjbXLlE7Edg"
+ ]
+ },
+ "Body": ""
+ }
+ },
+ {
+ "ID": "0ab5c557adf4d210",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/obj%2Fwith%2Fslashes?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "bfa8c9bbc4fe4bcd2dd20e47d1292d25/2973524548982094178;o=1"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/obj%2Fwith%2Fslashes?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 204,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "0"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:47 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051504000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vnaq187:4351,/bns/yk/borg/yk/bns/blobstore2/bitpusher/324.scotty,acatlm7:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=h8ysW7reIsHxqwXNrrqQBA"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "acatlm7:443,/bns/yk/borg/yk/bns/blobstore2/bitpusher/324.scotty,acatlm7:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yk/borg/yk/bns/blobstore2/bitpusher/324:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWU94SDhBWjdSeWVHSm16OFFSZV80RWc4RjdJOUFYemxhX1lqdU1TYkM3YkFFZ2hZY3JuVmR3ckppdUNMWlQyUXNhUWFlV01xeW1EbmRlY3EySHQ5b0ZjQmtGZDA5bk9yZTl4T3Q1Q081RXpHVkNNMGxQQjdneUR4Nm9iMWJFUlZqVTJ0QTJMX0tzMnhZZkRTaEU2cFhlTlpEMzR3Z3lJbUZXQjBUTVU0eDNvLTVFVG5Wa2VpSW9rR00wBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Uro06y0j7cAboYlh45nook9CsziqhW4GSDgzR0O41cP9mfrL9LCu-VXFQJN4j_ifc0VzCxPCC_pS8Xi1JsLbiGTQZ4kZw"
+ ]
+ },
+ "Body": ""
+ }
+ },
+ {
+ "ID": "5d15c1564955b248",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/obj1?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "1dd3e26a809feaa655da53979de2232c/3804899483611335857;o=1"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/obj1?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 204,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "0"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:47 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051504000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vnlw7:4165,/bns/yk/borg/yk/bns/blobstore2/bitpusher/613.scotty,acatlm7:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=h8ysW4WLLoOrqwXN27_QBg"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "acatlm7:443,/bns/yk/borg/yk/bns/blobstore2/bitpusher/613.scotty,acatlm7:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yk/borg/yk/bns/blobstore2/bitpusher/613:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWU94SDhBWjdSeWVHSm16OFFSZV80RWc4RjdJOUFYemxhX1lqdU1TYkM3YkFFZ2hZY3JuVmR3ckppdUNMWlQyUXNhUWFlV01xeW1EbmRlY3EySHQ5b0ZjQmtGZDA5bk9yZTl4T3Q1Q081RXpHVkNNMGxQQjdneUR4Nm9iMWJFUlZqVTJ0QTJMX0tzMnhZZkRTaEU2cFhlTlpEMzR3Z3lJbUZXQjBUTVU0eDNvLTVFVG5Wa2VpSW9rR00wBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Uog3n9HLH7oOSIA-N3pS-kf6I_aeZYEinxjeDg9glVhvv8Hn9ZUJk6oKyu1vLO3bDnjVJjdaVeyT_w5C9zqouTqbvFDQA"
+ ]
+ },
+ "Body": ""
+ }
+ },
+ {
+ "ID": "773d0d0e7c8de8d7",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/obj2?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "ae355ff20ff9094a11603f3171b80758/4563935353537683200;o=1"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/obj2?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 204,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "0"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:48 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051504000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vnbr125:4157,/bns/yk/borg/yk/bns/blobstore2/bitpusher/767.scotty,acatlm7:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=h8ysW8CeOY7HqwX96J_QBQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "acatlm7:443,/bns/yk/borg/yk/bns/blobstore2/bitpusher/767.scotty,acatlm7:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yk/borg/yk/bns/blobstore2/bitpusher/767:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWU94SDhBWjdSeWVHSm16OFFSZV80RWc4RjdJOUFYemxhX1lqdU1TYkM3YkFFZ2hZY3JuVmR3ckppdUNMWlQyUXNhUWFlV01xeW1EbmRlY3EySHQ5b0ZjQmtGZDA5bk9yZTl4T3Q1Q081RXpHVkNNMGxQQjdneUR4Nm9iMWJFUlZqVTJ0QTJMX0tzMnhZZkRTaEU2cFhlTlpEMzR3Z3lJbUZXQjBUTVU0eDNvLTVFVG5Wa2VpSW9rR00wBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UoEeadrUiIgvDLmHfsXIxGMbZwpdL5mrSCwSpoLJsFgNtv3HwESa9z6p58RBQEkI0ybLZtmCC4m5J7pliw5PcoJY-I9_w"
+ ]
+ },
+ "Body": ""
+ }
+ },
+ {
+ "ID": "7fbeaf8b3cf1b91c",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/posc?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "1d8302757f1cbbac298d60752aae572f/5395310283871957584;o=1"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/posc?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 204,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "0"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:48 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051504000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vngg82:4082,/bns/yk/borg/yk/bns/blobstore2/bitpusher/454.scotty,acatlm7:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=iMysW5mlB4n_qAXV4q7QBg"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "acatlm7:443,/bns/yk/borg/yk/bns/blobstore2/bitpusher/454.scotty,acatlm7:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yk/borg/yk/bns/blobstore2/bitpusher/454:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWU94SDhBWjdSeWVHSm16OFFSZV80RWc4RjdJOUFYemxhX1lqdU1TYkM3YkFFZ2hZY3JuVmR3ckppdUNMWlQyUXNhUWFlV01xeW1EbmRlY3EySHQ5b0ZjQmtGZDA5bk9yZTl4T3Q1Q081RXpHVkNNMGxQQjdneUR4Nm9iMWJFUlZqVTJ0QTJMX0tzMnhZZkRTaEU2cFhlTlpEMzR3Z3lJbUZXQjBUTVU0eDNvLTVFVG5Wa2VpSW9rR00wBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UoY53cxU4F-dLTTWSvF_miS_w7rFCL6M3gLqmlhu57v_ZofFq1LhJsb7oj9A0OzWgKqL7LnByKllH5uDb02LVJYHZlTqQ"
+ ]
+ },
+ "Body": ""
+ }
+ },
+ {
+ "ID": "7a869ae16e04acab",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/posc2?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "0f17da0653514183f41837352b13cac1/6154347253309932703;o=1"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/posc2?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 204,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "0"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:48 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051504000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vlfu144:4148,/bns/yk/borg/yk/bns/blobstore2/bitpusher/345.scotty,acatlm7:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=iMysW5rwEoLHqQXhy6ugCQ"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "acatlm7:443,/bns/yk/borg/yk/bns/blobstore2/bitpusher/345.scotty,acatlm7:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yk/borg/yk/bns/blobstore2/bitpusher/345:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWU94SDhBWjdSeWVHSm16OFFSZV80RWc4RjdJOUFYemxhX1lqdU1TYkM3YkFFZ2hZY3JuVmR3ckppdUNMWlQyUXNhUWFlV01xeW1EbmRlY3EySHQ5b0ZjQmtGZDA5bk9yZTl4T3Q1Q081RXpHVkNNMGxQQjdneUR4Nm9iMWJFUlZqVTJ0QTJMX0tzMnhZZkRTaEU2cFhlTlpEMzR3Z3lJbUZXQjBUTVU0eDNvLTVFVG5Wa2VpSW9rR00wBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Uo6NddOzIil9_TPreOmibWWAp0uuzawHLKoTgLsR5TFz4BdvjhLEPqJWnyQlbvuGu64LRM69DdFAU46Kv4G3wPMi1cDFg"
+ ]
+ },
+ "Body": ""
+ }
+ },
+ {
+ "ID": "90d1290d9e8338e4",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/signedURL?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "56769fe6f7799f8cce8d412e696c8d0d/6985440717257431022;o=1"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/signedURL?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 204,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "0"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:48 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051504000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vly135:4474,/bns/yk/borg/yk/bns/blobstore2/bitpusher/735.scotty,acatlm7:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=iMysW-uFHsGsqQWeuYfgCA"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "acatlm7:443,/bns/yk/borg/yk/bns/blobstore2/bitpusher/735.scotty,acatlm7:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yk/borg/yk/bns/blobstore2/bitpusher/735:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWU94SDhBWjdSeWVHSm16OFFSZV80RWc4RjdJOUFYemxhX1lqdU1TYkM3YkFFZ2hZY3JuVmR3ckppdUNMWlQyUXNhUWFlV01xeW1EbmRlY3EySHQ5b0ZjQmtGZDA5bk9yZTl4T3Q1Q081RXpHVkNNMGxQQjdneUR4Nm9iMWJFUlZqVTJ0QTJMX0tzMnhZZkRTaEU2cFhlTlpEMzR3Z3lJbUZXQjBUTVU0eDNvLTVFVG5Wa2VpSW9rR00wBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UqvbeFGjeDdPJCJQCgDngxkPzKNvOQ8FdU1SY7YNAwACJ1YgjQxl6ogh-FGD6uYGinljM1qCH4diAOJC3qSsqKj1ZtNrw"
+ ]
+ },
+ "Body": ""
+ }
+ },
+ {
+ "ID": "9c1feb92dadcfc24",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/some-object?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "da9b41949711014098fef2c91d0f75d3/7744759157360306750;o=1"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/some-object?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 204,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "0"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:48 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051504000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vlba65:4352,/bns/yk/borg/yk/bns/blobstore2/bitpusher/169.scotty,acatlm7:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=iMysW_-jKYOPqQWX5o6wBA"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "acatlm7:443,/bns/yk/borg/yk/bns/blobstore2/bitpusher/169.scotty,acatlm7:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yk/borg/yk/bns/blobstore2/bitpusher/169:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWU94SDhBWjdSeWVHSm16OFFSZV80RWc4RjdJOUFYemxhX1lqdU1TYkM3YkFFZ2hZY3JuVmR3ckppdUNMWlQyUXNhUWFlV01xeW1EbmRlY3EySHQ5b0ZjQmtGZDA5bk9yZTl4T3Q1Q081RXpHVkNNMGxQQjdneUR4Nm9iMWJFUlZqVTJ0QTJMX0tzMnhZZkRTaEU2cFhlTlpEMzR3Z3lJbUZXQjBUTVU0eDNvLTVFVG5Wa2VpSW9rR00wBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UpXqAP9xLjQWdcgz7d8Q_Cbf4AnteqAh9Y73lfxN3Sf3RY2c88hpqs6As4zmkoi7IsdRwxSFQpbwjdWxFHktKceAVTcgg"
+ ]
+ },
+ "Body": ""
+ }
+ },
+ {
+ "ID": "32dbe6fe59803fdd",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/zero-object?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "b038092da7535a6b1a016b5969d43816/8503796126781504909;o=1"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001/o/zero-object?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 204,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "0"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:49 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051504000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vnll189:4029,/bns/yk/borg/yk/bns/blobstore2/bitpusher/96.scotty,acatlm7:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=iMysW56MNYWyqgWbr4X4Bw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "acatlm7:443,/bns/yk/borg/yk/bns/blobstore2/bitpusher/96.scotty,acatlm7:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yk/borg/yk/bns/blobstore2/bitpusher/96:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWU94SDhBWjdSeWVHSm16OFFSZV80RWc4RjdJOUFYemxhX1lqdU1TYkM3YkFFZ2hZY3JuVmR3ckppdUNMWlQyUXNhUWFlV01xeW1EbmRlY3EySHQ5b0ZjQmtGZDA5bk9yZTl4T3Q1Q081RXpHVkNNMGxQQjdneUR4Nm9iMWJFUlZqVTJ0QTJMX0tzMnhZZkRTaEU2cFhlTlpEMzR3Z3lJbUZXQjBUTVU0eDNvLTVFVG5Wa2VpSW9rR00wBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Uo3Gb0e8jwES-jB53Gxhy2Tmlp0VZUOMS4ml-qTNRDKPhFArOCBgKBoQ7ncCW6FqolC3nizW4el-fG3AzpD-xocDeXw4g"
+ ]
+ },
+ "Body": ""
+ }
+ },
+ {
+ "ID": "57411c02a06c30c2",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "7e48b2dfc255815f0f8966e31ae6a811/10094208030848655916;o=1"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180927-44630911863640-0001?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 204,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "no-cache, no-store, max-age=0, must-revalidate"
+ ],
+ "Content-Length": [
+ "0"
+ ],
+ "Content-Type": [
+ "application/json"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:49 GMT"
+ ],
+ "Expires": [
+ "Mon, 01 Jan 1990 00:00:00 GMT"
+ ],
+ "Pragma": [
+ "no-cache"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051504000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vngg200:4073,/bns/yk/borg/yk/bns/blobstore2/bitpusher/608.scotty,acatlm7:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=icysW43NBNPuqgXrl4aACg"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "acatlm7:443,/bns/yk/borg/yk/bns/blobstore2/bitpusher/608.scotty,acatlm7:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yk/borg/yk/bns/blobstore2/bitpusher/608:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWU94SDhBWjdSeWVHSm16OFFSZV80RWc4RjdJOUFYemxhX1lqdU1TYkM3YkFFZ2hZY3JuVmR3ckppdUNMWlQyUXNhUWFlV01xeW1EbmRlY3EySHQ5b0ZjQmtGZDA5bk9yZTl4T3Q1Q081RXpHVkNNMGxQQjdneUR4Nm9iMWJFUlZqVTJ0QTJMX0tzMnhZZkRTaEU2cFhlTlpEMzR3Z3lJbUZXQjBUTVU0eDNvLTVFVG5Wa2VpSW9rR00wBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UolMTGCP9CHjJUePEKE4nRrZ1BxgPKXRv5wjE2rGWQ3hVauimcqefSaoRlr42ly3N6m8U8W3eKK42b_zjLI6lQmBK_ptA"
+ ]
+ },
+ "Body": ""
+ }
+ },
+ {
+ "ID": "94f77b6c25ff6aee",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b?alt=json\u0026pageToken=\u0026prefix=go-integration-test\u0026prettyPrint=false\u0026project=dulcet-port-762\u0026projection=full",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "4a5bbb92754558627e8dd36fe23e7902/10925301490501252475;o=1"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b?alt=json\u0026pageToken=\u0026prefix=go-integration-test\u0026prettyPrint=false\u0026project=dulcet-port-762\u0026projection=full"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0, must-revalidate, no-transform"
+ ],
+ "Content-Length": [
+ "77624"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:49 GMT"
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:26:49 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051503000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vldj144:4070,/bns/yk/borg/yk/bns/blobstore2/bitpusher/595.scotty,acatlm7:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=icysW7nUGNe2qwXao6yQDw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "acatlm7:443,/bns/yk/borg/yk/bns/blobstore2/bitpusher/595.scotty,acatlm7:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yk/borg/yk/bns/blobstore2/bitpusher/595:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRWU94SDhBWjdSeWVHSm16OFFSZV80RWc4RjdJOUFYemxhX1lqdU1TYkM3YkFFZ2hZY3JuVmR3ckppdUNMWlQyUXNhUWFlV01xeW1EbmRlY3EySHQ5b0ZjQmtGZDA5bk9yZTl4T3Q1Q081RXpHVkNNMGxQQjdneUR4Nm9iMWJFUlZqVTJ0QTJMX0tzMnhZZkRTaEU2cFhlTlpEMzR3Z3lJbUZXQjBUTVU0eDNvLTVFVG5Wa2VpSW9rR00wBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2Up6TaL9Fk0PBYIR55LIqT8d93Peu8cpyc6QcENB7DInI2b12XEHdBbjY03_Ue-SY_V4i-E2t4QOnymAaoC9kwgvkpiB9w"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNidWNrZXRzIiwiaXRlbXMiOlt7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOC00MTMxNzY3MzE4MDAwLTAwMDIiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE4LTQxMzE3NjczMTgwMDAtMDAwMiIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE4LTQxMzE3NjczMTgwMDAtMDAwMiIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0xOFQwMTowODo1My4yOTVaIiwidXBkYXRlZCI6IjIwMTgtMDktMThUMDE6MDg6NTMuMjk1WiIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImFjbCI6W3sia2luZCI6InN0b3JhZ2UjYnVja2V0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOC00MTMxNzY3MzE4MDAwLTAwMDIvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE4LTQxMzE3NjczMTgwMDAtMDAwMi9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE4LTQxMzE3NjczMTgwMDAtMDAwMiIsImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6Im93bmVycyJ9LCJldGFnIjoiQ0FFPSJ9LHsia2luZCI6InN0b3JhZ2UjYnVja2V0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOC00MTMxNzY3MzE4MDAwLTAwMDIvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOC00MTMxNzY3MzE4MDAwLTAwMDIvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTgtNDEzMTc2NzMxODAwMC0wMDAyIiwiZW50aXR5IjoicHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6ImVkaXRvcnMifSwiZXRhZyI6IkNBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTgtNDEzMTc2NzMxODAwMC0wMDAyL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTgtNDEzMTc2NzMxODAwMC0wMDAyL2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE4LTQxMzE3NjczMTgwMDAtMDAwMiIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0FFPSJ9XSwiZGVmYXVsdE9iamVjdEFjbCI6W3sia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6Im93bmVycyJ9LCJldGFnIjoiQ0FFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiZW50aXR5IjoicHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6IlJFQURFUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJ2aWV3ZXJzIn0sImV0YWciOiJDQUU9In1dLCJvd25lciI6eyJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSJ9LCJsb2NhdGlvbiI6IlVTIiwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJldGFnIjoiQ0FFPSJ9LHsia2luZCI6InN0b3JhZ2UjYnVja2V0IiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE4LTQ3MzQyMDk0ODMwMDAtMDAwMSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTgtNDczNDIwOTQ4MzAwMC0wMDAxIiwicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwibmFtZSI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTgtNDczNDIwOTQ4MzAwMC0wMDAxIiwidGltZUNyZWF0ZWQiOiIyMDE4LTA5LTE4VDAxOjE4OjU1LjA5NloiLCJ1cGRhdGVkIjoiMjAxOC0wOS0xOFQwMToxODo1NS4wOTZaIiwibWV0YWdlbmVyYXRpb24iOiIxIiwiYWNsIjpbeyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE4LTQ3MzQyMDk0ODMwMDAtMDAwMS9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTgtNDczNDIwOTQ4MzAwMC0wMDAxL2FjbC9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTgtNDczNDIwOTQ4MzAwMC0wMDAxIiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDQUU9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE4LTQ3MzQyMDk0ODMwMDAtMDAwMS9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE4LTQ3MzQyMDk0ODMwMDAtMDAwMS9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOC00NzM0MjA5NDgzMDAwLTAwMDEiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0FFPSJ9LHsia2luZCI6InN0b3JhZ2UjYnVja2V0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOC00NzM0MjA5NDgzMDAwLTAwMDEvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOC00NzM0MjA5NDgzMDAwLTAwMDEvYWNsL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTgtNDczNDIwOTQ4MzAwMC0wMDAxIiwiZW50aXR5IjoicHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6IlJFQURFUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJ2aWV3ZXJzIn0sImV0YWciOiJDQUU9In1dLCJkZWZhdWx0T2JqZWN0QWNsIjpbeyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiZW50aXR5IjoicHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6ImVkaXRvcnMifSwiZXRhZyI6IkNBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNBRT0ifV0sIm93bmVyIjp7ImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1In0sImxvY2F0aW9uIjoiVVMiLCJzdG9yYWdlQ2xhc3MiOiJTVEFOREFSRCIsImV0YWciOiJDQUU9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTgtNDczNDIwOTQ4MzAwMC0wMDAyIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOC00NzM0MjA5NDgzMDAwLTAwMDIiLCJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJuYW1lIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOC00NzM0MjA5NDgzMDAwLTAwMDIiLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMThUMDE6MTg6NTUuOTkwWiIsInVwZGF0ZWQiOiIyMDE4LTA5LTE4VDAxOjE4OjU1Ljk5MFoiLCJtZXRhZ2VuZXJhdGlvbiI6IjEiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTgtNDczNDIwOTQ4MzAwMC0wMDAyL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOC00NzM0MjA5NDgzMDAwLTAwMDIvYWNsL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOC00NzM0MjA5NDgzMDAwLTAwMDIiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTgtNDczNDIwOTQ4MzAwMC0wMDAyL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTgtNDczNDIwOTQ4MzAwMC0wMDAyL2FjbC9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE4LTQ3MzQyMDk0ODMwMDAtMDAwMiIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDQUU9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE4LTQ3MzQyMDk0ODMwMDAtMDAwMi9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE4LTQ3MzQyMDk0ODMwMDAtMDAwMi9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOC00NzM0MjA5NDgzMDAwLTAwMDIiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNBRT0ifV0sImRlZmF1bHRPYmplY3RBY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0FFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0FFPSJ9XSwib3duZXIiOnsiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUifSwibG9jYXRpb24iOiJVUyIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwiZXRhZyI6IkNBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOC00OTUzNTYyODAzMDAwLTAwMDIiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE4LTQ5NTM1NjI4MDMwMDAtMDAwMiIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE4LTQ5NTM1NjI4MDMwMDAtMDAwMiIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0xOFQwMToyMjozNC44NjBaIiwidXBkYXRlZCI6IjIwMTgtMDktMThUMDE6MjI6MzQuODYwWiIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImFjbCI6W3sia2luZCI6InN0b3JhZ2UjYnVja2V0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOC00OTUzNTYyODAzMDAwLTAwMDIvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE4LTQ5NTM1NjI4MDMwMDAtMDAwMi9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE4LTQ5NTM1NjI4MDMwMDAtMDAwMiIsImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6Im93bmVycyJ9LCJldGFnIjoiQ0FFPSJ9LHsia2luZCI6InN0b3JhZ2UjYnVja2V0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOC00OTUzNTYyODAzMDAwLTAwMDIvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOC00OTUzNTYyODAzMDAwLTAwMDIvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTgtNDk1MzU2MjgwMzAwMC0wMDAyIiwiZW50aXR5IjoicHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6ImVkaXRvcnMifSwiZXRhZyI6IkNBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTgtNDk1MzU2MjgwMzAwMC0wMDAyL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTgtNDk1MzU2MjgwMzAwMC0wMDAyL2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE4LTQ5NTM1NjI4MDMwMDAtMDAwMiIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0FFPSJ9XSwiZGVmYXVsdE9iamVjdEFjbCI6W3sia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6Im93bmVycyJ9LCJldGFnIjoiQ0FFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiZW50aXR5IjoicHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6IlJFQURFUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJ2aWV3ZXJzIn0sImV0YWciOiJDQUU9In1dLCJvd25lciI6eyJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSJ9LCJsb2NhdGlvbiI6IlVTIiwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJldGFnIjoiQ0FFPSJ9LHsia2luZCI6InN0b3JhZ2UjYnVja2V0IiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE4LTU0NjE3OTA0MDcwMDAtMDAwMiIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTgtNTQ2MTc5MDQwNzAwMC0wMDAyIiwicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwibmFtZSI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTgtNTQ2MTc5MDQwNzAwMC0wMDAyIiwidGltZUNyZWF0ZWQiOiIyMDE4LTA5LTE4VDAxOjMxOjA1LjQ5MloiLCJ1cGRhdGVkIjoiMjAxOC0wOS0xOFQwMTozMTowNS40OTJaIiwibWV0YWdlbmVyYXRpb24iOiIxIiwiYWNsIjpbeyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE4LTU0NjE3OTA0MDcwMDAtMDAwMi9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTgtNTQ2MTc5MDQwNzAwMC0wMDAyL2FjbC9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTgtNTQ2MTc5MDQwNzAwMC0wMDAyIiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDQUU9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE4LTU0NjE3OTA0MDcwMDAtMDAwMi9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE4LTU0NjE3OTA0MDcwMDAtMDAwMi9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOC01NDYxNzkwNDA3MDAwLTAwMDIiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0FFPSJ9LHsia2luZCI6InN0b3JhZ2UjYnVja2V0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOC01NDYxNzkwNDA3MDAwLTAwMDIvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOC01NDYxNzkwNDA3MDAwLTAwMDIvYWNsL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTgtNTQ2MTc5MDQwNzAwMC0wMDAyIiwiZW50aXR5IjoicHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6IlJFQURFUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJ2aWV3ZXJzIn0sImV0YWciOiJDQUU9In1dLCJkZWZhdWx0T2JqZWN0QWNsIjpbeyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiZW50aXR5IjoicHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6ImVkaXRvcnMifSwiZXRhZyI6IkNBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNBRT0ifV0sIm93bmVyIjp7ImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1In0sImxvY2F0aW9uIjoiVVMiLCJzdG9yYWdlQ2xhc3MiOiJTVEFOREFSRCIsImV0YWciOiJDQUU9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTgtNTU2MTc3OTI0NjAwMC0wMDAyIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOC01NTYxNzc5MjQ2MDAwLTAwMDIiLCJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJuYW1lIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOC01NTYxNzc5MjQ2MDAwLTAwMDIiLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMThUMDE6MzI6NDMuMjk3WiIsInVwZGF0ZWQiOiIyMDE4LTA5LTE4VDAxOjMyOjQzLjI5N1oiLCJtZXRhZ2VuZXJhdGlvbiI6IjEiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTgtNTU2MTc3OTI0NjAwMC0wMDAyL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOC01NTYxNzc5MjQ2MDAwLTAwMDIvYWNsL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOC01NTYxNzc5MjQ2MDAwLTAwMDIiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTgtNTU2MTc3OTI0NjAwMC0wMDAyL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTgtNTU2MTc3OTI0NjAwMC0wMDAyL2FjbC9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE4LTU1NjE3NzkyNDYwMDAtMDAwMiIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDQUU9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE4LTU1NjE3NzkyNDYwMDAtMDAwMi9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE4LTU1NjE3NzkyNDYwMDAtMDAwMi9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOC01NTYxNzc5MjQ2MDAwLTAwMDIiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNBRT0ifV0sImRlZmF1bHRPYmplY3RBY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0FFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0FFPSJ9XSwib3duZXIiOnsiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUifSwibG9jYXRpb24iOiJVUyIsInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwiZXRhZyI6IkNBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOC02Njg0MjM5MDAzMDAwLTAwMDIiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE4LTY2ODQyMzkwMDMwMDAtMDAwMiIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE4LTY2ODQyMzkwMDMwMDAtMDAwMiIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0xOFQwMTo1MToyNS43OTVaIiwidXBkYXRlZCI6IjIwMTgtMDktMThUMDE6NTE6MjUuNzk1WiIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImFjbCI6W3sia2luZCI6InN0b3JhZ2UjYnVja2V0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOC02Njg0MjM5MDAzMDAwLTAwMDIvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE4LTY2ODQyMzkwMDMwMDAtMDAwMi9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE4LTY2ODQyMzkwMDMwMDAtMDAwMiIsImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6Im93bmVycyJ9LCJldGFnIjoiQ0FFPSJ9LHsia2luZCI6InN0b3JhZ2UjYnVja2V0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOC02Njg0MjM5MDAzMDAwLTAwMDIvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOC02Njg0MjM5MDAzMDAwLTAwMDIvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTgtNjY4NDIzOTAwMzAwMC0wMDAyIiwiZW50aXR5IjoicHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6ImVkaXRvcnMifSwiZXRhZyI6IkNBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTgtNjY4NDIzOTAwMzAwMC0wMDAyL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTgtNjY4NDIzOTAwMzAwMC0wMDAyL2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE4LTY2ODQyMzkwMDMwMDAtMDAwMiIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0FFPSJ9XSwiZGVmYXVsdE9iamVjdEFjbCI6W3sia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6Im93bmVycyJ9LCJldGFnIjoiQ0FFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiZW50aXR5IjoicHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6IlJFQURFUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJ2aWV3ZXJzIn0sImV0YWciOiJDQUU9In1dLCJvd25lciI6eyJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSJ9LCJsb2NhdGlvbiI6IlVTIiwicmV0ZW50aW9uUG9saWN5Ijp7InJldGVudGlvblBlcmlvZCI6IjM2MDAiLCJlZmZlY3RpdmVUaW1lIjoiMjAxOC0wOS0xOFQwMTo1MToyNS43OTVaIn0sInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwiZXRhZyI6IkNBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOC02ODM3NzA3MzQxMDAwLTAwMTciLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE4LTY4Mzc3MDczNDEwMDAtMDAxNyIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE4LTY4Mzc3MDczNDEwMDAtMDAxNyIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0xOFQwMTo1NjoyNC44OTZaIiwidXBkYXRlZCI6IjIwMTgtMDktMThUMDE6NTY6MjYuODY1WiIsIm1ldGFnZW5lcmF0aW9uIjoiMiIsImFjbCI6W3sia2luZCI6InN0b3JhZ2UjYnVja2V0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOC02ODM3NzA3MzQxMDAwLTAwMTcvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE4LTY4Mzc3MDczNDEwMDAtMDAxNy9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE4LTY4Mzc3MDczNDEwMDAtMDAxNyIsImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6Im93bmVycyJ9LCJldGFnIjoiQ0FJPSJ9LHsia2luZCI6InN0b3JhZ2UjYnVja2V0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOC02ODM3NzA3MzQxMDAwLTAwMTcvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOC02ODM3NzA3MzQxMDAwLTAwMTcvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTgtNjgzNzcwNzM0MTAwMC0wMDE3IiwiZW50aXR5IjoicHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6ImVkaXRvcnMifSwiZXRhZyI6IkNBST0ifSx7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTgtNjgzNzcwNzM0MTAwMC0wMDE3L3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTgtNjgzNzcwNzM0MTAwMC0wMDE3L2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE4LTY4Mzc3MDczNDEwMDAtMDAxNyIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0FJPSJ9XSwiZGVmYXVsdE9iamVjdEFjbCI6W3sia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6Im93bmVycyJ9LCJldGFnIjoiQ0FJPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDQUk9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiZW50aXR5IjoicHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6IlJFQURFUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJ2aWV3ZXJzIn0sImV0YWciOiJDQUk9In1dLCJvd25lciI6eyJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSJ9LCJsb2NhdGlvbiI6IlVTIiwicmV0ZW50aW9uUG9saWN5Ijp7InJldGVudGlvblBlcmlvZCI6IjkwMDAwIiwiZWZmZWN0aXZlVGltZSI6IjIwMTgtMDktMThUMDE6NTY6MjQuODk2WiIsImlzTG9ja2VkIjp0cnVlfSwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJldGFnIjoiQ0FJPSJ9LHsia2luZCI6InN0b3JhZ2UjYnVja2V0IiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE4LTY4Mzc3MDczNDEwMDAtMDAxOCIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTgtNjgzNzcwNzM0MTAwMC0wMDE4IiwicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwibmFtZSI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTgtNjgzNzcwNzM0MTAwMC0wMDE4IiwidGltZUNyZWF0ZWQiOiIyMDE4LTA5LTE4VDAxOjU2OjI5LjA5MVoiLCJ1cGRhdGVkIjoiMjAxOC0wOS0xOFQwMTo1NjoyOS4wOTFaIiwibWV0YWdlbmVyYXRpb24iOiIxIiwiYWNsIjpbeyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE4LTY4Mzc3MDczNDEwMDAtMDAxOC9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTgtNjgzNzcwNzM0MTAwMC0wMDE4L2FjbC9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTgtNjgzNzcwNzM0MTAwMC0wMDE4IiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDQUU9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE4LTY4Mzc3MDczNDEwMDAtMDAxOC9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE4LTY4Mzc3MDczNDEwMDAtMDAxOC9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOC02ODM3NzA3MzQxMDAwLTAwMTgiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0FFPSJ9LHsia2luZCI6InN0b3JhZ2UjYnVja2V0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOC02ODM3NzA3MzQxMDAwLTAwMTgvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOC02ODM3NzA3MzQxMDAwLTAwMTgvYWNsL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTgtNjgzNzcwNzM0MTAwMC0wMDE4IiwiZW50aXR5IjoicHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6IlJFQURFUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJ2aWV3ZXJzIn0sImV0YWciOiJDQUU9In1dLCJkZWZhdWx0T2JqZWN0QWNsIjpbeyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiZW50aXR5IjoicHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6ImVkaXRvcnMifSwiZXRhZyI6IkNBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNBRT0ifV0sIm93bmVyIjp7ImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1In0sImxvY2F0aW9uIjoiVVMiLCJyZXRlbnRpb25Qb2xpY3kiOnsicmV0ZW50aW9uUGVyaW9kIjoiOTAwMDAiLCJlZmZlY3RpdmVUaW1lIjoiMjAxOC0wOS0xOFQwMTo1NjoyOS4wOTFaIn0sInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwiZXRhZyI6IkNBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOC03NTg3NzI5ODMwMDAwLTAwMTciLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE4LTc1ODc3Mjk4MzAwMDAtMDAxNyIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE4LTc1ODc3Mjk4MzAwMDAtMDAxNyIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0xOFQwMjowODo0Ny42MDFaIiwidXBkYXRlZCI6IjIwMTgtMDktMThUMDI6MDg6NDkuMzQ2WiIsIm1ldGFnZW5lcmF0aW9uIjoiMiIsImFjbCI6W3sia2luZCI6InN0b3JhZ2UjYnVja2V0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOC03NTg3NzI5ODMwMDAwLTAwMTcvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE4LTc1ODc3Mjk4MzAwMDAtMDAxNy9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE4LTc1ODc3Mjk4MzAwMDAtMDAxNyIsImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6Im93bmVycyJ9LCJldGFnIjoiQ0FJPSJ9LHsia2luZCI6InN0b3JhZ2UjYnVja2V0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOC03NTg3NzI5ODMwMDAwLTAwMTcvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOC03NTg3NzI5ODMwMDAwLTAwMTcvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTgtNzU4NzcyOTgzMDAwMC0wMDE3IiwiZW50aXR5IjoicHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6ImVkaXRvcnMifSwiZXRhZyI6IkNBST0ifSx7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTgtNzU4NzcyOTgzMDAwMC0wMDE3L3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTgtNzU4NzcyOTgzMDAwMC0wMDE3L2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE4LTc1ODc3Mjk4MzAwMDAtMDAxNyIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0FJPSJ9XSwiZGVmYXVsdE9iamVjdEFjbCI6W3sia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6Im93bmVycyJ9LCJldGFnIjoiQ0FJPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDQUk9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiZW50aXR5IjoicHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6IlJFQURFUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJ2aWV3ZXJzIn0sImV0YWciOiJDQUk9In1dLCJvd25lciI6eyJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSJ9LCJsb2NhdGlvbiI6IlVTIiwicmV0ZW50aW9uUG9saWN5Ijp7InJldGVudGlvblBlcmlvZCI6IjkwMDAwIiwiZWZmZWN0aXZlVGltZSI6IjIwMTgtMDktMThUMDI6MDg6NDcuNjAxWiIsImlzTG9ja2VkIjp0cnVlfSwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJldGFnIjoiQ0FJPSJ9LHsia2luZCI6InN0b3JhZ2UjYnVja2V0IiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE4LTc1ODc3Mjk4MzAwMDAtMDAxOCIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTgtNzU4NzcyOTgzMDAwMC0wMDE4IiwicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwibmFtZSI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTgtNzU4NzcyOTgzMDAwMC0wMDE4IiwidGltZUNyZWF0ZWQiOiIyMDE4LTA5LTE4VDAyOjA4OjU0LjA5NFoiLCJ1cGRhdGVkIjoiMjAxOC0wOS0xOFQwMjowODo1NC4wOTRaIiwibWV0YWdlbmVyYXRpb24iOiIxIiwiYWNsIjpbeyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE4LTc1ODc3Mjk4MzAwMDAtMDAxOC9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTgtNzU4NzcyOTgzMDAwMC0wMDE4L2FjbC9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTgtNzU4NzcyOTgzMDAwMC0wMDE4IiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDQUU9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE4LTc1ODc3Mjk4MzAwMDAtMDAxOC9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE4LTc1ODc3Mjk4MzAwMDAtMDAxOC9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOC03NTg3NzI5ODMwMDAwLTAwMTgiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0FFPSJ9LHsia2luZCI6InN0b3JhZ2UjYnVja2V0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOC03NTg3NzI5ODMwMDAwLTAwMTgvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOC03NTg3NzI5ODMwMDAwLTAwMTgvYWNsL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTgtNzU4NzcyOTgzMDAwMC0wMDE4IiwiZW50aXR5IjoicHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6IlJFQURFUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJ2aWV3ZXJzIn0sImV0YWciOiJDQUU9In1dLCJkZWZhdWx0T2JqZWN0QWNsIjpbeyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiZW50aXR5IjoicHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6ImVkaXRvcnMifSwiZXRhZyI6IkNBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNBRT0ifV0sIm93bmVyIjp7ImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1In0sImxvY2F0aW9uIjoiVVMiLCJyZXRlbnRpb25Qb2xpY3kiOnsicmV0ZW50aW9uUGVyaW9kIjoiOTAwMDAiLCJlZmZlY3RpdmVUaW1lIjoiMjAxOC0wOS0xOFQwMjowODo1NC4wOTRaIn0sInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwiZXRhZyI6IkNBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOS01MTgzMzUwOTM2MDAwLTAwMTciLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE5LTUxODMzNTA5MzYwMDAtMDAxNyIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE5LTUxODMzNTA5MzYwMDAtMDAxNyIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0xOVQwMToyOToxMC45OTJaIiwidXBkYXRlZCI6IjIwMTgtMDktMTlUMDE6Mjk6MTMuMDUzWiIsIm1ldGFnZW5lcmF0aW9uIjoiMiIsImFjbCI6W3sia2luZCI6InN0b3JhZ2UjYnVja2V0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOS01MTgzMzUwOTM2MDAwLTAwMTcvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE5LTUxODMzNTA5MzYwMDAtMDAxNy9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE5LTUxODMzNTA5MzYwMDAtMDAxNyIsImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6Im93bmVycyJ9LCJldGFnIjoiQ0FJPSJ9LHsia2luZCI6InN0b3JhZ2UjYnVja2V0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOS01MTgzMzUwOTM2MDAwLTAwMTcvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOS01MTgzMzUwOTM2MDAwLTAwMTcvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTktNTE4MzM1MDkzNjAwMC0wMDE3IiwiZW50aXR5IjoicHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6ImVkaXRvcnMifSwiZXRhZyI6IkNBST0ifSx7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTktNTE4MzM1MDkzNjAwMC0wMDE3L3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTktNTE4MzM1MDkzNjAwMC0wMDE3L2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE5LTUxODMzNTA5MzYwMDAtMDAxNyIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0FJPSJ9XSwiZGVmYXVsdE9iamVjdEFjbCI6W3sia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6Im93bmVycyJ9LCJldGFnIjoiQ0FJPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDQUk9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiZW50aXR5IjoicHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6IlJFQURFUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJ2aWV3ZXJzIn0sImV0YWciOiJDQUk9In1dLCJvd25lciI6eyJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSJ9LCJsb2NhdGlvbiI6IlVTIiwicmV0ZW50aW9uUG9saWN5Ijp7InJldGVudGlvblBlcmlvZCI6IjkwMDAwIiwiZWZmZWN0aXZlVGltZSI6IjIwMTgtMDktMTlUMDE6Mjk6MTAuOTkyWiIsImlzTG9ja2VkIjp0cnVlfSwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJldGFnIjoiQ0FJPSJ9LHsia2luZCI6InN0b3JhZ2UjYnVja2V0IiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE5LTUxODMzNTA5MzYwMDAtMDAxOCIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTktNTE4MzM1MDkzNjAwMC0wMDE4IiwicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwibmFtZSI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTktNTE4MzM1MDkzNjAwMC0wMDE4IiwidGltZUNyZWF0ZWQiOiIyMDE4LTA5LTE5VDAxOjI5OjE1LjUwMloiLCJ1cGRhdGVkIjoiMjAxOC0wOS0xOVQwMToyOToxNS41MDJaIiwibWV0YWdlbmVyYXRpb24iOiIxIiwiYWNsIjpbeyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE5LTUxODMzNTA5MzYwMDAtMDAxOC9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTktNTE4MzM1MDkzNjAwMC0wMDE4L2FjbC9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTktNTE4MzM1MDkzNjAwMC0wMDE4IiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDQUU9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE5LTUxODMzNTA5MzYwMDAtMDAxOC9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE5LTUxODMzNTA5MzYwMDAtMDAxOC9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOS01MTgzMzUwOTM2MDAwLTAwMTgiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0FFPSJ9LHsia2luZCI6InN0b3JhZ2UjYnVja2V0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOS01MTgzMzUwOTM2MDAwLTAwMTgvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOS01MTgzMzUwOTM2MDAwLTAwMTgvYWNsL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTktNTE4MzM1MDkzNjAwMC0wMDE4IiwiZW50aXR5IjoicHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6IlJFQURFUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJ2aWV3ZXJzIn0sImV0YWciOiJDQUU9In1dLCJkZWZhdWx0T2JqZWN0QWNsIjpbeyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiZW50aXR5IjoicHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6ImVkaXRvcnMifSwiZXRhZyI6IkNBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNBRT0ifV0sIm93bmVyIjp7ImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1In0sImxvY2F0aW9uIjoiVVMiLCJyZXRlbnRpb25Qb2xpY3kiOnsicmV0ZW50aW9uUGVyaW9kIjoiOTAwMDAiLCJlZmZlY3RpdmVUaW1lIjoiMjAxOC0wOS0xOVQwMToyOToxNS41MDJaIn0sInN0b3JhZ2VDbGFzcyI6IlNUQU5EQVJEIiwiZXRhZyI6IkNBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOS03NDI0NjMxNjM4ODAwMC0wMDAxIiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOS03NDI0NjMxNjM4ODAwMC0wMDAxIiwicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwibmFtZSI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTktNzQyNDYzMTYzODgwMDAtMDAwMSIsInRpbWVDcmVhdGVkIjoiMjAxOC0wOS0xOVQyMDozNzoyOC4wODVaIiwidXBkYXRlZCI6IjIwMTgtMDktMTlUMjA6Mzc6MjguMDg1WiIsIm1ldGFnZW5lcmF0aW9uIjoiMSIsImFjbCI6W3sia2luZCI6InN0b3JhZ2UjYnVja2V0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOS03NDI0NjMxNjM4ODAwMC0wMDAxL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOS03NDI0NjMxNjM4ODAwMC0wMDAxL2FjbC9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTktNzQyNDYzMTYzODgwMDAtMDAwMSIsImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6Im93bmVycyJ9LCJldGFnIjoiQ0FFPSJ9LHsia2luZCI6InN0b3JhZ2UjYnVja2V0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOS03NDI0NjMxNjM4ODAwMC0wMDAxL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTktNzQyNDYzMTYzODgwMDAtMDAwMS9hY2wvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOS03NDI0NjMxNjM4ODAwMC0wMDAxIiwiZW50aXR5IjoicHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6ImVkaXRvcnMifSwiZXRhZyI6IkNBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTktNzQyNDYzMTYzODgwMDAtMDAwMS9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE5LTc0MjQ2MzE2Mzg4MDAwLTAwMDEvYWNsL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTktNzQyNDYzMTYzODgwMDAtMDAwMSIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0FFPSJ9XSwiZGVmYXVsdE9iamVjdEFjbCI6W3sia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6Im93bmVycyJ9LCJldGFnIjoiQ0FFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDQUU9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiZW50aXR5IjoicHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6IlJFQURFUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJ2aWV3ZXJzIn0sImV0YWciOiJDQUU9In1dLCJvd25lciI6eyJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSJ9LCJsb2NhdGlvbiI6IlVTIiwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJldGFnIjoiQ0FFPSJ9LHsia2luZCI6InN0b3JhZ2UjYnVja2V0IiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE5LTc0MjQ2MzE2Mzg4MDAwLTAwMDIiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE5LTc0MjQ2MzE2Mzg4MDAwLTAwMDIiLCJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJuYW1lIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOS03NDI0NjMxNjM4ODAwMC0wMDAyIiwidGltZUNyZWF0ZWQiOiIyMDE4LTA5LTE5VDIwOjM3OjI5LjM4NFoiLCJ1cGRhdGVkIjoiMjAxOC0wOS0xOVQyMDozNzozMi41NzdaIiwibWV0YWdlbmVyYXRpb24iOiIyIiwiYWNsIjpbeyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE5LTc0MjQ2MzE2Mzg4MDAwLTAwMDIvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE5LTc0MjQ2MzE2Mzg4MDAwLTAwMDIvYWNsL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOS03NDI0NjMxNjM4ODAwMC0wMDAyIiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDQUk9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE5LTc0MjQ2MzE2Mzg4MDAwLTAwMDIvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOS03NDI0NjMxNjM4ODAwMC0wMDAyL2FjbC9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE5LTc0MjQ2MzE2Mzg4MDAwLTAwMDIiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0FJPSJ9LHsia2luZCI6InN0b3JhZ2UjYnVja2V0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOS03NDI0NjMxNjM4ODAwMC0wMDAyL3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTktNzQyNDYzMTYzODgwMDAtMDAwMi9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOS03NDI0NjMxNjM4ODAwMC0wMDAyIiwiZW50aXR5IjoicHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6IlJFQURFUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJ2aWV3ZXJzIn0sImV0YWciOiJDQUk9In1dLCJkZWZhdWx0T2JqZWN0QWNsIjpbeyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDQUk9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiZW50aXR5IjoicHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6ImVkaXRvcnMifSwiZXRhZyI6IkNBST0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNBST0ifV0sIm93bmVyIjp7ImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1In0sImxvY2F0aW9uIjoiVVMiLCJyZXRlbnRpb25Qb2xpY3kiOnsicmV0ZW50aW9uUGVyaW9kIjoiOTAwMDAiLCJlZmZlY3RpdmVUaW1lIjoiMjAxOC0wOS0xOVQyMDozNzoyOS4zODRaIiwiaXNMb2NrZWQiOnRydWV9LCJzdG9yYWdlQ2xhc3MiOiJTVEFOREFSRCIsImV0YWciOiJDQUk9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTktNzQyNDYzMTYzODgwMDAtMDAwMyIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTktNzQyNDYzMTYzODgwMDAtMDAwMyIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE5LTc0MjQ2MzE2Mzg4MDAwLTAwMDMiLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMTlUMjA6Mzc6MzYuMzg1WiIsInVwZGF0ZWQiOiIyMDE4LTA5LTE5VDIwOjM3OjM2LjM4NVoiLCJtZXRhZ2VuZXJhdGlvbiI6IjEiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTktNzQyNDYzMTYzODgwMDAtMDAwMy9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTktNzQyNDYzMTYzODgwMDAtMDAwMy9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE5LTc0MjQ2MzE2Mzg4MDAwLTAwMDMiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTktNzQyNDYzMTYzODgwMDAtMDAwMy9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE5LTc0MjQ2MzE2Mzg4MDAwLTAwMDMvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTktNzQyNDYzMTYzODgwMDAtMDAwMyIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDQUU9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE5LTc0MjQ2MzE2Mzg4MDAwLTAwMDMvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOS03NDI0NjMxNjM4ODAwMC0wMDAzL2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE5LTc0MjQ2MzE2Mzg4MDAwLTAwMDMiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNBRT0ifV0sImRlZmF1bHRPYmplY3RBY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0FFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0FFPSJ9XSwib3duZXIiOnsiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUifSwibG9jYXRpb24iOiJVUyIsInJldGVudGlvblBvbGljeSI6eyJyZXRlbnRpb25QZXJpb2QiOiI5MDAwMCIsImVmZmVjdGl2ZVRpbWUiOiIyMDE4LTA5LTE5VDIwOjM3OjM2LjM4NVoifSwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJldGFnIjoiQ0FFPSJ9LHsia2luZCI6InN0b3JhZ2UjYnVja2V0IiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE5LTgwMDg2MTI0OTA4MDAwLTAwMTciLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE5LTgwMDg2MTI0OTA4MDAwLTAwMTciLCJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJuYW1lIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOS04MDA4NjEyNDkwODAwMC0wMDE3IiwidGltZUNyZWF0ZWQiOiIyMDE4LTA5LTE5VDIyOjE3OjExLjc5MFoiLCJ1cGRhdGVkIjoiMjAxOC0wOS0xOVQyMjoxNzoxMy40NDZaIiwibWV0YWdlbmVyYXRpb24iOiIyIiwiYWNsIjpbeyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE5LTgwMDg2MTI0OTA4MDAwLTAwMTcvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE5LTgwMDg2MTI0OTA4MDAwLTAwMTcvYWNsL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOS04MDA4NjEyNDkwODAwMC0wMDE3IiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDQUk9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE5LTgwMDg2MTI0OTA4MDAwLTAwMTcvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOS04MDA4NjEyNDkwODAwMC0wMDE3L2FjbC9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE5LTgwMDg2MTI0OTA4MDAwLTAwMTciLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0FJPSJ9LHsia2luZCI6InN0b3JhZ2UjYnVja2V0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOS04MDA4NjEyNDkwODAwMC0wMDE3L3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTktODAwODYxMjQ5MDgwMDAtMDAxNy9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOS04MDA4NjEyNDkwODAwMC0wMDE3IiwiZW50aXR5IjoicHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6IlJFQURFUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJ2aWV3ZXJzIn0sImV0YWciOiJDQUk9In1dLCJkZWZhdWx0T2JqZWN0QWNsIjpbeyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDQUk9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiZW50aXR5IjoicHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6ImVkaXRvcnMifSwiZXRhZyI6IkNBST0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNBST0ifV0sIm93bmVyIjp7ImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1In0sImxvY2F0aW9uIjoiVVMiLCJyZXRlbnRpb25Qb2xpY3kiOnsicmV0ZW50aW9uUGVyaW9kIjoiOTAwMDAiLCJlZmZlY3RpdmVUaW1lIjoiMjAxOC0wOS0xOVQyMjoxNzoxMS43OTBaIiwiaXNMb2NrZWQiOnRydWV9LCJzdG9yYWdlQ2xhc3MiOiJTVEFOREFSRCIsImV0YWciOiJDQUk9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTktODAwODYxMjQ5MDgwMDAtMDAxOCIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTktODAwODYxMjQ5MDgwMDAtMDAxOCIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE5LTgwMDg2MTI0OTA4MDAwLTAwMTgiLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMTlUMjI6MTc6MTUuNDkzWiIsInVwZGF0ZWQiOiIyMDE4LTA5LTE5VDIyOjE3OjE1LjQ5M1oiLCJtZXRhZ2VuZXJhdGlvbiI6IjEiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTktODAwODYxMjQ5MDgwMDAtMDAxOC9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTktODAwODYxMjQ5MDgwMDAtMDAxOC9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE5LTgwMDg2MTI0OTA4MDAwLTAwMTgiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTktODAwODYxMjQ5MDgwMDAtMDAxOC9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE5LTgwMDg2MTI0OTA4MDAwLTAwMTgvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTktODAwODYxMjQ5MDgwMDAtMDAxOCIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDQUU9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE5LTgwMDg2MTI0OTA4MDAwLTAwMTgvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOS04MDA4NjEyNDkwODAwMC0wMDE4L2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE5LTgwMDg2MTI0OTA4MDAwLTAwMTgiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNBRT0ifV0sImRlZmF1bHRPYmplY3RBY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0FFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0FFPSJ9XSwib3duZXIiOnsiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUifSwibG9jYXRpb24iOiJVUyIsInJldGVudGlvblBvbGljeSI6eyJyZXRlbnRpb25QZXJpb2QiOiI5MDAwMCIsImVmZmVjdGl2ZVRpbWUiOiIyMDE4LTA5LTE5VDIyOjE3OjE1LjQ5M1oifSwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJldGFnIjoiQ0FFPSJ9LHsia2luZCI6InN0b3JhZ2UjYnVja2V0IiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTIwLTUzMzQ2MjQyMDU2NTQxLTAwMTciLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTIwLTUzMzQ2MjQyMDU2NTQxLTAwMTciLCJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJuYW1lIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyMC01MzM0NjI0MjA1NjU0MS0wMDE3IiwidGltZUNyZWF0ZWQiOiIyMDE4LTA5LTIwVDE0OjUyOjQ1LjU4NloiLCJ1cGRhdGVkIjoiMjAxOC0wOS0yMFQxNDo1Mjo0OC4xMjJaIiwibWV0YWdlbmVyYXRpb24iOiIyIiwiYWNsIjpbeyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTIwLTUzMzQ2MjQyMDU2NTQxLTAwMTcvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTIwLTUzMzQ2MjQyMDU2NTQxLTAwMTcvYWNsL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyMC01MzM0NjI0MjA1NjU0MS0wMDE3IiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDQUk9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTIwLTUzMzQ2MjQyMDU2NTQxLTAwMTcvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyMC01MzM0NjI0MjA1NjU0MS0wMDE3L2FjbC9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTIwLTUzMzQ2MjQyMDU2NTQxLTAwMTciLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0FJPSJ9LHsia2luZCI6InN0b3JhZ2UjYnVja2V0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyMC01MzM0NjI0MjA1NjU0MS0wMDE3L3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjAtNTMzNDYyNDIwNTY1NDEtMDAxNy9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyMC01MzM0NjI0MjA1NjU0MS0wMDE3IiwiZW50aXR5IjoicHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6IlJFQURFUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJ2aWV3ZXJzIn0sImV0YWciOiJDQUk9In1dLCJkZWZhdWx0T2JqZWN0QWNsIjpbeyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDQUk9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiZW50aXR5IjoicHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6ImVkaXRvcnMifSwiZXRhZyI6IkNBST0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNBST0ifV0sIm93bmVyIjp7ImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1In0sImxvY2F0aW9uIjoiVVMiLCJyZXRlbnRpb25Qb2xpY3kiOnsicmV0ZW50aW9uUGVyaW9kIjoiOTAwMDAiLCJlZmZlY3RpdmVUaW1lIjoiMjAxOC0wOS0yMFQxNDo1Mjo0NS41ODZaIiwiaXNMb2NrZWQiOnRydWV9LCJzdG9yYWdlQ2xhc3MiOiJTVEFOREFSRCIsImV0YWciOiJDQUk9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjAtNTMzNDYyNDIwNTY1NDEtMDAxOCIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjAtNTMzNDYyNDIwNTY1NDEtMDAxOCIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTIwLTUzMzQ2MjQyMDU2NTQxLTAwMTgiLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjBUMTQ6NTI6NTEuNjQ5WiIsInVwZGF0ZWQiOiIyMDE4LTA5LTIwVDE0OjUyOjUxLjY0OVoiLCJtZXRhZ2VuZXJhdGlvbiI6IjEiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjAtNTMzNDYyNDIwNTY1NDEtMDAxOC9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjAtNTMzNDYyNDIwNTY1NDEtMDAxOC9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTIwLTUzMzQ2MjQyMDU2NTQxLTAwMTgiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjAtNTMzNDYyNDIwNTY1NDEtMDAxOC9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTIwLTUzMzQ2MjQyMDU2NTQxLTAwMTgvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjAtNTMzNDYyNDIwNTY1NDEtMDAxOCIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDQUU9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTIwLTUzMzQ2MjQyMDU2NTQxLTAwMTgvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyMC01MzM0NjI0MjA1NjU0MS0wMDE4L2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTIwLTUzMzQ2MjQyMDU2NTQxLTAwMTgiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNBRT0ifV0sImRlZmF1bHRPYmplY3RBY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0FFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0FFPSJ9XSwib3duZXIiOnsiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUifSwibG9jYXRpb24iOiJVUyIsInJldGVudGlvblBvbGljeSI6eyJyZXRlbnRpb25QZXJpb2QiOiI5MDAwMCIsImVmZmVjdGl2ZVRpbWUiOiIyMDE4LTA5LTIwVDE0OjUyOjUxLjY0OVoifSwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJldGFnIjoiQ0FFPSJ9LHsia2luZCI6InN0b3JhZ2UjYnVja2V0IiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTIwLTU0MDE5NjI4NDM5MDIyLTAwMTciLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTIwLTU0MDE5NjI4NDM5MDIyLTAwMTciLCJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJuYW1lIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyMC01NDAxOTYyODQzOTAyMi0wMDE3IiwidGltZUNyZWF0ZWQiOiIyMDE4LTA5LTIwVDE1OjAyOjQ2LjE3MFoiLCJ1cGRhdGVkIjoiMjAxOC0wOS0yMFQxNTowMjo0OC40NDFaIiwibWV0YWdlbmVyYXRpb24iOiIyIiwiYWNsIjpbeyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTIwLTU0MDE5NjI4NDM5MDIyLTAwMTcvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTIwLTU0MDE5NjI4NDM5MDIyLTAwMTcvYWNsL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyMC01NDAxOTYyODQzOTAyMi0wMDE3IiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDQUk9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTIwLTU0MDE5NjI4NDM5MDIyLTAwMTcvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyMC01NDAxOTYyODQzOTAyMi0wMDE3L2FjbC9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTIwLTU0MDE5NjI4NDM5MDIyLTAwMTciLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0FJPSJ9LHsia2luZCI6InN0b3JhZ2UjYnVja2V0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyMC01NDAxOTYyODQzOTAyMi0wMDE3L3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjAtNTQwMTk2Mjg0MzkwMjItMDAxNy9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyMC01NDAxOTYyODQzOTAyMi0wMDE3IiwiZW50aXR5IjoicHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6IlJFQURFUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJ2aWV3ZXJzIn0sImV0YWciOiJDQUk9In1dLCJkZWZhdWx0T2JqZWN0QWNsIjpbeyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDQUk9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiZW50aXR5IjoicHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6ImVkaXRvcnMifSwiZXRhZyI6IkNBST0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNBST0ifV0sIm93bmVyIjp7ImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1In0sImxvY2F0aW9uIjoiVVMiLCJyZXRlbnRpb25Qb2xpY3kiOnsicmV0ZW50aW9uUGVyaW9kIjoiOTAwMDAiLCJlZmZlY3RpdmVUaW1lIjoiMjAxOC0wOS0yMFQxNTowMjo0Ni4xNzBaIiwiaXNMb2NrZWQiOnRydWV9LCJzdG9yYWdlQ2xhc3MiOiJTVEFOREFSRCIsImV0YWciOiJDQUk9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjAtNTQwMTk2Mjg0MzkwMjItMDAxOCIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjAtNTQwMTk2Mjg0MzkwMjItMDAxOCIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTIwLTU0MDE5NjI4NDM5MDIyLTAwMTgiLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjBUMTU6MDI6NTEuMDg3WiIsInVwZGF0ZWQiOiIyMDE4LTA5LTIwVDE1OjAyOjUxLjA4N1oiLCJtZXRhZ2VuZXJhdGlvbiI6IjEiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjAtNTQwMTk2Mjg0MzkwMjItMDAxOC9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjAtNTQwMTk2Mjg0MzkwMjItMDAxOC9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTIwLTU0MDE5NjI4NDM5MDIyLTAwMTgiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjAtNTQwMTk2Mjg0MzkwMjItMDAxOC9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTIwLTU0MDE5NjI4NDM5MDIyLTAwMTgvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjAtNTQwMTk2Mjg0MzkwMjItMDAxOCIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDQUU9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTIwLTU0MDE5NjI4NDM5MDIyLTAwMTgvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyMC01NDAxOTYyODQzOTAyMi0wMDE4L2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTIwLTU0MDE5NjI4NDM5MDIyLTAwMTgiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNBRT0ifV0sImRlZmF1bHRPYmplY3RBY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0FFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0FFPSJ9XSwib3duZXIiOnsiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUifSwibG9jYXRpb24iOiJVUyIsInJldGVudGlvblBvbGljeSI6eyJyZXRlbnRpb25QZXJpb2QiOiI5MDAwMCIsImVmZmVjdGl2ZVRpbWUiOiIyMDE4LTA5LTIwVDE1OjAyOjUxLjA4N1oifSwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJldGFnIjoiQ0FFPSJ9LHsia2luZCI6InN0b3JhZ2UjYnVja2V0IiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTIwLTU0NzE1NjE3NzI2NzAyLTAwMTciLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTIwLTU0NzE1NjE3NzI2NzAyLTAwMTciLCJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJuYW1lIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyMC01NDcxNTYxNzcyNjcwMi0wMDE3IiwidGltZUNyZWF0ZWQiOiIyMDE4LTA5LTIwVDE1OjE0OjI2Ljk1NVoiLCJ1cGRhdGVkIjoiMjAxOC0wOS0yMFQxNToxNDoyOS4xMjZaIiwibWV0YWdlbmVyYXRpb24iOiIyIiwiYWNsIjpbeyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTIwLTU0NzE1NjE3NzI2NzAyLTAwMTcvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTIwLTU0NzE1NjE3NzI2NzAyLTAwMTcvYWNsL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyMC01NDcxNTYxNzcyNjcwMi0wMDE3IiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDQUk9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTIwLTU0NzE1NjE3NzI2NzAyLTAwMTcvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyMC01NDcxNTYxNzcyNjcwMi0wMDE3L2FjbC9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTIwLTU0NzE1NjE3NzI2NzAyLTAwMTciLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0FJPSJ9LHsia2luZCI6InN0b3JhZ2UjYnVja2V0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyMC01NDcxNTYxNzcyNjcwMi0wMDE3L3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjAtNTQ3MTU2MTc3MjY3MDItMDAxNy9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyMC01NDcxNTYxNzcyNjcwMi0wMDE3IiwiZW50aXR5IjoicHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6IlJFQURFUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJ2aWV3ZXJzIn0sImV0YWciOiJDQUk9In1dLCJkZWZhdWx0T2JqZWN0QWNsIjpbeyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDQUk9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiZW50aXR5IjoicHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6ImVkaXRvcnMifSwiZXRhZyI6IkNBST0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNBST0ifV0sIm93bmVyIjp7ImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1In0sImxvY2F0aW9uIjoiVVMiLCJyZXRlbnRpb25Qb2xpY3kiOnsicmV0ZW50aW9uUGVyaW9kIjoiOTAwMDAiLCJlZmZlY3RpdmVUaW1lIjoiMjAxOC0wOS0yMFQxNToxNDoyNi45NTVaIiwiaXNMb2NrZWQiOnRydWV9LCJzdG9yYWdlQ2xhc3MiOiJTVEFOREFSRCIsImV0YWciOiJDQUk9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjAtNTQ3MTU2MTc3MjY3MDItMDAxOCIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjAtNTQ3MTU2MTc3MjY3MDItMDAxOCIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTIwLTU0NzE1NjE3NzI2NzAyLTAwMTgiLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjBUMTU6MTQ6MzEuNjAxWiIsInVwZGF0ZWQiOiIyMDE4LTA5LTIwVDE1OjE0OjMxLjYwMVoiLCJtZXRhZ2VuZXJhdGlvbiI6IjEiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjAtNTQ3MTU2MTc3MjY3MDItMDAxOC9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjAtNTQ3MTU2MTc3MjY3MDItMDAxOC9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTIwLTU0NzE1NjE3NzI2NzAyLTAwMTgiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjAtNTQ3MTU2MTc3MjY3MDItMDAxOC9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTIwLTU0NzE1NjE3NzI2NzAyLTAwMTgvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjAtNTQ3MTU2MTc3MjY3MDItMDAxOCIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDQUU9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTIwLTU0NzE1NjE3NzI2NzAyLTAwMTgvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyMC01NDcxNTYxNzcyNjcwMi0wMDE4L2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTIwLTU0NzE1NjE3NzI2NzAyLTAwMTgiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNBRT0ifV0sImRlZmF1bHRPYmplY3RBY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0FFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0FFPSJ9XSwib3duZXIiOnsiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUifSwibG9jYXRpb24iOiJVUyIsInJldGVudGlvblBvbGljeSI6eyJyZXRlbnRpb25QZXJpb2QiOiI5MDAwMCIsImVmZmVjdGl2ZVRpbWUiOiIyMDE4LTA5LTIwVDE1OjE0OjMxLjYwMVoifSwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJldGFnIjoiQ0FFPSJ9LHsia2luZCI6InN0b3JhZ2UjYnVja2V0IiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTIwLTU1MzkxMTkyMjU2ODk2LTAwMTciLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTIwLTU1MzkxMTkyMjU2ODk2LTAwMTciLCJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJuYW1lIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyMC01NTM5MTE5MjI1Njg5Ni0wMDE3IiwidGltZUNyZWF0ZWQiOiIyMDE4LTA5LTIwVDE1OjI1OjMyLjk4N1oiLCJ1cGRhdGVkIjoiMjAxOC0wOS0yMFQxNToyNTozNC44MzRaIiwibWV0YWdlbmVyYXRpb24iOiIyIiwiYWNsIjpbeyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTIwLTU1MzkxMTkyMjU2ODk2LTAwMTcvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTIwLTU1MzkxMTkyMjU2ODk2LTAwMTcvYWNsL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyMC01NTM5MTE5MjI1Njg5Ni0wMDE3IiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDQUk9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTIwLTU1MzkxMTkyMjU2ODk2LTAwMTcvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyMC01NTM5MTE5MjI1Njg5Ni0wMDE3L2FjbC9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTIwLTU1MzkxMTkyMjU2ODk2LTAwMTciLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0FJPSJ9LHsia2luZCI6InN0b3JhZ2UjYnVja2V0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyMC01NTM5MTE5MjI1Njg5Ni0wMDE3L3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjAtNTUzOTExOTIyNTY4OTYtMDAxNy9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyMC01NTM5MTE5MjI1Njg5Ni0wMDE3IiwiZW50aXR5IjoicHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6IlJFQURFUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJ2aWV3ZXJzIn0sImV0YWciOiJDQUk9In1dLCJkZWZhdWx0T2JqZWN0QWNsIjpbeyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDQUk9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiZW50aXR5IjoicHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6ImVkaXRvcnMifSwiZXRhZyI6IkNBST0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNBST0ifV0sIm93bmVyIjp7ImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1In0sImxvY2F0aW9uIjoiVVMiLCJyZXRlbnRpb25Qb2xpY3kiOnsicmV0ZW50aW9uUGVyaW9kIjoiOTAwMDAiLCJlZmZlY3RpdmVUaW1lIjoiMjAxOC0wOS0yMFQxNToyNTozMi45ODdaIiwiaXNMb2NrZWQiOnRydWV9LCJzdG9yYWdlQ2xhc3MiOiJTVEFOREFSRCIsImV0YWciOiJDQUk9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjAtNTUzOTExOTIyNTY4OTYtMDAxOCIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjAtNTUzOTExOTIyNTY4OTYtMDAxOCIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTIwLTU1MzkxMTkyMjU2ODk2LTAwMTgiLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjBUMTU6MjU6MzcuMzU3WiIsInVwZGF0ZWQiOiIyMDE4LTA5LTIwVDE1OjI1OjM3LjM1N1oiLCJtZXRhZ2VuZXJhdGlvbiI6IjEiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjAtNTUzOTExOTIyNTY4OTYtMDAxOC9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjAtNTUzOTExOTIyNTY4OTYtMDAxOC9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTIwLTU1MzkxMTkyMjU2ODk2LTAwMTgiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjAtNTUzOTExOTIyNTY4OTYtMDAxOC9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTIwLTU1MzkxMTkyMjU2ODk2LTAwMTgvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjAtNTUzOTExOTIyNTY4OTYtMDAxOCIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDQUU9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTIwLTU1MzkxMTkyMjU2ODk2LTAwMTgvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyMC01NTM5MTE5MjI1Njg5Ni0wMDE4L2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTIwLTU1MzkxMTkyMjU2ODk2LTAwMTgiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNBRT0ifV0sImRlZmF1bHRPYmplY3RBY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0FFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0FFPSJ9XSwib3duZXIiOnsiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUifSwibG9jYXRpb24iOiJVUyIsInJldGVudGlvblBvbGljeSI6eyJyZXRlbnRpb25QZXJpb2QiOiI5MDAwMCIsImVmZmVjdGl2ZVRpbWUiOiIyMDE4LTA5LTIwVDE1OjI1OjM3LjM1N1oifSwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJldGFnIjoiQ0FFPSJ9LHsia2luZCI6InN0b3JhZ2UjYnVja2V0IiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTIwLTU1OTkzMDU4NzAzNTE2LTAwMTciLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTIwLTU1OTkzMDU4NzAzNTE2LTAwMTciLCJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJuYW1lIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyMC01NTk5MzA1ODcwMzUxNi0wMDE3IiwidGltZUNyZWF0ZWQiOiIyMDE4LTA5LTIwVDE1OjM1OjM4LjYwN1oiLCJ1cGRhdGVkIjoiMjAxOC0wOS0yMFQxNTozNTo0MC43MzVaIiwibWV0YWdlbmVyYXRpb24iOiIyIiwiYWNsIjpbeyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTIwLTU1OTkzMDU4NzAzNTE2LTAwMTcvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTIwLTU1OTkzMDU4NzAzNTE2LTAwMTcvYWNsL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyMC01NTk5MzA1ODcwMzUxNi0wMDE3IiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDQUk9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTIwLTU1OTkzMDU4NzAzNTE2LTAwMTcvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyMC01NTk5MzA1ODcwMzUxNi0wMDE3L2FjbC9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTIwLTU1OTkzMDU4NzAzNTE2LTAwMTciLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0FJPSJ9LHsia2luZCI6InN0b3JhZ2UjYnVja2V0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyMC01NTk5MzA1ODcwMzUxNi0wMDE3L3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjAtNTU5OTMwNTg3MDM1MTYtMDAxNy9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyMC01NTk5MzA1ODcwMzUxNi0wMDE3IiwiZW50aXR5IjoicHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6IlJFQURFUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJ2aWV3ZXJzIn0sImV0YWciOiJDQUk9In1dLCJkZWZhdWx0T2JqZWN0QWNsIjpbeyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDQUk9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiZW50aXR5IjoicHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6ImVkaXRvcnMifSwiZXRhZyI6IkNBST0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNBST0ifV0sIm93bmVyIjp7ImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1In0sImxvY2F0aW9uIjoiVVMiLCJyZXRlbnRpb25Qb2xpY3kiOnsicmV0ZW50aW9uUGVyaW9kIjoiOTAwMDAiLCJlZmZlY3RpdmVUaW1lIjoiMjAxOC0wOS0yMFQxNTozNTozOC42MDdaIiwiaXNMb2NrZWQiOnRydWV9LCJzdG9yYWdlQ2xhc3MiOiJTVEFOREFSRCIsImV0YWciOiJDQUk9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjAtNTU5OTMwNTg3MDM1MTYtMDAxOCIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjAtNTU5OTMwNTg3MDM1MTYtMDAxOCIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTIwLTU1OTkzMDU4NzAzNTE2LTAwMTgiLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjBUMTU6MzU6NDMuNDY2WiIsInVwZGF0ZWQiOiIyMDE4LTA5LTIwVDE1OjM1OjQzLjQ2NloiLCJtZXRhZ2VuZXJhdGlvbiI6IjEiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjAtNTU5OTMwNTg3MDM1MTYtMDAxOC9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjAtNTU5OTMwNTg3MDM1MTYtMDAxOC9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTIwLTU1OTkzMDU4NzAzNTE2LTAwMTgiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjAtNTU5OTMwNTg3MDM1MTYtMDAxOC9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTIwLTU1OTkzMDU4NzAzNTE2LTAwMTgvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjAtNTU5OTMwNTg3MDM1MTYtMDAxOCIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDQUU9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTIwLTU1OTkzMDU4NzAzNTE2LTAwMTgvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyMC01NTk5MzA1ODcwMzUxNi0wMDE4L2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTIwLTU1OTkzMDU4NzAzNTE2LTAwMTgiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNBRT0ifV0sImRlZmF1bHRPYmplY3RBY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0FFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0FFPSJ9XSwib3duZXIiOnsiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUifSwibG9jYXRpb24iOiJVUyIsInJldGVudGlvblBvbGljeSI6eyJyZXRlbnRpb25QZXJpb2QiOiI5MDAwMCIsImVmZmVjdGl2ZVRpbWUiOiIyMDE4LTA5LTIwVDE1OjM1OjQzLjQ2NloifSwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJldGFnIjoiQ0FFPSJ9LHsia2luZCI6InN0b3JhZ2UjYnVja2V0IiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTIwLTU2OTY2NzE5NzUxMjQzLTAwMTciLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTIwLTU2OTY2NzE5NzUxMjQzLTAwMTciLCJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJuYW1lIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyMC01Njk2NjcxOTc1MTI0My0wMDE3IiwidGltZUNyZWF0ZWQiOiIyMDE4LTA5LTIwVDE1OjUxOjUzLjQwMFoiLCJ1cGRhdGVkIjoiMjAxOC0wOS0yMFQxNTo1MTo1NS4zMjRaIiwibWV0YWdlbmVyYXRpb24iOiIyIiwiYWNsIjpbeyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTIwLTU2OTY2NzE5NzUxMjQzLTAwMTcvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTIwLTU2OTY2NzE5NzUxMjQzLTAwMTcvYWNsL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyMC01Njk2NjcxOTc1MTI0My0wMDE3IiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDQUk9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTIwLTU2OTY2NzE5NzUxMjQzLTAwMTcvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyMC01Njk2NjcxOTc1MTI0My0wMDE3L2FjbC9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTIwLTU2OTY2NzE5NzUxMjQzLTAwMTciLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0FJPSJ9LHsia2luZCI6InN0b3JhZ2UjYnVja2V0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyMC01Njk2NjcxOTc1MTI0My0wMDE3L3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjAtNTY5NjY3MTk3NTEyNDMtMDAxNy9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyMC01Njk2NjcxOTc1MTI0My0wMDE3IiwiZW50aXR5IjoicHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6IlJFQURFUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJ2aWV3ZXJzIn0sImV0YWciOiJDQUk9In1dLCJkZWZhdWx0T2JqZWN0QWNsIjpbeyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDQUk9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiZW50aXR5IjoicHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6ImVkaXRvcnMifSwiZXRhZyI6IkNBST0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNBST0ifV0sIm93bmVyIjp7ImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1In0sImxvY2F0aW9uIjoiVVMiLCJyZXRlbnRpb25Qb2xpY3kiOnsicmV0ZW50aW9uUGVyaW9kIjoiOTAwMDAiLCJlZmZlY3RpdmVUaW1lIjoiMjAxOC0wOS0yMFQxNTo1MTo1My40MDBaIiwiaXNMb2NrZWQiOnRydWV9LCJzdG9yYWdlQ2xhc3MiOiJTVEFOREFSRCIsImV0YWciOiJDQUk9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjAtNTY5NjY3MTk3NTEyNDMtMDAxOCIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjAtNTY5NjY3MTk3NTEyNDMtMDAxOCIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTIwLTU2OTY2NzE5NzUxMjQzLTAwMTgiLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjBUMTU6NTE6NTcuODAwWiIsInVwZGF0ZWQiOiIyMDE4LTA5LTIwVDE1OjUxOjU3LjgwMFoiLCJtZXRhZ2VuZXJhdGlvbiI6IjEiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjAtNTY5NjY3MTk3NTEyNDMtMDAxOC9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjAtNTY5NjY3MTk3NTEyNDMtMDAxOC9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTIwLTU2OTY2NzE5NzUxMjQzLTAwMTgiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjAtNTY5NjY3MTk3NTEyNDMtMDAxOC9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTIwLTU2OTY2NzE5NzUxMjQzLTAwMTgvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjAtNTY5NjY3MTk3NTEyNDMtMDAxOCIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDQUU9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTIwLTU2OTY2NzE5NzUxMjQzLTAwMTgvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyMC01Njk2NjcxOTc1MTI0My0wMDE4L2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTIwLTU2OTY2NzE5NzUxMjQzLTAwMTgiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNBRT0ifV0sImRlZmF1bHRPYmplY3RBY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0FFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0FFPSJ9XSwib3duZXIiOnsiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUifSwibG9jYXRpb24iOiJVUyIsInJldGVudGlvblBvbGljeSI6eyJyZXRlbnRpb25QZXJpb2QiOiI5MDAwMCIsImVmZmVjdGl2ZVRpbWUiOiIyMDE4LTA5LTIwVDE1OjUxOjU3LjgwMFoifSwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJldGFnIjoiQ0FFPSJ9LHsia2luZCI6InN0b3JhZ2UjYnVja2V0IiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTciLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTciLCJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJuYW1lIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDE3IiwidGltZUNyZWF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI2OjEzLjg4N1oiLCJ1cGRhdGVkIjoiMjAxOC0wOS0yN1QxMjoyNjoxNS45MzZaIiwibWV0YWdlbmVyYXRpb24iOiIyIiwiYWNsIjpbeyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTcvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTcvYWNsL3Byb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDE3IiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDQUk9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTcvcHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDE3L2FjbC9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTciLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0FJPSJ9LHsia2luZCI6InN0b3JhZ2UjYnVja2V0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDE3L3Byb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxNy9hY2wvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1IiwiYnVja2V0IjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDE3IiwiZW50aXR5IjoicHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6IlJFQURFUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJ2aWV3ZXJzIn0sImV0YWciOiJDQUk9In1dLCJkZWZhdWx0T2JqZWN0QWNsIjpbeyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoib3duZXJzIn0sImV0YWciOiJDQUk9In0seyJraW5kIjoic3RvcmFnZSNvYmplY3RBY2Nlc3NDb250cm9sIiwiZW50aXR5IjoicHJvamVjdC1lZGl0b3JzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6ImVkaXRvcnMifSwiZXRhZyI6IkNBST0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNBST0ifV0sIm93bmVyIjp7ImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1In0sImxvY2F0aW9uIjoiVVMiLCJyZXRlbnRpb25Qb2xpY3kiOnsicmV0ZW50aW9uUGVyaW9kIjoiOTAwMDAiLCJlZmZlY3RpdmVUaW1lIjoiMjAxOC0wOS0yN1QxMjoyNjoxMy44ODdaIiwiaXNMb2NrZWQiOnRydWV9LCJzdG9yYWdlQ2xhc3MiOiJTVEFOREFSRCIsImV0YWciOiJDQUk9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXQiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxOCIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxOCIsInByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsIm5hbWUiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTgiLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMjdUMTI6MjY6MTguMjU5WiIsInVwZGF0ZWQiOiIyMDE4LTA5LTI3VDEyOjI2OjE4LjI1OVoiLCJtZXRhZ2VuZXJhdGlvbiI6IjEiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxOC9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxOC9hY2wvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTgiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI2J1Y2tldEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxOC9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTgvYWNsL3Byb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MjctNDQ2MzA5MTE4NjM2NDAtMDAxOCIsImVudGl0eSI6InByb2plY3QtZWRpdG9ycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJlZGl0b3JzIn0sImV0YWciOiJDQUU9In0seyJraW5kIjoic3RvcmFnZSNidWNrZXRBY2Nlc3NDb250cm9sIiwiaWQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTgvcHJvamVjdC12aWV3ZXJzLTM2NjM5OTMzMTQ1Iiwic2VsZkxpbmsiOiJodHRwczovL3d3dy5nb29nbGVhcGlzLmNvbS9zdG9yYWdlL3YxL2IvZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkyNy00NDYzMDkxMTg2MzY0MC0wMDE4L2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTI3LTQ0NjMwOTExODYzNjQwLTAwMTgiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNBRT0ifV0sImRlZmF1bHRPYmplY3RBY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJPV05FUiIsInByb2plY3RUZWFtIjp7InByb2plY3ROdW1iZXIiOiIzNjYzOTkzMzE0NSIsInRlYW0iOiJvd25lcnMifSwiZXRhZyI6IkNBRT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0FFPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImVudGl0eSI6InByb2plY3Qtdmlld2Vycy0zNjYzOTkzMzE0NSIsInJvbGUiOiJSRUFERVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoidmlld2VycyJ9LCJldGFnIjoiQ0FFPSJ9XSwib3duZXIiOnsiZW50aXR5IjoicHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUifSwibG9jYXRpb24iOiJVUyIsInJldGVudGlvblBvbGljeSI6eyJyZXRlbnRpb25QZXJpb2QiOiI5MDAwMCIsImVmZmVjdGl2ZVRpbWUiOiIyMDE4LTA5LTI3VDEyOjI2OjE4LjI1OVoifSwic3RvcmFnZUNsYXNzIjoiU1RBTkRBUkQiLCJldGFnIjoiQ0FFPSJ9XX0="
+ }
+ },
+ {
+ "ID": "a4e69be0e239962d",
+ "Request": {
+ "Method": "GET",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180918-4131767318000-0002/o?alt=json\u0026delimiter=\u0026pageToken=\u0026prefix=\u0026prettyPrint=false\u0026projection=full\u0026versions=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "882c02022466c15c2d708f6ccc043bea/11684338459922450634;o=1"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180918-4131767318000-0002/o?alt=json\u0026delimiter=\u0026pageToken=\u0026prefix=\u0026prettyPrint=false\u0026projection=full\u0026versions=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 200,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0, must-revalidate, no-transform"
+ ],
+ "Content-Length": [
+ "3307"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:50 GMT"
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:26:50 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051503000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.read_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vlfx126:4091,/bns/yk/borg/yk/bns/blobstore2/bitpusher/559.scotty,acatlm7:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=icysW_ORN8GDqQW4zYjQAw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "acatlm7:443,/bns/yk/borg/yk/bns/blobstore2/bitpusher/559.scotty,acatlm7:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yk/borg/yk/bns/blobstore2/bitpusher/559:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4itK4wESxgF5YTI5LmMuRW93QkpRWU94SDhBWjdSeWVHSm16OFFSZV80RWc4RjdJOUFYemxhX1lqdU1TYkM3YkFFZ2hZY3JuVmR3ckppdUNMWlQyUXNhUWFlV01xeW1EbmRlY3EySHQ5b0ZjQmtGZDA5bk9yZTl4T3Q1Q081RXpHVkNNMGxQQjdneUR4Nm9iMWJFUlZqVTJ0QTJMX0tzMnhZZkRTaEU2cFhlTlpEMzR3Z3lJbUZXQjBUTVU0eDNvLTVFVG5Wa2VpSW9rR00wBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "success"
+ ],
+ "X-Guploader-Upload-Result": [
+ "success"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UpwEgzCXs8iMGXWCPB6Hq6LFaljM5D8sntRbfhs9lY4TSkWGfDHHRzPddyJVjVzaDcLNy8fYOr07OgVIElY_eNXzVUR9Q"
+ ]
+ },
+ "Body": "eyJraW5kIjoic3RvcmFnZSNvYmplY3RzIiwiaXRlbXMiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOC00MTMxNzY3MzE4MDAwLTAwMDIvc29tZS1vYmovMTUzNzIzMjkzMzc2Mjk1NSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTgtNDEzMTc2NzMxODAwMC0wMDAyL28vc29tZS1vYmoiLCJuYW1lIjoic29tZS1vYmoiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE4LTQxMzE3NjczMTgwMDAtMDAwMiIsImdlbmVyYXRpb24iOiIxNTM3MjMyOTMzNzYyOTU1IiwibWV0YWdlbmVyYXRpb24iOiIzIiwiY29udGVudFR5cGUiOiJmb28iLCJ0aW1lQ3JlYXRlZCI6IjIwMTgtMDktMThUMDE6MDg6NTMuNzYyWiIsInVwZGF0ZWQiOiIyMDE4LTA5LTE4VDAxOjA4OjU0LjU5MloiLCJzdG9yYWdlQ2xhc3MiOiJTVEFOREFSRCIsInRpbWVTdG9yYWdlQ2xhc3NVcGRhdGVkIjoiMjAxOC0wOS0xOFQwMTowODo1My43NjJaIiwic2l6ZSI6IjE2IiwibWQ1SGFzaCI6InJWZ0NOcVVrd1JpV3pDOUtvNUlIanc9PSIsIm1lZGlhTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL2Rvd25sb2FkL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE4LTQxMzE3NjczMTgwMDAtMDAwMi9vL3NvbWUtb2JqP2dlbmVyYXRpb249MTUzNzIzMjkzMzc2Mjk1NSZhbHQ9bWVkaWEiLCJhY2wiOlt7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTgtNDEzMTc2NzMxODAwMC0wMDAyL3NvbWUtb2JqLzE1MzcyMzI5MzM3NjI5NTUvcHJvamVjdC1vd25lcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE4LTQxMzE3NjczMTgwMDAtMDAwMi9vL3NvbWUtb2JqL2FjbC9wcm9qZWN0LW93bmVycy0zNjYzOTkzMzE0NSIsImJ1Y2tldCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTgtNDEzMTc2NzMxODAwMC0wMDAyIiwib2JqZWN0Ijoic29tZS1vYmoiLCJnZW5lcmF0aW9uIjoiMTUzNzIzMjkzMzc2Mjk1NSIsImVudGl0eSI6InByb2plY3Qtb3duZXJzLTM2NjM5OTMzMTQ1Iiwicm9sZSI6Ik9XTkVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6Im93bmVycyJ9LCJldGFnIjoiQ0l2djBQZXV3OTBDRUFNPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOC00MTMxNzY3MzE4MDAwLTAwMDIvc29tZS1vYmovMTUzNzIzMjkzMzc2Mjk1NS9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE4LTQxMzE3NjczMTgwMDAtMDAwMi9vL3NvbWUtb2JqL2FjbC9wcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE4LTQxMzE3NjczMTgwMDAtMDAwMiIsIm9iamVjdCI6InNvbWUtb2JqIiwiZ2VuZXJhdGlvbiI6IjE1MzcyMzI5MzM3NjI5NTUiLCJlbnRpdHkiOiJwcm9qZWN0LWVkaXRvcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiT1dORVIiLCJwcm9qZWN0VGVhbSI6eyJwcm9qZWN0TnVtYmVyIjoiMzY2Mzk5MzMxNDUiLCJ0ZWFtIjoiZWRpdG9ycyJ9LCJldGFnIjoiQ0l2djBQZXV3OTBDRUFNPSJ9LHsia2luZCI6InN0b3JhZ2Ujb2JqZWN0QWNjZXNzQ29udHJvbCIsImlkIjoiZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOC00MTMxNzY3MzE4MDAwLTAwMDIvc29tZS1vYmovMTUzNzIzMjkzMzc2Mjk1NS9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJzZWxmTGluayI6Imh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL3N0b3JhZ2UvdjEvYi9nby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE4LTQxMzE3NjczMTgwMDAtMDAwMi9vL3NvbWUtb2JqL2FjbC9wcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE4LTQxMzE3NjczMTgwMDAtMDAwMiIsIm9iamVjdCI6InNvbWUtb2JqIiwiZ2VuZXJhdGlvbiI6IjE1MzcyMzI5MzM3NjI5NTUiLCJlbnRpdHkiOiJwcm9qZWN0LXZpZXdlcnMtMzY2Mzk5MzMxNDUiLCJyb2xlIjoiUkVBREVSIiwicHJvamVjdFRlYW0iOnsicHJvamVjdE51bWJlciI6IjM2NjM5OTMzMTQ1IiwidGVhbSI6InZpZXdlcnMifSwiZXRhZyI6IkNJdnYwUGV1dzkwQ0VBTT0ifSx7ImtpbmQiOiJzdG9yYWdlI29iamVjdEFjY2Vzc0NvbnRyb2wiLCJpZCI6ImdvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTgtNDEzMTc2NzMxODAwMC0wMDAyL3NvbWUtb2JqLzE1MzcyMzI5MzM3NjI5NTUvdXNlci0zNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsInNlbGZMaW5rIjoiaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vc3RvcmFnZS92MS9iL2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTgtNDEzMTc2NzMxODAwMC0wMDAyL28vc29tZS1vYmovYWNsL3VzZXItMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHVAZGV2ZWxvcGVyLmdzZXJ2aWNlYWNjb3VudC5jb20iLCJidWNrZXQiOiJnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE4LTQxMzE3NjczMTgwMDAtMDAwMiIsIm9iamVjdCI6InNvbWUtb2JqIiwiZ2VuZXJhdGlvbiI6IjE1MzcyMzI5MzM3NjI5NTUiLCJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIiwicm9sZSI6Ik9XTkVSIiwiZW1haWwiOiIzNjYzOTkzMzE0NS1iMTh0MDFvbXQ5YTI3OWtjM2djZ2lxaHFrbDhib2JodUBkZXZlbG9wZXIuZ3NlcnZpY2VhY2NvdW50LmNvbSIsImV0YWciOiJDSXZ2MFBldXc5MENFQU09In1dLCJvd25lciI6eyJlbnRpdHkiOiJ1c2VyLTM2NjM5OTMzMTQ1LWIxOHQwMW9tdDlhMjc5a2MzZ2NnaXFocWtsOGJvYmh1QGRldmVsb3Blci5nc2VydmljZWFjY291bnQuY29tIn0sImNyYzMyYyI6ImdTSjJJUT09IiwiZXRhZyI6IkNJdnYwUGV1dzkwQ0VBTT0iLCJldmVudEJhc2VkSG9sZCI6dHJ1ZX1dfQ=="
+ }
+ },
+ {
+ "ID": "cf09ae4a1ba8491f",
+ "Request": {
+ "Method": "DELETE",
+ "URL": "https://www.googleapis.com/storage/v1/b/go-integration-test-20180918-4131767318000-0002/o/some-obj?alt=json\u0026prettyPrint=false",
+ "Proto": "HTTP/1.1",
+ "Header": {
+ "Accept-Encoding": [
+ "gzip"
+ ],
+ "Authorization": [
+ "REDACTED"
+ ],
+ "User-Agent": [
+ "google-api-go-client/0.5"
+ ],
+ "Via": [
+ "1.1 httpr-f4507be84cc405ed397a"
+ ],
+ "X-Cloud-Trace-Context": [
+ "d45c92e9f8b203c29533eacb69213e0a/12515712295073552922;o=1"
+ ],
+ "X-Forwarded-For": [
+ "127.0.0.1"
+ ],
+ "X-Forwarded-Host": [
+ "www.googleapis.com"
+ ],
+ "X-Forwarded-Proto": [
+ "https"
+ ],
+ "X-Forwarded-Url": [
+ "https://www.googleapis.com/storage/v1/b/go-integration-test-20180918-4131767318000-0002/o/some-obj?alt=json\u0026prettyPrint=false"
+ ],
+ "X-Goog-Api-Client": [
+ "gl-go/1.11.0-rc2 gccl/20180226"
+ ]
+ },
+ "Body": ""
+ },
+ "Response": {
+ "StatusCode": 403,
+ "Proto": "HTTP/1.1",
+ "ProtoMajor": 1,
+ "ProtoMinor": 1,
+ "Header": {
+ "Alt-Svc": [
+ "quic=\":443\"; ma=2592000; v=\"44,43,39,35\""
+ ],
+ "Cache-Control": [
+ "private, max-age=0"
+ ],
+ "Content-Length": [
+ "13398"
+ ],
+ "Content-Type": [
+ "application/json; charset=UTF-8"
+ ],
+ "Date": [
+ "Thu, 27 Sep 2018 12:26:50 GMT"
+ ],
+ "Expires": [
+ "Thu, 27 Sep 2018 12:26:50 GMT"
+ ],
+ "Server": [
+ "UploadServer"
+ ],
+ "Vary": [
+ "Origin",
+ "X-Origin"
+ ],
+ "X-Google-Apiary-Auth-Expires": [
+ "1538051504000"
+ ],
+ "X-Google-Apiary-Auth-Scopes": [
+ "https://www.googleapis.com/auth/devstorage.full_control https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/devstorage.write_only"
+ ],
+ "X-Google-Apiary-Auth-User": [
+ "998958384336"
+ ],
+ "X-Google-Backends": [
+ "vlhl7:4477,/bns/yk/borg/yk/bns/blobstore2/bitpusher/202.scotty,acatlm7:443"
+ ],
+ "X-Google-Dos-Service-Trace": [
+ "main:apps-upload-cloud-storage-unified"
+ ],
+ "X-Google-Gfe-Backend-Request-Info": [
+ "eid=isysW_KtDZPlqAXbqbOADw"
+ ],
+ "X-Google-Gfe-Request-Trace": [
+ "acatlm7:443,/bns/yk/borg/yk/bns/blobstore2/bitpusher/202.scotty,acatlm7:443"
+ ],
+ "X-Google-Gfe-Response-Code-Details-Trace": [
+ "response_code_set_by_backend"
+ ],
+ "X-Google-Gfe-Service-Trace": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Netmon-Label": [
+ "/bns/yk/borg/yk/bns/blobstore2/bitpusher/202:caf3"
+ ],
+ "X-Google-Service": [
+ "bitpusher-gcs-apiary"
+ ],
+ "X-Google-Session-Info": [
+ "CNCJvbSJHRoCGAYoATp3ChJjbG91ZC1zdG9yYWdlLXJvc3kSCGJpZ3N0b3JlGNmFpL-IASJHMzY2Mzk5MzMxNDUtYjE4dDAxb210OWEyNzlrYzNnY2dpcWhxa2w4Ym9iaHUuYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20w4Csw4Ssw4ytK4wESxgF5YTI5LmMuRW93QkpRWU94SDhBWjdSeWVHSm16OFFSZV80RWc4RjdJOUFYemxhX1lqdU1TYkM3YkFFZ2hZY3JuVmR3ckppdUNMWlQyUXNhUWFlV01xeW1EbmRlY3EySHQ5b0ZjQmtGZDA5bk9yZTl4T3Q1Q081RXpHVkNNMGxQQjdneUR4Nm9iMWJFUlZqVTJ0QTJMX0tzMnhZZkRTaEU2cFhlTlpEMzR3Z3lJbUZXQjBUTVU0eDNvLTVFVG5Wa2VpSW9rR00wBDoWTk9UX0FfUEVSU0lTVEVOVF9UT0tFTg"
+ ],
+ "X-Google-Shellfish-Status": [
+ "CA0gBEBG"
+ ],
+ "X-Guploader-Customer": [
+ "apiary_cloudstorage_metadata"
+ ],
+ "X-Guploader-Request-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Upload-Result": [
+ "agent_rejected"
+ ],
+ "X-Guploader-Uploadid": [
+ "AEnB2UpxwthGRvjv9oE6KLGMR2nM0RaOpyc3u06tE-6RseFdQnMw_wlaHX9a2iR7Z8UF6e5pAUkE-2-kKutOohrLN7o6-JFZgw"
+ ]
+ },
+ "Body": "eyJlcnJvciI6eyJlcnJvcnMiOlt7ImRvbWFpbiI6Imdsb2JhbCIsInJlYXNvbiI6ImZvcmJpZGRlbiIsIm1lc3NhZ2UiOiJPYmplY3QgJ2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTgtNDEzMTc2NzMxODAwMC0wMDAyL3NvbWUtb2JqJyBpcyB1bmRlciBhY3RpdmUgRXZlbnQtQmFzZWQgaG9sZCBhbmQgY2Fubm90IGJlIGRlbGV0ZWQsIG92ZXJ3cml0dGVuIG9yIGFyY2hpdmVkIHVudGlsIGhvbGQgaXMgcmVtb3ZlZC4iLCJkZWJ1Z0luZm8iOiJjb20uZ29vZ2xlLm5ldC5ycGMzLlJwY0V4Y2VwdGlvbjogY2xvdWQuYmlnc3RvcmUuUmVzcG9uc2VDb2RlLkVycm9yQ29kZTo6T0JKRUNUX0lTX1VOREVSX0FDVElWRV9IT0xEOiBPYmplY3QgJ2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTgtNDEzMTc2NzMxODAwMC0wMDAyL3NvbWUtb2JqJyBpcyB1bmRlciBhY3RpdmUgRXZlbnQtQmFzZWQgaG9sZCBhbmQgY2Fubm90IGJlIGRlbGV0ZWQsIG92ZXJ3cml0dGVuIG9yIGFyY2hpdmVkIHVudGlsIGhvbGQgaXMgcmVtb3ZlZC5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udG9ScGMzRXhjZXB0aW9uKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MTM1KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuRGVsZXRlT2JqZWN0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChEZWxldGVPYmplY3QuamF2YTo3Nylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5vYmplY3RzLkRlbGV0ZU9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoRGVsZXRlT2JqZWN0LmphdmE6MjMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uZnJhbWV3b3JrLlJlcXVlc3RIYW5kbGVyLmhhbmRsZShSZXF1ZXN0SGFuZGxlci5qYXZhOjI5NClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5PYmplY3RzRGVsZWdhdG9yLmRlbGV0ZShPYmplY3RzRGVsZWdhdG9yLmphdmE6MTEzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5ScGNSZWNlaXZlci5sYW1iZGEkcHJvY2Vzc1JlcXVlc3RBc3luYyQ0KFJwY1JlY2VpdmVyLmphdmE6MjAzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmlzb2xhdGlvbi5Bc3luY0V4ZWN1dG9yLmxhbWJkYSRzdWJtaXQkMChBc3luY0V4ZWN1dG9yLmphdmE6MjcyKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW5JbkNvbnRleHQoQ29udGV4dFJ1bm5hYmxlLmphdmE6NTApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlJDEucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM5KVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuQ3VycmVudENvbnRleHQucnVuSW5Db250ZXh0KEN1cnJlbnRDb250ZXh0LmphdmE6MzIwKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo3Milcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0KEdlbmVyaWNDb250ZXh0Q2FsbGJhY2suamF2YTo2NClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuKENvbnRleHRSdW5uYWJsZS5qYXZhOjM2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5FeGVjdXRvcnMkUnVubmFibGVBZGFwdGVyLmNhbGwoRXhlY3V0b3JzLmphdmE6NTExKVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5GdXR1cmVUYXNrLnJ1bihGdXR1cmVUYXNrLmphdmE6MjY2KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IucnVuV29ya2VyKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjExNDkpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvciRXb3JrZXIucnVuKFRocmVhZFBvb2xFeGVjdXRvci5qYXZhOjYyNClcblx0YXQgamF2YS5sYW5nLlRocmVhZC5ydW4oVGhyZWFkLmphdmE6NzQ4KVxuQ2F1c2VkIGJ5OiBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbjogT2JqZWN0ICdnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE4LTQxMzE3NjczMTgwMDAtMDAwMi9zb21lLW9iaicgaXMgdW5kZXIgYWN0aXZlIEV2ZW50LUJhc2VkIGhvbGQgYW5kIGNhbm5vdCBiZSBkZWxldGVkLCBvdmVyd3JpdHRlbiBvciBhcmNoaXZlZCB1bnRpbCBob2xkIGlzIHJlbW92ZWQuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93T25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjI5MClcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMSlcblx0Li4uIDE3IG1vcmVcblxuY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUuRmF1bHQ6IEltbXV0YWJsZUVycm9yRGVmaW5pdGlvbntiYXNlPUZPUkJJRERFTiwgY2F0ZWdvcnk9VVNFUl9FUlJPUiwgY2F1c2U9bnVsbCwgZGVidWdJbmZvPWNvbS5nb29nbGUubmV0LnJwYzMuUnBjRXhjZXB0aW9uOiBjbG91ZC5iaWdzdG9yZS5SZXNwb25zZUNvZGUuRXJyb3JDb2RlOjpPQkpFQ1RfSVNfVU5ERVJfQUNUSVZFX0hPTEQ6IE9iamVjdCAnZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOC00MTMxNzY3MzE4MDAwLTAwMDIvc29tZS1vYmonIGlzIHVuZGVyIGFjdGl2ZSBFdmVudC1CYXNlZCBob2xkIGFuZCBjYW5ub3QgYmUgZGVsZXRlZCwgb3ZlcndyaXR0ZW4gb3IgYXJjaGl2ZWQgdW50aWwgaG9sZCBpcyByZW1vdmVkLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5EZWxldGVPYmplY3QuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKERlbGV0ZU9iamVjdC5qYXZhOjc3KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuRGVsZXRlT2JqZWN0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChEZWxldGVPYmplY3QuamF2YToyMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLk9iamVjdHNEZWxlZ2F0b3IuZGVsZXRlKE9iamVjdHNEZWxlZ2F0b3IuamF2YToxMTMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBPYmplY3QgJ2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTgtNDEzMTc2NzMxODAwMC0wMDAyL3NvbWUtb2JqJyBpcyB1bmRlciBhY3RpdmUgRXZlbnQtQmFzZWQgaG9sZCBhbmQgY2Fubm90IGJlIGRlbGV0ZWQsIG92ZXJ3cml0dGVuIG9yIGFyY2hpdmVkIHVudGlsIGhvbGQgaXMgcmVtb3ZlZC5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MjkwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAxKVxuXHQuLi4gMTcgbW9yZVxuLCBkb21haW49Z2xvYmFsLCBleHRlbmRlZEhlbHA9bnVsbCwgaHR0cEhlYWRlcnM9e30sIGh0dHBTdGF0dXM9Zm9yYmlkZGVuLCBpbnRlcm5hbFJlYXNvbj1SZWFzb257YXJndW1lbnRzPXt9LCBjYXVzZT1udWxsLCBjb2RlPWdkYXRhLkNvcmVFcnJvckRvbWFpbi5GT1JCSURERU4sIGNyZWF0ZWRCeUJhY2tlbmQ9dHJ1ZSwgZGVidWdNZXNzYWdlPWNvbS5nb29nbGUubmV0LnJwYzMuUnBjRXhjZXB0aW9uOiBjbG91ZC5iaWdzdG9yZS5SZXNwb25zZUNvZGUuRXJyb3JDb2RlOjpPQkpFQ1RfSVNfVU5ERVJfQUNUSVZFX0hPTEQ6IE9iamVjdCAnZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOC00MTMxNzY3MzE4MDAwLTAwMDIvc29tZS1vYmonIGlzIHVuZGVyIGFjdGl2ZSBFdmVudC1CYXNlZCBob2xkIGFuZCBjYW5ub3QgYmUgZGVsZXRlZCwgb3ZlcndyaXR0ZW4gb3IgYXJjaGl2ZWQgdW50aWwgaG9sZCBpcyByZW1vdmVkLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50b1JwYzNFeGNlcHRpb24oQmlnc3RvcmVFeGNlcHRpb24uamF2YToxMzUpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5EZWxldGVPYmplY3QuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKERlbGV0ZU9iamVjdC5qYXZhOjc3KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmhhbmRsZXJzLm9iamVjdHMuRGVsZXRlT2JqZWN0LmhhbmRsZVJlcXVlc3RSZWNlaXZlZChEZWxldGVPYmplY3QuamF2YToyMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5mcmFtZXdvcmsuUmVxdWVzdEhhbmRsZXIuaGFuZGxlKFJlcXVlc3RIYW5kbGVyLmphdmE6Mjk0KVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLk9iamVjdHNEZWxlZ2F0b3IuZGVsZXRlKE9iamVjdHNEZWxlZ2F0b3IuamF2YToxMTMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLlJwY1JlY2VpdmVyLmxhbWJkYSRwcm9jZXNzUmVxdWVzdEFzeW5jJDQoUnBjUmVjZWl2ZXIuamF2YToyMDMpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuaXNvbGF0aW9uLkFzeW5jRXhlY3V0b3IubGFtYmRhJHN1Ym1pdCQwKEFzeW5jRXhlY3V0b3IuamF2YToyNzIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bkluQ29udGV4dChDb250ZXh0UnVubmFibGUuamF2YTo1MClcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUkMS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzkpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dE5vVW5yZWYoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjcyKVxuXHRhdCBjb20uZ29vZ2xlLnRyYWNpbmcuR2VuZXJpY0NvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHQoR2VuZXJpY0NvbnRleHRDYWxsYmFjay5qYXZhOjY0KVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZS5ydW4oQ29udGV4dFJ1bm5hYmxlLmphdmE6MzYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkV4ZWN1dG9ycyRSdW5uYWJsZUFkYXB0ZXIuY2FsbChFeGVjdXRvcnMuamF2YTo1MTEpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LkZ1dHVyZVRhc2sucnVuKEZ1dHVyZVRhc2suamF2YToyNjYpXG5cdGF0IGphdmEudXRpbC5jb25jdXJyZW50LlRocmVhZFBvb2xFeGVjdXRvci5ydW5Xb3JrZXIoVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6MTE0OSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yJFdvcmtlci5ydW4oVGhyZWFkUG9vbEV4ZWN1dG9yLmphdmE6NjI0KVxuXHRhdCBqYXZhLmxhbmcuVGhyZWFkLnJ1bihUaHJlYWQuamF2YTo3NDgpXG5DYXVzZWQgYnk6IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uOiBPYmplY3QgJ2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTgtNDEzMTc2NzMxODAwMC0wMDAyL3NvbWUtb2JqJyBpcyB1bmRlciBhY3RpdmUgRXZlbnQtQmFzZWQgaG9sZCBhbmQgY2Fubm90IGJlIGRlbGV0ZWQsIG92ZXJ3cml0dGVuIG9yIGFyY2hpdmVkIHVudGlsIGhvbGQgaXMgcmVtb3ZlZC5cblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MjkwKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd1JwYzNPbkVycm9yKEJpZ3N0b3JlRXhjZXB0aW9uLmphdmE6MzAxKVxuXHQuLi4gMTcgbW9yZVxuLCBlcnJvclByb3RvQ29kZT1GT1JCSURERU4sIGVycm9yUHJvdG9Eb21haW49Z2RhdGEuQ29yZUVycm9yRG9tYWluLCBmaWx0ZXJlZE1lc3NhZ2U9bnVsbCwgbG9jYXRpb249bnVsbCwgbWVzc2FnZT1PYmplY3QgJ2dvLWludGVncmF0aW9uLXRlc3QtMjAxODA5MTgtNDEzMTc2NzMxODAwMC0wMDAyL3NvbWUtb2JqJyBpcyB1bmRlciBhY3RpdmUgRXZlbnQtQmFzZWQgaG9sZCBhbmQgY2Fubm90IGJlIGRlbGV0ZWQsIG92ZXJ3cml0dGVuIG9yIGFyY2hpdmVkIHVudGlsIGhvbGQgaXMgcmVtb3ZlZC4sIHVubmFtZWRBcmd1bWVudHM9W119LCBsb2NhdGlvbj1udWxsLCBtZXNzYWdlPU9iamVjdCAnZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOC00MTMxNzY3MzE4MDAwLTAwMDIvc29tZS1vYmonIGlzIHVuZGVyIGFjdGl2ZSBFdmVudC1CYXNlZCBob2xkIGFuZCBjYW5ub3QgYmUgZGVsZXRlZCwgb3ZlcndyaXR0ZW4gb3IgYXJjaGl2ZWQgdW50aWwgaG9sZCBpcyByZW1vdmVkLiwgcmVhc29uPWZvcmJpZGRlbiwgcnBjQ29kZT00MDN9IE9iamVjdCAnZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOC00MTMxNzY3MzE4MDAwLTAwMDIvc29tZS1vYmonIGlzIHVuZGVyIGFjdGl2ZSBFdmVudC1CYXNlZCBob2xkIGFuZCBjYW5ub3QgYmUgZGVsZXRlZCwgb3ZlcndyaXR0ZW4gb3IgYXJjaGl2ZWQgdW50aWwgaG9sZCBpcyByZW1vdmVkLjogY29tLmdvb2dsZS5uZXQucnBjMy5ScGNFeGNlcHRpb246IGNsb3VkLmJpZ3N0b3JlLlJlc3BvbnNlQ29kZS5FcnJvckNvZGU6Ok9CSkVDVF9JU19VTkRFUl9BQ1RJVkVfSE9MRDogT2JqZWN0ICdnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE4LTQxMzE3NjczMTgwMDAtMDAwMi9zb21lLW9iaicgaXMgdW5kZXIgYWN0aXZlIEV2ZW50LUJhc2VkIGhvbGQgYW5kIGNhbm5vdCBiZSBkZWxldGVkLCBvdmVyd3JpdHRlbiBvciBhcmNoaXZlZCB1bnRpbCBob2xkIGlzIHJlbW92ZWQuXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRvUnBjM0V4Y2VwdGlvbihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjEzNSlcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb24udGhyb3dScGMzT25FcnJvcihCaWdzdG9yZUV4Y2VwdGlvbi5qYXZhOjMwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5hcGkuanNvbi5oYW5kbGVycy5vYmplY3RzLkRlbGV0ZU9iamVjdC5oYW5kbGVSZXF1ZXN0UmVjZWl2ZWQoRGVsZXRlT2JqZWN0LmphdmE6NzcpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uaGFuZGxlcnMub2JqZWN0cy5EZWxldGVPYmplY3QuaGFuZGxlUmVxdWVzdFJlY2VpdmVkKERlbGV0ZU9iamVjdC5qYXZhOjIzKVxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmFwaS5qc29uLmZyYW1ld29yay5SZXF1ZXN0SGFuZGxlci5oYW5kbGUoUmVxdWVzdEhhbmRsZXIuamF2YToyOTQpXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuYXBpLmpzb24uT2JqZWN0c0RlbGVnYXRvci5kZWxldGUoT2JqZWN0c0RlbGVnYXRvci5qYXZhOjExMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uUnBjUmVjZWl2ZXIubGFtYmRhJHByb2Nlc3NSZXF1ZXN0QXN5bmMkNChScGNSZWNlaXZlci5qYXZhOjIwMylcblx0YXQgY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5pc29sYXRpb24uQXN5bmNFeGVjdXRvci5sYW1iZGEkc3VibWl0JDAoQXN5bmNFeGVjdXRvci5qYXZhOjI3Milcblx0YXQgY29tLmdvb2dsZS5jb21tb24uY29udGV4dC5Db250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KENvbnRleHRSdW5uYWJsZS5qYXZhOjUwKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi5jb250ZXh0LkNvbnRleHRSdW5uYWJsZSQxLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozOSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkN1cnJlbnRDb250ZXh0LnJ1bkluQ29udGV4dChDdXJyZW50Q29udGV4dC5qYXZhOjMyMClcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLkdlbmVyaWNDb250ZXh0Q2FsbGJhY2sucnVuSW5Jbmhlcml0ZWRDb250ZXh0Tm9VbnJlZihHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NzIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5HZW5lcmljQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChHZW5lcmljQ29udGV4dENhbGxiYWNrLmphdmE6NjQpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLmNvbnRleHQuQ29udGV4dFJ1bm5hYmxlLnJ1bihDb250ZXh0UnVubmFibGUuamF2YTozNilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRXhlY3V0b3JzJFJ1bm5hYmxlQWRhcHRlci5jYWxsKEV4ZWN1dG9ycy5qYXZhOjUxMSlcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuRnV0dXJlVGFzay5ydW4oRnV0dXJlVGFzay5qYXZhOjI2Nilcblx0YXQgamF2YS51dGlsLmNvbmN1cnJlbnQuVGhyZWFkUG9vbEV4ZWN1dG9yLnJ1bldvcmtlcihUaHJlYWRQb29sRXhlY3V0b3IuamF2YToxMTQ5KVxuXHRhdCBqYXZhLnV0aWwuY29uY3VycmVudC5UaHJlYWRQb29sRXhlY3V0b3IkV29ya2VyLnJ1bihUaHJlYWRQb29sRXhlY3V0b3IuamF2YTo2MjQpXG5cdGF0IGphdmEubGFuZy5UaHJlYWQucnVuKFRocmVhZC5qYXZhOjc0OClcbkNhdXNlZCBieTogY29tLmdvb2dsZS5jbG91ZC5iaWdzdG9yZS5jb21tb24uQmlnc3RvcmVFeGNlcHRpb246IE9iamVjdCAnZ28taW50ZWdyYXRpb24tdGVzdC0yMDE4MDkxOC00MTMxNzY3MzE4MDAwLTAwMDIvc29tZS1vYmonIGlzIHVuZGVyIGFjdGl2ZSBFdmVudC1CYXNlZCBob2xkIGFuZCBjYW5ub3QgYmUgZGVsZXRlZCwgb3ZlcndyaXR0ZW4gb3IgYXJjaGl2ZWQgdW50aWwgaG9sZCBpcyByZW1vdmVkLlxuXHRhdCBjb20uZ29vZ2xlLmNsb3VkLmJpZ3N0b3JlLmNvbW1vbi5CaWdzdG9yZUV4Y2VwdGlvbi50aHJvd09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YToyOTApXG5cdGF0IGNvbS5nb29nbGUuY2xvdWQuYmlnc3RvcmUuY29tbW9uLkJpZ3N0b3JlRXhjZXB0aW9uLnRocm93UnBjM09uRXJyb3IoQmlnc3RvcmVFeGNlcHRpb24uamF2YTozMDEpXG5cdC4uLiAxNyBtb3JlXG5cblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLmNvcmUuRXJyb3JDb2xsZWN0b3IudG9GYXVsdChFcnJvckNvbGxlY3Rvci5qYXZhOjU0KVxuXHRhdCBjb20uZ29vZ2xlLmFwaS5zZXJ2ZXIucmVzdC5hZGFwdGVyLnJvc3kuUm9zeUVycm9yQ29udmVydGVyLnRvRmF1bHQoUm9zeUVycm9yQ29udmVydGVyLmphdmE6NjcpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5yZXN0LmFkYXB0ZXIucm9zeS5Sb3N5SGFuZGxlciQyLmNhbGwoUm9zeUhhbmRsZXIuamF2YToyNTgpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5yZXN0LmFkYXB0ZXIucm9zeS5Sb3N5SGFuZGxlciQyLmNhbGwoUm9zeUhhbmRsZXIuamF2YToyMzgpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLnV0aWwuQ2FsbGFibGVGdXR1cmUucnVuKENhbGxhYmxlRnV0dXJlLmphdmE6NjIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5EaXJlY3RFeGVjdXRvci5leGVjdXRlKERpcmVjdEV4ZWN1dG9yLmphdmE6MzApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5leGVjdXRlTGlzdGVuZXIoQWJzdHJhY3RGdXR1cmUuamF2YToxMTQzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuY29tcGxldGUoQWJzdHJhY3RGdXR1cmUuamF2YTo5NjMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5zZXQoQWJzdHJhY3RGdXR1cmUuamF2YTo3MzEpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLnV0aWwuQ2FsbGFibGVGdXR1cmUucnVuKENhbGxhYmxlRnV0dXJlLmphdmE6NjIpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5EaXJlY3RFeGVjdXRvci5leGVjdXRlKERpcmVjdEV4ZWN1dG9yLmphdmE6MzApXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5leGVjdXRlTGlzdGVuZXIoQWJzdHJhY3RGdXR1cmUuamF2YToxMTQzKVxuXHRhdCBjb20uZ29vZ2xlLmNvbW1vbi51dGlsLmNvbmN1cnJlbnQuQWJzdHJhY3RGdXR1cmUuY29tcGxldGUoQWJzdHJhY3RGdXR1cmUuamF2YTo5NjMpXG5cdGF0IGNvbS5nb29nbGUuY29tbW9uLnV0aWwuY29uY3VycmVudC5BYnN0cmFjdEZ1dHVyZS5zZXQoQWJzdHJhY3RGdXR1cmUuamF2YTo3MzEpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci5jb3JlLnV0aWwuQ2FsbGFibGVGdXR1cmUucnVuKENhbGxhYmxlRnV0dXJlLmphdmE6NjIpXG5cdGF0IGNvbS5nb29nbGUuYXBpLnNlcnZlci50aHJlYWQuVGhyZWFkVHJhY2tlcnMkVGhyZWFkVHJhY2tpbmdSdW5uYWJsZS5ydW4oVGhyZWFkVHJhY2tlcnMuamF2YToxMjYpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkVHJhY2VDb250ZXh0UnVubmFibGUucnVuSW5Db250ZXh0KFRyYWNlQ29udGV4dC5qYXZhOjQ1NSlcblx0YXQgY29tLmdvb2dsZS5hcGkuc2VydmVyLnNlcnZlci5Db21tb25Nb2R1bGUkQ29udGV4dENhcnJ5aW5nRXhlY3V0b3JTZXJ2aWNlJDEucnVuSW5Db250ZXh0KENvbW1vbk1vZHVsZS5qYXZhOjg0Nilcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRUcmFjZUNvbnRleHRSdW5uYWJsZSQxLnJ1bihUcmFjZUNvbnRleHQuamF2YTo0NjIpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5DdXJyZW50Q29udGV4dC5ydW5JbkNvbnRleHQoQ3VycmVudENvbnRleHQuamF2YTozMjApXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkQWJzdHJhY3RUcmFjZUNvbnRleHRDYWxsYmFjay5ydW5JbkluaGVyaXRlZENvbnRleHROb1VucmVmKFRyYWNlQ29udGV4dC5qYXZhOjMyMSlcblx0YXQgY29tLmdvb2dsZS50cmFjaW5nLlRyYWNlQ29udGV4dCRBYnN0cmFjdFRyYWNlQ29udGV4dENhbGxiYWNrLnJ1bkluSW5oZXJpdGVkQ29udGV4dChUcmFjZUNvbnRleHQuamF2YTozMTMpXG5cdGF0IGNvbS5nb29nbGUudHJhY2luZy5UcmFjZUNvbnRleHQkVHJhY2VDb250ZXh0UnVubmFibGUucnVuKFRyYWNlQ29udGV4dC5qYXZhOjQ1OSlcblx0YXQgY29tLmdvb2dsZS5nc2UuaW50ZXJuYWwuRGlzcGF0Y2hRdWV1ZUltcGwkV29ya2VyVGhyZWFkLnJ1bihEaXNwYXRjaFF1ZXVlSW1wbC5qYXZhOjQwMylcbiJ9XSwiY29kZSI6NDAzLCJtZXNzYWdlIjoiT2JqZWN0ICdnby1pbnRlZ3JhdGlvbi10ZXN0LTIwMTgwOTE4LTQxMzE3NjczMTgwMDAtMDAwMi9zb21lLW9iaicgaXMgdW5kZXIgYWN0aXZlIEV2ZW50LUJhc2VkIGhvbGQgYW5kIGNhbm5vdCBiZSBkZWxldGVkLCBvdmVyd3JpdHRlbiBvciBhcmNoaXZlZCB1bnRpbCBob2xkIGlzIHJlbW92ZWQuIn19"
+ }
+ }
+ ]
+} \ No newline at end of file
diff --git a/vendor/cloud.google.com/go/storage/writer.go b/vendor/cloud.google.com/go/storage/writer.go
new file mode 100644
index 000000000..3a58c404e
--- /dev/null
+++ b/vendor/cloud.google.com/go/storage/writer.go
@@ -0,0 +1,261 @@
+// Copyright 2014 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package storage
+
+import (
+ "context"
+ "encoding/base64"
+ "errors"
+ "fmt"
+ "io"
+ "sync"
+ "unicode/utf8"
+
+ "google.golang.org/api/googleapi"
+ raw "google.golang.org/api/storage/v1"
+)
+
+// A Writer writes a Cloud Storage object.
+type Writer struct {
+ // ObjectAttrs are optional attributes to set on the object. Any attributes
+ // must be initialized before the first Write call. Nil or zero-valued
+ // attributes are ignored.
+ ObjectAttrs
+
+ // SendCRC specifies whether to transmit a CRC32C field. It should be set
+ // to true in addition to setting the Writer's CRC32C field, because zero
+ // is a valid CRC and normally a zero would not be transmitted.
+ // If a CRC32C is sent, and the data written does not match the checksum,
+ // the write will be rejected.
+ SendCRC32C bool
+
+ // ChunkSize controls the maximum number of bytes of the object that the
+ // Writer will attempt to send to the server in a single request. Objects
+ // smaller than the size will be sent in a single request, while larger
+ // objects will be split over multiple requests. The size will be rounded up
+ // to the nearest multiple of 256K. If zero, chunking will be disabled and
+ // the object will be uploaded in a single request.
+ //
+ // ChunkSize will default to a reasonable value. If you perform many concurrent
+ // writes of small objects, you may wish set ChunkSize to a value that matches
+ // your objects' sizes to avoid consuming large amounts of memory.
+ //
+ // ChunkSize must be set before the first Write call.
+ ChunkSize int
+
+ // ProgressFunc can be used to monitor the progress of a large write.
+ // operation. If ProgressFunc is not nil and writing requires multiple
+ // calls to the underlying service (see
+ // https://cloud.google.com/storage/docs/json_api/v1/how-tos/resumable-upload),
+ // then ProgressFunc will be invoked after each call with the number of bytes of
+ // content copied so far.
+ //
+ // ProgressFunc should return quickly without blocking.
+ ProgressFunc func(int64)
+
+ ctx context.Context
+ o *ObjectHandle
+
+ opened bool
+ pw *io.PipeWriter
+
+ donec chan struct{} // closed after err and obj are set.
+ obj *ObjectAttrs
+
+ mu sync.Mutex
+ err error
+}
+
+func (w *Writer) open() error {
+ attrs := w.ObjectAttrs
+ // Check the developer didn't change the object Name (this is unfortunate, but
+ // we don't want to store an object under the wrong name).
+ if attrs.Name != w.o.object {
+ return fmt.Errorf("storage: Writer.Name %q does not match object name %q", attrs.Name, w.o.object)
+ }
+ if !utf8.ValidString(attrs.Name) {
+ return fmt.Errorf("storage: object name %q is not valid UTF-8", attrs.Name)
+ }
+ if attrs.KMSKeyName != "" && w.o.encryptionKey != nil {
+ return errors.New("storage: cannot use KMSKeyName with a customer-supplied encryption key")
+ }
+ pr, pw := io.Pipe()
+ w.pw = pw
+ w.opened = true
+
+ go w.monitorCancel()
+
+ if w.ChunkSize < 0 {
+ return errors.New("storage: Writer.ChunkSize must be non-negative")
+ }
+ mediaOpts := []googleapi.MediaOption{
+ googleapi.ChunkSize(w.ChunkSize),
+ }
+ if c := attrs.ContentType; c != "" {
+ mediaOpts = append(mediaOpts, googleapi.ContentType(c))
+ }
+
+ go func() {
+ defer close(w.donec)
+
+ rawObj := attrs.toRawObject(w.o.bucket)
+ if w.SendCRC32C {
+ rawObj.Crc32c = encodeUint32(attrs.CRC32C)
+ }
+ if w.MD5 != nil {
+ rawObj.Md5Hash = base64.StdEncoding.EncodeToString(w.MD5)
+ }
+ call := w.o.c.raw.Objects.Insert(w.o.bucket, rawObj).
+ Media(pr, mediaOpts...).
+ Projection("full").
+ Context(w.ctx)
+ if w.ProgressFunc != nil {
+ call.ProgressUpdater(func(n, _ int64) { w.ProgressFunc(n) })
+ }
+ if attrs.KMSKeyName != "" {
+ call.KmsKeyName(attrs.KMSKeyName)
+ }
+ if attrs.PredefinedACL != "" {
+ call.PredefinedAcl(attrs.PredefinedACL)
+ }
+ if err := setEncryptionHeaders(call.Header(), w.o.encryptionKey, false); err != nil {
+ w.mu.Lock()
+ w.err = err
+ w.mu.Unlock()
+ pr.CloseWithError(err)
+ return
+ }
+ var resp *raw.Object
+ err := applyConds("NewWriter", w.o.gen, w.o.conds, call)
+ if err == nil {
+ if w.o.userProject != "" {
+ call.UserProject(w.o.userProject)
+ }
+ setClientHeader(call.Header())
+ // If the chunk size is zero, then no chunking is done on the Reader,
+ // which means we cannot retry: the first call will read the data, and if
+ // it fails, there is no way to re-read.
+ if w.ChunkSize == 0 {
+ resp, err = call.Do()
+ } else {
+ // We will only retry here if the initial POST, which obtains a URI for
+ // the resumable upload, fails with a retryable error. The upload itself
+ // has its own retry logic.
+ err = runWithRetry(w.ctx, func() error {
+ var err2 error
+ resp, err2 = call.Do()
+ return err2
+ })
+ }
+ }
+ if err != nil {
+ w.mu.Lock()
+ w.err = err
+ w.mu.Unlock()
+ pr.CloseWithError(err)
+ return
+ }
+ w.obj = newObject(resp)
+ }()
+ return nil
+}
+
+// Write appends to w. It implements the io.Writer interface.
+//
+// Since writes happen asynchronously, Write may return a nil
+// error even though the write failed (or will fail). Always
+// use the error returned from Writer.Close to determine if
+// the upload was successful.
+func (w *Writer) Write(p []byte) (n int, err error) {
+ w.mu.Lock()
+ werr := w.err
+ w.mu.Unlock()
+ if werr != nil {
+ return 0, werr
+ }
+ if !w.opened {
+ if err := w.open(); err != nil {
+ return 0, err
+ }
+ }
+ n, err = w.pw.Write(p)
+ if err != nil {
+ w.mu.Lock()
+ werr := w.err
+ w.mu.Unlock()
+ // Preserve existing functionality that when context is canceled, Write will return
+ // context.Canceled instead of "io: read/write on closed pipe". This hides the
+ // pipe implementation detail from users and makes Write seem as though it's an RPC.
+ if werr == context.Canceled || werr == context.DeadlineExceeded {
+ return n, werr
+ }
+ }
+ return n, err
+}
+
+// Close completes the write operation and flushes any buffered data.
+// If Close doesn't return an error, metadata about the written object
+// can be retrieved by calling Attrs.
+func (w *Writer) Close() error {
+ if !w.opened {
+ if err := w.open(); err != nil {
+ return err
+ }
+ }
+
+ // Closing either the read or write causes the entire pipe to close.
+ if err := w.pw.Close(); err != nil {
+ return err
+ }
+
+ <-w.donec
+ w.mu.Lock()
+ defer w.mu.Unlock()
+ return w.err
+}
+
+// monitorCancel is intended to be used as a background goroutine. It monitors the
+// the context, and when it observes that the context has been canceled, it manually
+// closes things that do not take a context.
+func (w *Writer) monitorCancel() {
+ select {
+ case <-w.ctx.Done():
+ w.mu.Lock()
+ werr := w.ctx.Err()
+ w.err = werr
+ w.mu.Unlock()
+
+ // Closing either the read or write causes the entire pipe to close.
+ w.CloseWithError(werr)
+ case <-w.donec:
+ }
+}
+
+// CloseWithError aborts the write operation with the provided error.
+// CloseWithError always returns nil.
+//
+// Deprecated: cancel the context passed to NewWriter instead.
+func (w *Writer) CloseWithError(err error) error {
+ if !w.opened {
+ return nil
+ }
+ return w.pw.CloseWithError(err)
+}
+
+// Attrs returns metadata about a successfully-written object.
+// It's only valid to call it after Close returns nil.
+func (w *Writer) Attrs() *ObjectAttrs {
+ return w.obj
+}
diff --git a/vendor/github.com/golang/protobuf/LICENSE b/vendor/github.com/golang/protobuf/LICENSE
index 1b1b1921e..0f646931a 100644
--- a/vendor/github.com/golang/protobuf/LICENSE
+++ b/vendor/github.com/golang/protobuf/LICENSE
@@ -1,7 +1,4 @@
-Go support for Protocol Buffers - Google's data interchange format
-
Copyright 2010 The Go Authors. All rights reserved.
-https://github.com/golang/protobuf
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
diff --git a/vendor/github.com/golang/protobuf/proto/Makefile b/vendor/github.com/golang/protobuf/proto/Makefile
deleted file mode 100644
index e2e0651a9..000000000
--- a/vendor/github.com/golang/protobuf/proto/Makefile
+++ /dev/null
@@ -1,43 +0,0 @@
-# Go support for Protocol Buffers - Google's data interchange format
-#
-# Copyright 2010 The Go Authors. All rights reserved.
-# https://github.com/golang/protobuf
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are
-# met:
-#
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above
-# copyright notice, this list of conditions and the following disclaimer
-# in the documentation and/or other materials provided with the
-# distribution.
-# * Neither the name of Google Inc. nor the names of its
-# contributors may be used to endorse or promote products derived from
-# this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-install:
- go install
-
-test: install generate-test-pbs
- go test
-
-
-generate-test-pbs:
- make install
- make -C testdata
- protoc --go_out=Mtestdata/test.proto=github.com/golang/protobuf/proto/testdata,Mgoogle/protobuf/any.proto=github.com/golang/protobuf/ptypes/any:. proto3_proto/proto3.proto
- make
diff --git a/vendor/github.com/golang/protobuf/proto/clone.go b/vendor/github.com/golang/protobuf/proto/clone.go
index e392575b3..3cd3249f7 100644
--- a/vendor/github.com/golang/protobuf/proto/clone.go
+++ b/vendor/github.com/golang/protobuf/proto/clone.go
@@ -35,22 +35,39 @@
package proto
import (
+ "fmt"
"log"
"reflect"
"strings"
)
// Clone returns a deep copy of a protocol buffer.
-func Clone(pb Message) Message {
- in := reflect.ValueOf(pb)
+func Clone(src Message) Message {
+ in := reflect.ValueOf(src)
if in.IsNil() {
- return pb
+ return src
}
-
out := reflect.New(in.Type().Elem())
- // out is empty so a merge is a deep copy.
- mergeStruct(out.Elem(), in.Elem())
- return out.Interface().(Message)
+ dst := out.Interface().(Message)
+ Merge(dst, src)
+ return dst
+}
+
+// Merger is the interface representing objects that can merge messages of the same type.
+type Merger interface {
+ // Merge merges src into this message.
+ // Required and optional fields that are set in src will be set to that value in dst.
+ // Elements of repeated fields will be appended.
+ //
+ // Merge may panic if called with a different argument type than the receiver.
+ Merge(src Message)
+}
+
+// generatedMerger is the custom merge method that generated protos will have.
+// We must add this method since a generate Merge method will conflict with
+// many existing protos that have a Merge data field already defined.
+type generatedMerger interface {
+ XXX_Merge(src Message)
}
// Merge merges src into dst.
@@ -58,17 +75,24 @@ func Clone(pb Message) Message {
// Elements of repeated fields will be appended.
// Merge panics if src and dst are not the same type, or if dst is nil.
func Merge(dst, src Message) {
+ if m, ok := dst.(Merger); ok {
+ m.Merge(src)
+ return
+ }
+
in := reflect.ValueOf(src)
out := reflect.ValueOf(dst)
if out.IsNil() {
panic("proto: nil destination")
}
if in.Type() != out.Type() {
- // Explicit test prior to mergeStruct so that mistyped nils will fail
- panic("proto: type mismatch")
+ panic(fmt.Sprintf("proto.Merge(%T, %T) type mismatch", dst, src))
}
if in.IsNil() {
- // Merging nil into non-nil is a quiet no-op
+ return // Merge from nil src is a noop
+ }
+ if m, ok := dst.(generatedMerger); ok {
+ m.XXX_Merge(src)
return
}
mergeStruct(out.Elem(), in.Elem())
@@ -84,7 +108,7 @@ func mergeStruct(out, in reflect.Value) {
mergeAny(out.Field(i), in.Field(i), false, sprop.Prop[i])
}
- if emIn, ok := extendable(in.Addr().Interface()); ok {
+ if emIn, err := extendable(in.Addr().Interface()); err == nil {
emOut, _ := extendable(out.Addr().Interface())
mIn, muIn := emIn.extensionsRead()
if mIn != nil {
diff --git a/vendor/github.com/golang/protobuf/proto/decode.go b/vendor/github.com/golang/protobuf/proto/decode.go
index aa207298f..63b0f08be 100644
--- a/vendor/github.com/golang/protobuf/proto/decode.go
+++ b/vendor/github.com/golang/protobuf/proto/decode.go
@@ -39,8 +39,6 @@ import (
"errors"
"fmt"
"io"
- "os"
- "reflect"
)
// errOverflow is returned when an integer is too large to be represented.
@@ -50,10 +48,6 @@ var errOverflow = errors.New("proto: integer overflow")
// wire type is encountered. It does not get returned to user code.
var ErrInternalBadWireType = errors.New("proto: internal error: bad wiretype for oneof")
-// The fundamental decoders that interpret bytes on the wire.
-// Those that take integer types all return uint64 and are
-// therefore of type valueDecoder.
-
// DecodeVarint reads a varint-encoded integer from the slice.
// It returns the integer and the number of bytes consumed, or
// zero if there is not enough.
@@ -192,7 +186,6 @@ func (p *Buffer) DecodeVarint() (x uint64, err error) {
if b&0x80 == 0 {
goto done
}
- // x -= 0x80 << 63 // Always zero.
return 0, errOverflow
@@ -267,9 +260,6 @@ func (p *Buffer) DecodeZigzag32() (x uint64, err error) {
return
}
-// These are not ValueDecoders: they produce an array of bytes or a string.
-// bytes, embedded messages
-
// DecodeRawBytes reads a count-delimited byte buffer from the Buffer.
// This is the format used for the bytes protocol buffer
// type and for embedded messages.
@@ -311,81 +301,29 @@ func (p *Buffer) DecodeStringBytes() (s string, err error) {
return string(buf), nil
}
-// Skip the next item in the buffer. Its wire type is decoded and presented as an argument.
-// If the protocol buffer has extensions, and the field matches, add it as an extension.
-// Otherwise, if the XXX_unrecognized field exists, append the skipped data there.
-func (o *Buffer) skipAndSave(t reflect.Type, tag, wire int, base structPointer, unrecField field) error {
- oi := o.index
-
- err := o.skip(t, tag, wire)
- if err != nil {
- return err
- }
-
- if !unrecField.IsValid() {
- return nil
- }
-
- ptr := structPointer_Bytes(base, unrecField)
-
- // Add the skipped field to struct field
- obuf := o.buf
-
- o.buf = *ptr
- o.EncodeVarint(uint64(tag<<3 | wire))
- *ptr = append(o.buf, obuf[oi:o.index]...)
-
- o.buf = obuf
-
- return nil
-}
-
-// Skip the next item in the buffer. Its wire type is decoded and presented as an argument.
-func (o *Buffer) skip(t reflect.Type, tag, wire int) error {
-
- var u uint64
- var err error
-
- switch wire {
- case WireVarint:
- _, err = o.DecodeVarint()
- case WireFixed64:
- _, err = o.DecodeFixed64()
- case WireBytes:
- _, err = o.DecodeRawBytes(false)
- case WireFixed32:
- _, err = o.DecodeFixed32()
- case WireStartGroup:
- for {
- u, err = o.DecodeVarint()
- if err != nil {
- break
- }
- fwire := int(u & 0x7)
- if fwire == WireEndGroup {
- break
- }
- ftag := int(u >> 3)
- err = o.skip(t, ftag, fwire)
- if err != nil {
- break
- }
- }
- default:
- err = fmt.Errorf("proto: can't skip unknown wire type %d for %s", wire, t)
- }
- return err
-}
-
// Unmarshaler is the interface representing objects that can
-// unmarshal themselves. The method should reset the receiver before
-// decoding starts. The argument points to data that may be
+// unmarshal themselves. The argument points to data that may be
// overwritten, so implementations should not keep references to the
// buffer.
+// Unmarshal implementations should not clear the receiver.
+// Any unmarshaled data should be merged into the receiver.
+// Callers of Unmarshal that do not want to retain existing data
+// should Reset the receiver before calling Unmarshal.
type Unmarshaler interface {
Unmarshal([]byte) error
}
+// newUnmarshaler is the interface representing objects that can
+// unmarshal themselves. The semantics are identical to Unmarshaler.
+//
+// This exists to support protoc-gen-go generated messages.
+// The proto package will stop type-asserting to this interface in the future.
+//
+// DO NOT DEPEND ON THIS.
+type newUnmarshaler interface {
+ XXX_Unmarshal([]byte) error
+}
+
// Unmarshal parses the protocol buffer representation in buf and places the
// decoded result in pb. If the struct underlying pb does not match
// the data in buf, the results can be unpredictable.
@@ -395,7 +333,13 @@ type Unmarshaler interface {
// to preserve and append to existing data.
func Unmarshal(buf []byte, pb Message) error {
pb.Reset()
- return UnmarshalMerge(buf, pb)
+ if u, ok := pb.(newUnmarshaler); ok {
+ return u.XXX_Unmarshal(buf)
+ }
+ if u, ok := pb.(Unmarshaler); ok {
+ return u.Unmarshal(buf)
+ }
+ return NewBuffer(buf).Unmarshal(pb)
}
// UnmarshalMerge parses the protocol buffer representation in buf and
@@ -405,8 +349,16 @@ func Unmarshal(buf []byte, pb Message) error {
// UnmarshalMerge merges into existing data in pb.
// Most code should use Unmarshal instead.
func UnmarshalMerge(buf []byte, pb Message) error {
- // If the object can unmarshal itself, let it.
+ if u, ok := pb.(newUnmarshaler); ok {
+ return u.XXX_Unmarshal(buf)
+ }
if u, ok := pb.(Unmarshaler); ok {
+ // NOTE: The history of proto have unfortunately been inconsistent
+ // whether Unmarshaler should or should not implicitly clear itself.
+ // Some implementations do, most do not.
+ // Thus, calling this here may or may not do what people want.
+ //
+ // See https://github.com/golang/protobuf/issues/424
return u.Unmarshal(buf)
}
return NewBuffer(buf).Unmarshal(pb)
@@ -422,12 +374,17 @@ func (p *Buffer) DecodeMessage(pb Message) error {
}
// DecodeGroup reads a tag-delimited group from the Buffer.
+// StartGroup tag is already consumed. This function consumes
+// EndGroup tag.
func (p *Buffer) DecodeGroup(pb Message) error {
- typ, base, err := getbase(pb)
- if err != nil {
- return err
+ b := p.buf[p.index:]
+ x, y := findEndGroup(b)
+ if x < 0 {
+ return io.ErrUnexpectedEOF
}
- return p.unmarshalType(typ.Elem(), GetProperties(typ.Elem()), true, base)
+ err := Unmarshal(b[:x], pb)
+ p.index += y
+ return err
}
// Unmarshal parses the protocol buffer representation in the
@@ -438,533 +395,33 @@ func (p *Buffer) DecodeGroup(pb Message) error {
// Unlike proto.Unmarshal, this does not reset pb before starting to unmarshal.
func (p *Buffer) Unmarshal(pb Message) error {
// If the object can unmarshal itself, let it.
- if u, ok := pb.(Unmarshaler); ok {
- err := u.Unmarshal(p.buf[p.index:])
+ if u, ok := pb.(newUnmarshaler); ok {
+ err := u.XXX_Unmarshal(p.buf[p.index:])
p.index = len(p.buf)
return err
}
-
- typ, base, err := getbase(pb)
- if err != nil {
- return err
- }
-
- err = p.unmarshalType(typ.Elem(), GetProperties(typ.Elem()), false, base)
-
- if collectStats {
- stats.Decode++
- }
-
- return err
-}
-
-// unmarshalType does the work of unmarshaling a structure.
-func (o *Buffer) unmarshalType(st reflect.Type, prop *StructProperties, is_group bool, base structPointer) error {
- var state errorState
- required, reqFields := prop.reqCount, uint64(0)
-
- var err error
- for err == nil && o.index < len(o.buf) {
- oi := o.index
- var u uint64
- u, err = o.DecodeVarint()
- if err != nil {
- break
- }
- wire := int(u & 0x7)
- if wire == WireEndGroup {
- if is_group {
- if required > 0 {
- // Not enough information to determine the exact field.
- // (See below.)
- return &RequiredNotSetError{"{Unknown}"}
- }
- return nil // input is satisfied
- }
- return fmt.Errorf("proto: %s: wiretype end group for non-group", st)
- }
- tag := int(u >> 3)
- if tag <= 0 {
- return fmt.Errorf("proto: %s: illegal tag %d (wire type %d)", st, tag, wire)
- }
- fieldnum, ok := prop.decoderTags.get(tag)
- if !ok {
- // Maybe it's an extension?
- if prop.extendable {
- if e, _ := extendable(structPointer_Interface(base, st)); isExtensionField(e, int32(tag)) {
- if err = o.skip(st, tag, wire); err == nil {
- extmap := e.extensionsWrite()
- ext := extmap[int32(tag)] // may be missing
- ext.enc = append(ext.enc, o.buf[oi:o.index]...)
- extmap[int32(tag)] = ext
- }
- continue
- }
- }
- // Maybe it's a oneof?
- if prop.oneofUnmarshaler != nil {
- m := structPointer_Interface(base, st).(Message)
- // First return value indicates whether tag is a oneof field.
- ok, err = prop.oneofUnmarshaler(m, tag, wire, o)
- if err == ErrInternalBadWireType {
- // Map the error to something more descriptive.
- // Do the formatting here to save generated code space.
- err = fmt.Errorf("bad wiretype for oneof field in %T", m)
- }
- if ok {
- continue
- }
- }
- err = o.skipAndSave(st, tag, wire, base, prop.unrecField)
- continue
- }
- p := prop.Prop[fieldnum]
-
- if p.dec == nil {
- fmt.Fprintf(os.Stderr, "proto: no protobuf decoder for %s.%s\n", st, st.Field(fieldnum).Name)
- continue
- }
- dec := p.dec
- if wire != WireStartGroup && wire != p.WireType {
- if wire == WireBytes && p.packedDec != nil {
- // a packable field
- dec = p.packedDec
- } else {
- err = fmt.Errorf("proto: bad wiretype for field %s.%s: got wiretype %d, want %d", st, st.Field(fieldnum).Name, wire, p.WireType)
- continue
- }
- }
- decErr := dec(o, p, base)
- if decErr != nil && !state.shouldContinue(decErr, p) {
- err = decErr
- }
- if err == nil && p.Required {
- // Successfully decoded a required field.
- if tag <= 64 {
- // use bitmap for fields 1-64 to catch field reuse.
- var mask uint64 = 1 << uint64(tag-1)
- if reqFields&mask == 0 {
- // new required field
- reqFields |= mask
- required--
- }
- } else {
- // This is imprecise. It can be fooled by a required field
- // with a tag > 64 that is encoded twice; that's very rare.
- // A fully correct implementation would require allocating
- // a data structure, which we would like to avoid.
- required--
- }
- }
- }
- if err == nil {
- if is_group {
- return io.ErrUnexpectedEOF
- }
- if state.err != nil {
- return state.err
- }
- if required > 0 {
- // Not enough information to determine the exact field. If we use extra
- // CPU, we could determine the field only if the missing required field
- // has a tag <= 64 and we check reqFields.
- return &RequiredNotSetError{"{Unknown}"}
- }
- }
- return err
-}
-
-// Individual type decoders
-// For each,
-// u is the decoded value,
-// v is a pointer to the field (pointer) in the struct
-
-// Sizes of the pools to allocate inside the Buffer.
-// The goal is modest amortization and allocation
-// on at least 16-byte boundaries.
-const (
- boolPoolSize = 16
- uint32PoolSize = 8
- uint64PoolSize = 4
-)
-
-// Decode a bool.
-func (o *Buffer) dec_bool(p *Properties, base structPointer) error {
- u, err := p.valDec(o)
- if err != nil {
- return err
- }
- if len(o.bools) == 0 {
- o.bools = make([]bool, boolPoolSize)
- }
- o.bools[0] = u != 0
- *structPointer_Bool(base, p.field) = &o.bools[0]
- o.bools = o.bools[1:]
- return nil
-}
-
-func (o *Buffer) dec_proto3_bool(p *Properties, base structPointer) error {
- u, err := p.valDec(o)
- if err != nil {
- return err
- }
- *structPointer_BoolVal(base, p.field) = u != 0
- return nil
-}
-
-// Decode an int32.
-func (o *Buffer) dec_int32(p *Properties, base structPointer) error {
- u, err := p.valDec(o)
- if err != nil {
- return err
- }
- word32_Set(structPointer_Word32(base, p.field), o, uint32(u))
- return nil
-}
-
-func (o *Buffer) dec_proto3_int32(p *Properties, base structPointer) error {
- u, err := p.valDec(o)
- if err != nil {
- return err
- }
- word32Val_Set(structPointer_Word32Val(base, p.field), uint32(u))
- return nil
-}
-
-// Decode an int64.
-func (o *Buffer) dec_int64(p *Properties, base structPointer) error {
- u, err := p.valDec(o)
- if err != nil {
- return err
- }
- word64_Set(structPointer_Word64(base, p.field), o, u)
- return nil
-}
-
-func (o *Buffer) dec_proto3_int64(p *Properties, base structPointer) error {
- u, err := p.valDec(o)
- if err != nil {
- return err
- }
- word64Val_Set(structPointer_Word64Val(base, p.field), o, u)
- return nil
-}
-
-// Decode a string.
-func (o *Buffer) dec_string(p *Properties, base structPointer) error {
- s, err := o.DecodeStringBytes()
- if err != nil {
- return err
- }
- *structPointer_String(base, p.field) = &s
- return nil
-}
-
-func (o *Buffer) dec_proto3_string(p *Properties, base structPointer) error {
- s, err := o.DecodeStringBytes()
- if err != nil {
- return err
- }
- *structPointer_StringVal(base, p.field) = s
- return nil
-}
-
-// Decode a slice of bytes ([]byte).
-func (o *Buffer) dec_slice_byte(p *Properties, base structPointer) error {
- b, err := o.DecodeRawBytes(true)
- if err != nil {
- return err
- }
- *structPointer_Bytes(base, p.field) = b
- return nil
-}
-
-// Decode a slice of bools ([]bool).
-func (o *Buffer) dec_slice_bool(p *Properties, base structPointer) error {
- u, err := p.valDec(o)
- if err != nil {
- return err
- }
- v := structPointer_BoolSlice(base, p.field)
- *v = append(*v, u != 0)
- return nil
-}
-
-// Decode a slice of bools ([]bool) in packed format.
-func (o *Buffer) dec_slice_packed_bool(p *Properties, base structPointer) error {
- v := structPointer_BoolSlice(base, p.field)
-
- nn, err := o.DecodeVarint()
- if err != nil {
- return err
- }
- nb := int(nn) // number of bytes of encoded bools
- fin := o.index + nb
- if fin < o.index {
- return errOverflow
- }
-
- y := *v
- for o.index < fin {
- u, err := p.valDec(o)
- if err != nil {
- return err
- }
- y = append(y, u != 0)
- }
-
- *v = y
- return nil
-}
-
-// Decode a slice of int32s ([]int32).
-func (o *Buffer) dec_slice_int32(p *Properties, base structPointer) error {
- u, err := p.valDec(o)
- if err != nil {
- return err
- }
- structPointer_Word32Slice(base, p.field).Append(uint32(u))
- return nil
-}
-
-// Decode a slice of int32s ([]int32) in packed format.
-func (o *Buffer) dec_slice_packed_int32(p *Properties, base structPointer) error {
- v := structPointer_Word32Slice(base, p.field)
-
- nn, err := o.DecodeVarint()
- if err != nil {
- return err
- }
- nb := int(nn) // number of bytes of encoded int32s
-
- fin := o.index + nb
- if fin < o.index {
- return errOverflow
- }
- for o.index < fin {
- u, err := p.valDec(o)
- if err != nil {
- return err
- }
- v.Append(uint32(u))
- }
- return nil
-}
-
-// Decode a slice of int64s ([]int64).
-func (o *Buffer) dec_slice_int64(p *Properties, base structPointer) error {
- u, err := p.valDec(o)
- if err != nil {
- return err
- }
-
- structPointer_Word64Slice(base, p.field).Append(u)
- return nil
-}
-
-// Decode a slice of int64s ([]int64) in packed format.
-func (o *Buffer) dec_slice_packed_int64(p *Properties, base structPointer) error {
- v := structPointer_Word64Slice(base, p.field)
-
- nn, err := o.DecodeVarint()
- if err != nil {
- return err
- }
- nb := int(nn) // number of bytes of encoded int64s
-
- fin := o.index + nb
- if fin < o.index {
- return errOverflow
- }
- for o.index < fin {
- u, err := p.valDec(o)
- if err != nil {
- return err
- }
- v.Append(u)
- }
- return nil
-}
-
-// Decode a slice of strings ([]string).
-func (o *Buffer) dec_slice_string(p *Properties, base structPointer) error {
- s, err := o.DecodeStringBytes()
- if err != nil {
- return err
- }
- v := structPointer_StringSlice(base, p.field)
- *v = append(*v, s)
- return nil
-}
-
-// Decode a slice of slice of bytes ([][]byte).
-func (o *Buffer) dec_slice_slice_byte(p *Properties, base structPointer) error {
- b, err := o.DecodeRawBytes(true)
- if err != nil {
- return err
- }
- v := structPointer_BytesSlice(base, p.field)
- *v = append(*v, b)
- return nil
-}
-
-// Decode a map field.
-func (o *Buffer) dec_new_map(p *Properties, base structPointer) error {
- raw, err := o.DecodeRawBytes(false)
- if err != nil {
- return err
- }
- oi := o.index // index at the end of this map entry
- o.index -= len(raw) // move buffer back to start of map entry
-
- mptr := structPointer_NewAt(base, p.field, p.mtype) // *map[K]V
- if mptr.Elem().IsNil() {
- mptr.Elem().Set(reflect.MakeMap(mptr.Type().Elem()))
- }
- v := mptr.Elem() // map[K]V
-
- // Prepare addressable doubly-indirect placeholders for the key and value types.
- // See enc_new_map for why.
- keyptr := reflect.New(reflect.PtrTo(p.mtype.Key())).Elem() // addressable *K
- keybase := toStructPointer(keyptr.Addr()) // **K
-
- var valbase structPointer
- var valptr reflect.Value
- switch p.mtype.Elem().Kind() {
- case reflect.Slice:
- // []byte
- var dummy []byte
- valptr = reflect.ValueOf(&dummy) // *[]byte
- valbase = toStructPointer(valptr) // *[]byte
- case reflect.Ptr:
- // message; valptr is **Msg; need to allocate the intermediate pointer
- valptr = reflect.New(reflect.PtrTo(p.mtype.Elem())).Elem() // addressable *V
- valptr.Set(reflect.New(valptr.Type().Elem()))
- valbase = toStructPointer(valptr)
- default:
- // everything else
- valptr = reflect.New(reflect.PtrTo(p.mtype.Elem())).Elem() // addressable *V
- valbase = toStructPointer(valptr.Addr()) // **V
- }
-
- // Decode.
- // This parses a restricted wire format, namely the encoding of a message
- // with two fields. See enc_new_map for the format.
- for o.index < oi {
- // tagcode for key and value properties are always a single byte
- // because they have tags 1 and 2.
- tagcode := o.buf[o.index]
- o.index++
- switch tagcode {
- case p.mkeyprop.tagcode[0]:
- if err := p.mkeyprop.dec(o, p.mkeyprop, keybase); err != nil {
- return err
- }
- case p.mvalprop.tagcode[0]:
- if err := p.mvalprop.dec(o, p.mvalprop, valbase); err != nil {
- return err
- }
- default:
- // TODO: Should we silently skip this instead?
- return fmt.Errorf("proto: bad map data tag %d", raw[0])
- }
- }
- keyelem, valelem := keyptr.Elem(), valptr.Elem()
- if !keyelem.IsValid() {
- keyelem = reflect.Zero(p.mtype.Key())
- }
- if !valelem.IsValid() {
- valelem = reflect.Zero(p.mtype.Elem())
- }
-
- v.SetMapIndex(keyelem, valelem)
- return nil
-}
-
-// Decode a group.
-func (o *Buffer) dec_struct_group(p *Properties, base structPointer) error {
- bas := structPointer_GetStructPointer(base, p.field)
- if structPointer_IsNil(bas) {
- // allocate new nested message
- bas = toStructPointer(reflect.New(p.stype))
- structPointer_SetStructPointer(base, p.field, bas)
- }
- return o.unmarshalType(p.stype, p.sprop, true, bas)
-}
-
-// Decode an embedded message.
-func (o *Buffer) dec_struct_message(p *Properties, base structPointer) (err error) {
- raw, e := o.DecodeRawBytes(false)
- if e != nil {
- return e
- }
-
- bas := structPointer_GetStructPointer(base, p.field)
- if structPointer_IsNil(bas) {
- // allocate new nested message
- bas = toStructPointer(reflect.New(p.stype))
- structPointer_SetStructPointer(base, p.field, bas)
- }
-
- // If the object can unmarshal itself, let it.
- if p.isUnmarshaler {
- iv := structPointer_Interface(bas, p.stype)
- return iv.(Unmarshaler).Unmarshal(raw)
- }
-
- obuf := o.buf
- oi := o.index
- o.buf = raw
- o.index = 0
-
- err = o.unmarshalType(p.stype, p.sprop, false, bas)
- o.buf = obuf
- o.index = oi
-
- return err
-}
-
-// Decode a slice of embedded messages.
-func (o *Buffer) dec_slice_struct_message(p *Properties, base structPointer) error {
- return o.dec_slice_struct(p, false, base)
-}
-
-// Decode a slice of embedded groups.
-func (o *Buffer) dec_slice_struct_group(p *Properties, base structPointer) error {
- return o.dec_slice_struct(p, true, base)
-}
-
-// Decode a slice of structs ([]*struct).
-func (o *Buffer) dec_slice_struct(p *Properties, is_group bool, base structPointer) error {
- v := reflect.New(p.stype)
- bas := toStructPointer(v)
- structPointer_StructPointerSlice(base, p.field).Append(bas)
-
- if is_group {
- err := o.unmarshalType(p.stype, p.sprop, is_group, bas)
- return err
- }
-
- raw, err := o.DecodeRawBytes(false)
- if err != nil {
+ if u, ok := pb.(Unmarshaler); ok {
+ // NOTE: The history of proto have unfortunately been inconsistent
+ // whether Unmarshaler should or should not implicitly clear itself.
+ // Some implementations do, most do not.
+ // Thus, calling this here may or may not do what people want.
+ //
+ // See https://github.com/golang/protobuf/issues/424
+ err := u.Unmarshal(p.buf[p.index:])
+ p.index = len(p.buf)
return err
}
- // If the object can unmarshal itself, let it.
- if p.isUnmarshaler {
- iv := v.Interface()
- return iv.(Unmarshaler).Unmarshal(raw)
- }
-
- obuf := o.buf
- oi := o.index
- o.buf = raw
- o.index = 0
-
- err = o.unmarshalType(p.stype, p.sprop, is_group, bas)
-
- o.buf = obuf
- o.index = oi
-
+ // Slow workaround for messages that aren't Unmarshalers.
+ // This includes some hand-coded .pb.go files and
+ // bootstrap protos.
+ // TODO: fix all of those and then add Unmarshal to
+ // the Message interface. Then:
+ // The cast above and code below can be deleted.
+ // The old unmarshaler can be deleted.
+ // Clients can call Unmarshal directly (can already do that, actually).
+ var info InternalMessageInfo
+ err := info.Unmarshal(pb, p.buf[p.index:])
+ p.index = len(p.buf)
return err
}
diff --git a/vendor/github.com/golang/protobuf/proto/deprecated.go b/vendor/github.com/golang/protobuf/proto/deprecated.go
new file mode 100644
index 000000000..35b882c09
--- /dev/null
+++ b/vendor/github.com/golang/protobuf/proto/deprecated.go
@@ -0,0 +1,63 @@
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2018 The Go Authors. All rights reserved.
+// https://github.com/golang/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package proto
+
+import "errors"
+
+// Deprecated: do not use.
+type Stats struct{ Emalloc, Dmalloc, Encode, Decode, Chit, Cmiss, Size uint64 }
+
+// Deprecated: do not use.
+func GetStats() Stats { return Stats{} }
+
+// Deprecated: do not use.
+func MarshalMessageSet(interface{}) ([]byte, error) {
+ return nil, errors.New("proto: not implemented")
+}
+
+// Deprecated: do not use.
+func UnmarshalMessageSet([]byte, interface{}) error {
+ return errors.New("proto: not implemented")
+}
+
+// Deprecated: do not use.
+func MarshalMessageSetJSON(interface{}) ([]byte, error) {
+ return nil, errors.New("proto: not implemented")
+}
+
+// Deprecated: do not use.
+func UnmarshalMessageSetJSON([]byte, interface{}) error {
+ return errors.New("proto: not implemented")
+}
+
+// Deprecated: do not use.
+func RegisterMessageSetType(Message, int32, string) {}
diff --git a/vendor/github.com/golang/protobuf/proto/discard.go b/vendor/github.com/golang/protobuf/proto/discard.go
new file mode 100644
index 000000000..dea2617ce
--- /dev/null
+++ b/vendor/github.com/golang/protobuf/proto/discard.go
@@ -0,0 +1,350 @@
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2017 The Go Authors. All rights reserved.
+// https://github.com/golang/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package proto
+
+import (
+ "fmt"
+ "reflect"
+ "strings"
+ "sync"
+ "sync/atomic"
+)
+
+type generatedDiscarder interface {
+ XXX_DiscardUnknown()
+}
+
+// DiscardUnknown recursively discards all unknown fields from this message
+// and all embedded messages.
+//
+// When unmarshaling a message with unrecognized fields, the tags and values
+// of such fields are preserved in the Message. This allows a later call to
+// marshal to be able to produce a message that continues to have those
+// unrecognized fields. To avoid this, DiscardUnknown is used to
+// explicitly clear the unknown fields after unmarshaling.
+//
+// For proto2 messages, the unknown fields of message extensions are only
+// discarded from messages that have been accessed via GetExtension.
+func DiscardUnknown(m Message) {
+ if m, ok := m.(generatedDiscarder); ok {
+ m.XXX_DiscardUnknown()
+ return
+ }
+ // TODO: Dynamically populate a InternalMessageInfo for legacy messages,
+ // but the master branch has no implementation for InternalMessageInfo,
+ // so it would be more work to replicate that approach.
+ discardLegacy(m)
+}
+
+// DiscardUnknown recursively discards all unknown fields.
+func (a *InternalMessageInfo) DiscardUnknown(m Message) {
+ di := atomicLoadDiscardInfo(&a.discard)
+ if di == nil {
+ di = getDiscardInfo(reflect.TypeOf(m).Elem())
+ atomicStoreDiscardInfo(&a.discard, di)
+ }
+ di.discard(toPointer(&m))
+}
+
+type discardInfo struct {
+ typ reflect.Type
+
+ initialized int32 // 0: only typ is valid, 1: everything is valid
+ lock sync.Mutex
+
+ fields []discardFieldInfo
+ unrecognized field
+}
+
+type discardFieldInfo struct {
+ field field // Offset of field, guaranteed to be valid
+ discard func(src pointer)
+}
+
+var (
+ discardInfoMap = map[reflect.Type]*discardInfo{}
+ discardInfoLock sync.Mutex
+)
+
+func getDiscardInfo(t reflect.Type) *discardInfo {
+ discardInfoLock.Lock()
+ defer discardInfoLock.Unlock()
+ di := discardInfoMap[t]
+ if di == nil {
+ di = &discardInfo{typ: t}
+ discardInfoMap[t] = di
+ }
+ return di
+}
+
+func (di *discardInfo) discard(src pointer) {
+ if src.isNil() {
+ return // Nothing to do.
+ }
+
+ if atomic.LoadInt32(&di.initialized) == 0 {
+ di.computeDiscardInfo()
+ }
+
+ for _, fi := range di.fields {
+ sfp := src.offset(fi.field)
+ fi.discard(sfp)
+ }
+
+ // For proto2 messages, only discard unknown fields in message extensions
+ // that have been accessed via GetExtension.
+ if em, err := extendable(src.asPointerTo(di.typ).Interface()); err == nil {
+ // Ignore lock since DiscardUnknown is not concurrency safe.
+ emm, _ := em.extensionsRead()
+ for _, mx := range emm {
+ if m, ok := mx.value.(Message); ok {
+ DiscardUnknown(m)
+ }
+ }
+ }
+
+ if di.unrecognized.IsValid() {
+ *src.offset(di.unrecognized).toBytes() = nil
+ }
+}
+
+func (di *discardInfo) computeDiscardInfo() {
+ di.lock.Lock()
+ defer di.lock.Unlock()
+ if di.initialized != 0 {
+ return
+ }
+ t := di.typ
+ n := t.NumField()
+
+ for i := 0; i < n; i++ {
+ f := t.Field(i)
+ if strings.HasPrefix(f.Name, "XXX_") {
+ continue
+ }
+
+ dfi := discardFieldInfo{field: toField(&f)}
+ tf := f.Type
+
+ // Unwrap tf to get its most basic type.
+ var isPointer, isSlice bool
+ if tf.Kind() == reflect.Slice && tf.Elem().Kind() != reflect.Uint8 {
+ isSlice = true
+ tf = tf.Elem()
+ }
+ if tf.Kind() == reflect.Ptr {
+ isPointer = true
+ tf = tf.Elem()
+ }
+ if isPointer && isSlice && tf.Kind() != reflect.Struct {
+ panic(fmt.Sprintf("%v.%s cannot be a slice of pointers to primitive types", t, f.Name))
+ }
+
+ switch tf.Kind() {
+ case reflect.Struct:
+ switch {
+ case !isPointer:
+ panic(fmt.Sprintf("%v.%s cannot be a direct struct value", t, f.Name))
+ case isSlice: // E.g., []*pb.T
+ di := getDiscardInfo(tf)
+ dfi.discard = func(src pointer) {
+ sps := src.getPointerSlice()
+ for _, sp := range sps {
+ if !sp.isNil() {
+ di.discard(sp)
+ }
+ }
+ }
+ default: // E.g., *pb.T
+ di := getDiscardInfo(tf)
+ dfi.discard = func(src pointer) {
+ sp := src.getPointer()
+ if !sp.isNil() {
+ di.discard(sp)
+ }
+ }
+ }
+ case reflect.Map:
+ switch {
+ case isPointer || isSlice:
+ panic(fmt.Sprintf("%v.%s cannot be a pointer to a map or a slice of map values", t, f.Name))
+ default: // E.g., map[K]V
+ if tf.Elem().Kind() == reflect.Ptr { // Proto struct (e.g., *T)
+ dfi.discard = func(src pointer) {
+ sm := src.asPointerTo(tf).Elem()
+ if sm.Len() == 0 {
+ return
+ }
+ for _, key := range sm.MapKeys() {
+ val := sm.MapIndex(key)
+ DiscardUnknown(val.Interface().(Message))
+ }
+ }
+ } else {
+ dfi.discard = func(pointer) {} // Noop
+ }
+ }
+ case reflect.Interface:
+ // Must be oneof field.
+ switch {
+ case isPointer || isSlice:
+ panic(fmt.Sprintf("%v.%s cannot be a pointer to a interface or a slice of interface values", t, f.Name))
+ default: // E.g., interface{}
+ // TODO: Make this faster?
+ dfi.discard = func(src pointer) {
+ su := src.asPointerTo(tf).Elem()
+ if !su.IsNil() {
+ sv := su.Elem().Elem().Field(0)
+ if sv.Kind() == reflect.Ptr && sv.IsNil() {
+ return
+ }
+ switch sv.Type().Kind() {
+ case reflect.Ptr: // Proto struct (e.g., *T)
+ DiscardUnknown(sv.Interface().(Message))
+ }
+ }
+ }
+ }
+ default:
+ continue
+ }
+ di.fields = append(di.fields, dfi)
+ }
+
+ di.unrecognized = invalidField
+ if f, ok := t.FieldByName("XXX_unrecognized"); ok {
+ if f.Type != reflect.TypeOf([]byte{}) {
+ panic("expected XXX_unrecognized to be of type []byte")
+ }
+ di.unrecognized = toField(&f)
+ }
+
+ atomic.StoreInt32(&di.initialized, 1)
+}
+
+func discardLegacy(m Message) {
+ v := reflect.ValueOf(m)
+ if v.Kind() != reflect.Ptr || v.IsNil() {
+ return
+ }
+ v = v.Elem()
+ if v.Kind() != reflect.Struct {
+ return
+ }
+ t := v.Type()
+
+ for i := 0; i < v.NumField(); i++ {
+ f := t.Field(i)
+ if strings.HasPrefix(f.Name, "XXX_") {
+ continue
+ }
+ vf := v.Field(i)
+ tf := f.Type
+
+ // Unwrap tf to get its most basic type.
+ var isPointer, isSlice bool
+ if tf.Kind() == reflect.Slice && tf.Elem().Kind() != reflect.Uint8 {
+ isSlice = true
+ tf = tf.Elem()
+ }
+ if tf.Kind() == reflect.Ptr {
+ isPointer = true
+ tf = tf.Elem()
+ }
+ if isPointer && isSlice && tf.Kind() != reflect.Struct {
+ panic(fmt.Sprintf("%T.%s cannot be a slice of pointers to primitive types", m, f.Name))
+ }
+
+ switch tf.Kind() {
+ case reflect.Struct:
+ switch {
+ case !isPointer:
+ panic(fmt.Sprintf("%T.%s cannot be a direct struct value", m, f.Name))
+ case isSlice: // E.g., []*pb.T
+ for j := 0; j < vf.Len(); j++ {
+ discardLegacy(vf.Index(j).Interface().(Message))
+ }
+ default: // E.g., *pb.T
+ discardLegacy(vf.Interface().(Message))
+ }
+ case reflect.Map:
+ switch {
+ case isPointer || isSlice:
+ panic(fmt.Sprintf("%T.%s cannot be a pointer to a map or a slice of map values", m, f.Name))
+ default: // E.g., map[K]V
+ tv := vf.Type().Elem()
+ if tv.Kind() == reflect.Ptr && tv.Implements(protoMessageType) { // Proto struct (e.g., *T)
+ for _, key := range vf.MapKeys() {
+ val := vf.MapIndex(key)
+ discardLegacy(val.Interface().(Message))
+ }
+ }
+ }
+ case reflect.Interface:
+ // Must be oneof field.
+ switch {
+ case isPointer || isSlice:
+ panic(fmt.Sprintf("%T.%s cannot be a pointer to a interface or a slice of interface values", m, f.Name))
+ default: // E.g., test_proto.isCommunique_Union interface
+ if !vf.IsNil() && f.Tag.Get("protobuf_oneof") != "" {
+ vf = vf.Elem() // E.g., *test_proto.Communique_Msg
+ if !vf.IsNil() {
+ vf = vf.Elem() // E.g., test_proto.Communique_Msg
+ vf = vf.Field(0) // E.g., Proto struct (e.g., *T) or primitive value
+ if vf.Kind() == reflect.Ptr {
+ discardLegacy(vf.Interface().(Message))
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if vf := v.FieldByName("XXX_unrecognized"); vf.IsValid() {
+ if vf.Type() != reflect.TypeOf([]byte{}) {
+ panic("expected XXX_unrecognized to be of type []byte")
+ }
+ vf.Set(reflect.ValueOf([]byte(nil)))
+ }
+
+ // For proto2 messages, only discard unknown fields in message extensions
+ // that have been accessed via GetExtension.
+ if em, err := extendable(m); err == nil {
+ // Ignore lock since discardLegacy is not concurrency safe.
+ emm, _ := em.extensionsRead()
+ for _, mx := range emm {
+ if m, ok := mx.value.(Message); ok {
+ discardLegacy(m)
+ }
+ }
+ }
+}
diff --git a/vendor/github.com/golang/protobuf/proto/encode.go b/vendor/github.com/golang/protobuf/proto/encode.go
index 8b84d1b22..3abfed2cf 100644
--- a/vendor/github.com/golang/protobuf/proto/encode.go
+++ b/vendor/github.com/golang/protobuf/proto/encode.go
@@ -37,28 +37,9 @@ package proto
import (
"errors"
- "fmt"
"reflect"
- "sort"
)
-// RequiredNotSetError is the error returned if Marshal is called with
-// a protocol buffer struct whose required fields have not
-// all been initialized. It is also the error returned if Unmarshal is
-// called with an encoded protocol buffer that does not include all the
-// required fields.
-//
-// When printed, RequiredNotSetError reports the first unset required field in a
-// message. If the field cannot be precisely determined, it is reported as
-// "{Unknown}".
-type RequiredNotSetError struct {
- field string
-}
-
-func (e *RequiredNotSetError) Error() string {
- return fmt.Sprintf("proto: required field %q not set", e.field)
-}
-
var (
// errRepeatedHasNil is the error returned if Marshal is called with
// a struct with a repeated field containing a nil element.
@@ -82,10 +63,6 @@ var (
const maxVarintBytes = 10 // maximum length of a varint
-// maxMarshalSize is the largest allowed size of an encoded protobuf,
-// since C++ and Java use signed int32s for the size.
-const maxMarshalSize = 1<<31 - 1
-
// EncodeVarint returns the varint encoding of x.
// This is the format for the
// int32, int64, uint32, uint64, bool, and enum
@@ -119,18 +96,27 @@ func (p *Buffer) EncodeVarint(x uint64) error {
// SizeVarint returns the varint encoding size of an integer.
func SizeVarint(x uint64) int {
- return sizeVarint(x)
-}
-
-func sizeVarint(x uint64) (n int) {
- for {
- n++
- x >>= 7
- if x == 0 {
- break
- }
- }
- return n
+ switch {
+ case x < 1<<7:
+ return 1
+ case x < 1<<14:
+ return 2
+ case x < 1<<21:
+ return 3
+ case x < 1<<28:
+ return 4
+ case x < 1<<35:
+ return 5
+ case x < 1<<42:
+ return 6
+ case x < 1<<49:
+ return 7
+ case x < 1<<56:
+ return 8
+ case x < 1<<63:
+ return 9
+ }
+ return 10
}
// EncodeFixed64 writes a 64-bit integer to the Buffer.
@@ -149,10 +135,6 @@ func (p *Buffer) EncodeFixed64(x uint64) error {
return nil
}
-func sizeFixed64(x uint64) int {
- return 8
-}
-
// EncodeFixed32 writes a 32-bit integer to the Buffer.
// This is the format for the
// fixed32, sfixed32, and float protocol buffer types.
@@ -165,20 +147,12 @@ func (p *Buffer) EncodeFixed32(x uint64) error {
return nil
}
-func sizeFixed32(x uint64) int {
- return 4
-}
-
// EncodeZigzag64 writes a zigzag-encoded 64-bit integer
// to the Buffer.
// This is the format used for the sint64 protocol buffer type.
func (p *Buffer) EncodeZigzag64(x uint64) error {
// use signed number to get arithmetic right shift.
- return p.EncodeVarint((x << 1) ^ uint64((int64(x) >> 63)))
-}
-
-func sizeZigzag64(x uint64) int {
- return sizeVarint((x << 1) ^ uint64((int64(x) >> 63)))
+ return p.EncodeVarint(uint64((x << 1) ^ uint64((int64(x) >> 63))))
}
// EncodeZigzag32 writes a zigzag-encoded 32-bit integer
@@ -189,10 +163,6 @@ func (p *Buffer) EncodeZigzag32(x uint64) error {
return p.EncodeVarint(uint64((uint32(x) << 1) ^ uint32((int32(x) >> 31))))
}
-func sizeZigzag32(x uint64) int {
- return sizeVarint(uint64((uint32(x) << 1) ^ uint32((int32(x) >> 31))))
-}
-
// EncodeRawBytes writes a count-delimited byte buffer to the Buffer.
// This is the format used for the bytes protocol buffer
// type and for embedded messages.
@@ -202,11 +172,6 @@ func (p *Buffer) EncodeRawBytes(b []byte) error {
return nil
}
-func sizeRawBytes(b []byte) int {
- return sizeVarint(uint64(len(b))) +
- len(b)
-}
-
// EncodeStringBytes writes an encoded string to the Buffer.
// This is the format used for the proto2 string type.
func (p *Buffer) EncodeStringBytes(s string) error {
@@ -215,319 +180,17 @@ func (p *Buffer) EncodeStringBytes(s string) error {
return nil
}
-func sizeStringBytes(s string) int {
- return sizeVarint(uint64(len(s))) +
- len(s)
-}
-
// Marshaler is the interface representing objects that can marshal themselves.
type Marshaler interface {
Marshal() ([]byte, error)
}
-// Marshal takes the protocol buffer
-// and encodes it into the wire format, returning the data.
-func Marshal(pb Message) ([]byte, error) {
- // Can the object marshal itself?
- if m, ok := pb.(Marshaler); ok {
- return m.Marshal()
- }
- p := NewBuffer(nil)
- err := p.Marshal(pb)
- if p.buf == nil && err == nil {
- // Return a non-nil slice on success.
- return []byte{}, nil
- }
- return p.buf, err
-}
-
// EncodeMessage writes the protocol buffer to the Buffer,
// prefixed by a varint-encoded length.
func (p *Buffer) EncodeMessage(pb Message) error {
- t, base, err := getbase(pb)
- if structPointer_IsNil(base) {
- return ErrNil
- }
- if err == nil {
- var state errorState
- err = p.enc_len_struct(GetProperties(t.Elem()), base, &state)
- }
- return err
-}
-
-// Marshal takes the protocol buffer
-// and encodes it into the wire format, writing the result to the
-// Buffer.
-func (p *Buffer) Marshal(pb Message) error {
- // Can the object marshal itself?
- if m, ok := pb.(Marshaler); ok {
- data, err := m.Marshal()
- p.buf = append(p.buf, data...)
- return err
- }
-
- t, base, err := getbase(pb)
- if structPointer_IsNil(base) {
- return ErrNil
- }
- if err == nil {
- err = p.enc_struct(GetProperties(t.Elem()), base)
- }
-
- if collectStats {
- (stats).Encode++ // Parens are to work around a goimports bug.
- }
-
- if len(p.buf) > maxMarshalSize {
- return ErrTooLarge
- }
- return err
-}
-
-// Size returns the encoded size of a protocol buffer.
-func Size(pb Message) (n int) {
- // Can the object marshal itself? If so, Size is slow.
- // TODO: add Size to Marshaler, or add a Sizer interface.
- if m, ok := pb.(Marshaler); ok {
- b, _ := m.Marshal()
- return len(b)
- }
-
- t, base, err := getbase(pb)
- if structPointer_IsNil(base) {
- return 0
- }
- if err == nil {
- n = size_struct(GetProperties(t.Elem()), base)
- }
-
- if collectStats {
- (stats).Size++ // Parens are to work around a goimports bug.
- }
-
- return
-}
-
-// Individual type encoders.
-
-// Encode a bool.
-func (o *Buffer) enc_bool(p *Properties, base structPointer) error {
- v := *structPointer_Bool(base, p.field)
- if v == nil {
- return ErrNil
- }
- x := 0
- if *v {
- x = 1
- }
- o.buf = append(o.buf, p.tagcode...)
- p.valEnc(o, uint64(x))
- return nil
-}
-
-func (o *Buffer) enc_proto3_bool(p *Properties, base structPointer) error {
- v := *structPointer_BoolVal(base, p.field)
- if !v {
- return ErrNil
- }
- o.buf = append(o.buf, p.tagcode...)
- p.valEnc(o, 1)
- return nil
-}
-
-func size_bool(p *Properties, base structPointer) int {
- v := *structPointer_Bool(base, p.field)
- if v == nil {
- return 0
- }
- return len(p.tagcode) + 1 // each bool takes exactly one byte
-}
-
-func size_proto3_bool(p *Properties, base structPointer) int {
- v := *structPointer_BoolVal(base, p.field)
- if !v && !p.oneof {
- return 0
- }
- return len(p.tagcode) + 1 // each bool takes exactly one byte
-}
-
-// Encode an int32.
-func (o *Buffer) enc_int32(p *Properties, base structPointer) error {
- v := structPointer_Word32(base, p.field)
- if word32_IsNil(v) {
- return ErrNil
- }
- x := int32(word32_Get(v)) // permit sign extension to use full 64-bit range
- o.buf = append(o.buf, p.tagcode...)
- p.valEnc(o, uint64(x))
- return nil
-}
-
-func (o *Buffer) enc_proto3_int32(p *Properties, base structPointer) error {
- v := structPointer_Word32Val(base, p.field)
- x := int32(word32Val_Get(v)) // permit sign extension to use full 64-bit range
- if x == 0 {
- return ErrNil
- }
- o.buf = append(o.buf, p.tagcode...)
- p.valEnc(o, uint64(x))
- return nil
-}
-
-func size_int32(p *Properties, base structPointer) (n int) {
- v := structPointer_Word32(base, p.field)
- if word32_IsNil(v) {
- return 0
- }
- x := int32(word32_Get(v)) // permit sign extension to use full 64-bit range
- n += len(p.tagcode)
- n += p.valSize(uint64(x))
- return
-}
-
-func size_proto3_int32(p *Properties, base structPointer) (n int) {
- v := structPointer_Word32Val(base, p.field)
- x := int32(word32Val_Get(v)) // permit sign extension to use full 64-bit range
- if x == 0 && !p.oneof {
- return 0
- }
- n += len(p.tagcode)
- n += p.valSize(uint64(x))
- return
-}
-
-// Encode a uint32.
-// Exactly the same as int32, except for no sign extension.
-func (o *Buffer) enc_uint32(p *Properties, base structPointer) error {
- v := structPointer_Word32(base, p.field)
- if word32_IsNil(v) {
- return ErrNil
- }
- x := word32_Get(v)
- o.buf = append(o.buf, p.tagcode...)
- p.valEnc(o, uint64(x))
- return nil
-}
-
-func (o *Buffer) enc_proto3_uint32(p *Properties, base structPointer) error {
- v := structPointer_Word32Val(base, p.field)
- x := word32Val_Get(v)
- if x == 0 {
- return ErrNil
- }
- o.buf = append(o.buf, p.tagcode...)
- p.valEnc(o, uint64(x))
- return nil
-}
-
-func size_uint32(p *Properties, base structPointer) (n int) {
- v := structPointer_Word32(base, p.field)
- if word32_IsNil(v) {
- return 0
- }
- x := word32_Get(v)
- n += len(p.tagcode)
- n += p.valSize(uint64(x))
- return
-}
-
-func size_proto3_uint32(p *Properties, base structPointer) (n int) {
- v := structPointer_Word32Val(base, p.field)
- x := word32Val_Get(v)
- if x == 0 && !p.oneof {
- return 0
- }
- n += len(p.tagcode)
- n += p.valSize(uint64(x))
- return
-}
-
-// Encode an int64.
-func (o *Buffer) enc_int64(p *Properties, base structPointer) error {
- v := structPointer_Word64(base, p.field)
- if word64_IsNil(v) {
- return ErrNil
- }
- x := word64_Get(v)
- o.buf = append(o.buf, p.tagcode...)
- p.valEnc(o, x)
- return nil
-}
-
-func (o *Buffer) enc_proto3_int64(p *Properties, base structPointer) error {
- v := structPointer_Word64Val(base, p.field)
- x := word64Val_Get(v)
- if x == 0 {
- return ErrNil
- }
- o.buf = append(o.buf, p.tagcode...)
- p.valEnc(o, x)
- return nil
-}
-
-func size_int64(p *Properties, base structPointer) (n int) {
- v := structPointer_Word64(base, p.field)
- if word64_IsNil(v) {
- return 0
- }
- x := word64_Get(v)
- n += len(p.tagcode)
- n += p.valSize(x)
- return
-}
-
-func size_proto3_int64(p *Properties, base structPointer) (n int) {
- v := structPointer_Word64Val(base, p.field)
- x := word64Val_Get(v)
- if x == 0 && !p.oneof {
- return 0
- }
- n += len(p.tagcode)
- n += p.valSize(x)
- return
-}
-
-// Encode a string.
-func (o *Buffer) enc_string(p *Properties, base structPointer) error {
- v := *structPointer_String(base, p.field)
- if v == nil {
- return ErrNil
- }
- x := *v
- o.buf = append(o.buf, p.tagcode...)
- o.EncodeStringBytes(x)
- return nil
-}
-
-func (o *Buffer) enc_proto3_string(p *Properties, base structPointer) error {
- v := *structPointer_StringVal(base, p.field)
- if v == "" {
- return ErrNil
- }
- o.buf = append(o.buf, p.tagcode...)
- o.EncodeStringBytes(v)
- return nil
-}
-
-func size_string(p *Properties, base structPointer) (n int) {
- v := *structPointer_String(base, p.field)
- if v == nil {
- return 0
- }
- x := *v
- n += len(p.tagcode)
- n += sizeStringBytes(x)
- return
-}
-
-func size_proto3_string(p *Properties, base structPointer) (n int) {
- v := *structPointer_StringVal(base, p.field)
- if v == "" && !p.oneof {
- return 0
- }
- n += len(p.tagcode)
- n += sizeStringBytes(v)
- return
+ siz := Size(pb)
+ p.EncodeVarint(uint64(siz))
+ return p.Marshal(pb)
}
// All protocol buffer fields are nillable, but be careful.
@@ -538,825 +201,3 @@ func isNil(v reflect.Value) bool {
}
return false
}
-
-// Encode a message struct.
-func (o *Buffer) enc_struct_message(p *Properties, base structPointer) error {
- var state errorState
- structp := structPointer_GetStructPointer(base, p.field)
- if structPointer_IsNil(structp) {
- return ErrNil
- }
-
- // Can the object marshal itself?
- if p.isMarshaler {
- m := structPointer_Interface(structp, p.stype).(Marshaler)
- data, err := m.Marshal()
- if err != nil && !state.shouldContinue(err, nil) {
- return err
- }
- o.buf = append(o.buf, p.tagcode...)
- o.EncodeRawBytes(data)
- return state.err
- }
-
- o.buf = append(o.buf, p.tagcode...)
- return o.enc_len_struct(p.sprop, structp, &state)
-}
-
-func size_struct_message(p *Properties, base structPointer) int {
- structp := structPointer_GetStructPointer(base, p.field)
- if structPointer_IsNil(structp) {
- return 0
- }
-
- // Can the object marshal itself?
- if p.isMarshaler {
- m := structPointer_Interface(structp, p.stype).(Marshaler)
- data, _ := m.Marshal()
- n0 := len(p.tagcode)
- n1 := sizeRawBytes(data)
- return n0 + n1
- }
-
- n0 := len(p.tagcode)
- n1 := size_struct(p.sprop, structp)
- n2 := sizeVarint(uint64(n1)) // size of encoded length
- return n0 + n1 + n2
-}
-
-// Encode a group struct.
-func (o *Buffer) enc_struct_group(p *Properties, base structPointer) error {
- var state errorState
- b := structPointer_GetStructPointer(base, p.field)
- if structPointer_IsNil(b) {
- return ErrNil
- }
-
- o.EncodeVarint(uint64((p.Tag << 3) | WireStartGroup))
- err := o.enc_struct(p.sprop, b)
- if err != nil && !state.shouldContinue(err, nil) {
- return err
- }
- o.EncodeVarint(uint64((p.Tag << 3) | WireEndGroup))
- return state.err
-}
-
-func size_struct_group(p *Properties, base structPointer) (n int) {
- b := structPointer_GetStructPointer(base, p.field)
- if structPointer_IsNil(b) {
- return 0
- }
-
- n += sizeVarint(uint64((p.Tag << 3) | WireStartGroup))
- n += size_struct(p.sprop, b)
- n += sizeVarint(uint64((p.Tag << 3) | WireEndGroup))
- return
-}
-
-// Encode a slice of bools ([]bool).
-func (o *Buffer) enc_slice_bool(p *Properties, base structPointer) error {
- s := *structPointer_BoolSlice(base, p.field)
- l := len(s)
- if l == 0 {
- return ErrNil
- }
- for _, x := range s {
- o.buf = append(o.buf, p.tagcode...)
- v := uint64(0)
- if x {
- v = 1
- }
- p.valEnc(o, v)
- }
- return nil
-}
-
-func size_slice_bool(p *Properties, base structPointer) int {
- s := *structPointer_BoolSlice(base, p.field)
- l := len(s)
- if l == 0 {
- return 0
- }
- return l * (len(p.tagcode) + 1) // each bool takes exactly one byte
-}
-
-// Encode a slice of bools ([]bool) in packed format.
-func (o *Buffer) enc_slice_packed_bool(p *Properties, base structPointer) error {
- s := *structPointer_BoolSlice(base, p.field)
- l := len(s)
- if l == 0 {
- return ErrNil
- }
- o.buf = append(o.buf, p.tagcode...)
- o.EncodeVarint(uint64(l)) // each bool takes exactly one byte
- for _, x := range s {
- v := uint64(0)
- if x {
- v = 1
- }
- p.valEnc(o, v)
- }
- return nil
-}
-
-func size_slice_packed_bool(p *Properties, base structPointer) (n int) {
- s := *structPointer_BoolSlice(base, p.field)
- l := len(s)
- if l == 0 {
- return 0
- }
- n += len(p.tagcode)
- n += sizeVarint(uint64(l))
- n += l // each bool takes exactly one byte
- return
-}
-
-// Encode a slice of bytes ([]byte).
-func (o *Buffer) enc_slice_byte(p *Properties, base structPointer) error {
- s := *structPointer_Bytes(base, p.field)
- if s == nil {
- return ErrNil
- }
- o.buf = append(o.buf, p.tagcode...)
- o.EncodeRawBytes(s)
- return nil
-}
-
-func (o *Buffer) enc_proto3_slice_byte(p *Properties, base structPointer) error {
- s := *structPointer_Bytes(base, p.field)
- if len(s) == 0 {
- return ErrNil
- }
- o.buf = append(o.buf, p.tagcode...)
- o.EncodeRawBytes(s)
- return nil
-}
-
-func size_slice_byte(p *Properties, base structPointer) (n int) {
- s := *structPointer_Bytes(base, p.field)
- if s == nil && !p.oneof {
- return 0
- }
- n += len(p.tagcode)
- n += sizeRawBytes(s)
- return
-}
-
-func size_proto3_slice_byte(p *Properties, base structPointer) (n int) {
- s := *structPointer_Bytes(base, p.field)
- if len(s) == 0 && !p.oneof {
- return 0
- }
- n += len(p.tagcode)
- n += sizeRawBytes(s)
- return
-}
-
-// Encode a slice of int32s ([]int32).
-func (o *Buffer) enc_slice_int32(p *Properties, base structPointer) error {
- s := structPointer_Word32Slice(base, p.field)
- l := s.Len()
- if l == 0 {
- return ErrNil
- }
- for i := 0; i < l; i++ {
- o.buf = append(o.buf, p.tagcode...)
- x := int32(s.Index(i)) // permit sign extension to use full 64-bit range
- p.valEnc(o, uint64(x))
- }
- return nil
-}
-
-func size_slice_int32(p *Properties, base structPointer) (n int) {
- s := structPointer_Word32Slice(base, p.field)
- l := s.Len()
- if l == 0 {
- return 0
- }
- for i := 0; i < l; i++ {
- n += len(p.tagcode)
- x := int32(s.Index(i)) // permit sign extension to use full 64-bit range
- n += p.valSize(uint64(x))
- }
- return
-}
-
-// Encode a slice of int32s ([]int32) in packed format.
-func (o *Buffer) enc_slice_packed_int32(p *Properties, base structPointer) error {
- s := structPointer_Word32Slice(base, p.field)
- l := s.Len()
- if l == 0 {
- return ErrNil
- }
- // TODO: Reuse a Buffer.
- buf := NewBuffer(nil)
- for i := 0; i < l; i++ {
- x := int32(s.Index(i)) // permit sign extension to use full 64-bit range
- p.valEnc(buf, uint64(x))
- }
-
- o.buf = append(o.buf, p.tagcode...)
- o.EncodeVarint(uint64(len(buf.buf)))
- o.buf = append(o.buf, buf.buf...)
- return nil
-}
-
-func size_slice_packed_int32(p *Properties, base structPointer) (n int) {
- s := structPointer_Word32Slice(base, p.field)
- l := s.Len()
- if l == 0 {
- return 0
- }
- var bufSize int
- for i := 0; i < l; i++ {
- x := int32(s.Index(i)) // permit sign extension to use full 64-bit range
- bufSize += p.valSize(uint64(x))
- }
-
- n += len(p.tagcode)
- n += sizeVarint(uint64(bufSize))
- n += bufSize
- return
-}
-
-// Encode a slice of uint32s ([]uint32).
-// Exactly the same as int32, except for no sign extension.
-func (o *Buffer) enc_slice_uint32(p *Properties, base structPointer) error {
- s := structPointer_Word32Slice(base, p.field)
- l := s.Len()
- if l == 0 {
- return ErrNil
- }
- for i := 0; i < l; i++ {
- o.buf = append(o.buf, p.tagcode...)
- x := s.Index(i)
- p.valEnc(o, uint64(x))
- }
- return nil
-}
-
-func size_slice_uint32(p *Properties, base structPointer) (n int) {
- s := structPointer_Word32Slice(base, p.field)
- l := s.Len()
- if l == 0 {
- return 0
- }
- for i := 0; i < l; i++ {
- n += len(p.tagcode)
- x := s.Index(i)
- n += p.valSize(uint64(x))
- }
- return
-}
-
-// Encode a slice of uint32s ([]uint32) in packed format.
-// Exactly the same as int32, except for no sign extension.
-func (o *Buffer) enc_slice_packed_uint32(p *Properties, base structPointer) error {
- s := structPointer_Word32Slice(base, p.field)
- l := s.Len()
- if l == 0 {
- return ErrNil
- }
- // TODO: Reuse a Buffer.
- buf := NewBuffer(nil)
- for i := 0; i < l; i++ {
- p.valEnc(buf, uint64(s.Index(i)))
- }
-
- o.buf = append(o.buf, p.tagcode...)
- o.EncodeVarint(uint64(len(buf.buf)))
- o.buf = append(o.buf, buf.buf...)
- return nil
-}
-
-func size_slice_packed_uint32(p *Properties, base structPointer) (n int) {
- s := structPointer_Word32Slice(base, p.field)
- l := s.Len()
- if l == 0 {
- return 0
- }
- var bufSize int
- for i := 0; i < l; i++ {
- bufSize += p.valSize(uint64(s.Index(i)))
- }
-
- n += len(p.tagcode)
- n += sizeVarint(uint64(bufSize))
- n += bufSize
- return
-}
-
-// Encode a slice of int64s ([]int64).
-func (o *Buffer) enc_slice_int64(p *Properties, base structPointer) error {
- s := structPointer_Word64Slice(base, p.field)
- l := s.Len()
- if l == 0 {
- return ErrNil
- }
- for i := 0; i < l; i++ {
- o.buf = append(o.buf, p.tagcode...)
- p.valEnc(o, s.Index(i))
- }
- return nil
-}
-
-func size_slice_int64(p *Properties, base structPointer) (n int) {
- s := structPointer_Word64Slice(base, p.field)
- l := s.Len()
- if l == 0 {
- return 0
- }
- for i := 0; i < l; i++ {
- n += len(p.tagcode)
- n += p.valSize(s.Index(i))
- }
- return
-}
-
-// Encode a slice of int64s ([]int64) in packed format.
-func (o *Buffer) enc_slice_packed_int64(p *Properties, base structPointer) error {
- s := structPointer_Word64Slice(base, p.field)
- l := s.Len()
- if l == 0 {
- return ErrNil
- }
- // TODO: Reuse a Buffer.
- buf := NewBuffer(nil)
- for i := 0; i < l; i++ {
- p.valEnc(buf, s.Index(i))
- }
-
- o.buf = append(o.buf, p.tagcode...)
- o.EncodeVarint(uint64(len(buf.buf)))
- o.buf = append(o.buf, buf.buf...)
- return nil
-}
-
-func size_slice_packed_int64(p *Properties, base structPointer) (n int) {
- s := structPointer_Word64Slice(base, p.field)
- l := s.Len()
- if l == 0 {
- return 0
- }
- var bufSize int
- for i := 0; i < l; i++ {
- bufSize += p.valSize(s.Index(i))
- }
-
- n += len(p.tagcode)
- n += sizeVarint(uint64(bufSize))
- n += bufSize
- return
-}
-
-// Encode a slice of slice of bytes ([][]byte).
-func (o *Buffer) enc_slice_slice_byte(p *Properties, base structPointer) error {
- ss := *structPointer_BytesSlice(base, p.field)
- l := len(ss)
- if l == 0 {
- return ErrNil
- }
- for i := 0; i < l; i++ {
- o.buf = append(o.buf, p.tagcode...)
- o.EncodeRawBytes(ss[i])
- }
- return nil
-}
-
-func size_slice_slice_byte(p *Properties, base structPointer) (n int) {
- ss := *structPointer_BytesSlice(base, p.field)
- l := len(ss)
- if l == 0 {
- return 0
- }
- n += l * len(p.tagcode)
- for i := 0; i < l; i++ {
- n += sizeRawBytes(ss[i])
- }
- return
-}
-
-// Encode a slice of strings ([]string).
-func (o *Buffer) enc_slice_string(p *Properties, base structPointer) error {
- ss := *structPointer_StringSlice(base, p.field)
- l := len(ss)
- for i := 0; i < l; i++ {
- o.buf = append(o.buf, p.tagcode...)
- o.EncodeStringBytes(ss[i])
- }
- return nil
-}
-
-func size_slice_string(p *Properties, base structPointer) (n int) {
- ss := *structPointer_StringSlice(base, p.field)
- l := len(ss)
- n += l * len(p.tagcode)
- for i := 0; i < l; i++ {
- n += sizeStringBytes(ss[i])
- }
- return
-}
-
-// Encode a slice of message structs ([]*struct).
-func (o *Buffer) enc_slice_struct_message(p *Properties, base structPointer) error {
- var state errorState
- s := structPointer_StructPointerSlice(base, p.field)
- l := s.Len()
-
- for i := 0; i < l; i++ {
- structp := s.Index(i)
- if structPointer_IsNil(structp) {
- return errRepeatedHasNil
- }
-
- // Can the object marshal itself?
- if p.isMarshaler {
- m := structPointer_Interface(structp, p.stype).(Marshaler)
- data, err := m.Marshal()
- if err != nil && !state.shouldContinue(err, nil) {
- return err
- }
- o.buf = append(o.buf, p.tagcode...)
- o.EncodeRawBytes(data)
- continue
- }
-
- o.buf = append(o.buf, p.tagcode...)
- err := o.enc_len_struct(p.sprop, structp, &state)
- if err != nil && !state.shouldContinue(err, nil) {
- if err == ErrNil {
- return errRepeatedHasNil
- }
- return err
- }
- }
- return state.err
-}
-
-func size_slice_struct_message(p *Properties, base structPointer) (n int) {
- s := structPointer_StructPointerSlice(base, p.field)
- l := s.Len()
- n += l * len(p.tagcode)
- for i := 0; i < l; i++ {
- structp := s.Index(i)
- if structPointer_IsNil(structp) {
- return // return the size up to this point
- }
-
- // Can the object marshal itself?
- if p.isMarshaler {
- m := structPointer_Interface(structp, p.stype).(Marshaler)
- data, _ := m.Marshal()
- n += sizeRawBytes(data)
- continue
- }
-
- n0 := size_struct(p.sprop, structp)
- n1 := sizeVarint(uint64(n0)) // size of encoded length
- n += n0 + n1
- }
- return
-}
-
-// Encode a slice of group structs ([]*struct).
-func (o *Buffer) enc_slice_struct_group(p *Properties, base structPointer) error {
- var state errorState
- s := structPointer_StructPointerSlice(base, p.field)
- l := s.Len()
-
- for i := 0; i < l; i++ {
- b := s.Index(i)
- if structPointer_IsNil(b) {
- return errRepeatedHasNil
- }
-
- o.EncodeVarint(uint64((p.Tag << 3) | WireStartGroup))
-
- err := o.enc_struct(p.sprop, b)
-
- if err != nil && !state.shouldContinue(err, nil) {
- if err == ErrNil {
- return errRepeatedHasNil
- }
- return err
- }
-
- o.EncodeVarint(uint64((p.Tag << 3) | WireEndGroup))
- }
- return state.err
-}
-
-func size_slice_struct_group(p *Properties, base structPointer) (n int) {
- s := structPointer_StructPointerSlice(base, p.field)
- l := s.Len()
-
- n += l * sizeVarint(uint64((p.Tag<<3)|WireStartGroup))
- n += l * sizeVarint(uint64((p.Tag<<3)|WireEndGroup))
- for i := 0; i < l; i++ {
- b := s.Index(i)
- if structPointer_IsNil(b) {
- return // return size up to this point
- }
-
- n += size_struct(p.sprop, b)
- }
- return
-}
-
-// Encode an extension map.
-func (o *Buffer) enc_map(p *Properties, base structPointer) error {
- exts := structPointer_ExtMap(base, p.field)
- if err := encodeExtensionsMap(*exts); err != nil {
- return err
- }
-
- return o.enc_map_body(*exts)
-}
-
-func (o *Buffer) enc_exts(p *Properties, base structPointer) error {
- exts := structPointer_Extensions(base, p.field)
-
- v, mu := exts.extensionsRead()
- if v == nil {
- return nil
- }
-
- mu.Lock()
- defer mu.Unlock()
- if err := encodeExtensionsMap(v); err != nil {
- return err
- }
-
- return o.enc_map_body(v)
-}
-
-func (o *Buffer) enc_map_body(v map[int32]Extension) error {
- // Fast-path for common cases: zero or one extensions.
- if len(v) <= 1 {
- for _, e := range v {
- o.buf = append(o.buf, e.enc...)
- }
- return nil
- }
-
- // Sort keys to provide a deterministic encoding.
- keys := make([]int, 0, len(v))
- for k := range v {
- keys = append(keys, int(k))
- }
- sort.Ints(keys)
-
- for _, k := range keys {
- o.buf = append(o.buf, v[int32(k)].enc...)
- }
- return nil
-}
-
-func size_map(p *Properties, base structPointer) int {
- v := structPointer_ExtMap(base, p.field)
- return extensionsMapSize(*v)
-}
-
-func size_exts(p *Properties, base structPointer) int {
- v := structPointer_Extensions(base, p.field)
- return extensionsSize(v)
-}
-
-// Encode a map field.
-func (o *Buffer) enc_new_map(p *Properties, base structPointer) error {
- var state errorState // XXX: or do we need to plumb this through?
-
- /*
- A map defined as
- map<key_type, value_type> map_field = N;
- is encoded in the same way as
- message MapFieldEntry {
- key_type key = 1;
- value_type value = 2;
- }
- repeated MapFieldEntry map_field = N;
- */
-
- v := structPointer_NewAt(base, p.field, p.mtype).Elem() // map[K]V
- if v.Len() == 0 {
- return nil
- }
-
- keycopy, valcopy, keybase, valbase := mapEncodeScratch(p.mtype)
-
- enc := func() error {
- if err := p.mkeyprop.enc(o, p.mkeyprop, keybase); err != nil {
- return err
- }
- if err := p.mvalprop.enc(o, p.mvalprop, valbase); err != nil && err != ErrNil {
- return err
- }
- return nil
- }
-
- // Don't sort map keys. It is not required by the spec, and C++ doesn't do it.
- for _, key := range v.MapKeys() {
- val := v.MapIndex(key)
-
- keycopy.Set(key)
- valcopy.Set(val)
-
- o.buf = append(o.buf, p.tagcode...)
- if err := o.enc_len_thing(enc, &state); err != nil {
- return err
- }
- }
- return nil
-}
-
-func size_new_map(p *Properties, base structPointer) int {
- v := structPointer_NewAt(base, p.field, p.mtype).Elem() // map[K]V
-
- keycopy, valcopy, keybase, valbase := mapEncodeScratch(p.mtype)
-
- n := 0
- for _, key := range v.MapKeys() {
- val := v.MapIndex(key)
- keycopy.Set(key)
- valcopy.Set(val)
-
- // Tag codes for key and val are the responsibility of the sub-sizer.
- keysize := p.mkeyprop.size(p.mkeyprop, keybase)
- valsize := p.mvalprop.size(p.mvalprop, valbase)
- entry := keysize + valsize
- // Add on tag code and length of map entry itself.
- n += len(p.tagcode) + sizeVarint(uint64(entry)) + entry
- }
- return n
-}
-
-// mapEncodeScratch returns a new reflect.Value matching the map's value type,
-// and a structPointer suitable for passing to an encoder or sizer.
-func mapEncodeScratch(mapType reflect.Type) (keycopy, valcopy reflect.Value, keybase, valbase structPointer) {
- // Prepare addressable doubly-indirect placeholders for the key and value types.
- // This is needed because the element-type encoders expect **T, but the map iteration produces T.
-
- keycopy = reflect.New(mapType.Key()).Elem() // addressable K
- keyptr := reflect.New(reflect.PtrTo(keycopy.Type())).Elem() // addressable *K
- keyptr.Set(keycopy.Addr()) //
- keybase = toStructPointer(keyptr.Addr()) // **K
-
- // Value types are more varied and require special handling.
- switch mapType.Elem().Kind() {
- case reflect.Slice:
- // []byte
- var dummy []byte
- valcopy = reflect.ValueOf(&dummy).Elem() // addressable []byte
- valbase = toStructPointer(valcopy.Addr())
- case reflect.Ptr:
- // message; the generated field type is map[K]*Msg (so V is *Msg),
- // so we only need one level of indirection.
- valcopy = reflect.New(mapType.Elem()).Elem() // addressable V
- valbase = toStructPointer(valcopy.Addr())
- default:
- // everything else
- valcopy = reflect.New(mapType.Elem()).Elem() // addressable V
- valptr := reflect.New(reflect.PtrTo(valcopy.Type())).Elem() // addressable *V
- valptr.Set(valcopy.Addr()) //
- valbase = toStructPointer(valptr.Addr()) // **V
- }
- return
-}
-
-// Encode a struct.
-func (o *Buffer) enc_struct(prop *StructProperties, base structPointer) error {
- var state errorState
- // Encode fields in tag order so that decoders may use optimizations
- // that depend on the ordering.
- // https://developers.google.com/protocol-buffers/docs/encoding#order
- for _, i := range prop.order {
- p := prop.Prop[i]
- if p.enc != nil {
- err := p.enc(o, p, base)
- if err != nil {
- if err == ErrNil {
- if p.Required && state.err == nil {
- state.err = &RequiredNotSetError{p.Name}
- }
- } else if err == errRepeatedHasNil {
- // Give more context to nil values in repeated fields.
- return errors.New("repeated field " + p.OrigName + " has nil element")
- } else if !state.shouldContinue(err, p) {
- return err
- }
- }
- if len(o.buf) > maxMarshalSize {
- return ErrTooLarge
- }
- }
- }
-
- // Do oneof fields.
- if prop.oneofMarshaler != nil {
- m := structPointer_Interface(base, prop.stype).(Message)
- if err := prop.oneofMarshaler(m, o); err == ErrNil {
- return errOneofHasNil
- } else if err != nil {
- return err
- }
- }
-
- // Add unrecognized fields at the end.
- if prop.unrecField.IsValid() {
- v := *structPointer_Bytes(base, prop.unrecField)
- if len(o.buf)+len(v) > maxMarshalSize {
- return ErrTooLarge
- }
- if len(v) > 0 {
- o.buf = append(o.buf, v...)
- }
- }
-
- return state.err
-}
-
-func size_struct(prop *StructProperties, base structPointer) (n int) {
- for _, i := range prop.order {
- p := prop.Prop[i]
- if p.size != nil {
- n += p.size(p, base)
- }
- }
-
- // Add unrecognized fields at the end.
- if prop.unrecField.IsValid() {
- v := *structPointer_Bytes(base, prop.unrecField)
- n += len(v)
- }
-
- // Factor in any oneof fields.
- if prop.oneofSizer != nil {
- m := structPointer_Interface(base, prop.stype).(Message)
- n += prop.oneofSizer(m)
- }
-
- return
-}
-
-var zeroes [20]byte // longer than any conceivable sizeVarint
-
-// Encode a struct, preceded by its encoded length (as a varint).
-func (o *Buffer) enc_len_struct(prop *StructProperties, base structPointer, state *errorState) error {
- return o.enc_len_thing(func() error { return o.enc_struct(prop, base) }, state)
-}
-
-// Encode something, preceded by its encoded length (as a varint).
-func (o *Buffer) enc_len_thing(enc func() error, state *errorState) error {
- iLen := len(o.buf)
- o.buf = append(o.buf, 0, 0, 0, 0) // reserve four bytes for length
- iMsg := len(o.buf)
- err := enc()
- if err != nil && !state.shouldContinue(err, nil) {
- return err
- }
- lMsg := len(o.buf) - iMsg
- lLen := sizeVarint(uint64(lMsg))
- switch x := lLen - (iMsg - iLen); {
- case x > 0: // actual length is x bytes larger than the space we reserved
- // Move msg x bytes right.
- o.buf = append(o.buf, zeroes[:x]...)
- copy(o.buf[iMsg+x:], o.buf[iMsg:iMsg+lMsg])
- case x < 0: // actual length is x bytes smaller than the space we reserved
- // Move msg x bytes left.
- copy(o.buf[iMsg+x:], o.buf[iMsg:iMsg+lMsg])
- o.buf = o.buf[:len(o.buf)+x] // x is negative
- }
- // Encode the length in the reserved space.
- o.buf = o.buf[:iLen]
- o.EncodeVarint(uint64(lMsg))
- o.buf = o.buf[:len(o.buf)+lMsg]
- return state.err
-}
-
-// errorState maintains the first error that occurs and updates that error
-// with additional context.
-type errorState struct {
- err error
-}
-
-// shouldContinue reports whether encoding should continue upon encountering the
-// given error. If the error is RequiredNotSetError, shouldContinue returns true
-// and, if this is the first appearance of that error, remembers it for future
-// reporting.
-//
-// If prop is not nil, it may update any error with additional context about the
-// field with the error.
-func (s *errorState) shouldContinue(err error, prop *Properties) bool {
- // Ignore unset required fields.
- reqNotSet, ok := err.(*RequiredNotSetError)
- if !ok {
- return false
- }
- if s.err == nil {
- if prop != nil {
- err = &RequiredNotSetError{prop.Name + "." + reqNotSet.field}
- }
- s.err = err
- }
- return true
-}
diff --git a/vendor/github.com/golang/protobuf/proto/equal.go b/vendor/github.com/golang/protobuf/proto/equal.go
index 2ed1cf596..f9b6e41b3 100644
--- a/vendor/github.com/golang/protobuf/proto/equal.go
+++ b/vendor/github.com/golang/protobuf/proto/equal.go
@@ -109,15 +109,6 @@ func equalStruct(v1, v2 reflect.Value) bool {
// set/unset mismatch
return false
}
- b1, ok := f1.Interface().(raw)
- if ok {
- b2 := f2.Interface().(raw)
- // RawMessage
- if !bytes.Equal(b1.Bytes(), b2.Bytes()) {
- return false
- }
- continue
- }
f1, f2 = f1.Elem(), f2.Elem()
}
if !equalAny(f1, f2, sprop.Prop[i]) {
@@ -146,11 +137,7 @@ func equalStruct(v1, v2 reflect.Value) bool {
u1 := uf.Bytes()
u2 := v2.FieldByName("XXX_unrecognized").Bytes()
- if !bytes.Equal(u1, u2) {
- return false
- }
-
- return true
+ return bytes.Equal(u1, u2)
}
// v1 and v2 are known to have the same type.
@@ -259,7 +246,17 @@ func equalExtMap(base reflect.Type, em1, em2 map[int32]Extension) bool {
return false
}
- m1, m2 := e1.value, e2.value
+ m1 := extensionAsLegacyType(e1.value)
+ m2 := extensionAsLegacyType(e2.value)
+
+ if m1 == nil && m2 == nil {
+ // Both have only encoded form.
+ if bytes.Equal(e1.enc, e2.enc) {
+ continue
+ }
+ // The bytes are different, but the extensions might still be
+ // equal. We need to decode them to compare.
+ }
if m1 != nil && m2 != nil {
// Both are unencoded.
@@ -276,8 +273,12 @@ func equalExtMap(base reflect.Type, em1, em2 map[int32]Extension) bool {
desc = m[extNum]
}
if desc == nil {
+ // If both have only encoded form and the bytes are the same,
+ // it is handled above. We get here when the bytes are different.
+ // We don't know how to decode it, so just compare them as byte
+ // slices.
log.Printf("proto: don't know how to compare extension %d of %v", extNum, base)
- continue
+ return false
}
var err error
if m1 == nil {
diff --git a/vendor/github.com/golang/protobuf/proto/extensions.go b/vendor/github.com/golang/protobuf/proto/extensions.go
index eaad21831..fa88add30 100644
--- a/vendor/github.com/golang/protobuf/proto/extensions.go
+++ b/vendor/github.com/golang/protobuf/proto/extensions.go
@@ -38,6 +38,7 @@ package proto
import (
"errors"
"fmt"
+ "io"
"reflect"
"strconv"
"sync"
@@ -91,14 +92,29 @@ func (n notLocker) Unlock() {}
// extendable returns the extendableProto interface for the given generated proto message.
// If the proto message has the old extension format, it returns a wrapper that implements
// the extendableProto interface.
-func extendable(p interface{}) (extendableProto, bool) {
- if ep, ok := p.(extendableProto); ok {
- return ep, ok
- }
- if ep, ok := p.(extendableProtoV1); ok {
- return extensionAdapter{ep}, ok
+func extendable(p interface{}) (extendableProto, error) {
+ switch p := p.(type) {
+ case extendableProto:
+ if isNilPtr(p) {
+ return nil, fmt.Errorf("proto: nil %T is not extendable", p)
+ }
+ return p, nil
+ case extendableProtoV1:
+ if isNilPtr(p) {
+ return nil, fmt.Errorf("proto: nil %T is not extendable", p)
+ }
+ return extensionAdapter{p}, nil
}
- return nil, false
+ // Don't allocate a specific error containing %T:
+ // this is the hot path for Clone and MarshalText.
+ return nil, errNotExtendable
+}
+
+var errNotExtendable = errors.New("proto: not an extendable proto.Message")
+
+func isNilPtr(x interface{}) bool {
+ v := reflect.ValueOf(x)
+ return v.Kind() == reflect.Ptr && v.IsNil()
}
// XXX_InternalExtensions is an internal representation of proto extensions.
@@ -143,9 +159,6 @@ func (e *XXX_InternalExtensions) extensionsRead() (map[int32]Extension, sync.Loc
return e.p.extensionMap, &e.p.mu
}
-var extendableProtoType = reflect.TypeOf((*extendableProto)(nil)).Elem()
-var extendableProtoV1Type = reflect.TypeOf((*extendableProtoV1)(nil)).Elem()
-
// ExtensionDesc represents an extension specification.
// Used in generated code from the protocol compiler.
type ExtensionDesc struct {
@@ -172,15 +185,31 @@ type Extension struct {
// extension will have only enc set. When such an extension is
// accessed using GetExtension (or GetExtensions) desc and value
// will be set.
- desc *ExtensionDesc
+ desc *ExtensionDesc
+
+ // value is a concrete value for the extension field. Let the type of
+ // desc.ExtensionType be the "API type" and the type of Extension.value
+ // be the "storage type". The API type and storage type are the same except:
+ // * For scalars (except []byte), the API type uses *T,
+ // while the storage type uses T.
+ // * For repeated fields, the API type uses []T, while the storage type
+ // uses *[]T.
+ //
+ // The reason for the divergence is so that the storage type more naturally
+ // matches what is expected of when retrieving the values through the
+ // protobuf reflection APIs.
+ //
+ // The value may only be populated if desc is also populated.
value interface{}
- enc []byte
+
+ // enc is the raw bytes for the extension field.
+ enc []byte
}
// SetRawExtension is for testing only.
func SetRawExtension(base Message, id int32, b []byte) {
- epb, ok := extendable(base)
- if !ok {
+ epb, err := extendable(base)
+ if err != nil {
return
}
extmap := epb.extensionsWrite()
@@ -205,7 +234,7 @@ func checkExtensionTypes(pb extendableProto, extension *ExtensionDesc) error {
pbi = ea.extendableProtoV1
}
if a, b := reflect.TypeOf(pbi), reflect.TypeOf(extension.ExtendedType); a != b {
- return errors.New("proto: bad extended type; " + b.String() + " does not extend " + a.String())
+ return fmt.Errorf("proto: bad extended type; %v does not extend %v", b, a)
}
// Check the range.
if !isExtensionField(pb, extension.Field) {
@@ -250,85 +279,11 @@ func extensionProperties(ed *ExtensionDesc) *Properties {
return prop
}
-// encode encodes any unmarshaled (unencoded) extensions in e.
-func encodeExtensions(e *XXX_InternalExtensions) error {
- m, mu := e.extensionsRead()
- if m == nil {
- return nil // fast path
- }
- mu.Lock()
- defer mu.Unlock()
- return encodeExtensionsMap(m)
-}
-
-// encode encodes any unmarshaled (unencoded) extensions in e.
-func encodeExtensionsMap(m map[int32]Extension) error {
- for k, e := range m {
- if e.value == nil || e.desc == nil {
- // Extension is only in its encoded form.
- continue
- }
-
- // We don't skip extensions that have an encoded form set,
- // because the extension value may have been mutated after
- // the last time this function was called.
-
- et := reflect.TypeOf(e.desc.ExtensionType)
- props := extensionProperties(e.desc)
-
- p := NewBuffer(nil)
- // If e.value has type T, the encoder expects a *struct{ X T }.
- // Pass a *T with a zero field and hope it all works out.
- x := reflect.New(et)
- x.Elem().Set(reflect.ValueOf(e.value))
- if err := props.enc(p, props, toStructPointer(x)); err != nil {
- return err
- }
- e.enc = p.buf
- m[k] = e
- }
- return nil
-}
-
-func extensionsSize(e *XXX_InternalExtensions) (n int) {
- m, mu := e.extensionsRead()
- if m == nil {
- return 0
- }
- mu.Lock()
- defer mu.Unlock()
- return extensionsMapSize(m)
-}
-
-func extensionsMapSize(m map[int32]Extension) (n int) {
- for _, e := range m {
- if e.value == nil || e.desc == nil {
- // Extension is only in its encoded form.
- n += len(e.enc)
- continue
- }
-
- // We don't skip extensions that have an encoded form set,
- // because the extension value may have been mutated after
- // the last time this function was called.
-
- et := reflect.TypeOf(e.desc.ExtensionType)
- props := extensionProperties(e.desc)
-
- // If e.value has type T, the encoder expects a *struct{ X T }.
- // Pass a *T with a zero field and hope it all works out.
- x := reflect.New(et)
- x.Elem().Set(reflect.ValueOf(e.value))
- n += props.size(props, toStructPointer(x))
- }
- return
-}
-
// HasExtension returns whether the given extension is present in pb.
func HasExtension(pb Message, extension *ExtensionDesc) bool {
// TODO: Check types, field numbers, etc.?
- epb, ok := extendable(pb)
- if !ok {
+ epb, err := extendable(pb)
+ if err != nil {
return false
}
extmap, mu := epb.extensionsRead()
@@ -336,15 +291,15 @@ func HasExtension(pb Message, extension *ExtensionDesc) bool {
return false
}
mu.Lock()
- _, ok = extmap[extension.Field]
+ _, ok := extmap[extension.Field]
mu.Unlock()
return ok
}
// ClearExtension removes the given extension from pb.
func ClearExtension(pb Message, extension *ExtensionDesc) {
- epb, ok := extendable(pb)
- if !ok {
+ epb, err := extendable(pb)
+ if err != nil {
return
}
// TODO: Check types, field numbers, etc.?
@@ -352,16 +307,26 @@ func ClearExtension(pb Message, extension *ExtensionDesc) {
delete(extmap, extension.Field)
}
-// GetExtension parses and returns the given extension of pb.
-// If the extension is not present and has no default value it returns ErrMissingExtension.
+// GetExtension retrieves a proto2 extended field from pb.
+//
+// If the descriptor is type complete (i.e., ExtensionDesc.ExtensionType is non-nil),
+// then GetExtension parses the encoded field and returns a Go value of the specified type.
+// If the field is not present, then the default value is returned (if one is specified),
+// otherwise ErrMissingExtension is reported.
+//
+// If the descriptor is not type complete (i.e., ExtensionDesc.ExtensionType is nil),
+// then GetExtension returns the raw encoded bytes of the field extension.
func GetExtension(pb Message, extension *ExtensionDesc) (interface{}, error) {
- epb, ok := extendable(pb)
- if !ok {
- return nil, errors.New("proto: not an extendable proto")
+ epb, err := extendable(pb)
+ if err != nil {
+ return nil, err
}
- if err := checkExtensionTypes(epb, extension); err != nil {
- return nil, err
+ if extension.ExtendedType != nil {
+ // can only check type if this is a complete descriptor
+ if err := checkExtensionTypes(epb, extension); err != nil {
+ return nil, err
+ }
}
emap, mu := epb.extensionsRead()
@@ -385,7 +350,12 @@ func GetExtension(pb Message, extension *ExtensionDesc) (interface{}, error) {
// descriptors with the same field number.
return nil, errors.New("proto: descriptor conflict")
}
- return e.value, nil
+ return extensionAsLegacyType(e.value), nil
+ }
+
+ if extension.ExtensionType == nil {
+ // incomplete descriptor
+ return e.enc, nil
}
v, err := decodeExtension(e.enc, extension)
@@ -395,16 +365,21 @@ func GetExtension(pb Message, extension *ExtensionDesc) (interface{}, error) {
// Remember the decoded version and drop the encoded version.
// That way it is safe to mutate what we return.
- e.value = v
+ e.value = extensionAsStorageType(v)
e.desc = extension
e.enc = nil
emap[extension.Field] = e
- return e.value, nil
+ return extensionAsLegacyType(e.value), nil
}
// defaultExtensionValue returns the default value for extension.
// If no default for an extension is defined ErrMissingExtension is returned.
func defaultExtensionValue(extension *ExtensionDesc) (interface{}, error) {
+ if extension.ExtensionType == nil {
+ // incomplete descriptor, so no default
+ return nil, ErrMissingExtension
+ }
+
t := reflect.TypeOf(extension.ExtensionType)
props := extensionProperties(extension)
@@ -439,31 +414,28 @@ func defaultExtensionValue(extension *ExtensionDesc) (interface{}, error) {
// decodeExtension decodes an extension encoded in b.
func decodeExtension(b []byte, extension *ExtensionDesc) (interface{}, error) {
- o := NewBuffer(b)
-
t := reflect.TypeOf(extension.ExtensionType)
-
- props := extensionProperties(extension)
+ unmarshal := typeUnmarshaler(t, extension.Tag)
// t is a pointer to a struct, pointer to basic type or a slice.
- // Allocate a "field" to store the pointer/slice itself; the
- // pointer/slice will be stored here. We pass
- // the address of this field to props.dec.
- // This passes a zero field and a *t and lets props.dec
- // interpret it as a *struct{ x t }.
+ // Allocate space to store the pointer/slice.
value := reflect.New(t).Elem()
+ var err error
for {
- // Discard wire type and field number varint. It isn't needed.
- if _, err := o.DecodeVarint(); err != nil {
- return nil, err
+ x, n := decodeVarint(b)
+ if n == 0 {
+ return nil, io.ErrUnexpectedEOF
}
+ b = b[n:]
+ wire := int(x) & 7
- if err := props.dec(o, props, toStructPointer(value.Addr())); err != nil {
+ b, err = unmarshal(b, valToPointer(value.Addr()), wire)
+ if err != nil {
return nil, err
}
- if o.index >= len(o.buf) {
+ if len(b) == 0 {
break
}
}
@@ -473,9 +445,9 @@ func decodeExtension(b []byte, extension *ExtensionDesc) (interface{}, error) {
// GetExtensions returns a slice of the extensions present in pb that are also listed in es.
// The returned slice has the same length as es; missing extensions will appear as nil elements.
func GetExtensions(pb Message, es []*ExtensionDesc) (extensions []interface{}, err error) {
- epb, ok := extendable(pb)
- if !ok {
- return nil, errors.New("proto: not an extendable proto")
+ epb, err := extendable(pb)
+ if err != nil {
+ return nil, err
}
extensions = make([]interface{}, len(es))
for i, e := range es {
@@ -494,9 +466,9 @@ func GetExtensions(pb Message, es []*ExtensionDesc) (extensions []interface{}, e
// For non-registered extensions, ExtensionDescs returns an incomplete descriptor containing
// just the Field field, which defines the extension's field number.
func ExtensionDescs(pb Message) ([]*ExtensionDesc, error) {
- epb, ok := extendable(pb)
- if !ok {
- return nil, fmt.Errorf("proto: %T is not an extendable proto.Message", pb)
+ epb, err := extendable(pb)
+ if err != nil {
+ return nil, err
}
registeredExtensions := RegisteredExtensions(pb)
@@ -523,16 +495,16 @@ func ExtensionDescs(pb Message) ([]*ExtensionDesc, error) {
// SetExtension sets the specified extension of pb to the specified value.
func SetExtension(pb Message, extension *ExtensionDesc, value interface{}) error {
- epb, ok := extendable(pb)
- if !ok {
- return errors.New("proto: not an extendable proto")
+ epb, err := extendable(pb)
+ if err != nil {
+ return err
}
if err := checkExtensionTypes(epb, extension); err != nil {
return err
}
typ := reflect.TypeOf(extension.ExtensionType)
if typ != reflect.TypeOf(value) {
- return errors.New("proto: bad extension value type")
+ return fmt.Errorf("proto: bad extension value type. got: %T, want: %T", value, extension.ExtensionType)
}
// nil extension values need to be caught early, because the
// encoder can't distinguish an ErrNil due to a nil extension
@@ -544,14 +516,14 @@ func SetExtension(pb Message, extension *ExtensionDesc, value interface{}) error
}
extmap := epb.extensionsWrite()
- extmap[extension.Field] = Extension{desc: extension, value: value}
+ extmap[extension.Field] = Extension{desc: extension, value: extensionAsStorageType(value)}
return nil
}
// ClearAllExtensions clears all extensions from pb.
func ClearAllExtensions(pb Message) {
- epb, ok := extendable(pb)
- if !ok {
+ epb, err := extendable(pb)
+ if err != nil {
return
}
m := epb.extensionsWrite()
@@ -585,3 +557,51 @@ func RegisterExtension(desc *ExtensionDesc) {
func RegisteredExtensions(pb Message) map[int32]*ExtensionDesc {
return extensionMaps[reflect.TypeOf(pb).Elem()]
}
+
+// extensionAsLegacyType converts an value in the storage type as the API type.
+// See Extension.value.
+func extensionAsLegacyType(v interface{}) interface{} {
+ switch rv := reflect.ValueOf(v); rv.Kind() {
+ case reflect.Bool, reflect.Int32, reflect.Int64, reflect.Uint32, reflect.Uint64, reflect.Float32, reflect.Float64, reflect.String:
+ // Represent primitive types as a pointer to the value.
+ rv2 := reflect.New(rv.Type())
+ rv2.Elem().Set(rv)
+ v = rv2.Interface()
+ case reflect.Ptr:
+ // Represent slice types as the value itself.
+ switch rv.Type().Elem().Kind() {
+ case reflect.Slice:
+ if rv.IsNil() {
+ v = reflect.Zero(rv.Type().Elem()).Interface()
+ } else {
+ v = rv.Elem().Interface()
+ }
+ }
+ }
+ return v
+}
+
+// extensionAsStorageType converts an value in the API type as the storage type.
+// See Extension.value.
+func extensionAsStorageType(v interface{}) interface{} {
+ switch rv := reflect.ValueOf(v); rv.Kind() {
+ case reflect.Ptr:
+ // Represent slice types as the value itself.
+ switch rv.Type().Elem().Kind() {
+ case reflect.Bool, reflect.Int32, reflect.Int64, reflect.Uint32, reflect.Uint64, reflect.Float32, reflect.Float64, reflect.String:
+ if rv.IsNil() {
+ v = reflect.Zero(rv.Type().Elem()).Interface()
+ } else {
+ v = rv.Elem().Interface()
+ }
+ }
+ case reflect.Slice:
+ // Represent slice types as a pointer to the value.
+ if rv.Type().Elem().Kind() != reflect.Uint8 {
+ rv2 := reflect.New(rv.Type())
+ rv2.Elem().Set(rv)
+ v = rv2.Interface()
+ }
+ }
+ return v
+}
diff --git a/vendor/github.com/golang/protobuf/proto/lib.go b/vendor/github.com/golang/protobuf/proto/lib.go
index 1c225504a..fdd328bb7 100644
--- a/vendor/github.com/golang/protobuf/proto/lib.go
+++ b/vendor/github.com/golang/protobuf/proto/lib.go
@@ -273,32 +273,73 @@ import (
"sync"
)
-// Message is implemented by generated protocol buffer messages.
-type Message interface {
- Reset()
- String() string
- ProtoMessage()
+// RequiredNotSetError is an error type returned by either Marshal or Unmarshal.
+// Marshal reports this when a required field is not initialized.
+// Unmarshal reports this when a required field is missing from the wire data.
+type RequiredNotSetError struct{ field string }
+
+func (e *RequiredNotSetError) Error() string {
+ if e.field == "" {
+ return fmt.Sprintf("proto: required field not set")
+ }
+ return fmt.Sprintf("proto: required field %q not set", e.field)
+}
+func (e *RequiredNotSetError) RequiredNotSet() bool {
+ return true
}
-// Stats records allocation details about the protocol buffer encoders
-// and decoders. Useful for tuning the library itself.
-type Stats struct {
- Emalloc uint64 // mallocs in encode
- Dmalloc uint64 // mallocs in decode
- Encode uint64 // number of encodes
- Decode uint64 // number of decodes
- Chit uint64 // number of cache hits
- Cmiss uint64 // number of cache misses
- Size uint64 // number of sizes
+type invalidUTF8Error struct{ field string }
+
+func (e *invalidUTF8Error) Error() string {
+ if e.field == "" {
+ return "proto: invalid UTF-8 detected"
+ }
+ return fmt.Sprintf("proto: field %q contains invalid UTF-8", e.field)
+}
+func (e *invalidUTF8Error) InvalidUTF8() bool {
+ return true
}
-// Set to true to enable stats collection.
-const collectStats = false
+// errInvalidUTF8 is a sentinel error to identify fields with invalid UTF-8.
+// This error should not be exposed to the external API as such errors should
+// be recreated with the field information.
+var errInvalidUTF8 = &invalidUTF8Error{}
-var stats Stats
+// isNonFatal reports whether the error is either a RequiredNotSet error
+// or a InvalidUTF8 error.
+func isNonFatal(err error) bool {
+ if re, ok := err.(interface{ RequiredNotSet() bool }); ok && re.RequiredNotSet() {
+ return true
+ }
+ if re, ok := err.(interface{ InvalidUTF8() bool }); ok && re.InvalidUTF8() {
+ return true
+ }
+ return false
+}
-// GetStats returns a copy of the global Stats structure.
-func GetStats() Stats { return stats }
+type nonFatal struct{ E error }
+
+// Merge merges err into nf and reports whether it was successful.
+// Otherwise it returns false for any fatal non-nil errors.
+func (nf *nonFatal) Merge(err error) (ok bool) {
+ if err == nil {
+ return true // not an error
+ }
+ if !isNonFatal(err) {
+ return false // fatal error
+ }
+ if nf.E == nil {
+ nf.E = err // store first instance of non-fatal error
+ }
+ return true
+}
+
+// Message is implemented by generated protocol buffer messages.
+type Message interface {
+ Reset()
+ String() string
+ ProtoMessage()
+}
// A Buffer is a buffer manager for marshaling and unmarshaling
// protocol buffers. It may be reused between invocations to
@@ -309,16 +350,7 @@ type Buffer struct {
buf []byte // encode/decode byte stream
index int // read point
- // pools of basic types to amortize allocation.
- bools []bool
- uint32s []uint32
- uint64s []uint64
-
- // extra pools, only used with pointer_reflect.go
- int32s []int32
- int64s []int64
- float32s []float32
- float64s []float64
+ deterministic bool
}
// NewBuffer allocates a new Buffer and initializes its internal data to
@@ -343,6 +375,30 @@ func (p *Buffer) SetBuf(s []byte) {
// Bytes returns the contents of the Buffer.
func (p *Buffer) Bytes() []byte { return p.buf }
+// SetDeterministic sets whether to use deterministic serialization.
+//
+// Deterministic serialization guarantees that for a given binary, equal
+// messages will always be serialized to the same bytes. This implies:
+//
+// - Repeated serialization of a message will return the same bytes.
+// - Different processes of the same binary (which may be executing on
+// different machines) will serialize equal messages to the same bytes.
+//
+// Note that the deterministic serialization is NOT canonical across
+// languages. It is not guaranteed to remain stable over time. It is unstable
+// across different builds with schema changes due to unknown fields.
+// Users who need canonical serialization (e.g., persistent storage in a
+// canonical form, fingerprinting, etc.) should define their own
+// canonicalization specification and implement their own serializer rather
+// than relying on this API.
+//
+// If deterministic serialization is requested, map entries will be sorted
+// by keys in lexographical order. This is an implementation detail and
+// subject to change.
+func (p *Buffer) SetDeterministic(deterministic bool) {
+ p.deterministic = deterministic
+}
+
/*
* Helper routines for simplifying the creation of optional fields of basic type.
*/
@@ -831,22 +887,12 @@ func fieldDefault(ft reflect.Type, prop *Properties) (sf *scalarField, nestedMes
return sf, false, nil
}
+// mapKeys returns a sort.Interface to be used for sorting the map keys.
// Map fields may have key types of non-float scalars, strings and enums.
-// The easiest way to sort them in some deterministic order is to use fmt.
-// If this turns out to be inefficient we can always consider other options,
-// such as doing a Schwartzian transform.
-
func mapKeys(vs []reflect.Value) sort.Interface {
- s := mapKeySorter{
- vs: vs,
- // default Less function: textual comparison
- less: func(a, b reflect.Value) bool {
- return fmt.Sprint(a.Interface()) < fmt.Sprint(b.Interface())
- },
- }
+ s := mapKeySorter{vs: vs}
- // Type specialization per https://developers.google.com/protocol-buffers/docs/proto#maps;
- // numeric keys are sorted numerically.
+ // Type specialization per https://developers.google.com/protocol-buffers/docs/proto#maps.
if len(vs) == 0 {
return s
}
@@ -855,6 +901,12 @@ func mapKeys(vs []reflect.Value) sort.Interface {
s.less = func(a, b reflect.Value) bool { return a.Int() < b.Int() }
case reflect.Uint32, reflect.Uint64:
s.less = func(a, b reflect.Value) bool { return a.Uint() < b.Uint() }
+ case reflect.Bool:
+ s.less = func(a, b reflect.Value) bool { return !a.Bool() && b.Bool() } // false < true
+ case reflect.String:
+ s.less = func(a, b reflect.Value) bool { return a.String() < b.String() }
+ default:
+ panic(fmt.Sprintf("unsupported map key type: %v", vs[0].Kind()))
}
return s
@@ -888,10 +940,26 @@ func isProto3Zero(v reflect.Value) bool {
return false
}
-// ProtoPackageIsVersion2 is referenced from generated protocol buffer files
-// to assert that that code is compatible with this version of the proto package.
-const ProtoPackageIsVersion2 = true
+const (
+ // ProtoPackageIsVersion3 is referenced from generated protocol buffer files
+ // to assert that that code is compatible with this version of the proto package.
+ ProtoPackageIsVersion3 = true
+
+ // ProtoPackageIsVersion2 is referenced from generated protocol buffer files
+ // to assert that that code is compatible with this version of the proto package.
+ ProtoPackageIsVersion2 = true
-// ProtoPackageIsVersion1 is referenced from generated protocol buffer files
-// to assert that that code is compatible with this version of the proto package.
-const ProtoPackageIsVersion1 = true
+ // ProtoPackageIsVersion1 is referenced from generated protocol buffer files
+ // to assert that that code is compatible with this version of the proto package.
+ ProtoPackageIsVersion1 = true
+)
+
+// InternalMessageInfo is a type used internally by generated .pb.go files.
+// This type is not intended to be used by non-generated code.
+// This type is not subject to any compatibility guarantee.
+type InternalMessageInfo struct {
+ marshal *marshalInfo
+ unmarshal *unmarshalInfo
+ merge *mergeInfo
+ discard *discardInfo
+}
diff --git a/vendor/github.com/golang/protobuf/proto/message_set.go b/vendor/github.com/golang/protobuf/proto/message_set.go
index fd982decd..f48a75676 100644
--- a/vendor/github.com/golang/protobuf/proto/message_set.go
+++ b/vendor/github.com/golang/protobuf/proto/message_set.go
@@ -36,12 +36,7 @@ package proto
*/
import (
- "bytes"
- "encoding/json"
"errors"
- "fmt"
- "reflect"
- "sort"
)
// errNoMessageTypeID occurs when a protocol buffer does not have a message type ID.
@@ -94,10 +89,7 @@ func (ms *messageSet) find(pb Message) *_MessageSet_Item {
}
func (ms *messageSet) Has(pb Message) bool {
- if ms.find(pb) != nil {
- return true
- }
- return false
+ return ms.find(pb) != nil
}
func (ms *messageSet) Unmarshal(pb Message) error {
@@ -147,50 +139,9 @@ func skipVarint(buf []byte) []byte {
return buf[i+1:]
}
-// MarshalMessageSet encodes the extension map represented by m in the message set wire format.
-// It is called by generated Marshal methods on protocol buffer messages with the message_set_wire_format option.
-func MarshalMessageSet(exts interface{}) ([]byte, error) {
- var m map[int32]Extension
- switch exts := exts.(type) {
- case *XXX_InternalExtensions:
- if err := encodeExtensions(exts); err != nil {
- return nil, err
- }
- m, _ = exts.extensionsRead()
- case map[int32]Extension:
- if err := encodeExtensionsMap(exts); err != nil {
- return nil, err
- }
- m = exts
- default:
- return nil, errors.New("proto: not an extension map")
- }
-
- // Sort extension IDs to provide a deterministic encoding.
- // See also enc_map in encode.go.
- ids := make([]int, 0, len(m))
- for id := range m {
- ids = append(ids, int(id))
- }
- sort.Ints(ids)
-
- ms := &messageSet{Item: make([]*_MessageSet_Item, 0, len(m))}
- for _, id := range ids {
- e := m[int32(id)]
- // Remove the wire type and field number varint, as well as the length varint.
- msg := skipVarint(skipVarint(e.enc))
-
- ms.Item = append(ms.Item, &_MessageSet_Item{
- TypeId: Int32(int32(id)),
- Message: msg,
- })
- }
- return Marshal(ms)
-}
-
-// UnmarshalMessageSet decodes the extension map encoded in buf in the message set wire format.
-// It is called by generated Unmarshal methods on protocol buffer messages with the message_set_wire_format option.
-func UnmarshalMessageSet(buf []byte, exts interface{}) error {
+// unmarshalMessageSet decodes the extension map encoded in buf in the message set wire format.
+// It is called by Unmarshal methods on protocol buffer messages with the message_set_wire_format option.
+func unmarshalMessageSet(buf []byte, exts interface{}) error {
var m map[int32]Extension
switch exts := exts.(type) {
case *XXX_InternalExtensions:
@@ -228,84 +179,3 @@ func UnmarshalMessageSet(buf []byte, exts interface{}) error {
}
return nil
}
-
-// MarshalMessageSetJSON encodes the extension map represented by m in JSON format.
-// It is called by generated MarshalJSON methods on protocol buffer messages with the message_set_wire_format option.
-func MarshalMessageSetJSON(exts interface{}) ([]byte, error) {
- var m map[int32]Extension
- switch exts := exts.(type) {
- case *XXX_InternalExtensions:
- m, _ = exts.extensionsRead()
- case map[int32]Extension:
- m = exts
- default:
- return nil, errors.New("proto: not an extension map")
- }
- var b bytes.Buffer
- b.WriteByte('{')
-
- // Process the map in key order for deterministic output.
- ids := make([]int32, 0, len(m))
- for id := range m {
- ids = append(ids, id)
- }
- sort.Sort(int32Slice(ids)) // int32Slice defined in text.go
-
- for i, id := range ids {
- ext := m[id]
- if i > 0 {
- b.WriteByte(',')
- }
-
- msd, ok := messageSetMap[id]
- if !ok {
- // Unknown type; we can't render it, so skip it.
- continue
- }
- fmt.Fprintf(&b, `"[%s]":`, msd.name)
-
- x := ext.value
- if x == nil {
- x = reflect.New(msd.t.Elem()).Interface()
- if err := Unmarshal(ext.enc, x.(Message)); err != nil {
- return nil, err
- }
- }
- d, err := json.Marshal(x)
- if err != nil {
- return nil, err
- }
- b.Write(d)
- }
- b.WriteByte('}')
- return b.Bytes(), nil
-}
-
-// UnmarshalMessageSetJSON decodes the extension map encoded in buf in JSON format.
-// It is called by generated UnmarshalJSON methods on protocol buffer messages with the message_set_wire_format option.
-func UnmarshalMessageSetJSON(buf []byte, exts interface{}) error {
- // Common-case fast path.
- if len(buf) == 0 || bytes.Equal(buf, []byte("{}")) {
- return nil
- }
-
- // This is fairly tricky, and it's not clear that it is needed.
- return errors.New("TODO: UnmarshalMessageSetJSON not yet implemented")
-}
-
-// A global registry of types that can be used in a MessageSet.
-
-var messageSetMap = make(map[int32]messageSetDesc)
-
-type messageSetDesc struct {
- t reflect.Type // pointer to struct
- name string
-}
-
-// RegisterMessageSetType is called from the generated code.
-func RegisterMessageSetType(m Message, fieldNum int32, name string) {
- messageSetMap[fieldNum] = messageSetDesc{
- t: reflect.TypeOf(m),
- name: name,
- }
-}
diff --git a/vendor/github.com/golang/protobuf/proto/pointer_reflect.go b/vendor/github.com/golang/protobuf/proto/pointer_reflect.go
index fb512e2e1..94fa9194a 100644
--- a/vendor/github.com/golang/protobuf/proto/pointer_reflect.go
+++ b/vendor/github.com/golang/protobuf/proto/pointer_reflect.go
@@ -29,7 +29,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-// +build appengine js
+// +build purego appengine js
// This file contains an implementation of proto field accesses using package reflect.
// It is slower than the code in pointer_unsafe.go but it avoids package unsafe and can
@@ -38,32 +38,13 @@
package proto
import (
- "math"
"reflect"
+ "sync"
)
-// A structPointer is a pointer to a struct.
-type structPointer struct {
- v reflect.Value
-}
-
-// toStructPointer returns a structPointer equivalent to the given reflect value.
-// The reflect value must itself be a pointer to a struct.
-func toStructPointer(v reflect.Value) structPointer {
- return structPointer{v}
-}
-
-// IsNil reports whether p is nil.
-func structPointer_IsNil(p structPointer) bool {
- return p.v.IsNil()
-}
+const unsafeAllowed = false
-// Interface returns the struct pointer as an interface value.
-func structPointer_Interface(p structPointer, _ reflect.Type) interface{} {
- return p.v.Interface()
-}
-
-// A field identifies a field in a struct, accessible from a structPointer.
+// A field identifies a field in a struct, accessible from a pointer.
// In this implementation, a field is identified by the sequence of field indices
// passed to reflect's FieldByIndex.
type field []int
@@ -76,409 +57,304 @@ func toField(f *reflect.StructField) field {
// invalidField is an invalid field identifier.
var invalidField = field(nil)
+// zeroField is a noop when calling pointer.offset.
+var zeroField = field([]int{})
+
// IsValid reports whether the field identifier is valid.
func (f field) IsValid() bool { return f != nil }
-// field returns the given field in the struct as a reflect value.
-func structPointer_field(p structPointer, f field) reflect.Value {
- // Special case: an extension map entry with a value of type T
- // passes a *T to the struct-handling code with a zero field,
- // expecting that it will be treated as equivalent to *struct{ X T },
- // which has the same memory layout. We have to handle that case
- // specially, because reflect will panic if we call FieldByIndex on a
- // non-struct.
- if f == nil {
- return p.v.Elem()
- }
-
- return p.v.Elem().FieldByIndex(f)
+// The pointer type is for the table-driven decoder.
+// The implementation here uses a reflect.Value of pointer type to
+// create a generic pointer. In pointer_unsafe.go we use unsafe
+// instead of reflect to implement the same (but faster) interface.
+type pointer struct {
+ v reflect.Value
}
-// ifield returns the given field in the struct as an interface value.
-func structPointer_ifield(p structPointer, f field) interface{} {
- return structPointer_field(p, f).Addr().Interface()
+// toPointer converts an interface of pointer type to a pointer
+// that points to the same target.
+func toPointer(i *Message) pointer {
+ return pointer{v: reflect.ValueOf(*i)}
}
-// Bytes returns the address of a []byte field in the struct.
-func structPointer_Bytes(p structPointer, f field) *[]byte {
- return structPointer_ifield(p, f).(*[]byte)
+// toAddrPointer converts an interface to a pointer that points to
+// the interface data.
+func toAddrPointer(i *interface{}, isptr, deref bool) pointer {
+ v := reflect.ValueOf(*i)
+ u := reflect.New(v.Type())
+ u.Elem().Set(v)
+ if deref {
+ u = u.Elem()
+ }
+ return pointer{v: u}
}
-// BytesSlice returns the address of a [][]byte field in the struct.
-func structPointer_BytesSlice(p structPointer, f field) *[][]byte {
- return structPointer_ifield(p, f).(*[][]byte)
+// valToPointer converts v to a pointer. v must be of pointer type.
+func valToPointer(v reflect.Value) pointer {
+ return pointer{v: v}
}
-// Bool returns the address of a *bool field in the struct.
-func structPointer_Bool(p structPointer, f field) **bool {
- return structPointer_ifield(p, f).(**bool)
+// offset converts from a pointer to a structure to a pointer to
+// one of its fields.
+func (p pointer) offset(f field) pointer {
+ return pointer{v: p.v.Elem().FieldByIndex(f).Addr()}
}
-// BoolVal returns the address of a bool field in the struct.
-func structPointer_BoolVal(p structPointer, f field) *bool {
- return structPointer_ifield(p, f).(*bool)
+func (p pointer) isNil() bool {
+ return p.v.IsNil()
}
-// BoolSlice returns the address of a []bool field in the struct.
-func structPointer_BoolSlice(p structPointer, f field) *[]bool {
- return structPointer_ifield(p, f).(*[]bool)
+// grow updates the slice s in place to make it one element longer.
+// s must be addressable.
+// Returns the (addressable) new element.
+func grow(s reflect.Value) reflect.Value {
+ n, m := s.Len(), s.Cap()
+ if n < m {
+ s.SetLen(n + 1)
+ } else {
+ s.Set(reflect.Append(s, reflect.Zero(s.Type().Elem())))
+ }
+ return s.Index(n)
}
-// String returns the address of a *string field in the struct.
-func structPointer_String(p structPointer, f field) **string {
- return structPointer_ifield(p, f).(**string)
+func (p pointer) toInt64() *int64 {
+ return p.v.Interface().(*int64)
}
-
-// StringVal returns the address of a string field in the struct.
-func structPointer_StringVal(p structPointer, f field) *string {
- return structPointer_ifield(p, f).(*string)
+func (p pointer) toInt64Ptr() **int64 {
+ return p.v.Interface().(**int64)
}
-
-// StringSlice returns the address of a []string field in the struct.
-func structPointer_StringSlice(p structPointer, f field) *[]string {
- return structPointer_ifield(p, f).(*[]string)
+func (p pointer) toInt64Slice() *[]int64 {
+ return p.v.Interface().(*[]int64)
}
-// Extensions returns the address of an extension map field in the struct.
-func structPointer_Extensions(p structPointer, f field) *XXX_InternalExtensions {
- return structPointer_ifield(p, f).(*XXX_InternalExtensions)
-}
+var int32ptr = reflect.TypeOf((*int32)(nil))
-// ExtMap returns the address of an extension map field in the struct.
-func structPointer_ExtMap(p structPointer, f field) *map[int32]Extension {
- return structPointer_ifield(p, f).(*map[int32]Extension)
+func (p pointer) toInt32() *int32 {
+ return p.v.Convert(int32ptr).Interface().(*int32)
}
-// NewAt returns the reflect.Value for a pointer to a field in the struct.
-func structPointer_NewAt(p structPointer, f field, typ reflect.Type) reflect.Value {
- return structPointer_field(p, f).Addr()
+// The toInt32Ptr/Slice methods don't work because of enums.
+// Instead, we must use set/get methods for the int32ptr/slice case.
+/*
+ func (p pointer) toInt32Ptr() **int32 {
+ return p.v.Interface().(**int32)
}
-
-// SetStructPointer writes a *struct field in the struct.
-func structPointer_SetStructPointer(p structPointer, f field, q structPointer) {
- structPointer_field(p, f).Set(q.v)
+ func (p pointer) toInt32Slice() *[]int32 {
+ return p.v.Interface().(*[]int32)
}
-
-// GetStructPointer reads a *struct field in the struct.
-func structPointer_GetStructPointer(p structPointer, f field) structPointer {
- return structPointer{structPointer_field(p, f)}
+*/
+func (p pointer) getInt32Ptr() *int32 {
+ if p.v.Type().Elem().Elem() == reflect.TypeOf(int32(0)) {
+ // raw int32 type
+ return p.v.Elem().Interface().(*int32)
+ }
+ // an enum
+ return p.v.Elem().Convert(int32PtrType).Interface().(*int32)
+}
+func (p pointer) setInt32Ptr(v int32) {
+ // Allocate value in a *int32. Possibly convert that to a *enum.
+ // Then assign it to a **int32 or **enum.
+ // Note: we can convert *int32 to *enum, but we can't convert
+ // **int32 to **enum!
+ p.v.Elem().Set(reflect.ValueOf(&v).Convert(p.v.Type().Elem()))
+}
+
+// getInt32Slice copies []int32 from p as a new slice.
+// This behavior differs from the implementation in pointer_unsafe.go.
+func (p pointer) getInt32Slice() []int32 {
+ if p.v.Type().Elem().Elem() == reflect.TypeOf(int32(0)) {
+ // raw int32 type
+ return p.v.Elem().Interface().([]int32)
+ }
+ // an enum
+ // Allocate a []int32, then assign []enum's values into it.
+ // Note: we can't convert []enum to []int32.
+ slice := p.v.Elem()
+ s := make([]int32, slice.Len())
+ for i := 0; i < slice.Len(); i++ {
+ s[i] = int32(slice.Index(i).Int())
+ }
+ return s
}
-// StructPointerSlice the address of a []*struct field in the struct.
-func structPointer_StructPointerSlice(p structPointer, f field) structPointerSlice {
- return structPointerSlice{structPointer_field(p, f)}
+// setInt32Slice copies []int32 into p as a new slice.
+// This behavior differs from the implementation in pointer_unsafe.go.
+func (p pointer) setInt32Slice(v []int32) {
+ if p.v.Type().Elem().Elem() == reflect.TypeOf(int32(0)) {
+ // raw int32 type
+ p.v.Elem().Set(reflect.ValueOf(v))
+ return
+ }
+ // an enum
+ // Allocate a []enum, then assign []int32's values into it.
+ // Note: we can't convert []enum to []int32.
+ slice := reflect.MakeSlice(p.v.Type().Elem(), len(v), cap(v))
+ for i, x := range v {
+ slice.Index(i).SetInt(int64(x))
+ }
+ p.v.Elem().Set(slice)
}
-
-// A structPointerSlice represents the address of a slice of pointers to structs
-// (themselves messages or groups). That is, v.Type() is *[]*struct{...}.
-type structPointerSlice struct {
- v reflect.Value
+func (p pointer) appendInt32Slice(v int32) {
+ grow(p.v.Elem()).SetInt(int64(v))
}
-func (p structPointerSlice) Len() int { return p.v.Len() }
-func (p structPointerSlice) Index(i int) structPointer { return structPointer{p.v.Index(i)} }
-func (p structPointerSlice) Append(q structPointer) {
- p.v.Set(reflect.Append(p.v, q.v))
+func (p pointer) toUint64() *uint64 {
+ return p.v.Interface().(*uint64)
}
-
-var (
- int32Type = reflect.TypeOf(int32(0))
- uint32Type = reflect.TypeOf(uint32(0))
- float32Type = reflect.TypeOf(float32(0))
- int64Type = reflect.TypeOf(int64(0))
- uint64Type = reflect.TypeOf(uint64(0))
- float64Type = reflect.TypeOf(float64(0))
-)
-
-// A word32 represents a field of type *int32, *uint32, *float32, or *enum.
-// That is, v.Type() is *int32, *uint32, *float32, or *enum and v is assignable.
-type word32 struct {
- v reflect.Value
+func (p pointer) toUint64Ptr() **uint64 {
+ return p.v.Interface().(**uint64)
}
-
-// IsNil reports whether p is nil.
-func word32_IsNil(p word32) bool {
- return p.v.IsNil()
+func (p pointer) toUint64Slice() *[]uint64 {
+ return p.v.Interface().(*[]uint64)
}
-
-// Set sets p to point at a newly allocated word with bits set to x.
-func word32_Set(p word32, o *Buffer, x uint32) {
- t := p.v.Type().Elem()
- switch t {
- case int32Type:
- if len(o.int32s) == 0 {
- o.int32s = make([]int32, uint32PoolSize)
- }
- o.int32s[0] = int32(x)
- p.v.Set(reflect.ValueOf(&o.int32s[0]))
- o.int32s = o.int32s[1:]
- return
- case uint32Type:
- if len(o.uint32s) == 0 {
- o.uint32s = make([]uint32, uint32PoolSize)
- }
- o.uint32s[0] = x
- p.v.Set(reflect.ValueOf(&o.uint32s[0]))
- o.uint32s = o.uint32s[1:]
- return
- case float32Type:
- if len(o.float32s) == 0 {
- o.float32s = make([]float32, uint32PoolSize)
- }
- o.float32s[0] = math.Float32frombits(x)
- p.v.Set(reflect.ValueOf(&o.float32s[0]))
- o.float32s = o.float32s[1:]
- return
- }
-
- // must be enum
- p.v.Set(reflect.New(t))
- p.v.Elem().SetInt(int64(int32(x)))
+func (p pointer) toUint32() *uint32 {
+ return p.v.Interface().(*uint32)
}
-
-// Get gets the bits pointed at by p, as a uint32.
-func word32_Get(p word32) uint32 {
- elem := p.v.Elem()
- switch elem.Kind() {
- case reflect.Int32:
- return uint32(elem.Int())
- case reflect.Uint32:
- return uint32(elem.Uint())
- case reflect.Float32:
- return math.Float32bits(float32(elem.Float()))
- }
- panic("unreachable")
+func (p pointer) toUint32Ptr() **uint32 {
+ return p.v.Interface().(**uint32)
}
-
-// Word32 returns a reference to a *int32, *uint32, *float32, or *enum field in the struct.
-func structPointer_Word32(p structPointer, f field) word32 {
- return word32{structPointer_field(p, f)}
+func (p pointer) toUint32Slice() *[]uint32 {
+ return p.v.Interface().(*[]uint32)
}
-
-// A word32Val represents a field of type int32, uint32, float32, or enum.
-// That is, v.Type() is int32, uint32, float32, or enum and v is assignable.
-type word32Val struct {
- v reflect.Value
+func (p pointer) toBool() *bool {
+ return p.v.Interface().(*bool)
}
-
-// Set sets *p to x.
-func word32Val_Set(p word32Val, x uint32) {
- switch p.v.Type() {
- case int32Type:
- p.v.SetInt(int64(x))
- return
- case uint32Type:
- p.v.SetUint(uint64(x))
- return
- case float32Type:
- p.v.SetFloat(float64(math.Float32frombits(x)))
- return
- }
-
- // must be enum
- p.v.SetInt(int64(int32(x)))
+func (p pointer) toBoolPtr() **bool {
+ return p.v.Interface().(**bool)
}
-
-// Get gets the bits pointed at by p, as a uint32.
-func word32Val_Get(p word32Val) uint32 {
- elem := p.v
- switch elem.Kind() {
- case reflect.Int32:
- return uint32(elem.Int())
- case reflect.Uint32:
- return uint32(elem.Uint())
- case reflect.Float32:
- return math.Float32bits(float32(elem.Float()))
- }
- panic("unreachable")
+func (p pointer) toBoolSlice() *[]bool {
+ return p.v.Interface().(*[]bool)
}
-
-// Word32Val returns a reference to a int32, uint32, float32, or enum field in the struct.
-func structPointer_Word32Val(p structPointer, f field) word32Val {
- return word32Val{structPointer_field(p, f)}
+func (p pointer) toFloat64() *float64 {
+ return p.v.Interface().(*float64)
}
-
-// A word32Slice is a slice of 32-bit values.
-// That is, v.Type() is []int32, []uint32, []float32, or []enum.
-type word32Slice struct {
- v reflect.Value
+func (p pointer) toFloat64Ptr() **float64 {
+ return p.v.Interface().(**float64)
}
-
-func (p word32Slice) Append(x uint32) {
- n, m := p.v.Len(), p.v.Cap()
- if n < m {
- p.v.SetLen(n + 1)
- } else {
- t := p.v.Type().Elem()
- p.v.Set(reflect.Append(p.v, reflect.Zero(t)))
- }
- elem := p.v.Index(n)
- switch elem.Kind() {
- case reflect.Int32:
- elem.SetInt(int64(int32(x)))
- case reflect.Uint32:
- elem.SetUint(uint64(x))
- case reflect.Float32:
- elem.SetFloat(float64(math.Float32frombits(x)))
- }
+func (p pointer) toFloat64Slice() *[]float64 {
+ return p.v.Interface().(*[]float64)
}
-
-func (p word32Slice) Len() int {
- return p.v.Len()
+func (p pointer) toFloat32() *float32 {
+ return p.v.Interface().(*float32)
}
-
-func (p word32Slice) Index(i int) uint32 {
- elem := p.v.Index(i)
- switch elem.Kind() {
- case reflect.Int32:
- return uint32(elem.Int())
- case reflect.Uint32:
- return uint32(elem.Uint())
- case reflect.Float32:
- return math.Float32bits(float32(elem.Float()))
- }
- panic("unreachable")
+func (p pointer) toFloat32Ptr() **float32 {
+ return p.v.Interface().(**float32)
}
-
-// Word32Slice returns a reference to a []int32, []uint32, []float32, or []enum field in the struct.
-func structPointer_Word32Slice(p structPointer, f field) word32Slice {
- return word32Slice{structPointer_field(p, f)}
+func (p pointer) toFloat32Slice() *[]float32 {
+ return p.v.Interface().(*[]float32)
}
-
-// word64 is like word32 but for 64-bit values.
-type word64 struct {
- v reflect.Value
+func (p pointer) toString() *string {
+ return p.v.Interface().(*string)
}
-
-func word64_Set(p word64, o *Buffer, x uint64) {
- t := p.v.Type().Elem()
- switch t {
- case int64Type:
- if len(o.int64s) == 0 {
- o.int64s = make([]int64, uint64PoolSize)
- }
- o.int64s[0] = int64(x)
- p.v.Set(reflect.ValueOf(&o.int64s[0]))
- o.int64s = o.int64s[1:]
- return
- case uint64Type:
- if len(o.uint64s) == 0 {
- o.uint64s = make([]uint64, uint64PoolSize)
- }
- o.uint64s[0] = x
- p.v.Set(reflect.ValueOf(&o.uint64s[0]))
- o.uint64s = o.uint64s[1:]
- return
- case float64Type:
- if len(o.float64s) == 0 {
- o.float64s = make([]float64, uint64PoolSize)
- }
- o.float64s[0] = math.Float64frombits(x)
- p.v.Set(reflect.ValueOf(&o.float64s[0]))
- o.float64s = o.float64s[1:]
- return
- }
- panic("unreachable")
+func (p pointer) toStringPtr() **string {
+ return p.v.Interface().(**string)
}
-
-func word64_IsNil(p word64) bool {
- return p.v.IsNil()
+func (p pointer) toStringSlice() *[]string {
+ return p.v.Interface().(*[]string)
}
-
-func word64_Get(p word64) uint64 {
- elem := p.v.Elem()
- switch elem.Kind() {
- case reflect.Int64:
- return uint64(elem.Int())
- case reflect.Uint64:
- return elem.Uint()
- case reflect.Float64:
- return math.Float64bits(elem.Float())
- }
- panic("unreachable")
+func (p pointer) toBytes() *[]byte {
+ return p.v.Interface().(*[]byte)
}
-
-func structPointer_Word64(p structPointer, f field) word64 {
- return word64{structPointer_field(p, f)}
+func (p pointer) toBytesSlice() *[][]byte {
+ return p.v.Interface().(*[][]byte)
+}
+func (p pointer) toExtensions() *XXX_InternalExtensions {
+ return p.v.Interface().(*XXX_InternalExtensions)
+}
+func (p pointer) toOldExtensions() *map[int32]Extension {
+ return p.v.Interface().(*map[int32]Extension)
+}
+func (p pointer) getPointer() pointer {
+ return pointer{v: p.v.Elem()}
+}
+func (p pointer) setPointer(q pointer) {
+ p.v.Elem().Set(q.v)
+}
+func (p pointer) appendPointer(q pointer) {
+ grow(p.v.Elem()).Set(q.v)
}
-// word64Val is like word32Val but for 64-bit values.
-type word64Val struct {
- v reflect.Value
+// getPointerSlice copies []*T from p as a new []pointer.
+// This behavior differs from the implementation in pointer_unsafe.go.
+func (p pointer) getPointerSlice() []pointer {
+ if p.v.IsNil() {
+ return nil
+ }
+ n := p.v.Elem().Len()
+ s := make([]pointer, n)
+ for i := 0; i < n; i++ {
+ s[i] = pointer{v: p.v.Elem().Index(i)}
+ }
+ return s
}
-func word64Val_Set(p word64Val, o *Buffer, x uint64) {
- switch p.v.Type() {
- case int64Type:
- p.v.SetInt(int64(x))
- return
- case uint64Type:
- p.v.SetUint(x)
- return
- case float64Type:
- p.v.SetFloat(math.Float64frombits(x))
+// setPointerSlice copies []pointer into p as a new []*T.
+// This behavior differs from the implementation in pointer_unsafe.go.
+func (p pointer) setPointerSlice(v []pointer) {
+ if v == nil {
+ p.v.Elem().Set(reflect.New(p.v.Elem().Type()).Elem())
return
}
- panic("unreachable")
+ s := reflect.MakeSlice(p.v.Elem().Type(), 0, len(v))
+ for _, p := range v {
+ s = reflect.Append(s, p.v)
+ }
+ p.v.Elem().Set(s)
}
-func word64Val_Get(p word64Val) uint64 {
- elem := p.v
- switch elem.Kind() {
- case reflect.Int64:
- return uint64(elem.Int())
- case reflect.Uint64:
- return elem.Uint()
- case reflect.Float64:
- return math.Float64bits(elem.Float())
+// getInterfacePointer returns a pointer that points to the
+// interface data of the interface pointed by p.
+func (p pointer) getInterfacePointer() pointer {
+ if p.v.Elem().IsNil() {
+ return pointer{v: p.v.Elem()}
}
- panic("unreachable")
+ return pointer{v: p.v.Elem().Elem().Elem().Field(0).Addr()} // *interface -> interface -> *struct -> struct
}
-func structPointer_Word64Val(p structPointer, f field) word64Val {
- return word64Val{structPointer_field(p, f)}
+func (p pointer) asPointerTo(t reflect.Type) reflect.Value {
+ // TODO: check that p.v.Type().Elem() == t?
+ return p.v
}
-type word64Slice struct {
- v reflect.Value
+func atomicLoadUnmarshalInfo(p **unmarshalInfo) *unmarshalInfo {
+ atomicLock.Lock()
+ defer atomicLock.Unlock()
+ return *p
}
-
-func (p word64Slice) Append(x uint64) {
- n, m := p.v.Len(), p.v.Cap()
- if n < m {
- p.v.SetLen(n + 1)
- } else {
- t := p.v.Type().Elem()
- p.v.Set(reflect.Append(p.v, reflect.Zero(t)))
- }
- elem := p.v.Index(n)
- switch elem.Kind() {
- case reflect.Int64:
- elem.SetInt(int64(int64(x)))
- case reflect.Uint64:
- elem.SetUint(uint64(x))
- case reflect.Float64:
- elem.SetFloat(float64(math.Float64frombits(x)))
- }
+func atomicStoreUnmarshalInfo(p **unmarshalInfo, v *unmarshalInfo) {
+ atomicLock.Lock()
+ defer atomicLock.Unlock()
+ *p = v
}
-
-func (p word64Slice) Len() int {
- return p.v.Len()
+func atomicLoadMarshalInfo(p **marshalInfo) *marshalInfo {
+ atomicLock.Lock()
+ defer atomicLock.Unlock()
+ return *p
}
-
-func (p word64Slice) Index(i int) uint64 {
- elem := p.v.Index(i)
- switch elem.Kind() {
- case reflect.Int64:
- return uint64(elem.Int())
- case reflect.Uint64:
- return uint64(elem.Uint())
- case reflect.Float64:
- return math.Float64bits(float64(elem.Float()))
- }
- panic("unreachable")
+func atomicStoreMarshalInfo(p **marshalInfo, v *marshalInfo) {
+ atomicLock.Lock()
+ defer atomicLock.Unlock()
+ *p = v
}
-
-func structPointer_Word64Slice(p structPointer, f field) word64Slice {
- return word64Slice{structPointer_field(p, f)}
+func atomicLoadMergeInfo(p **mergeInfo) *mergeInfo {
+ atomicLock.Lock()
+ defer atomicLock.Unlock()
+ return *p
+}
+func atomicStoreMergeInfo(p **mergeInfo, v *mergeInfo) {
+ atomicLock.Lock()
+ defer atomicLock.Unlock()
+ *p = v
}
+func atomicLoadDiscardInfo(p **discardInfo) *discardInfo {
+ atomicLock.Lock()
+ defer atomicLock.Unlock()
+ return *p
+}
+func atomicStoreDiscardInfo(p **discardInfo, v *discardInfo) {
+ atomicLock.Lock()
+ defer atomicLock.Unlock()
+ *p = v
+}
+
+var atomicLock sync.Mutex
diff --git a/vendor/github.com/golang/protobuf/proto/pointer_unsafe.go b/vendor/github.com/golang/protobuf/proto/pointer_unsafe.go
index 6b5567d47..dbfffe071 100644
--- a/vendor/github.com/golang/protobuf/proto/pointer_unsafe.go
+++ b/vendor/github.com/golang/protobuf/proto/pointer_unsafe.go
@@ -29,7 +29,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-// +build !appengine,!js
+// +build !purego,!appengine,!js
// This file contains the implementation of the proto field accesses using package unsafe.
@@ -37,38 +37,13 @@ package proto
import (
"reflect"
+ "sync/atomic"
"unsafe"
)
-// NOTE: These type_Foo functions would more idiomatically be methods,
-// but Go does not allow methods on pointer types, and we must preserve
-// some pointer type for the garbage collector. We use these
-// funcs with clunky names as our poor approximation to methods.
-//
-// An alternative would be
-// type structPointer struct { p unsafe.Pointer }
-// but that does not registerize as well.
-
-// A structPointer is a pointer to a struct.
-type structPointer unsafe.Pointer
-
-// toStructPointer returns a structPointer equivalent to the given reflect value.
-func toStructPointer(v reflect.Value) structPointer {
- return structPointer(unsafe.Pointer(v.Pointer()))
-}
-
-// IsNil reports whether p is nil.
-func structPointer_IsNil(p structPointer) bool {
- return p == nil
-}
-
-// Interface returns the struct pointer, assumed to have element type t,
-// as an interface value.
-func structPointer_Interface(p structPointer, t reflect.Type) interface{} {
- return reflect.NewAt(t, unsafe.Pointer(p)).Interface()
-}
+const unsafeAllowed = true
-// A field identifies a field in a struct, accessible from a structPointer.
+// A field identifies a field in a struct, accessible from a pointer.
// In this implementation, a field is identified by its byte offset from the start of the struct.
type field uintptr
@@ -80,191 +55,259 @@ func toField(f *reflect.StructField) field {
// invalidField is an invalid field identifier.
const invalidField = ^field(0)
+// zeroField is a noop when calling pointer.offset.
+const zeroField = field(0)
+
// IsValid reports whether the field identifier is valid.
func (f field) IsValid() bool {
- return f != ^field(0)
+ return f != invalidField
+}
+
+// The pointer type below is for the new table-driven encoder/decoder.
+// The implementation here uses unsafe.Pointer to create a generic pointer.
+// In pointer_reflect.go we use reflect instead of unsafe to implement
+// the same (but slower) interface.
+type pointer struct {
+ p unsafe.Pointer
+}
+
+// size of pointer
+var ptrSize = unsafe.Sizeof(uintptr(0))
+
+// toPointer converts an interface of pointer type to a pointer
+// that points to the same target.
+func toPointer(i *Message) pointer {
+ // Super-tricky - read pointer out of data word of interface value.
+ // Saves ~25ns over the equivalent:
+ // return valToPointer(reflect.ValueOf(*i))
+ return pointer{p: (*[2]unsafe.Pointer)(unsafe.Pointer(i))[1]}
+}
+
+// toAddrPointer converts an interface to a pointer that points to
+// the interface data.
+func toAddrPointer(i *interface{}, isptr, deref bool) (p pointer) {
+ // Super-tricky - read or get the address of data word of interface value.
+ if isptr {
+ // The interface is of pointer type, thus it is a direct interface.
+ // The data word is the pointer data itself. We take its address.
+ p = pointer{p: unsafe.Pointer(uintptr(unsafe.Pointer(i)) + ptrSize)}
+ } else {
+ // The interface is not of pointer type. The data word is the pointer
+ // to the data.
+ p = pointer{p: (*[2]unsafe.Pointer)(unsafe.Pointer(i))[1]}
+ }
+ if deref {
+ p.p = *(*unsafe.Pointer)(p.p)
+ }
+ return p
}
-// Bytes returns the address of a []byte field in the struct.
-func structPointer_Bytes(p structPointer, f field) *[]byte {
- return (*[]byte)(unsafe.Pointer(uintptr(p) + uintptr(f)))
+// valToPointer converts v to a pointer. v must be of pointer type.
+func valToPointer(v reflect.Value) pointer {
+ return pointer{p: unsafe.Pointer(v.Pointer())}
}
-// BytesSlice returns the address of a [][]byte field in the struct.
-func structPointer_BytesSlice(p structPointer, f field) *[][]byte {
- return (*[][]byte)(unsafe.Pointer(uintptr(p) + uintptr(f)))
+// offset converts from a pointer to a structure to a pointer to
+// one of its fields.
+func (p pointer) offset(f field) pointer {
+ // For safety, we should panic if !f.IsValid, however calling panic causes
+ // this to no longer be inlineable, which is a serious performance cost.
+ /*
+ if !f.IsValid() {
+ panic("invalid field")
+ }
+ */
+ return pointer{p: unsafe.Pointer(uintptr(p.p) + uintptr(f))}
}
-// Bool returns the address of a *bool field in the struct.
-func structPointer_Bool(p structPointer, f field) **bool {
- return (**bool)(unsafe.Pointer(uintptr(p) + uintptr(f)))
+func (p pointer) isNil() bool {
+ return p.p == nil
}
-// BoolVal returns the address of a bool field in the struct.
-func structPointer_BoolVal(p structPointer, f field) *bool {
- return (*bool)(unsafe.Pointer(uintptr(p) + uintptr(f)))
+func (p pointer) toInt64() *int64 {
+ return (*int64)(p.p)
}
-
-// BoolSlice returns the address of a []bool field in the struct.
-func structPointer_BoolSlice(p structPointer, f field) *[]bool {
- return (*[]bool)(unsafe.Pointer(uintptr(p) + uintptr(f)))
+func (p pointer) toInt64Ptr() **int64 {
+ return (**int64)(p.p)
}
-
-// String returns the address of a *string field in the struct.
-func structPointer_String(p structPointer, f field) **string {
- return (**string)(unsafe.Pointer(uintptr(p) + uintptr(f)))
+func (p pointer) toInt64Slice() *[]int64 {
+ return (*[]int64)(p.p)
}
-
-// StringVal returns the address of a string field in the struct.
-func structPointer_StringVal(p structPointer, f field) *string {
- return (*string)(unsafe.Pointer(uintptr(p) + uintptr(f)))
+func (p pointer) toInt32() *int32 {
+ return (*int32)(p.p)
}
-// StringSlice returns the address of a []string field in the struct.
-func structPointer_StringSlice(p structPointer, f field) *[]string {
- return (*[]string)(unsafe.Pointer(uintptr(p) + uintptr(f)))
+// See pointer_reflect.go for why toInt32Ptr/Slice doesn't exist.
+/*
+ func (p pointer) toInt32Ptr() **int32 {
+ return (**int32)(p.p)
+ }
+ func (p pointer) toInt32Slice() *[]int32 {
+ return (*[]int32)(p.p)
+ }
+*/
+func (p pointer) getInt32Ptr() *int32 {
+ return *(**int32)(p.p)
}
-
-// ExtMap returns the address of an extension map field in the struct.
-func structPointer_Extensions(p structPointer, f field) *XXX_InternalExtensions {
- return (*XXX_InternalExtensions)(unsafe.Pointer(uintptr(p) + uintptr(f)))
+func (p pointer) setInt32Ptr(v int32) {
+ *(**int32)(p.p) = &v
}
-func structPointer_ExtMap(p structPointer, f field) *map[int32]Extension {
- return (*map[int32]Extension)(unsafe.Pointer(uintptr(p) + uintptr(f)))
+// getInt32Slice loads a []int32 from p.
+// The value returned is aliased with the original slice.
+// This behavior differs from the implementation in pointer_reflect.go.
+func (p pointer) getInt32Slice() []int32 {
+ return *(*[]int32)(p.p)
}
-// NewAt returns the reflect.Value for a pointer to a field in the struct.
-func structPointer_NewAt(p structPointer, f field, typ reflect.Type) reflect.Value {
- return reflect.NewAt(typ, unsafe.Pointer(uintptr(p)+uintptr(f)))
+// setInt32Slice stores a []int32 to p.
+// The value set is aliased with the input slice.
+// This behavior differs from the implementation in pointer_reflect.go.
+func (p pointer) setInt32Slice(v []int32) {
+ *(*[]int32)(p.p) = v
}
-// SetStructPointer writes a *struct field in the struct.
-func structPointer_SetStructPointer(p structPointer, f field, q structPointer) {
- *(*structPointer)(unsafe.Pointer(uintptr(p) + uintptr(f))) = q
+// TODO: Can we get rid of appendInt32Slice and use setInt32Slice instead?
+func (p pointer) appendInt32Slice(v int32) {
+ s := (*[]int32)(p.p)
+ *s = append(*s, v)
}
-// GetStructPointer reads a *struct field in the struct.
-func structPointer_GetStructPointer(p structPointer, f field) structPointer {
- return *(*structPointer)(unsafe.Pointer(uintptr(p) + uintptr(f)))
+func (p pointer) toUint64() *uint64 {
+ return (*uint64)(p.p)
}
-
-// StructPointerSlice the address of a []*struct field in the struct.
-func structPointer_StructPointerSlice(p structPointer, f field) *structPointerSlice {
- return (*structPointerSlice)(unsafe.Pointer(uintptr(p) + uintptr(f)))
+func (p pointer) toUint64Ptr() **uint64 {
+ return (**uint64)(p.p)
}
-
-// A structPointerSlice represents a slice of pointers to structs (themselves submessages or groups).
-type structPointerSlice []structPointer
-
-func (v *structPointerSlice) Len() int { return len(*v) }
-func (v *structPointerSlice) Index(i int) structPointer { return (*v)[i] }
-func (v *structPointerSlice) Append(p structPointer) { *v = append(*v, p) }
-
-// A word32 is the address of a "pointer to 32-bit value" field.
-type word32 **uint32
-
-// IsNil reports whether *v is nil.
-func word32_IsNil(p word32) bool {
- return *p == nil
+func (p pointer) toUint64Slice() *[]uint64 {
+ return (*[]uint64)(p.p)
}
-
-// Set sets *v to point at a newly allocated word set to x.
-func word32_Set(p word32, o *Buffer, x uint32) {
- if len(o.uint32s) == 0 {
- o.uint32s = make([]uint32, uint32PoolSize)
- }
- o.uint32s[0] = x
- *p = &o.uint32s[0]
- o.uint32s = o.uint32s[1:]
+func (p pointer) toUint32() *uint32 {
+ return (*uint32)(p.p)
}
-
-// Get gets the value pointed at by *v.
-func word32_Get(p word32) uint32 {
- return **p
+func (p pointer) toUint32Ptr() **uint32 {
+ return (**uint32)(p.p)
}
-
-// Word32 returns the address of a *int32, *uint32, *float32, or *enum field in the struct.
-func structPointer_Word32(p structPointer, f field) word32 {
- return word32((**uint32)(unsafe.Pointer(uintptr(p) + uintptr(f))))
+func (p pointer) toUint32Slice() *[]uint32 {
+ return (*[]uint32)(p.p)
}
-
-// A word32Val is the address of a 32-bit value field.
-type word32Val *uint32
-
-// Set sets *p to x.
-func word32Val_Set(p word32Val, x uint32) {
- *p = x
+func (p pointer) toBool() *bool {
+ return (*bool)(p.p)
}
-
-// Get gets the value pointed at by p.
-func word32Val_Get(p word32Val) uint32 {
- return *p
+func (p pointer) toBoolPtr() **bool {
+ return (**bool)(p.p)
}
-
-// Word32Val returns the address of a *int32, *uint32, *float32, or *enum field in the struct.
-func structPointer_Word32Val(p structPointer, f field) word32Val {
- return word32Val((*uint32)(unsafe.Pointer(uintptr(p) + uintptr(f))))
+func (p pointer) toBoolSlice() *[]bool {
+ return (*[]bool)(p.p)
}
-
-// A word32Slice is a slice of 32-bit values.
-type word32Slice []uint32
-
-func (v *word32Slice) Append(x uint32) { *v = append(*v, x) }
-func (v *word32Slice) Len() int { return len(*v) }
-func (v *word32Slice) Index(i int) uint32 { return (*v)[i] }
-
-// Word32Slice returns the address of a []int32, []uint32, []float32, or []enum field in the struct.
-func structPointer_Word32Slice(p structPointer, f field) *word32Slice {
- return (*word32Slice)(unsafe.Pointer(uintptr(p) + uintptr(f)))
+func (p pointer) toFloat64() *float64 {
+ return (*float64)(p.p)
}
-
-// word64 is like word32 but for 64-bit values.
-type word64 **uint64
-
-func word64_Set(p word64, o *Buffer, x uint64) {
- if len(o.uint64s) == 0 {
- o.uint64s = make([]uint64, uint64PoolSize)
- }
- o.uint64s[0] = x
- *p = &o.uint64s[0]
- o.uint64s = o.uint64s[1:]
+func (p pointer) toFloat64Ptr() **float64 {
+ return (**float64)(p.p)
}
-
-func word64_IsNil(p word64) bool {
- return *p == nil
+func (p pointer) toFloat64Slice() *[]float64 {
+ return (*[]float64)(p.p)
}
-
-func word64_Get(p word64) uint64 {
- return **p
+func (p pointer) toFloat32() *float32 {
+ return (*float32)(p.p)
+}
+func (p pointer) toFloat32Ptr() **float32 {
+ return (**float32)(p.p)
+}
+func (p pointer) toFloat32Slice() *[]float32 {
+ return (*[]float32)(p.p)
+}
+func (p pointer) toString() *string {
+ return (*string)(p.p)
+}
+func (p pointer) toStringPtr() **string {
+ return (**string)(p.p)
+}
+func (p pointer) toStringSlice() *[]string {
+ return (*[]string)(p.p)
+}
+func (p pointer) toBytes() *[]byte {
+ return (*[]byte)(p.p)
+}
+func (p pointer) toBytesSlice() *[][]byte {
+ return (*[][]byte)(p.p)
+}
+func (p pointer) toExtensions() *XXX_InternalExtensions {
+ return (*XXX_InternalExtensions)(p.p)
+}
+func (p pointer) toOldExtensions() *map[int32]Extension {
+ return (*map[int32]Extension)(p.p)
}
-func structPointer_Word64(p structPointer, f field) word64 {
- return word64((**uint64)(unsafe.Pointer(uintptr(p) + uintptr(f))))
+// getPointerSlice loads []*T from p as a []pointer.
+// The value returned is aliased with the original slice.
+// This behavior differs from the implementation in pointer_reflect.go.
+func (p pointer) getPointerSlice() []pointer {
+ // Super-tricky - p should point to a []*T where T is a
+ // message type. We load it as []pointer.
+ return *(*[]pointer)(p.p)
}
-// word64Val is like word32Val but for 64-bit values.
-type word64Val *uint64
+// setPointerSlice stores []pointer into p as a []*T.
+// The value set is aliased with the input slice.
+// This behavior differs from the implementation in pointer_reflect.go.
+func (p pointer) setPointerSlice(v []pointer) {
+ // Super-tricky - p should point to a []*T where T is a
+ // message type. We store it as []pointer.
+ *(*[]pointer)(p.p) = v
+}
-func word64Val_Set(p word64Val, o *Buffer, x uint64) {
- *p = x
+// getPointer loads the pointer at p and returns it.
+func (p pointer) getPointer() pointer {
+ return pointer{p: *(*unsafe.Pointer)(p.p)}
}
-func word64Val_Get(p word64Val) uint64 {
- return *p
+// setPointer stores the pointer q at p.
+func (p pointer) setPointer(q pointer) {
+ *(*unsafe.Pointer)(p.p) = q.p
}
-func structPointer_Word64Val(p structPointer, f field) word64Val {
- return word64Val((*uint64)(unsafe.Pointer(uintptr(p) + uintptr(f))))
+// append q to the slice pointed to by p.
+func (p pointer) appendPointer(q pointer) {
+ s := (*[]unsafe.Pointer)(p.p)
+ *s = append(*s, q.p)
}
-// word64Slice is like word32Slice but for 64-bit values.
-type word64Slice []uint64
+// getInterfacePointer returns a pointer that points to the
+// interface data of the interface pointed by p.
+func (p pointer) getInterfacePointer() pointer {
+ // Super-tricky - read pointer out of data word of interface value.
+ return pointer{p: (*(*[2]unsafe.Pointer)(p.p))[1]}
+}
-func (v *word64Slice) Append(x uint64) { *v = append(*v, x) }
-func (v *word64Slice) Len() int { return len(*v) }
-func (v *word64Slice) Index(i int) uint64 { return (*v)[i] }
+// asPointerTo returns a reflect.Value that is a pointer to an
+// object of type t stored at p.
+func (p pointer) asPointerTo(t reflect.Type) reflect.Value {
+ return reflect.NewAt(t, p.p)
+}
-func structPointer_Word64Slice(p structPointer, f field) *word64Slice {
- return (*word64Slice)(unsafe.Pointer(uintptr(p) + uintptr(f)))
+func atomicLoadUnmarshalInfo(p **unmarshalInfo) *unmarshalInfo {
+ return (*unmarshalInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(p))))
+}
+func atomicStoreUnmarshalInfo(p **unmarshalInfo, v *unmarshalInfo) {
+ atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(p)), unsafe.Pointer(v))
+}
+func atomicLoadMarshalInfo(p **marshalInfo) *marshalInfo {
+ return (*marshalInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(p))))
+}
+func atomicStoreMarshalInfo(p **marshalInfo, v *marshalInfo) {
+ atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(p)), unsafe.Pointer(v))
+}
+func atomicLoadMergeInfo(p **mergeInfo) *mergeInfo {
+ return (*mergeInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(p))))
+}
+func atomicStoreMergeInfo(p **mergeInfo, v *mergeInfo) {
+ atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(p)), unsafe.Pointer(v))
+}
+func atomicLoadDiscardInfo(p **discardInfo) *discardInfo {
+ return (*discardInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(p))))
+}
+func atomicStoreDiscardInfo(p **discardInfo, v *discardInfo) {
+ atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(p)), unsafe.Pointer(v))
}
diff --git a/vendor/github.com/golang/protobuf/proto/properties.go b/vendor/github.com/golang/protobuf/proto/properties.go
index ec2289c00..79668ff5c 100644
--- a/vendor/github.com/golang/protobuf/proto/properties.go
+++ b/vendor/github.com/golang/protobuf/proto/properties.go
@@ -58,42 +58,6 @@ const (
WireFixed32 = 5
)
-const startSize = 10 // initial slice/string sizes
-
-// Encoders are defined in encode.go
-// An encoder outputs the full representation of a field, including its
-// tag and encoder type.
-type encoder func(p *Buffer, prop *Properties, base structPointer) error
-
-// A valueEncoder encodes a single integer in a particular encoding.
-type valueEncoder func(o *Buffer, x uint64) error
-
-// Sizers are defined in encode.go
-// A sizer returns the encoded size of a field, including its tag and encoder
-// type.
-type sizer func(prop *Properties, base structPointer) int
-
-// A valueSizer returns the encoded size of a single integer in a particular
-// encoding.
-type valueSizer func(x uint64) int
-
-// Decoders are defined in decode.go
-// A decoder creates a value from its wire representation.
-// Unrecognized subelements are saved in unrec.
-type decoder func(p *Buffer, prop *Properties, base structPointer) error
-
-// A valueDecoder decodes a single integer in a particular encoding.
-type valueDecoder func(o *Buffer) (x uint64, err error)
-
-// A oneofMarshaler does the marshaling for all oneof fields in a message.
-type oneofMarshaler func(Message, *Buffer) error
-
-// A oneofUnmarshaler does the unmarshaling for a oneof field in a message.
-type oneofUnmarshaler func(Message, int, int, *Buffer) (bool, error)
-
-// A oneofSizer does the sizing for all oneof fields in a message.
-type oneofSizer func(Message) int
-
// tagMap is an optimization over map[int]int for typical protocol buffer
// use-cases. Encoded protocol buffers are often in tag order with small tag
// numbers.
@@ -140,13 +104,6 @@ type StructProperties struct {
decoderTags tagMap // map from proto tag to struct field number
decoderOrigNames map[string]int // map from original name to struct field number
order []int // list of struct field numbers in tag order
- unrecField field // field id of the XXX_unrecognized []byte field
- extendable bool // is this an extendable proto
-
- oneofMarshaler oneofMarshaler
- oneofUnmarshaler oneofUnmarshaler
- oneofSizer oneofSizer
- stype reflect.Type
// OneofTypes contains information about the oneof fields in this message.
// It is keyed by the original name of a field.
@@ -182,41 +139,24 @@ type Properties struct {
Repeated bool
Packed bool // relevant for repeated primitives only
Enum string // set for enum types only
- proto3 bool // whether this is known to be a proto3 field; set for []byte only
+ proto3 bool // whether this is known to be a proto3 field
oneof bool // whether this is a oneof field
Default string // default value
HasDefault bool // whether an explicit default was provided
- def_uint64 uint64
-
- enc encoder
- valEnc valueEncoder // set for bool and numeric types only
- field field
- tagcode []byte // encoding of EncodeVarint((Tag<<3)|WireType)
- tagbuf [8]byte
- stype reflect.Type // set for struct types only
- sprop *StructProperties // set for struct types only
- isMarshaler bool
- isUnmarshaler bool
-
- mtype reflect.Type // set for map types only
- mkeyprop *Properties // set for map types only
- mvalprop *Properties // set for map types only
-
- size sizer
- valSize valueSizer // set for bool and numeric types only
-
- dec decoder
- valDec valueDecoder // set for bool and numeric types only
-
- // If this is a packable field, this will be the decoder for the packed version of the field.
- packedDec decoder
+
+ stype reflect.Type // set for struct types only
+ sprop *StructProperties // set for struct types only
+
+ mtype reflect.Type // set for map types only
+ MapKeyProp *Properties // set for map types only
+ MapValProp *Properties // set for map types only
}
// String formats the properties in the protobuf struct field tag style.
func (p *Properties) String() string {
s := p.Wire
- s = ","
+ s += ","
s += strconv.Itoa(p.Tag)
if p.Required {
s += ",req"
@@ -262,29 +202,14 @@ func (p *Properties) Parse(s string) {
switch p.Wire {
case "varint":
p.WireType = WireVarint
- p.valEnc = (*Buffer).EncodeVarint
- p.valDec = (*Buffer).DecodeVarint
- p.valSize = sizeVarint
case "fixed32":
p.WireType = WireFixed32
- p.valEnc = (*Buffer).EncodeFixed32
- p.valDec = (*Buffer).DecodeFixed32
- p.valSize = sizeFixed32
case "fixed64":
p.WireType = WireFixed64
- p.valEnc = (*Buffer).EncodeFixed64
- p.valDec = (*Buffer).DecodeFixed64
- p.valSize = sizeFixed64
case "zigzag32":
p.WireType = WireVarint
- p.valEnc = (*Buffer).EncodeZigzag32
- p.valDec = (*Buffer).DecodeZigzag32
- p.valSize = sizeZigzag32
case "zigzag64":
p.WireType = WireVarint
- p.valEnc = (*Buffer).EncodeZigzag64
- p.valDec = (*Buffer).DecodeZigzag64
- p.valSize = sizeZigzag64
case "bytes", "group":
p.WireType = WireBytes
// no numeric converter for non-numeric types
@@ -299,6 +224,7 @@ func (p *Properties) Parse(s string) {
return
}
+outer:
for i := 2; i < len(fields); i++ {
f := fields[i]
switch {
@@ -326,255 +252,40 @@ func (p *Properties) Parse(s string) {
if i+1 < len(fields) {
// Commas aren't escaped, and def is always last.
p.Default += "," + strings.Join(fields[i+1:], ",")
- break
+ break outer
}
}
}
}
-func logNoSliceEnc(t1, t2 reflect.Type) {
- fmt.Fprintf(os.Stderr, "proto: no slice oenc for %T = []%T\n", t1, t2)
-}
-
var protoMessageType = reflect.TypeOf((*Message)(nil)).Elem()
-// Initialize the fields for encoding and decoding.
-func (p *Properties) setEncAndDec(typ reflect.Type, f *reflect.StructField, lockGetProp bool) {
- p.enc = nil
- p.dec = nil
- p.size = nil
-
+// setFieldProps initializes the field properties for submessages and maps.
+func (p *Properties) setFieldProps(typ reflect.Type, f *reflect.StructField, lockGetProp bool) {
switch t1 := typ; t1.Kind() {
- default:
- fmt.Fprintf(os.Stderr, "proto: no coders for %v\n", t1)
-
- // proto3 scalar types
-
- case reflect.Bool:
- p.enc = (*Buffer).enc_proto3_bool
- p.dec = (*Buffer).dec_proto3_bool
- p.size = size_proto3_bool
- case reflect.Int32:
- p.enc = (*Buffer).enc_proto3_int32
- p.dec = (*Buffer).dec_proto3_int32
- p.size = size_proto3_int32
- case reflect.Uint32:
- p.enc = (*Buffer).enc_proto3_uint32
- p.dec = (*Buffer).dec_proto3_int32 // can reuse
- p.size = size_proto3_uint32
- case reflect.Int64, reflect.Uint64:
- p.enc = (*Buffer).enc_proto3_int64
- p.dec = (*Buffer).dec_proto3_int64
- p.size = size_proto3_int64
- case reflect.Float32:
- p.enc = (*Buffer).enc_proto3_uint32 // can just treat them as bits
- p.dec = (*Buffer).dec_proto3_int32
- p.size = size_proto3_uint32
- case reflect.Float64:
- p.enc = (*Buffer).enc_proto3_int64 // can just treat them as bits
- p.dec = (*Buffer).dec_proto3_int64
- p.size = size_proto3_int64
- case reflect.String:
- p.enc = (*Buffer).enc_proto3_string
- p.dec = (*Buffer).dec_proto3_string
- p.size = size_proto3_string
-
case reflect.Ptr:
- switch t2 := t1.Elem(); t2.Kind() {
- default:
- fmt.Fprintf(os.Stderr, "proto: no encoder function for %v -> %v\n", t1, t2)
- break
- case reflect.Bool:
- p.enc = (*Buffer).enc_bool
- p.dec = (*Buffer).dec_bool
- p.size = size_bool
- case reflect.Int32:
- p.enc = (*Buffer).enc_int32
- p.dec = (*Buffer).dec_int32
- p.size = size_int32
- case reflect.Uint32:
- p.enc = (*Buffer).enc_uint32
- p.dec = (*Buffer).dec_int32 // can reuse
- p.size = size_uint32
- case reflect.Int64, reflect.Uint64:
- p.enc = (*Buffer).enc_int64
- p.dec = (*Buffer).dec_int64
- p.size = size_int64
- case reflect.Float32:
- p.enc = (*Buffer).enc_uint32 // can just treat them as bits
- p.dec = (*Buffer).dec_int32
- p.size = size_uint32
- case reflect.Float64:
- p.enc = (*Buffer).enc_int64 // can just treat them as bits
- p.dec = (*Buffer).dec_int64
- p.size = size_int64
- case reflect.String:
- p.enc = (*Buffer).enc_string
- p.dec = (*Buffer).dec_string
- p.size = size_string
- case reflect.Struct:
+ if t1.Elem().Kind() == reflect.Struct {
p.stype = t1.Elem()
- p.isMarshaler = isMarshaler(t1)
- p.isUnmarshaler = isUnmarshaler(t1)
- if p.Wire == "bytes" {
- p.enc = (*Buffer).enc_struct_message
- p.dec = (*Buffer).dec_struct_message
- p.size = size_struct_message
- } else {
- p.enc = (*Buffer).enc_struct_group
- p.dec = (*Buffer).dec_struct_group
- p.size = size_struct_group
- }
}
case reflect.Slice:
- switch t2 := t1.Elem(); t2.Kind() {
- default:
- logNoSliceEnc(t1, t2)
- break
- case reflect.Bool:
- if p.Packed {
- p.enc = (*Buffer).enc_slice_packed_bool
- p.size = size_slice_packed_bool
- } else {
- p.enc = (*Buffer).enc_slice_bool
- p.size = size_slice_bool
- }
- p.dec = (*Buffer).dec_slice_bool
- p.packedDec = (*Buffer).dec_slice_packed_bool
- case reflect.Int32:
- if p.Packed {
- p.enc = (*Buffer).enc_slice_packed_int32
- p.size = size_slice_packed_int32
- } else {
- p.enc = (*Buffer).enc_slice_int32
- p.size = size_slice_int32
- }
- p.dec = (*Buffer).dec_slice_int32
- p.packedDec = (*Buffer).dec_slice_packed_int32
- case reflect.Uint32:
- if p.Packed {
- p.enc = (*Buffer).enc_slice_packed_uint32
- p.size = size_slice_packed_uint32
- } else {
- p.enc = (*Buffer).enc_slice_uint32
- p.size = size_slice_uint32
- }
- p.dec = (*Buffer).dec_slice_int32
- p.packedDec = (*Buffer).dec_slice_packed_int32
- case reflect.Int64, reflect.Uint64:
- if p.Packed {
- p.enc = (*Buffer).enc_slice_packed_int64
- p.size = size_slice_packed_int64
- } else {
- p.enc = (*Buffer).enc_slice_int64
- p.size = size_slice_int64
- }
- p.dec = (*Buffer).dec_slice_int64
- p.packedDec = (*Buffer).dec_slice_packed_int64
- case reflect.Uint8:
- p.dec = (*Buffer).dec_slice_byte
- if p.proto3 {
- p.enc = (*Buffer).enc_proto3_slice_byte
- p.size = size_proto3_slice_byte
- } else {
- p.enc = (*Buffer).enc_slice_byte
- p.size = size_slice_byte
- }
- case reflect.Float32, reflect.Float64:
- switch t2.Bits() {
- case 32:
- // can just treat them as bits
- if p.Packed {
- p.enc = (*Buffer).enc_slice_packed_uint32
- p.size = size_slice_packed_uint32
- } else {
- p.enc = (*Buffer).enc_slice_uint32
- p.size = size_slice_uint32
- }
- p.dec = (*Buffer).dec_slice_int32
- p.packedDec = (*Buffer).dec_slice_packed_int32
- case 64:
- // can just treat them as bits
- if p.Packed {
- p.enc = (*Buffer).enc_slice_packed_int64
- p.size = size_slice_packed_int64
- } else {
- p.enc = (*Buffer).enc_slice_int64
- p.size = size_slice_int64
- }
- p.dec = (*Buffer).dec_slice_int64
- p.packedDec = (*Buffer).dec_slice_packed_int64
- default:
- logNoSliceEnc(t1, t2)
- break
- }
- case reflect.String:
- p.enc = (*Buffer).enc_slice_string
- p.dec = (*Buffer).dec_slice_string
- p.size = size_slice_string
- case reflect.Ptr:
- switch t3 := t2.Elem(); t3.Kind() {
- default:
- fmt.Fprintf(os.Stderr, "proto: no ptr oenc for %T -> %T -> %T\n", t1, t2, t3)
- break
- case reflect.Struct:
- p.stype = t2.Elem()
- p.isMarshaler = isMarshaler(t2)
- p.isUnmarshaler = isUnmarshaler(t2)
- if p.Wire == "bytes" {
- p.enc = (*Buffer).enc_slice_struct_message
- p.dec = (*Buffer).dec_slice_struct_message
- p.size = size_slice_struct_message
- } else {
- p.enc = (*Buffer).enc_slice_struct_group
- p.dec = (*Buffer).dec_slice_struct_group
- p.size = size_slice_struct_group
- }
- }
- case reflect.Slice:
- switch t2.Elem().Kind() {
- default:
- fmt.Fprintf(os.Stderr, "proto: no slice elem oenc for %T -> %T -> %T\n", t1, t2, t2.Elem())
- break
- case reflect.Uint8:
- p.enc = (*Buffer).enc_slice_slice_byte
- p.dec = (*Buffer).dec_slice_slice_byte
- p.size = size_slice_slice_byte
- }
+ if t2 := t1.Elem(); t2.Kind() == reflect.Ptr && t2.Elem().Kind() == reflect.Struct {
+ p.stype = t2.Elem()
}
case reflect.Map:
- p.enc = (*Buffer).enc_new_map
- p.dec = (*Buffer).dec_new_map
- p.size = size_new_map
-
p.mtype = t1
- p.mkeyprop = &Properties{}
- p.mkeyprop.init(reflect.PtrTo(p.mtype.Key()), "Key", f.Tag.Get("protobuf_key"), nil, lockGetProp)
- p.mvalprop = &Properties{}
+ p.MapKeyProp = &Properties{}
+ p.MapKeyProp.init(reflect.PtrTo(p.mtype.Key()), "Key", f.Tag.Get("protobuf_key"), nil, lockGetProp)
+ p.MapValProp = &Properties{}
vtype := p.mtype.Elem()
if vtype.Kind() != reflect.Ptr && vtype.Kind() != reflect.Slice {
// The value type is not a message (*T) or bytes ([]byte),
// so we need encoders for the pointer to this type.
vtype = reflect.PtrTo(vtype)
}
- p.mvalprop.init(vtype, "Value", f.Tag.Get("protobuf_val"), nil, lockGetProp)
- }
-
- // precalculate tag code
- wire := p.WireType
- if p.Packed {
- wire = WireBytes
+ p.MapValProp.init(vtype, "Value", f.Tag.Get("protobuf_val"), nil, lockGetProp)
}
- x := uint32(p.Tag)<<3 | uint32(wire)
- i := 0
- for i = 0; x > 127; i++ {
- p.tagbuf[i] = 0x80 | uint8(x&0x7F)
- x >>= 7
- }
- p.tagbuf[i] = uint8(x)
- p.tagcode = p.tagbuf[0 : i+1]
if p.stype != nil {
if lockGetProp {
@@ -586,32 +297,9 @@ func (p *Properties) setEncAndDec(typ reflect.Type, f *reflect.StructField, lock
}
var (
- marshalerType = reflect.TypeOf((*Marshaler)(nil)).Elem()
- unmarshalerType = reflect.TypeOf((*Unmarshaler)(nil)).Elem()
+ marshalerType = reflect.TypeOf((*Marshaler)(nil)).Elem()
)
-// isMarshaler reports whether type t implements Marshaler.
-func isMarshaler(t reflect.Type) bool {
- // We're checking for (likely) pointer-receiver methods
- // so if t is not a pointer, something is very wrong.
- // The calls above only invoke isMarshaler on pointer types.
- if t.Kind() != reflect.Ptr {
- panic("proto: misuse of isMarshaler")
- }
- return t.Implements(marshalerType)
-}
-
-// isUnmarshaler reports whether type t implements Unmarshaler.
-func isUnmarshaler(t reflect.Type) bool {
- // We're checking for (likely) pointer-receiver methods
- // so if t is not a pointer, something is very wrong.
- // The calls above only invoke isUnmarshaler on pointer types.
- if t.Kind() != reflect.Ptr {
- panic("proto: misuse of isUnmarshaler")
- }
- return t.Implements(unmarshalerType)
-}
-
// Init populates the properties from a protocol buffer struct tag.
func (p *Properties) Init(typ reflect.Type, name, tag string, f *reflect.StructField) {
p.init(typ, name, tag, f, true)
@@ -621,14 +309,11 @@ func (p *Properties) init(typ reflect.Type, name, tag string, f *reflect.StructF
// "bytes,49,opt,def=hello!"
p.Name = name
p.OrigName = name
- if f != nil {
- p.field = toField(f)
- }
if tag == "" {
return
}
p.Parse(tag)
- p.setEncAndDec(typ, f, lockGetProp)
+ p.setFieldProps(typ, f, lockGetProp)
}
var (
@@ -649,9 +334,6 @@ func GetProperties(t reflect.Type) *StructProperties {
sprop, ok := propertiesMap[t]
propertiesMu.RUnlock()
if ok {
- if collectStats {
- stats.Chit++
- }
return sprop
}
@@ -661,26 +343,26 @@ func GetProperties(t reflect.Type) *StructProperties {
return sprop
}
+type (
+ oneofFuncsIface interface {
+ XXX_OneofFuncs() (func(Message, *Buffer) error, func(Message, int, int, *Buffer) (bool, error), func(Message) int, []interface{})
+ }
+ oneofWrappersIface interface {
+ XXX_OneofWrappers() []interface{}
+ }
+)
+
// getPropertiesLocked requires that propertiesMu is held.
func getPropertiesLocked(t reflect.Type) *StructProperties {
if prop, ok := propertiesMap[t]; ok {
- if collectStats {
- stats.Chit++
- }
return prop
}
- if collectStats {
- stats.Cmiss++
- }
prop := new(StructProperties)
// in case of recursive protos, fill this in now.
propertiesMap[t] = prop
// build properties
- prop.extendable = reflect.PtrTo(t).Implements(extendableProtoType) ||
- reflect.PtrTo(t).Implements(extendableProtoV1Type)
- prop.unrecField = invalidField
prop.Prop = make([]*Properties, t.NumField())
prop.order = make([]int, t.NumField())
@@ -690,17 +372,6 @@ func getPropertiesLocked(t reflect.Type) *StructProperties {
name := f.Name
p.init(f.Type, name, f.Tag.Get("protobuf"), &f, false)
- if f.Name == "XXX_InternalExtensions" { // special case
- p.enc = (*Buffer).enc_exts
- p.dec = nil // not needed
- p.size = size_exts
- } else if f.Name == "XXX_extensions" { // special case
- p.enc = (*Buffer).enc_map
- p.dec = nil // not needed
- p.size = size_map
- } else if f.Name == "XXX_unrecognized" { // special case
- prop.unrecField = toField(&f)
- }
oneof := f.Tag.Get("protobuf_oneof") // special case
if oneof != "" {
// Oneof fields don't use the traditional protobuf tag.
@@ -715,22 +386,19 @@ func getPropertiesLocked(t reflect.Type) *StructProperties {
}
print("\n")
}
- if p.enc == nil && !strings.HasPrefix(f.Name, "XXX_") && oneof == "" {
- fmt.Fprintln(os.Stderr, "proto: no encoder for", f.Name, f.Type.String(), "[GetProperties]")
- }
}
// Re-order prop.order.
sort.Sort(prop)
- type oneofMessage interface {
- XXX_OneofFuncs() (func(Message, *Buffer) error, func(Message, int, int, *Buffer) (bool, error), func(Message) int, []interface{})
+ var oots []interface{}
+ switch m := reflect.Zero(reflect.PtrTo(t)).Interface().(type) {
+ case oneofFuncsIface:
+ _, _, _, oots = m.XXX_OneofFuncs()
+ case oneofWrappersIface:
+ oots = m.XXX_OneofWrappers()
}
- if om, ok := reflect.Zero(reflect.PtrTo(t)).Interface().(oneofMessage); ok {
- var oots []interface{}
- prop.oneofMarshaler, prop.oneofUnmarshaler, prop.oneofSizer, oots = om.XXX_OneofFuncs()
- prop.stype = t
-
+ if len(oots) > 0 {
// Interpret oneof metadata.
prop.OneofTypes = make(map[string]*OneofProperties)
for _, oot := range oots {
@@ -779,30 +447,6 @@ func getPropertiesLocked(t reflect.Type) *StructProperties {
return prop
}
-// Return the Properties object for the x[0]'th field of the structure.
-func propByIndex(t reflect.Type, x []int) *Properties {
- if len(x) != 1 {
- fmt.Fprintf(os.Stderr, "proto: field index dimension %d (not 1) for type %s\n", len(x), t)
- return nil
- }
- prop := GetProperties(t)
- return prop.Prop[x[0]]
-}
-
-// Get the address and type of a pointer to a struct from an interface.
-func getbase(pb Message) (t reflect.Type, b structPointer, err error) {
- if pb == nil {
- err = ErrNil
- return
- }
- // get the reflect type of the pointer to the struct.
- t = reflect.TypeOf(pb)
- // get the address of the struct.
- value := reflect.ValueOf(pb)
- b = toStructPointer(value)
- return
-}
-
// A global registry of enum types.
// The generated code will register the generated maps by calling RegisterEnum.
@@ -826,20 +470,42 @@ func EnumValueMap(enumType string) map[string]int32 {
// A registry of all linked message types.
// The string is a fully-qualified proto name ("pkg.Message").
var (
- protoTypes = make(map[string]reflect.Type)
- revProtoTypes = make(map[reflect.Type]string)
+ protoTypedNils = make(map[string]Message) // a map from proto names to typed nil pointers
+ protoMapTypes = make(map[string]reflect.Type) // a map from proto names to map types
+ revProtoTypes = make(map[reflect.Type]string)
)
// RegisterType is called from generated code and maps from the fully qualified
// proto name to the type (pointer to struct) of the protocol buffer.
func RegisterType(x Message, name string) {
- if _, ok := protoTypes[name]; ok {
+ if _, ok := protoTypedNils[name]; ok {
// TODO: Some day, make this a panic.
log.Printf("proto: duplicate proto type registered: %s", name)
return
}
t := reflect.TypeOf(x)
- protoTypes[name] = t
+ if v := reflect.ValueOf(x); v.Kind() == reflect.Ptr && v.Pointer() == 0 {
+ // Generated code always calls RegisterType with nil x.
+ // This check is just for extra safety.
+ protoTypedNils[name] = x
+ } else {
+ protoTypedNils[name] = reflect.Zero(t).Interface().(Message)
+ }
+ revProtoTypes[t] = name
+}
+
+// RegisterMapType is called from generated code and maps from the fully qualified
+// proto name to the native map type of the proto map definition.
+func RegisterMapType(x interface{}, name string) {
+ if reflect.TypeOf(x).Kind() != reflect.Map {
+ panic(fmt.Sprintf("RegisterMapType(%T, %q); want map", x, name))
+ }
+ if _, ok := protoMapTypes[name]; ok {
+ log.Printf("proto: duplicate proto type registered: %s", name)
+ return
+ }
+ t := reflect.TypeOf(x)
+ protoMapTypes[name] = t
revProtoTypes[t] = name
}
@@ -855,7 +521,14 @@ func MessageName(x Message) string {
}
// MessageType returns the message type (pointer to struct) for a named message.
-func MessageType(name string) reflect.Type { return protoTypes[name] }
+// The type is not guaranteed to implement proto.Message if the name refers to a
+// map entry.
+func MessageType(name string) reflect.Type {
+ if t, ok := protoTypedNils[name]; ok {
+ return reflect.TypeOf(t)
+ }
+ return protoMapTypes[name]
+}
// A registry of all linked proto files.
var (
diff --git a/vendor/github.com/golang/protobuf/proto/table_marshal.go b/vendor/github.com/golang/protobuf/proto/table_marshal.go
new file mode 100644
index 000000000..5cb11fa95
--- /dev/null
+++ b/vendor/github.com/golang/protobuf/proto/table_marshal.go
@@ -0,0 +1,2776 @@
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2016 The Go Authors. All rights reserved.
+// https://github.com/golang/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package proto
+
+import (
+ "errors"
+ "fmt"
+ "math"
+ "reflect"
+ "sort"
+ "strconv"
+ "strings"
+ "sync"
+ "sync/atomic"
+ "unicode/utf8"
+)
+
+// a sizer takes a pointer to a field and the size of its tag, computes the size of
+// the encoded data.
+type sizer func(pointer, int) int
+
+// a marshaler takes a byte slice, a pointer to a field, and its tag (in wire format),
+// marshals the field to the end of the slice, returns the slice and error (if any).
+type marshaler func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error)
+
+// marshalInfo is the information used for marshaling a message.
+type marshalInfo struct {
+ typ reflect.Type
+ fields []*marshalFieldInfo
+ unrecognized field // offset of XXX_unrecognized
+ extensions field // offset of XXX_InternalExtensions
+ v1extensions field // offset of XXX_extensions
+ sizecache field // offset of XXX_sizecache
+ initialized int32 // 0 -- only typ is set, 1 -- fully initialized
+ messageset bool // uses message set wire format
+ hasmarshaler bool // has custom marshaler
+ sync.RWMutex // protect extElems map, also for initialization
+ extElems map[int32]*marshalElemInfo // info of extension elements
+}
+
+// marshalFieldInfo is the information used for marshaling a field of a message.
+type marshalFieldInfo struct {
+ field field
+ wiretag uint64 // tag in wire format
+ tagsize int // size of tag in wire format
+ sizer sizer
+ marshaler marshaler
+ isPointer bool
+ required bool // field is required
+ name string // name of the field, for error reporting
+ oneofElems map[reflect.Type]*marshalElemInfo // info of oneof elements
+}
+
+// marshalElemInfo is the information used for marshaling an extension or oneof element.
+type marshalElemInfo struct {
+ wiretag uint64 // tag in wire format
+ tagsize int // size of tag in wire format
+ sizer sizer
+ marshaler marshaler
+ isptr bool // elem is pointer typed, thus interface of this type is a direct interface (extension only)
+ deref bool // dereference the pointer before operating on it; implies isptr
+}
+
+var (
+ marshalInfoMap = map[reflect.Type]*marshalInfo{}
+ marshalInfoLock sync.Mutex
+)
+
+// getMarshalInfo returns the information to marshal a given type of message.
+// The info it returns may not necessarily initialized.
+// t is the type of the message (NOT the pointer to it).
+func getMarshalInfo(t reflect.Type) *marshalInfo {
+ marshalInfoLock.Lock()
+ u, ok := marshalInfoMap[t]
+ if !ok {
+ u = &marshalInfo{typ: t}
+ marshalInfoMap[t] = u
+ }
+ marshalInfoLock.Unlock()
+ return u
+}
+
+// Size is the entry point from generated code,
+// and should be ONLY called by generated code.
+// It computes the size of encoded data of msg.
+// a is a pointer to a place to store cached marshal info.
+func (a *InternalMessageInfo) Size(msg Message) int {
+ u := getMessageMarshalInfo(msg, a)
+ ptr := toPointer(&msg)
+ if ptr.isNil() {
+ // We get here if msg is a typed nil ((*SomeMessage)(nil)),
+ // so it satisfies the interface, and msg == nil wouldn't
+ // catch it. We don't want crash in this case.
+ return 0
+ }
+ return u.size(ptr)
+}
+
+// Marshal is the entry point from generated code,
+// and should be ONLY called by generated code.
+// It marshals msg to the end of b.
+// a is a pointer to a place to store cached marshal info.
+func (a *InternalMessageInfo) Marshal(b []byte, msg Message, deterministic bool) ([]byte, error) {
+ u := getMessageMarshalInfo(msg, a)
+ ptr := toPointer(&msg)
+ if ptr.isNil() {
+ // We get here if msg is a typed nil ((*SomeMessage)(nil)),
+ // so it satisfies the interface, and msg == nil wouldn't
+ // catch it. We don't want crash in this case.
+ return b, ErrNil
+ }
+ return u.marshal(b, ptr, deterministic)
+}
+
+func getMessageMarshalInfo(msg interface{}, a *InternalMessageInfo) *marshalInfo {
+ // u := a.marshal, but atomically.
+ // We use an atomic here to ensure memory consistency.
+ u := atomicLoadMarshalInfo(&a.marshal)
+ if u == nil {
+ // Get marshal information from type of message.
+ t := reflect.ValueOf(msg).Type()
+ if t.Kind() != reflect.Ptr {
+ panic(fmt.Sprintf("cannot handle non-pointer message type %v", t))
+ }
+ u = getMarshalInfo(t.Elem())
+ // Store it in the cache for later users.
+ // a.marshal = u, but atomically.
+ atomicStoreMarshalInfo(&a.marshal, u)
+ }
+ return u
+}
+
+// size is the main function to compute the size of the encoded data of a message.
+// ptr is the pointer to the message.
+func (u *marshalInfo) size(ptr pointer) int {
+ if atomic.LoadInt32(&u.initialized) == 0 {
+ u.computeMarshalInfo()
+ }
+
+ // If the message can marshal itself, let it do it, for compatibility.
+ // NOTE: This is not efficient.
+ if u.hasmarshaler {
+ m := ptr.asPointerTo(u.typ).Interface().(Marshaler)
+ b, _ := m.Marshal()
+ return len(b)
+ }
+
+ n := 0
+ for _, f := range u.fields {
+ if f.isPointer && ptr.offset(f.field).getPointer().isNil() {
+ // nil pointer always marshals to nothing
+ continue
+ }
+ n += f.sizer(ptr.offset(f.field), f.tagsize)
+ }
+ if u.extensions.IsValid() {
+ e := ptr.offset(u.extensions).toExtensions()
+ if u.messageset {
+ n += u.sizeMessageSet(e)
+ } else {
+ n += u.sizeExtensions(e)
+ }
+ }
+ if u.v1extensions.IsValid() {
+ m := *ptr.offset(u.v1extensions).toOldExtensions()
+ n += u.sizeV1Extensions(m)
+ }
+ if u.unrecognized.IsValid() {
+ s := *ptr.offset(u.unrecognized).toBytes()
+ n += len(s)
+ }
+ // cache the result for use in marshal
+ if u.sizecache.IsValid() {
+ atomic.StoreInt32(ptr.offset(u.sizecache).toInt32(), int32(n))
+ }
+ return n
+}
+
+// cachedsize gets the size from cache. If there is no cache (i.e. message is not generated),
+// fall back to compute the size.
+func (u *marshalInfo) cachedsize(ptr pointer) int {
+ if u.sizecache.IsValid() {
+ return int(atomic.LoadInt32(ptr.offset(u.sizecache).toInt32()))
+ }
+ return u.size(ptr)
+}
+
+// marshal is the main function to marshal a message. It takes a byte slice and appends
+// the encoded data to the end of the slice, returns the slice and error (if any).
+// ptr is the pointer to the message.
+// If deterministic is true, map is marshaled in deterministic order.
+func (u *marshalInfo) marshal(b []byte, ptr pointer, deterministic bool) ([]byte, error) {
+ if atomic.LoadInt32(&u.initialized) == 0 {
+ u.computeMarshalInfo()
+ }
+
+ // If the message can marshal itself, let it do it, for compatibility.
+ // NOTE: This is not efficient.
+ if u.hasmarshaler {
+ m := ptr.asPointerTo(u.typ).Interface().(Marshaler)
+ b1, err := m.Marshal()
+ b = append(b, b1...)
+ return b, err
+ }
+
+ var err, errLater error
+ // The old marshaler encodes extensions at beginning.
+ if u.extensions.IsValid() {
+ e := ptr.offset(u.extensions).toExtensions()
+ if u.messageset {
+ b, err = u.appendMessageSet(b, e, deterministic)
+ } else {
+ b, err = u.appendExtensions(b, e, deterministic)
+ }
+ if err != nil {
+ return b, err
+ }
+ }
+ if u.v1extensions.IsValid() {
+ m := *ptr.offset(u.v1extensions).toOldExtensions()
+ b, err = u.appendV1Extensions(b, m, deterministic)
+ if err != nil {
+ return b, err
+ }
+ }
+ for _, f := range u.fields {
+ if f.required {
+ if ptr.offset(f.field).getPointer().isNil() {
+ // Required field is not set.
+ // We record the error but keep going, to give a complete marshaling.
+ if errLater == nil {
+ errLater = &RequiredNotSetError{f.name}
+ }
+ continue
+ }
+ }
+ if f.isPointer && ptr.offset(f.field).getPointer().isNil() {
+ // nil pointer always marshals to nothing
+ continue
+ }
+ b, err = f.marshaler(b, ptr.offset(f.field), f.wiretag, deterministic)
+ if err != nil {
+ if err1, ok := err.(*RequiredNotSetError); ok {
+ // Required field in submessage is not set.
+ // We record the error but keep going, to give a complete marshaling.
+ if errLater == nil {
+ errLater = &RequiredNotSetError{f.name + "." + err1.field}
+ }
+ continue
+ }
+ if err == errRepeatedHasNil {
+ err = errors.New("proto: repeated field " + f.name + " has nil element")
+ }
+ if err == errInvalidUTF8 {
+ if errLater == nil {
+ fullName := revProtoTypes[reflect.PtrTo(u.typ)] + "." + f.name
+ errLater = &invalidUTF8Error{fullName}
+ }
+ continue
+ }
+ return b, err
+ }
+ }
+ if u.unrecognized.IsValid() {
+ s := *ptr.offset(u.unrecognized).toBytes()
+ b = append(b, s...)
+ }
+ return b, errLater
+}
+
+// computeMarshalInfo initializes the marshal info.
+func (u *marshalInfo) computeMarshalInfo() {
+ u.Lock()
+ defer u.Unlock()
+ if u.initialized != 0 { // non-atomic read is ok as it is protected by the lock
+ return
+ }
+
+ t := u.typ
+ u.unrecognized = invalidField
+ u.extensions = invalidField
+ u.v1extensions = invalidField
+ u.sizecache = invalidField
+
+ // If the message can marshal itself, let it do it, for compatibility.
+ // NOTE: This is not efficient.
+ if reflect.PtrTo(t).Implements(marshalerType) {
+ u.hasmarshaler = true
+ atomic.StoreInt32(&u.initialized, 1)
+ return
+ }
+
+ // get oneof implementers
+ var oneofImplementers []interface{}
+ switch m := reflect.Zero(reflect.PtrTo(t)).Interface().(type) {
+ case oneofFuncsIface:
+ _, _, _, oneofImplementers = m.XXX_OneofFuncs()
+ case oneofWrappersIface:
+ oneofImplementers = m.XXX_OneofWrappers()
+ }
+
+ n := t.NumField()
+
+ // deal with XXX fields first
+ for i := 0; i < t.NumField(); i++ {
+ f := t.Field(i)
+ if !strings.HasPrefix(f.Name, "XXX_") {
+ continue
+ }
+ switch f.Name {
+ case "XXX_sizecache":
+ u.sizecache = toField(&f)
+ case "XXX_unrecognized":
+ u.unrecognized = toField(&f)
+ case "XXX_InternalExtensions":
+ u.extensions = toField(&f)
+ u.messageset = f.Tag.Get("protobuf_messageset") == "1"
+ case "XXX_extensions":
+ u.v1extensions = toField(&f)
+ case "XXX_NoUnkeyedLiteral":
+ // nothing to do
+ default:
+ panic("unknown XXX field: " + f.Name)
+ }
+ n--
+ }
+
+ // normal fields
+ fields := make([]marshalFieldInfo, n) // batch allocation
+ u.fields = make([]*marshalFieldInfo, 0, n)
+ for i, j := 0, 0; i < t.NumField(); i++ {
+ f := t.Field(i)
+
+ if strings.HasPrefix(f.Name, "XXX_") {
+ continue
+ }
+ field := &fields[j]
+ j++
+ field.name = f.Name
+ u.fields = append(u.fields, field)
+ if f.Tag.Get("protobuf_oneof") != "" {
+ field.computeOneofFieldInfo(&f, oneofImplementers)
+ continue
+ }
+ if f.Tag.Get("protobuf") == "" {
+ // field has no tag (not in generated message), ignore it
+ u.fields = u.fields[:len(u.fields)-1]
+ j--
+ continue
+ }
+ field.computeMarshalFieldInfo(&f)
+ }
+
+ // fields are marshaled in tag order on the wire.
+ sort.Sort(byTag(u.fields))
+
+ atomic.StoreInt32(&u.initialized, 1)
+}
+
+// helper for sorting fields by tag
+type byTag []*marshalFieldInfo
+
+func (a byTag) Len() int { return len(a) }
+func (a byTag) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
+func (a byTag) Less(i, j int) bool { return a[i].wiretag < a[j].wiretag }
+
+// getExtElemInfo returns the information to marshal an extension element.
+// The info it returns is initialized.
+func (u *marshalInfo) getExtElemInfo(desc *ExtensionDesc) *marshalElemInfo {
+ // get from cache first
+ u.RLock()
+ e, ok := u.extElems[desc.Field]
+ u.RUnlock()
+ if ok {
+ return e
+ }
+
+ t := reflect.TypeOf(desc.ExtensionType) // pointer or slice to basic type or struct
+ tags := strings.Split(desc.Tag, ",")
+ tag, err := strconv.Atoi(tags[1])
+ if err != nil {
+ panic("tag is not an integer")
+ }
+ wt := wiretype(tags[0])
+ if t.Kind() == reflect.Ptr && t.Elem().Kind() != reflect.Struct {
+ t = t.Elem()
+ }
+ sizer, marshaler := typeMarshaler(t, tags, false, false)
+ var deref bool
+ if t.Kind() == reflect.Slice && t.Elem().Kind() != reflect.Uint8 {
+ t = reflect.PtrTo(t)
+ deref = true
+ }
+ e = &marshalElemInfo{
+ wiretag: uint64(tag)<<3 | wt,
+ tagsize: SizeVarint(uint64(tag) << 3),
+ sizer: sizer,
+ marshaler: marshaler,
+ isptr: t.Kind() == reflect.Ptr,
+ deref: deref,
+ }
+
+ // update cache
+ u.Lock()
+ if u.extElems == nil {
+ u.extElems = make(map[int32]*marshalElemInfo)
+ }
+ u.extElems[desc.Field] = e
+ u.Unlock()
+ return e
+}
+
+// computeMarshalFieldInfo fills up the information to marshal a field.
+func (fi *marshalFieldInfo) computeMarshalFieldInfo(f *reflect.StructField) {
+ // parse protobuf tag of the field.
+ // tag has format of "bytes,49,opt,name=foo,def=hello!"
+ tags := strings.Split(f.Tag.Get("protobuf"), ",")
+ if tags[0] == "" {
+ return
+ }
+ tag, err := strconv.Atoi(tags[1])
+ if err != nil {
+ panic("tag is not an integer")
+ }
+ wt := wiretype(tags[0])
+ if tags[2] == "req" {
+ fi.required = true
+ }
+ fi.setTag(f, tag, wt)
+ fi.setMarshaler(f, tags)
+}
+
+func (fi *marshalFieldInfo) computeOneofFieldInfo(f *reflect.StructField, oneofImplementers []interface{}) {
+ fi.field = toField(f)
+ fi.wiretag = math.MaxInt32 // Use a large tag number, make oneofs sorted at the end. This tag will not appear on the wire.
+ fi.isPointer = true
+ fi.sizer, fi.marshaler = makeOneOfMarshaler(fi, f)
+ fi.oneofElems = make(map[reflect.Type]*marshalElemInfo)
+
+ ityp := f.Type // interface type
+ for _, o := range oneofImplementers {
+ t := reflect.TypeOf(o)
+ if !t.Implements(ityp) {
+ continue
+ }
+ sf := t.Elem().Field(0) // oneof implementer is a struct with a single field
+ tags := strings.Split(sf.Tag.Get("protobuf"), ",")
+ tag, err := strconv.Atoi(tags[1])
+ if err != nil {
+ panic("tag is not an integer")
+ }
+ wt := wiretype(tags[0])
+ sizer, marshaler := typeMarshaler(sf.Type, tags, false, true) // oneof should not omit any zero value
+ fi.oneofElems[t.Elem()] = &marshalElemInfo{
+ wiretag: uint64(tag)<<3 | wt,
+ tagsize: SizeVarint(uint64(tag) << 3),
+ sizer: sizer,
+ marshaler: marshaler,
+ }
+ }
+}
+
+// wiretype returns the wire encoding of the type.
+func wiretype(encoding string) uint64 {
+ switch encoding {
+ case "fixed32":
+ return WireFixed32
+ case "fixed64":
+ return WireFixed64
+ case "varint", "zigzag32", "zigzag64":
+ return WireVarint
+ case "bytes":
+ return WireBytes
+ case "group":
+ return WireStartGroup
+ }
+ panic("unknown wire type " + encoding)
+}
+
+// setTag fills up the tag (in wire format) and its size in the info of a field.
+func (fi *marshalFieldInfo) setTag(f *reflect.StructField, tag int, wt uint64) {
+ fi.field = toField(f)
+ fi.wiretag = uint64(tag)<<3 | wt
+ fi.tagsize = SizeVarint(uint64(tag) << 3)
+}
+
+// setMarshaler fills up the sizer and marshaler in the info of a field.
+func (fi *marshalFieldInfo) setMarshaler(f *reflect.StructField, tags []string) {
+ switch f.Type.Kind() {
+ case reflect.Map:
+ // map field
+ fi.isPointer = true
+ fi.sizer, fi.marshaler = makeMapMarshaler(f)
+ return
+ case reflect.Ptr, reflect.Slice:
+ fi.isPointer = true
+ }
+ fi.sizer, fi.marshaler = typeMarshaler(f.Type, tags, true, false)
+}
+
+// typeMarshaler returns the sizer and marshaler of a given field.
+// t is the type of the field.
+// tags is the generated "protobuf" tag of the field.
+// If nozero is true, zero value is not marshaled to the wire.
+// If oneof is true, it is a oneof field.
+func typeMarshaler(t reflect.Type, tags []string, nozero, oneof bool) (sizer, marshaler) {
+ encoding := tags[0]
+
+ pointer := false
+ slice := false
+ if t.Kind() == reflect.Slice && t.Elem().Kind() != reflect.Uint8 {
+ slice = true
+ t = t.Elem()
+ }
+ if t.Kind() == reflect.Ptr {
+ pointer = true
+ t = t.Elem()
+ }
+
+ packed := false
+ proto3 := false
+ validateUTF8 := true
+ for i := 2; i < len(tags); i++ {
+ if tags[i] == "packed" {
+ packed = true
+ }
+ if tags[i] == "proto3" {
+ proto3 = true
+ }
+ }
+ validateUTF8 = validateUTF8 && proto3
+
+ switch t.Kind() {
+ case reflect.Bool:
+ if pointer {
+ return sizeBoolPtr, appendBoolPtr
+ }
+ if slice {
+ if packed {
+ return sizeBoolPackedSlice, appendBoolPackedSlice
+ }
+ return sizeBoolSlice, appendBoolSlice
+ }
+ if nozero {
+ return sizeBoolValueNoZero, appendBoolValueNoZero
+ }
+ return sizeBoolValue, appendBoolValue
+ case reflect.Uint32:
+ switch encoding {
+ case "fixed32":
+ if pointer {
+ return sizeFixed32Ptr, appendFixed32Ptr
+ }
+ if slice {
+ if packed {
+ return sizeFixed32PackedSlice, appendFixed32PackedSlice
+ }
+ return sizeFixed32Slice, appendFixed32Slice
+ }
+ if nozero {
+ return sizeFixed32ValueNoZero, appendFixed32ValueNoZero
+ }
+ return sizeFixed32Value, appendFixed32Value
+ case "varint":
+ if pointer {
+ return sizeVarint32Ptr, appendVarint32Ptr
+ }
+ if slice {
+ if packed {
+ return sizeVarint32PackedSlice, appendVarint32PackedSlice
+ }
+ return sizeVarint32Slice, appendVarint32Slice
+ }
+ if nozero {
+ return sizeVarint32ValueNoZero, appendVarint32ValueNoZero
+ }
+ return sizeVarint32Value, appendVarint32Value
+ }
+ case reflect.Int32:
+ switch encoding {
+ case "fixed32":
+ if pointer {
+ return sizeFixedS32Ptr, appendFixedS32Ptr
+ }
+ if slice {
+ if packed {
+ return sizeFixedS32PackedSlice, appendFixedS32PackedSlice
+ }
+ return sizeFixedS32Slice, appendFixedS32Slice
+ }
+ if nozero {
+ return sizeFixedS32ValueNoZero, appendFixedS32ValueNoZero
+ }
+ return sizeFixedS32Value, appendFixedS32Value
+ case "varint":
+ if pointer {
+ return sizeVarintS32Ptr, appendVarintS32Ptr
+ }
+ if slice {
+ if packed {
+ return sizeVarintS32PackedSlice, appendVarintS32PackedSlice
+ }
+ return sizeVarintS32Slice, appendVarintS32Slice
+ }
+ if nozero {
+ return sizeVarintS32ValueNoZero, appendVarintS32ValueNoZero
+ }
+ return sizeVarintS32Value, appendVarintS32Value
+ case "zigzag32":
+ if pointer {
+ return sizeZigzag32Ptr, appendZigzag32Ptr
+ }
+ if slice {
+ if packed {
+ return sizeZigzag32PackedSlice, appendZigzag32PackedSlice
+ }
+ return sizeZigzag32Slice, appendZigzag32Slice
+ }
+ if nozero {
+ return sizeZigzag32ValueNoZero, appendZigzag32ValueNoZero
+ }
+ return sizeZigzag32Value, appendZigzag32Value
+ }
+ case reflect.Uint64:
+ switch encoding {
+ case "fixed64":
+ if pointer {
+ return sizeFixed64Ptr, appendFixed64Ptr
+ }
+ if slice {
+ if packed {
+ return sizeFixed64PackedSlice, appendFixed64PackedSlice
+ }
+ return sizeFixed64Slice, appendFixed64Slice
+ }
+ if nozero {
+ return sizeFixed64ValueNoZero, appendFixed64ValueNoZero
+ }
+ return sizeFixed64Value, appendFixed64Value
+ case "varint":
+ if pointer {
+ return sizeVarint64Ptr, appendVarint64Ptr
+ }
+ if slice {
+ if packed {
+ return sizeVarint64PackedSlice, appendVarint64PackedSlice
+ }
+ return sizeVarint64Slice, appendVarint64Slice
+ }
+ if nozero {
+ return sizeVarint64ValueNoZero, appendVarint64ValueNoZero
+ }
+ return sizeVarint64Value, appendVarint64Value
+ }
+ case reflect.Int64:
+ switch encoding {
+ case "fixed64":
+ if pointer {
+ return sizeFixedS64Ptr, appendFixedS64Ptr
+ }
+ if slice {
+ if packed {
+ return sizeFixedS64PackedSlice, appendFixedS64PackedSlice
+ }
+ return sizeFixedS64Slice, appendFixedS64Slice
+ }
+ if nozero {
+ return sizeFixedS64ValueNoZero, appendFixedS64ValueNoZero
+ }
+ return sizeFixedS64Value, appendFixedS64Value
+ case "varint":
+ if pointer {
+ return sizeVarintS64Ptr, appendVarintS64Ptr
+ }
+ if slice {
+ if packed {
+ return sizeVarintS64PackedSlice, appendVarintS64PackedSlice
+ }
+ return sizeVarintS64Slice, appendVarintS64Slice
+ }
+ if nozero {
+ return sizeVarintS64ValueNoZero, appendVarintS64ValueNoZero
+ }
+ return sizeVarintS64Value, appendVarintS64Value
+ case "zigzag64":
+ if pointer {
+ return sizeZigzag64Ptr, appendZigzag64Ptr
+ }
+ if slice {
+ if packed {
+ return sizeZigzag64PackedSlice, appendZigzag64PackedSlice
+ }
+ return sizeZigzag64Slice, appendZigzag64Slice
+ }
+ if nozero {
+ return sizeZigzag64ValueNoZero, appendZigzag64ValueNoZero
+ }
+ return sizeZigzag64Value, appendZigzag64Value
+ }
+ case reflect.Float32:
+ if pointer {
+ return sizeFloat32Ptr, appendFloat32Ptr
+ }
+ if slice {
+ if packed {
+ return sizeFloat32PackedSlice, appendFloat32PackedSlice
+ }
+ return sizeFloat32Slice, appendFloat32Slice
+ }
+ if nozero {
+ return sizeFloat32ValueNoZero, appendFloat32ValueNoZero
+ }
+ return sizeFloat32Value, appendFloat32Value
+ case reflect.Float64:
+ if pointer {
+ return sizeFloat64Ptr, appendFloat64Ptr
+ }
+ if slice {
+ if packed {
+ return sizeFloat64PackedSlice, appendFloat64PackedSlice
+ }
+ return sizeFloat64Slice, appendFloat64Slice
+ }
+ if nozero {
+ return sizeFloat64ValueNoZero, appendFloat64ValueNoZero
+ }
+ return sizeFloat64Value, appendFloat64Value
+ case reflect.String:
+ if validateUTF8 {
+ if pointer {
+ return sizeStringPtr, appendUTF8StringPtr
+ }
+ if slice {
+ return sizeStringSlice, appendUTF8StringSlice
+ }
+ if nozero {
+ return sizeStringValueNoZero, appendUTF8StringValueNoZero
+ }
+ return sizeStringValue, appendUTF8StringValue
+ }
+ if pointer {
+ return sizeStringPtr, appendStringPtr
+ }
+ if slice {
+ return sizeStringSlice, appendStringSlice
+ }
+ if nozero {
+ return sizeStringValueNoZero, appendStringValueNoZero
+ }
+ return sizeStringValue, appendStringValue
+ case reflect.Slice:
+ if slice {
+ return sizeBytesSlice, appendBytesSlice
+ }
+ if oneof {
+ // Oneof bytes field may also have "proto3" tag.
+ // We want to marshal it as a oneof field. Do this
+ // check before the proto3 check.
+ return sizeBytesOneof, appendBytesOneof
+ }
+ if proto3 {
+ return sizeBytes3, appendBytes3
+ }
+ return sizeBytes, appendBytes
+ case reflect.Struct:
+ switch encoding {
+ case "group":
+ if slice {
+ return makeGroupSliceMarshaler(getMarshalInfo(t))
+ }
+ return makeGroupMarshaler(getMarshalInfo(t))
+ case "bytes":
+ if slice {
+ return makeMessageSliceMarshaler(getMarshalInfo(t))
+ }
+ return makeMessageMarshaler(getMarshalInfo(t))
+ }
+ }
+ panic(fmt.Sprintf("unknown or mismatched type: type: %v, wire type: %v", t, encoding))
+}
+
+// Below are functions to size/marshal a specific type of a field.
+// They are stored in the field's info, and called by function pointers.
+// They have type sizer or marshaler.
+
+func sizeFixed32Value(_ pointer, tagsize int) int {
+ return 4 + tagsize
+}
+func sizeFixed32ValueNoZero(ptr pointer, tagsize int) int {
+ v := *ptr.toUint32()
+ if v == 0 {
+ return 0
+ }
+ return 4 + tagsize
+}
+func sizeFixed32Ptr(ptr pointer, tagsize int) int {
+ p := *ptr.toUint32Ptr()
+ if p == nil {
+ return 0
+ }
+ return 4 + tagsize
+}
+func sizeFixed32Slice(ptr pointer, tagsize int) int {
+ s := *ptr.toUint32Slice()
+ return (4 + tagsize) * len(s)
+}
+func sizeFixed32PackedSlice(ptr pointer, tagsize int) int {
+ s := *ptr.toUint32Slice()
+ if len(s) == 0 {
+ return 0
+ }
+ return 4*len(s) + SizeVarint(uint64(4*len(s))) + tagsize
+}
+func sizeFixedS32Value(_ pointer, tagsize int) int {
+ return 4 + tagsize
+}
+func sizeFixedS32ValueNoZero(ptr pointer, tagsize int) int {
+ v := *ptr.toInt32()
+ if v == 0 {
+ return 0
+ }
+ return 4 + tagsize
+}
+func sizeFixedS32Ptr(ptr pointer, tagsize int) int {
+ p := ptr.getInt32Ptr()
+ if p == nil {
+ return 0
+ }
+ return 4 + tagsize
+}
+func sizeFixedS32Slice(ptr pointer, tagsize int) int {
+ s := ptr.getInt32Slice()
+ return (4 + tagsize) * len(s)
+}
+func sizeFixedS32PackedSlice(ptr pointer, tagsize int) int {
+ s := ptr.getInt32Slice()
+ if len(s) == 0 {
+ return 0
+ }
+ return 4*len(s) + SizeVarint(uint64(4*len(s))) + tagsize
+}
+func sizeFloat32Value(_ pointer, tagsize int) int {
+ return 4 + tagsize
+}
+func sizeFloat32ValueNoZero(ptr pointer, tagsize int) int {
+ v := math.Float32bits(*ptr.toFloat32())
+ if v == 0 {
+ return 0
+ }
+ return 4 + tagsize
+}
+func sizeFloat32Ptr(ptr pointer, tagsize int) int {
+ p := *ptr.toFloat32Ptr()
+ if p == nil {
+ return 0
+ }
+ return 4 + tagsize
+}
+func sizeFloat32Slice(ptr pointer, tagsize int) int {
+ s := *ptr.toFloat32Slice()
+ return (4 + tagsize) * len(s)
+}
+func sizeFloat32PackedSlice(ptr pointer, tagsize int) int {
+ s := *ptr.toFloat32Slice()
+ if len(s) == 0 {
+ return 0
+ }
+ return 4*len(s) + SizeVarint(uint64(4*len(s))) + tagsize
+}
+func sizeFixed64Value(_ pointer, tagsize int) int {
+ return 8 + tagsize
+}
+func sizeFixed64ValueNoZero(ptr pointer, tagsize int) int {
+ v := *ptr.toUint64()
+ if v == 0 {
+ return 0
+ }
+ return 8 + tagsize
+}
+func sizeFixed64Ptr(ptr pointer, tagsize int) int {
+ p := *ptr.toUint64Ptr()
+ if p == nil {
+ return 0
+ }
+ return 8 + tagsize
+}
+func sizeFixed64Slice(ptr pointer, tagsize int) int {
+ s := *ptr.toUint64Slice()
+ return (8 + tagsize) * len(s)
+}
+func sizeFixed64PackedSlice(ptr pointer, tagsize int) int {
+ s := *ptr.toUint64Slice()
+ if len(s) == 0 {
+ return 0
+ }
+ return 8*len(s) + SizeVarint(uint64(8*len(s))) + tagsize
+}
+func sizeFixedS64Value(_ pointer, tagsize int) int {
+ return 8 + tagsize
+}
+func sizeFixedS64ValueNoZero(ptr pointer, tagsize int) int {
+ v := *ptr.toInt64()
+ if v == 0 {
+ return 0
+ }
+ return 8 + tagsize
+}
+func sizeFixedS64Ptr(ptr pointer, tagsize int) int {
+ p := *ptr.toInt64Ptr()
+ if p == nil {
+ return 0
+ }
+ return 8 + tagsize
+}
+func sizeFixedS64Slice(ptr pointer, tagsize int) int {
+ s := *ptr.toInt64Slice()
+ return (8 + tagsize) * len(s)
+}
+func sizeFixedS64PackedSlice(ptr pointer, tagsize int) int {
+ s := *ptr.toInt64Slice()
+ if len(s) == 0 {
+ return 0
+ }
+ return 8*len(s) + SizeVarint(uint64(8*len(s))) + tagsize
+}
+func sizeFloat64Value(_ pointer, tagsize int) int {
+ return 8 + tagsize
+}
+func sizeFloat64ValueNoZero(ptr pointer, tagsize int) int {
+ v := math.Float64bits(*ptr.toFloat64())
+ if v == 0 {
+ return 0
+ }
+ return 8 + tagsize
+}
+func sizeFloat64Ptr(ptr pointer, tagsize int) int {
+ p := *ptr.toFloat64Ptr()
+ if p == nil {
+ return 0
+ }
+ return 8 + tagsize
+}
+func sizeFloat64Slice(ptr pointer, tagsize int) int {
+ s := *ptr.toFloat64Slice()
+ return (8 + tagsize) * len(s)
+}
+func sizeFloat64PackedSlice(ptr pointer, tagsize int) int {
+ s := *ptr.toFloat64Slice()
+ if len(s) == 0 {
+ return 0
+ }
+ return 8*len(s) + SizeVarint(uint64(8*len(s))) + tagsize
+}
+func sizeVarint32Value(ptr pointer, tagsize int) int {
+ v := *ptr.toUint32()
+ return SizeVarint(uint64(v)) + tagsize
+}
+func sizeVarint32ValueNoZero(ptr pointer, tagsize int) int {
+ v := *ptr.toUint32()
+ if v == 0 {
+ return 0
+ }
+ return SizeVarint(uint64(v)) + tagsize
+}
+func sizeVarint32Ptr(ptr pointer, tagsize int) int {
+ p := *ptr.toUint32Ptr()
+ if p == nil {
+ return 0
+ }
+ return SizeVarint(uint64(*p)) + tagsize
+}
+func sizeVarint32Slice(ptr pointer, tagsize int) int {
+ s := *ptr.toUint32Slice()
+ n := 0
+ for _, v := range s {
+ n += SizeVarint(uint64(v)) + tagsize
+ }
+ return n
+}
+func sizeVarint32PackedSlice(ptr pointer, tagsize int) int {
+ s := *ptr.toUint32Slice()
+ if len(s) == 0 {
+ return 0
+ }
+ n := 0
+ for _, v := range s {
+ n += SizeVarint(uint64(v))
+ }
+ return n + SizeVarint(uint64(n)) + tagsize
+}
+func sizeVarintS32Value(ptr pointer, tagsize int) int {
+ v := *ptr.toInt32()
+ return SizeVarint(uint64(v)) + tagsize
+}
+func sizeVarintS32ValueNoZero(ptr pointer, tagsize int) int {
+ v := *ptr.toInt32()
+ if v == 0 {
+ return 0
+ }
+ return SizeVarint(uint64(v)) + tagsize
+}
+func sizeVarintS32Ptr(ptr pointer, tagsize int) int {
+ p := ptr.getInt32Ptr()
+ if p == nil {
+ return 0
+ }
+ return SizeVarint(uint64(*p)) + tagsize
+}
+func sizeVarintS32Slice(ptr pointer, tagsize int) int {
+ s := ptr.getInt32Slice()
+ n := 0
+ for _, v := range s {
+ n += SizeVarint(uint64(v)) + tagsize
+ }
+ return n
+}
+func sizeVarintS32PackedSlice(ptr pointer, tagsize int) int {
+ s := ptr.getInt32Slice()
+ if len(s) == 0 {
+ return 0
+ }
+ n := 0
+ for _, v := range s {
+ n += SizeVarint(uint64(v))
+ }
+ return n + SizeVarint(uint64(n)) + tagsize
+}
+func sizeVarint64Value(ptr pointer, tagsize int) int {
+ v := *ptr.toUint64()
+ return SizeVarint(v) + tagsize
+}
+func sizeVarint64ValueNoZero(ptr pointer, tagsize int) int {
+ v := *ptr.toUint64()
+ if v == 0 {
+ return 0
+ }
+ return SizeVarint(v) + tagsize
+}
+func sizeVarint64Ptr(ptr pointer, tagsize int) int {
+ p := *ptr.toUint64Ptr()
+ if p == nil {
+ return 0
+ }
+ return SizeVarint(*p) + tagsize
+}
+func sizeVarint64Slice(ptr pointer, tagsize int) int {
+ s := *ptr.toUint64Slice()
+ n := 0
+ for _, v := range s {
+ n += SizeVarint(v) + tagsize
+ }
+ return n
+}
+func sizeVarint64PackedSlice(ptr pointer, tagsize int) int {
+ s := *ptr.toUint64Slice()
+ if len(s) == 0 {
+ return 0
+ }
+ n := 0
+ for _, v := range s {
+ n += SizeVarint(v)
+ }
+ return n + SizeVarint(uint64(n)) + tagsize
+}
+func sizeVarintS64Value(ptr pointer, tagsize int) int {
+ v := *ptr.toInt64()
+ return SizeVarint(uint64(v)) + tagsize
+}
+func sizeVarintS64ValueNoZero(ptr pointer, tagsize int) int {
+ v := *ptr.toInt64()
+ if v == 0 {
+ return 0
+ }
+ return SizeVarint(uint64(v)) + tagsize
+}
+func sizeVarintS64Ptr(ptr pointer, tagsize int) int {
+ p := *ptr.toInt64Ptr()
+ if p == nil {
+ return 0
+ }
+ return SizeVarint(uint64(*p)) + tagsize
+}
+func sizeVarintS64Slice(ptr pointer, tagsize int) int {
+ s := *ptr.toInt64Slice()
+ n := 0
+ for _, v := range s {
+ n += SizeVarint(uint64(v)) + tagsize
+ }
+ return n
+}
+func sizeVarintS64PackedSlice(ptr pointer, tagsize int) int {
+ s := *ptr.toInt64Slice()
+ if len(s) == 0 {
+ return 0
+ }
+ n := 0
+ for _, v := range s {
+ n += SizeVarint(uint64(v))
+ }
+ return n + SizeVarint(uint64(n)) + tagsize
+}
+func sizeZigzag32Value(ptr pointer, tagsize int) int {
+ v := *ptr.toInt32()
+ return SizeVarint(uint64((uint32(v)<<1)^uint32((int32(v)>>31)))) + tagsize
+}
+func sizeZigzag32ValueNoZero(ptr pointer, tagsize int) int {
+ v := *ptr.toInt32()
+ if v == 0 {
+ return 0
+ }
+ return SizeVarint(uint64((uint32(v)<<1)^uint32((int32(v)>>31)))) + tagsize
+}
+func sizeZigzag32Ptr(ptr pointer, tagsize int) int {
+ p := ptr.getInt32Ptr()
+ if p == nil {
+ return 0
+ }
+ v := *p
+ return SizeVarint(uint64((uint32(v)<<1)^uint32((int32(v)>>31)))) + tagsize
+}
+func sizeZigzag32Slice(ptr pointer, tagsize int) int {
+ s := ptr.getInt32Slice()
+ n := 0
+ for _, v := range s {
+ n += SizeVarint(uint64((uint32(v)<<1)^uint32((int32(v)>>31)))) + tagsize
+ }
+ return n
+}
+func sizeZigzag32PackedSlice(ptr pointer, tagsize int) int {
+ s := ptr.getInt32Slice()
+ if len(s) == 0 {
+ return 0
+ }
+ n := 0
+ for _, v := range s {
+ n += SizeVarint(uint64((uint32(v) << 1) ^ uint32((int32(v) >> 31))))
+ }
+ return n + SizeVarint(uint64(n)) + tagsize
+}
+func sizeZigzag64Value(ptr pointer, tagsize int) int {
+ v := *ptr.toInt64()
+ return SizeVarint(uint64(v<<1)^uint64((int64(v)>>63))) + tagsize
+}
+func sizeZigzag64ValueNoZero(ptr pointer, tagsize int) int {
+ v := *ptr.toInt64()
+ if v == 0 {
+ return 0
+ }
+ return SizeVarint(uint64(v<<1)^uint64((int64(v)>>63))) + tagsize
+}
+func sizeZigzag64Ptr(ptr pointer, tagsize int) int {
+ p := *ptr.toInt64Ptr()
+ if p == nil {
+ return 0
+ }
+ v := *p
+ return SizeVarint(uint64(v<<1)^uint64((int64(v)>>63))) + tagsize
+}
+func sizeZigzag64Slice(ptr pointer, tagsize int) int {
+ s := *ptr.toInt64Slice()
+ n := 0
+ for _, v := range s {
+ n += SizeVarint(uint64(v<<1)^uint64((int64(v)>>63))) + tagsize
+ }
+ return n
+}
+func sizeZigzag64PackedSlice(ptr pointer, tagsize int) int {
+ s := *ptr.toInt64Slice()
+ if len(s) == 0 {
+ return 0
+ }
+ n := 0
+ for _, v := range s {
+ n += SizeVarint(uint64(v<<1) ^ uint64((int64(v) >> 63)))
+ }
+ return n + SizeVarint(uint64(n)) + tagsize
+}
+func sizeBoolValue(_ pointer, tagsize int) int {
+ return 1 + tagsize
+}
+func sizeBoolValueNoZero(ptr pointer, tagsize int) int {
+ v := *ptr.toBool()
+ if !v {
+ return 0
+ }
+ return 1 + tagsize
+}
+func sizeBoolPtr(ptr pointer, tagsize int) int {
+ p := *ptr.toBoolPtr()
+ if p == nil {
+ return 0
+ }
+ return 1 + tagsize
+}
+func sizeBoolSlice(ptr pointer, tagsize int) int {
+ s := *ptr.toBoolSlice()
+ return (1 + tagsize) * len(s)
+}
+func sizeBoolPackedSlice(ptr pointer, tagsize int) int {
+ s := *ptr.toBoolSlice()
+ if len(s) == 0 {
+ return 0
+ }
+ return len(s) + SizeVarint(uint64(len(s))) + tagsize
+}
+func sizeStringValue(ptr pointer, tagsize int) int {
+ v := *ptr.toString()
+ return len(v) + SizeVarint(uint64(len(v))) + tagsize
+}
+func sizeStringValueNoZero(ptr pointer, tagsize int) int {
+ v := *ptr.toString()
+ if v == "" {
+ return 0
+ }
+ return len(v) + SizeVarint(uint64(len(v))) + tagsize
+}
+func sizeStringPtr(ptr pointer, tagsize int) int {
+ p := *ptr.toStringPtr()
+ if p == nil {
+ return 0
+ }
+ v := *p
+ return len(v) + SizeVarint(uint64(len(v))) + tagsize
+}
+func sizeStringSlice(ptr pointer, tagsize int) int {
+ s := *ptr.toStringSlice()
+ n := 0
+ for _, v := range s {
+ n += len(v) + SizeVarint(uint64(len(v))) + tagsize
+ }
+ return n
+}
+func sizeBytes(ptr pointer, tagsize int) int {
+ v := *ptr.toBytes()
+ if v == nil {
+ return 0
+ }
+ return len(v) + SizeVarint(uint64(len(v))) + tagsize
+}
+func sizeBytes3(ptr pointer, tagsize int) int {
+ v := *ptr.toBytes()
+ if len(v) == 0 {
+ return 0
+ }
+ return len(v) + SizeVarint(uint64(len(v))) + tagsize
+}
+func sizeBytesOneof(ptr pointer, tagsize int) int {
+ v := *ptr.toBytes()
+ return len(v) + SizeVarint(uint64(len(v))) + tagsize
+}
+func sizeBytesSlice(ptr pointer, tagsize int) int {
+ s := *ptr.toBytesSlice()
+ n := 0
+ for _, v := range s {
+ n += len(v) + SizeVarint(uint64(len(v))) + tagsize
+ }
+ return n
+}
+
+// appendFixed32 appends an encoded fixed32 to b.
+func appendFixed32(b []byte, v uint32) []byte {
+ b = append(b,
+ byte(v),
+ byte(v>>8),
+ byte(v>>16),
+ byte(v>>24))
+ return b
+}
+
+// appendFixed64 appends an encoded fixed64 to b.
+func appendFixed64(b []byte, v uint64) []byte {
+ b = append(b,
+ byte(v),
+ byte(v>>8),
+ byte(v>>16),
+ byte(v>>24),
+ byte(v>>32),
+ byte(v>>40),
+ byte(v>>48),
+ byte(v>>56))
+ return b
+}
+
+// appendVarint appends an encoded varint to b.
+func appendVarint(b []byte, v uint64) []byte {
+ // TODO: make 1-byte (maybe 2-byte) case inline-able, once we
+ // have non-leaf inliner.
+ switch {
+ case v < 1<<7:
+ b = append(b, byte(v))
+ case v < 1<<14:
+ b = append(b,
+ byte(v&0x7f|0x80),
+ byte(v>>7))
+ case v < 1<<21:
+ b = append(b,
+ byte(v&0x7f|0x80),
+ byte((v>>7)&0x7f|0x80),
+ byte(v>>14))
+ case v < 1<<28:
+ b = append(b,
+ byte(v&0x7f|0x80),
+ byte((v>>7)&0x7f|0x80),
+ byte((v>>14)&0x7f|0x80),
+ byte(v>>21))
+ case v < 1<<35:
+ b = append(b,
+ byte(v&0x7f|0x80),
+ byte((v>>7)&0x7f|0x80),
+ byte((v>>14)&0x7f|0x80),
+ byte((v>>21)&0x7f|0x80),
+ byte(v>>28))
+ case v < 1<<42:
+ b = append(b,
+ byte(v&0x7f|0x80),
+ byte((v>>7)&0x7f|0x80),
+ byte((v>>14)&0x7f|0x80),
+ byte((v>>21)&0x7f|0x80),
+ byte((v>>28)&0x7f|0x80),
+ byte(v>>35))
+ case v < 1<<49:
+ b = append(b,
+ byte(v&0x7f|0x80),
+ byte((v>>7)&0x7f|0x80),
+ byte((v>>14)&0x7f|0x80),
+ byte((v>>21)&0x7f|0x80),
+ byte((v>>28)&0x7f|0x80),
+ byte((v>>35)&0x7f|0x80),
+ byte(v>>42))
+ case v < 1<<56:
+ b = append(b,
+ byte(v&0x7f|0x80),
+ byte((v>>7)&0x7f|0x80),
+ byte((v>>14)&0x7f|0x80),
+ byte((v>>21)&0x7f|0x80),
+ byte((v>>28)&0x7f|0x80),
+ byte((v>>35)&0x7f|0x80),
+ byte((v>>42)&0x7f|0x80),
+ byte(v>>49))
+ case v < 1<<63:
+ b = append(b,
+ byte(v&0x7f|0x80),
+ byte((v>>7)&0x7f|0x80),
+ byte((v>>14)&0x7f|0x80),
+ byte((v>>21)&0x7f|0x80),
+ byte((v>>28)&0x7f|0x80),
+ byte((v>>35)&0x7f|0x80),
+ byte((v>>42)&0x7f|0x80),
+ byte((v>>49)&0x7f|0x80),
+ byte(v>>56))
+ default:
+ b = append(b,
+ byte(v&0x7f|0x80),
+ byte((v>>7)&0x7f|0x80),
+ byte((v>>14)&0x7f|0x80),
+ byte((v>>21)&0x7f|0x80),
+ byte((v>>28)&0x7f|0x80),
+ byte((v>>35)&0x7f|0x80),
+ byte((v>>42)&0x7f|0x80),
+ byte((v>>49)&0x7f|0x80),
+ byte((v>>56)&0x7f|0x80),
+ 1)
+ }
+ return b
+}
+
+func appendFixed32Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ v := *ptr.toUint32()
+ b = appendVarint(b, wiretag)
+ b = appendFixed32(b, v)
+ return b, nil
+}
+func appendFixed32ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ v := *ptr.toUint32()
+ if v == 0 {
+ return b, nil
+ }
+ b = appendVarint(b, wiretag)
+ b = appendFixed32(b, v)
+ return b, nil
+}
+func appendFixed32Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ p := *ptr.toUint32Ptr()
+ if p == nil {
+ return b, nil
+ }
+ b = appendVarint(b, wiretag)
+ b = appendFixed32(b, *p)
+ return b, nil
+}
+func appendFixed32Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ s := *ptr.toUint32Slice()
+ for _, v := range s {
+ b = appendVarint(b, wiretag)
+ b = appendFixed32(b, v)
+ }
+ return b, nil
+}
+func appendFixed32PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ s := *ptr.toUint32Slice()
+ if len(s) == 0 {
+ return b, nil
+ }
+ b = appendVarint(b, wiretag&^7|WireBytes)
+ b = appendVarint(b, uint64(4*len(s)))
+ for _, v := range s {
+ b = appendFixed32(b, v)
+ }
+ return b, nil
+}
+func appendFixedS32Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ v := *ptr.toInt32()
+ b = appendVarint(b, wiretag)
+ b = appendFixed32(b, uint32(v))
+ return b, nil
+}
+func appendFixedS32ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ v := *ptr.toInt32()
+ if v == 0 {
+ return b, nil
+ }
+ b = appendVarint(b, wiretag)
+ b = appendFixed32(b, uint32(v))
+ return b, nil
+}
+func appendFixedS32Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ p := ptr.getInt32Ptr()
+ if p == nil {
+ return b, nil
+ }
+ b = appendVarint(b, wiretag)
+ b = appendFixed32(b, uint32(*p))
+ return b, nil
+}
+func appendFixedS32Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ s := ptr.getInt32Slice()
+ for _, v := range s {
+ b = appendVarint(b, wiretag)
+ b = appendFixed32(b, uint32(v))
+ }
+ return b, nil
+}
+func appendFixedS32PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ s := ptr.getInt32Slice()
+ if len(s) == 0 {
+ return b, nil
+ }
+ b = appendVarint(b, wiretag&^7|WireBytes)
+ b = appendVarint(b, uint64(4*len(s)))
+ for _, v := range s {
+ b = appendFixed32(b, uint32(v))
+ }
+ return b, nil
+}
+func appendFloat32Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ v := math.Float32bits(*ptr.toFloat32())
+ b = appendVarint(b, wiretag)
+ b = appendFixed32(b, v)
+ return b, nil
+}
+func appendFloat32ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ v := math.Float32bits(*ptr.toFloat32())
+ if v == 0 {
+ return b, nil
+ }
+ b = appendVarint(b, wiretag)
+ b = appendFixed32(b, v)
+ return b, nil
+}
+func appendFloat32Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ p := *ptr.toFloat32Ptr()
+ if p == nil {
+ return b, nil
+ }
+ b = appendVarint(b, wiretag)
+ b = appendFixed32(b, math.Float32bits(*p))
+ return b, nil
+}
+func appendFloat32Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ s := *ptr.toFloat32Slice()
+ for _, v := range s {
+ b = appendVarint(b, wiretag)
+ b = appendFixed32(b, math.Float32bits(v))
+ }
+ return b, nil
+}
+func appendFloat32PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ s := *ptr.toFloat32Slice()
+ if len(s) == 0 {
+ return b, nil
+ }
+ b = appendVarint(b, wiretag&^7|WireBytes)
+ b = appendVarint(b, uint64(4*len(s)))
+ for _, v := range s {
+ b = appendFixed32(b, math.Float32bits(v))
+ }
+ return b, nil
+}
+func appendFixed64Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ v := *ptr.toUint64()
+ b = appendVarint(b, wiretag)
+ b = appendFixed64(b, v)
+ return b, nil
+}
+func appendFixed64ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ v := *ptr.toUint64()
+ if v == 0 {
+ return b, nil
+ }
+ b = appendVarint(b, wiretag)
+ b = appendFixed64(b, v)
+ return b, nil
+}
+func appendFixed64Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ p := *ptr.toUint64Ptr()
+ if p == nil {
+ return b, nil
+ }
+ b = appendVarint(b, wiretag)
+ b = appendFixed64(b, *p)
+ return b, nil
+}
+func appendFixed64Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ s := *ptr.toUint64Slice()
+ for _, v := range s {
+ b = appendVarint(b, wiretag)
+ b = appendFixed64(b, v)
+ }
+ return b, nil
+}
+func appendFixed64PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ s := *ptr.toUint64Slice()
+ if len(s) == 0 {
+ return b, nil
+ }
+ b = appendVarint(b, wiretag&^7|WireBytes)
+ b = appendVarint(b, uint64(8*len(s)))
+ for _, v := range s {
+ b = appendFixed64(b, v)
+ }
+ return b, nil
+}
+func appendFixedS64Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ v := *ptr.toInt64()
+ b = appendVarint(b, wiretag)
+ b = appendFixed64(b, uint64(v))
+ return b, nil
+}
+func appendFixedS64ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ v := *ptr.toInt64()
+ if v == 0 {
+ return b, nil
+ }
+ b = appendVarint(b, wiretag)
+ b = appendFixed64(b, uint64(v))
+ return b, nil
+}
+func appendFixedS64Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ p := *ptr.toInt64Ptr()
+ if p == nil {
+ return b, nil
+ }
+ b = appendVarint(b, wiretag)
+ b = appendFixed64(b, uint64(*p))
+ return b, nil
+}
+func appendFixedS64Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ s := *ptr.toInt64Slice()
+ for _, v := range s {
+ b = appendVarint(b, wiretag)
+ b = appendFixed64(b, uint64(v))
+ }
+ return b, nil
+}
+func appendFixedS64PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ s := *ptr.toInt64Slice()
+ if len(s) == 0 {
+ return b, nil
+ }
+ b = appendVarint(b, wiretag&^7|WireBytes)
+ b = appendVarint(b, uint64(8*len(s)))
+ for _, v := range s {
+ b = appendFixed64(b, uint64(v))
+ }
+ return b, nil
+}
+func appendFloat64Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ v := math.Float64bits(*ptr.toFloat64())
+ b = appendVarint(b, wiretag)
+ b = appendFixed64(b, v)
+ return b, nil
+}
+func appendFloat64ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ v := math.Float64bits(*ptr.toFloat64())
+ if v == 0 {
+ return b, nil
+ }
+ b = appendVarint(b, wiretag)
+ b = appendFixed64(b, v)
+ return b, nil
+}
+func appendFloat64Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ p := *ptr.toFloat64Ptr()
+ if p == nil {
+ return b, nil
+ }
+ b = appendVarint(b, wiretag)
+ b = appendFixed64(b, math.Float64bits(*p))
+ return b, nil
+}
+func appendFloat64Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ s := *ptr.toFloat64Slice()
+ for _, v := range s {
+ b = appendVarint(b, wiretag)
+ b = appendFixed64(b, math.Float64bits(v))
+ }
+ return b, nil
+}
+func appendFloat64PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ s := *ptr.toFloat64Slice()
+ if len(s) == 0 {
+ return b, nil
+ }
+ b = appendVarint(b, wiretag&^7|WireBytes)
+ b = appendVarint(b, uint64(8*len(s)))
+ for _, v := range s {
+ b = appendFixed64(b, math.Float64bits(v))
+ }
+ return b, nil
+}
+func appendVarint32Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ v := *ptr.toUint32()
+ b = appendVarint(b, wiretag)
+ b = appendVarint(b, uint64(v))
+ return b, nil
+}
+func appendVarint32ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ v := *ptr.toUint32()
+ if v == 0 {
+ return b, nil
+ }
+ b = appendVarint(b, wiretag)
+ b = appendVarint(b, uint64(v))
+ return b, nil
+}
+func appendVarint32Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ p := *ptr.toUint32Ptr()
+ if p == nil {
+ return b, nil
+ }
+ b = appendVarint(b, wiretag)
+ b = appendVarint(b, uint64(*p))
+ return b, nil
+}
+func appendVarint32Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ s := *ptr.toUint32Slice()
+ for _, v := range s {
+ b = appendVarint(b, wiretag)
+ b = appendVarint(b, uint64(v))
+ }
+ return b, nil
+}
+func appendVarint32PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ s := *ptr.toUint32Slice()
+ if len(s) == 0 {
+ return b, nil
+ }
+ b = appendVarint(b, wiretag&^7|WireBytes)
+ // compute size
+ n := 0
+ for _, v := range s {
+ n += SizeVarint(uint64(v))
+ }
+ b = appendVarint(b, uint64(n))
+ for _, v := range s {
+ b = appendVarint(b, uint64(v))
+ }
+ return b, nil
+}
+func appendVarintS32Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ v := *ptr.toInt32()
+ b = appendVarint(b, wiretag)
+ b = appendVarint(b, uint64(v))
+ return b, nil
+}
+func appendVarintS32ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ v := *ptr.toInt32()
+ if v == 0 {
+ return b, nil
+ }
+ b = appendVarint(b, wiretag)
+ b = appendVarint(b, uint64(v))
+ return b, nil
+}
+func appendVarintS32Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ p := ptr.getInt32Ptr()
+ if p == nil {
+ return b, nil
+ }
+ b = appendVarint(b, wiretag)
+ b = appendVarint(b, uint64(*p))
+ return b, nil
+}
+func appendVarintS32Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ s := ptr.getInt32Slice()
+ for _, v := range s {
+ b = appendVarint(b, wiretag)
+ b = appendVarint(b, uint64(v))
+ }
+ return b, nil
+}
+func appendVarintS32PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ s := ptr.getInt32Slice()
+ if len(s) == 0 {
+ return b, nil
+ }
+ b = appendVarint(b, wiretag&^7|WireBytes)
+ // compute size
+ n := 0
+ for _, v := range s {
+ n += SizeVarint(uint64(v))
+ }
+ b = appendVarint(b, uint64(n))
+ for _, v := range s {
+ b = appendVarint(b, uint64(v))
+ }
+ return b, nil
+}
+func appendVarint64Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ v := *ptr.toUint64()
+ b = appendVarint(b, wiretag)
+ b = appendVarint(b, v)
+ return b, nil
+}
+func appendVarint64ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ v := *ptr.toUint64()
+ if v == 0 {
+ return b, nil
+ }
+ b = appendVarint(b, wiretag)
+ b = appendVarint(b, v)
+ return b, nil
+}
+func appendVarint64Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ p := *ptr.toUint64Ptr()
+ if p == nil {
+ return b, nil
+ }
+ b = appendVarint(b, wiretag)
+ b = appendVarint(b, *p)
+ return b, nil
+}
+func appendVarint64Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ s := *ptr.toUint64Slice()
+ for _, v := range s {
+ b = appendVarint(b, wiretag)
+ b = appendVarint(b, v)
+ }
+ return b, nil
+}
+func appendVarint64PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ s := *ptr.toUint64Slice()
+ if len(s) == 0 {
+ return b, nil
+ }
+ b = appendVarint(b, wiretag&^7|WireBytes)
+ // compute size
+ n := 0
+ for _, v := range s {
+ n += SizeVarint(v)
+ }
+ b = appendVarint(b, uint64(n))
+ for _, v := range s {
+ b = appendVarint(b, v)
+ }
+ return b, nil
+}
+func appendVarintS64Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ v := *ptr.toInt64()
+ b = appendVarint(b, wiretag)
+ b = appendVarint(b, uint64(v))
+ return b, nil
+}
+func appendVarintS64ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ v := *ptr.toInt64()
+ if v == 0 {
+ return b, nil
+ }
+ b = appendVarint(b, wiretag)
+ b = appendVarint(b, uint64(v))
+ return b, nil
+}
+func appendVarintS64Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ p := *ptr.toInt64Ptr()
+ if p == nil {
+ return b, nil
+ }
+ b = appendVarint(b, wiretag)
+ b = appendVarint(b, uint64(*p))
+ return b, nil
+}
+func appendVarintS64Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ s := *ptr.toInt64Slice()
+ for _, v := range s {
+ b = appendVarint(b, wiretag)
+ b = appendVarint(b, uint64(v))
+ }
+ return b, nil
+}
+func appendVarintS64PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ s := *ptr.toInt64Slice()
+ if len(s) == 0 {
+ return b, nil
+ }
+ b = appendVarint(b, wiretag&^7|WireBytes)
+ // compute size
+ n := 0
+ for _, v := range s {
+ n += SizeVarint(uint64(v))
+ }
+ b = appendVarint(b, uint64(n))
+ for _, v := range s {
+ b = appendVarint(b, uint64(v))
+ }
+ return b, nil
+}
+func appendZigzag32Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ v := *ptr.toInt32()
+ b = appendVarint(b, wiretag)
+ b = appendVarint(b, uint64((uint32(v)<<1)^uint32((int32(v)>>31))))
+ return b, nil
+}
+func appendZigzag32ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ v := *ptr.toInt32()
+ if v == 0 {
+ return b, nil
+ }
+ b = appendVarint(b, wiretag)
+ b = appendVarint(b, uint64((uint32(v)<<1)^uint32((int32(v)>>31))))
+ return b, nil
+}
+func appendZigzag32Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ p := ptr.getInt32Ptr()
+ if p == nil {
+ return b, nil
+ }
+ b = appendVarint(b, wiretag)
+ v := *p
+ b = appendVarint(b, uint64((uint32(v)<<1)^uint32((int32(v)>>31))))
+ return b, nil
+}
+func appendZigzag32Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ s := ptr.getInt32Slice()
+ for _, v := range s {
+ b = appendVarint(b, wiretag)
+ b = appendVarint(b, uint64((uint32(v)<<1)^uint32((int32(v)>>31))))
+ }
+ return b, nil
+}
+func appendZigzag32PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ s := ptr.getInt32Slice()
+ if len(s) == 0 {
+ return b, nil
+ }
+ b = appendVarint(b, wiretag&^7|WireBytes)
+ // compute size
+ n := 0
+ for _, v := range s {
+ n += SizeVarint(uint64((uint32(v) << 1) ^ uint32((int32(v) >> 31))))
+ }
+ b = appendVarint(b, uint64(n))
+ for _, v := range s {
+ b = appendVarint(b, uint64((uint32(v)<<1)^uint32((int32(v)>>31))))
+ }
+ return b, nil
+}
+func appendZigzag64Value(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ v := *ptr.toInt64()
+ b = appendVarint(b, wiretag)
+ b = appendVarint(b, uint64(v<<1)^uint64((int64(v)>>63)))
+ return b, nil
+}
+func appendZigzag64ValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ v := *ptr.toInt64()
+ if v == 0 {
+ return b, nil
+ }
+ b = appendVarint(b, wiretag)
+ b = appendVarint(b, uint64(v<<1)^uint64((int64(v)>>63)))
+ return b, nil
+}
+func appendZigzag64Ptr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ p := *ptr.toInt64Ptr()
+ if p == nil {
+ return b, nil
+ }
+ b = appendVarint(b, wiretag)
+ v := *p
+ b = appendVarint(b, uint64(v<<1)^uint64((int64(v)>>63)))
+ return b, nil
+}
+func appendZigzag64Slice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ s := *ptr.toInt64Slice()
+ for _, v := range s {
+ b = appendVarint(b, wiretag)
+ b = appendVarint(b, uint64(v<<1)^uint64((int64(v)>>63)))
+ }
+ return b, nil
+}
+func appendZigzag64PackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ s := *ptr.toInt64Slice()
+ if len(s) == 0 {
+ return b, nil
+ }
+ b = appendVarint(b, wiretag&^7|WireBytes)
+ // compute size
+ n := 0
+ for _, v := range s {
+ n += SizeVarint(uint64(v<<1) ^ uint64((int64(v) >> 63)))
+ }
+ b = appendVarint(b, uint64(n))
+ for _, v := range s {
+ b = appendVarint(b, uint64(v<<1)^uint64((int64(v)>>63)))
+ }
+ return b, nil
+}
+func appendBoolValue(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ v := *ptr.toBool()
+ b = appendVarint(b, wiretag)
+ if v {
+ b = append(b, 1)
+ } else {
+ b = append(b, 0)
+ }
+ return b, nil
+}
+func appendBoolValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ v := *ptr.toBool()
+ if !v {
+ return b, nil
+ }
+ b = appendVarint(b, wiretag)
+ b = append(b, 1)
+ return b, nil
+}
+
+func appendBoolPtr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ p := *ptr.toBoolPtr()
+ if p == nil {
+ return b, nil
+ }
+ b = appendVarint(b, wiretag)
+ if *p {
+ b = append(b, 1)
+ } else {
+ b = append(b, 0)
+ }
+ return b, nil
+}
+func appendBoolSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ s := *ptr.toBoolSlice()
+ for _, v := range s {
+ b = appendVarint(b, wiretag)
+ if v {
+ b = append(b, 1)
+ } else {
+ b = append(b, 0)
+ }
+ }
+ return b, nil
+}
+func appendBoolPackedSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ s := *ptr.toBoolSlice()
+ if len(s) == 0 {
+ return b, nil
+ }
+ b = appendVarint(b, wiretag&^7|WireBytes)
+ b = appendVarint(b, uint64(len(s)))
+ for _, v := range s {
+ if v {
+ b = append(b, 1)
+ } else {
+ b = append(b, 0)
+ }
+ }
+ return b, nil
+}
+func appendStringValue(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ v := *ptr.toString()
+ b = appendVarint(b, wiretag)
+ b = appendVarint(b, uint64(len(v)))
+ b = append(b, v...)
+ return b, nil
+}
+func appendStringValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ v := *ptr.toString()
+ if v == "" {
+ return b, nil
+ }
+ b = appendVarint(b, wiretag)
+ b = appendVarint(b, uint64(len(v)))
+ b = append(b, v...)
+ return b, nil
+}
+func appendStringPtr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ p := *ptr.toStringPtr()
+ if p == nil {
+ return b, nil
+ }
+ v := *p
+ b = appendVarint(b, wiretag)
+ b = appendVarint(b, uint64(len(v)))
+ b = append(b, v...)
+ return b, nil
+}
+func appendStringSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ s := *ptr.toStringSlice()
+ for _, v := range s {
+ b = appendVarint(b, wiretag)
+ b = appendVarint(b, uint64(len(v)))
+ b = append(b, v...)
+ }
+ return b, nil
+}
+func appendUTF8StringValue(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ var invalidUTF8 bool
+ v := *ptr.toString()
+ if !utf8.ValidString(v) {
+ invalidUTF8 = true
+ }
+ b = appendVarint(b, wiretag)
+ b = appendVarint(b, uint64(len(v)))
+ b = append(b, v...)
+ if invalidUTF8 {
+ return b, errInvalidUTF8
+ }
+ return b, nil
+}
+func appendUTF8StringValueNoZero(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ var invalidUTF8 bool
+ v := *ptr.toString()
+ if v == "" {
+ return b, nil
+ }
+ if !utf8.ValidString(v) {
+ invalidUTF8 = true
+ }
+ b = appendVarint(b, wiretag)
+ b = appendVarint(b, uint64(len(v)))
+ b = append(b, v...)
+ if invalidUTF8 {
+ return b, errInvalidUTF8
+ }
+ return b, nil
+}
+func appendUTF8StringPtr(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ var invalidUTF8 bool
+ p := *ptr.toStringPtr()
+ if p == nil {
+ return b, nil
+ }
+ v := *p
+ if !utf8.ValidString(v) {
+ invalidUTF8 = true
+ }
+ b = appendVarint(b, wiretag)
+ b = appendVarint(b, uint64(len(v)))
+ b = append(b, v...)
+ if invalidUTF8 {
+ return b, errInvalidUTF8
+ }
+ return b, nil
+}
+func appendUTF8StringSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ var invalidUTF8 bool
+ s := *ptr.toStringSlice()
+ for _, v := range s {
+ if !utf8.ValidString(v) {
+ invalidUTF8 = true
+ }
+ b = appendVarint(b, wiretag)
+ b = appendVarint(b, uint64(len(v)))
+ b = append(b, v...)
+ }
+ if invalidUTF8 {
+ return b, errInvalidUTF8
+ }
+ return b, nil
+}
+func appendBytes(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ v := *ptr.toBytes()
+ if v == nil {
+ return b, nil
+ }
+ b = appendVarint(b, wiretag)
+ b = appendVarint(b, uint64(len(v)))
+ b = append(b, v...)
+ return b, nil
+}
+func appendBytes3(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ v := *ptr.toBytes()
+ if len(v) == 0 {
+ return b, nil
+ }
+ b = appendVarint(b, wiretag)
+ b = appendVarint(b, uint64(len(v)))
+ b = append(b, v...)
+ return b, nil
+}
+func appendBytesOneof(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ v := *ptr.toBytes()
+ b = appendVarint(b, wiretag)
+ b = appendVarint(b, uint64(len(v)))
+ b = append(b, v...)
+ return b, nil
+}
+func appendBytesSlice(b []byte, ptr pointer, wiretag uint64, _ bool) ([]byte, error) {
+ s := *ptr.toBytesSlice()
+ for _, v := range s {
+ b = appendVarint(b, wiretag)
+ b = appendVarint(b, uint64(len(v)))
+ b = append(b, v...)
+ }
+ return b, nil
+}
+
+// makeGroupMarshaler returns the sizer and marshaler for a group.
+// u is the marshal info of the underlying message.
+func makeGroupMarshaler(u *marshalInfo) (sizer, marshaler) {
+ return func(ptr pointer, tagsize int) int {
+ p := ptr.getPointer()
+ if p.isNil() {
+ return 0
+ }
+ return u.size(p) + 2*tagsize
+ },
+ func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) {
+ p := ptr.getPointer()
+ if p.isNil() {
+ return b, nil
+ }
+ var err error
+ b = appendVarint(b, wiretag) // start group
+ b, err = u.marshal(b, p, deterministic)
+ b = appendVarint(b, wiretag+(WireEndGroup-WireStartGroup)) // end group
+ return b, err
+ }
+}
+
+// makeGroupSliceMarshaler returns the sizer and marshaler for a group slice.
+// u is the marshal info of the underlying message.
+func makeGroupSliceMarshaler(u *marshalInfo) (sizer, marshaler) {
+ return func(ptr pointer, tagsize int) int {
+ s := ptr.getPointerSlice()
+ n := 0
+ for _, v := range s {
+ if v.isNil() {
+ continue
+ }
+ n += u.size(v) + 2*tagsize
+ }
+ return n
+ },
+ func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) {
+ s := ptr.getPointerSlice()
+ var err error
+ var nerr nonFatal
+ for _, v := range s {
+ if v.isNil() {
+ return b, errRepeatedHasNil
+ }
+ b = appendVarint(b, wiretag) // start group
+ b, err = u.marshal(b, v, deterministic)
+ b = appendVarint(b, wiretag+(WireEndGroup-WireStartGroup)) // end group
+ if !nerr.Merge(err) {
+ if err == ErrNil {
+ err = errRepeatedHasNil
+ }
+ return b, err
+ }
+ }
+ return b, nerr.E
+ }
+}
+
+// makeMessageMarshaler returns the sizer and marshaler for a message field.
+// u is the marshal info of the message.
+func makeMessageMarshaler(u *marshalInfo) (sizer, marshaler) {
+ return func(ptr pointer, tagsize int) int {
+ p := ptr.getPointer()
+ if p.isNil() {
+ return 0
+ }
+ siz := u.size(p)
+ return siz + SizeVarint(uint64(siz)) + tagsize
+ },
+ func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) {
+ p := ptr.getPointer()
+ if p.isNil() {
+ return b, nil
+ }
+ b = appendVarint(b, wiretag)
+ siz := u.cachedsize(p)
+ b = appendVarint(b, uint64(siz))
+ return u.marshal(b, p, deterministic)
+ }
+}
+
+// makeMessageSliceMarshaler returns the sizer and marshaler for a message slice.
+// u is the marshal info of the message.
+func makeMessageSliceMarshaler(u *marshalInfo) (sizer, marshaler) {
+ return func(ptr pointer, tagsize int) int {
+ s := ptr.getPointerSlice()
+ n := 0
+ for _, v := range s {
+ if v.isNil() {
+ continue
+ }
+ siz := u.size(v)
+ n += siz + SizeVarint(uint64(siz)) + tagsize
+ }
+ return n
+ },
+ func(b []byte, ptr pointer, wiretag uint64, deterministic bool) ([]byte, error) {
+ s := ptr.getPointerSlice()
+ var err error
+ var nerr nonFatal
+ for _, v := range s {
+ if v.isNil() {
+ return b, errRepeatedHasNil
+ }
+ b = appendVarint(b, wiretag)
+ siz := u.cachedsize(v)
+ b = appendVarint(b, uint64(siz))
+ b, err = u.marshal(b, v, deterministic)
+
+ if !nerr.Merge(err) {
+ if err == ErrNil {
+ err = errRepeatedHasNil
+ }
+ return b, err
+ }
+ }
+ return b, nerr.E
+ }
+}
+
+// makeMapMarshaler returns the sizer and marshaler for a map field.
+// f is the pointer to the reflect data structure of the field.
+func makeMapMarshaler(f *reflect.StructField) (sizer, marshaler) {
+ // figure out key and value type
+ t := f.Type
+ keyType := t.Key()
+ valType := t.Elem()
+ keyTags := strings.Split(f.Tag.Get("protobuf_key"), ",")
+ valTags := strings.Split(f.Tag.Get("protobuf_val"), ",")
+ keySizer, keyMarshaler := typeMarshaler(keyType, keyTags, false, false) // don't omit zero value in map
+ valSizer, valMarshaler := typeMarshaler(valType, valTags, false, false) // don't omit zero value in map
+ keyWireTag := 1<<3 | wiretype(keyTags[0])
+ valWireTag := 2<<3 | wiretype(valTags[0])
+
+ // We create an interface to get the addresses of the map key and value.
+ // If value is pointer-typed, the interface is a direct interface, the
+ // idata itself is the value. Otherwise, the idata is the pointer to the
+ // value.
+ // Key cannot be pointer-typed.
+ valIsPtr := valType.Kind() == reflect.Ptr
+
+ // If value is a message with nested maps, calling
+ // valSizer in marshal may be quadratic. We should use
+ // cached version in marshal (but not in size).
+ // If value is not message type, we don't have size cache,
+ // but it cannot be nested either. Just use valSizer.
+ valCachedSizer := valSizer
+ if valIsPtr && valType.Elem().Kind() == reflect.Struct {
+ u := getMarshalInfo(valType.Elem())
+ valCachedSizer = func(ptr pointer, tagsize int) int {
+ // Same as message sizer, but use cache.
+ p := ptr.getPointer()
+ if p.isNil() {
+ return 0
+ }
+ siz := u.cachedsize(p)
+ return siz + SizeVarint(uint64(siz)) + tagsize
+ }
+ }
+ return func(ptr pointer, tagsize int) int {
+ m := ptr.asPointerTo(t).Elem() // the map
+ n := 0
+ for _, k := range m.MapKeys() {
+ ki := k.Interface()
+ vi := m.MapIndex(k).Interface()
+ kaddr := toAddrPointer(&ki, false, false) // pointer to key
+ vaddr := toAddrPointer(&vi, valIsPtr, false) // pointer to value
+ siz := keySizer(kaddr, 1) + valSizer(vaddr, 1) // tag of key = 1 (size=1), tag of val = 2 (size=1)
+ n += siz + SizeVarint(uint64(siz)) + tagsize
+ }
+ return n
+ },
+ func(b []byte, ptr pointer, tag uint64, deterministic bool) ([]byte, error) {
+ m := ptr.asPointerTo(t).Elem() // the map
+ var err error
+ keys := m.MapKeys()
+ if len(keys) > 1 && deterministic {
+ sort.Sort(mapKeys(keys))
+ }
+
+ var nerr nonFatal
+ for _, k := range keys {
+ ki := k.Interface()
+ vi := m.MapIndex(k).Interface()
+ kaddr := toAddrPointer(&ki, false, false) // pointer to key
+ vaddr := toAddrPointer(&vi, valIsPtr, false) // pointer to value
+ b = appendVarint(b, tag)
+ siz := keySizer(kaddr, 1) + valCachedSizer(vaddr, 1) // tag of key = 1 (size=1), tag of val = 2 (size=1)
+ b = appendVarint(b, uint64(siz))
+ b, err = keyMarshaler(b, kaddr, keyWireTag, deterministic)
+ if !nerr.Merge(err) {
+ return b, err
+ }
+ b, err = valMarshaler(b, vaddr, valWireTag, deterministic)
+ if err != ErrNil && !nerr.Merge(err) { // allow nil value in map
+ return b, err
+ }
+ }
+ return b, nerr.E
+ }
+}
+
+// makeOneOfMarshaler returns the sizer and marshaler for a oneof field.
+// fi is the marshal info of the field.
+// f is the pointer to the reflect data structure of the field.
+func makeOneOfMarshaler(fi *marshalFieldInfo, f *reflect.StructField) (sizer, marshaler) {
+ // Oneof field is an interface. We need to get the actual data type on the fly.
+ t := f.Type
+ return func(ptr pointer, _ int) int {
+ p := ptr.getInterfacePointer()
+ if p.isNil() {
+ return 0
+ }
+ v := ptr.asPointerTo(t).Elem().Elem().Elem() // *interface -> interface -> *struct -> struct
+ telem := v.Type()
+ e := fi.oneofElems[telem]
+ return e.sizer(p, e.tagsize)
+ },
+ func(b []byte, ptr pointer, _ uint64, deterministic bool) ([]byte, error) {
+ p := ptr.getInterfacePointer()
+ if p.isNil() {
+ return b, nil
+ }
+ v := ptr.asPointerTo(t).Elem().Elem().Elem() // *interface -> interface -> *struct -> struct
+ telem := v.Type()
+ if telem.Field(0).Type.Kind() == reflect.Ptr && p.getPointer().isNil() {
+ return b, errOneofHasNil
+ }
+ e := fi.oneofElems[telem]
+ return e.marshaler(b, p, e.wiretag, deterministic)
+ }
+}
+
+// sizeExtensions computes the size of encoded data for a XXX_InternalExtensions field.
+func (u *marshalInfo) sizeExtensions(ext *XXX_InternalExtensions) int {
+ m, mu := ext.extensionsRead()
+ if m == nil {
+ return 0
+ }
+ mu.Lock()
+
+ n := 0
+ for _, e := range m {
+ if e.value == nil || e.desc == nil {
+ // Extension is only in its encoded form.
+ n += len(e.enc)
+ continue
+ }
+
+ // We don't skip extensions that have an encoded form set,
+ // because the extension value may have been mutated after
+ // the last time this function was called.
+ ei := u.getExtElemInfo(e.desc)
+ v := e.value
+ p := toAddrPointer(&v, ei.isptr, ei.deref)
+ n += ei.sizer(p, ei.tagsize)
+ }
+ mu.Unlock()
+ return n
+}
+
+// appendExtensions marshals a XXX_InternalExtensions field to the end of byte slice b.
+func (u *marshalInfo) appendExtensions(b []byte, ext *XXX_InternalExtensions, deterministic bool) ([]byte, error) {
+ m, mu := ext.extensionsRead()
+ if m == nil {
+ return b, nil
+ }
+ mu.Lock()
+ defer mu.Unlock()
+
+ var err error
+ var nerr nonFatal
+
+ // Fast-path for common cases: zero or one extensions.
+ // Don't bother sorting the keys.
+ if len(m) <= 1 {
+ for _, e := range m {
+ if e.value == nil || e.desc == nil {
+ // Extension is only in its encoded form.
+ b = append(b, e.enc...)
+ continue
+ }
+
+ // We don't skip extensions that have an encoded form set,
+ // because the extension value may have been mutated after
+ // the last time this function was called.
+
+ ei := u.getExtElemInfo(e.desc)
+ v := e.value
+ p := toAddrPointer(&v, ei.isptr, ei.deref)
+ b, err = ei.marshaler(b, p, ei.wiretag, deterministic)
+ if !nerr.Merge(err) {
+ return b, err
+ }
+ }
+ return b, nerr.E
+ }
+
+ // Sort the keys to provide a deterministic encoding.
+ // Not sure this is required, but the old code does it.
+ keys := make([]int, 0, len(m))
+ for k := range m {
+ keys = append(keys, int(k))
+ }
+ sort.Ints(keys)
+
+ for _, k := range keys {
+ e := m[int32(k)]
+ if e.value == nil || e.desc == nil {
+ // Extension is only in its encoded form.
+ b = append(b, e.enc...)
+ continue
+ }
+
+ // We don't skip extensions that have an encoded form set,
+ // because the extension value may have been mutated after
+ // the last time this function was called.
+
+ ei := u.getExtElemInfo(e.desc)
+ v := e.value
+ p := toAddrPointer(&v, ei.isptr, ei.deref)
+ b, err = ei.marshaler(b, p, ei.wiretag, deterministic)
+ if !nerr.Merge(err) {
+ return b, err
+ }
+ }
+ return b, nerr.E
+}
+
+// message set format is:
+// message MessageSet {
+// repeated group Item = 1 {
+// required int32 type_id = 2;
+// required string message = 3;
+// };
+// }
+
+// sizeMessageSet computes the size of encoded data for a XXX_InternalExtensions field
+// in message set format (above).
+func (u *marshalInfo) sizeMessageSet(ext *XXX_InternalExtensions) int {
+ m, mu := ext.extensionsRead()
+ if m == nil {
+ return 0
+ }
+ mu.Lock()
+
+ n := 0
+ for id, e := range m {
+ n += 2 // start group, end group. tag = 1 (size=1)
+ n += SizeVarint(uint64(id)) + 1 // type_id, tag = 2 (size=1)
+
+ if e.value == nil || e.desc == nil {
+ // Extension is only in its encoded form.
+ msgWithLen := skipVarint(e.enc) // skip old tag, but leave the length varint
+ siz := len(msgWithLen)
+ n += siz + 1 // message, tag = 3 (size=1)
+ continue
+ }
+
+ // We don't skip extensions that have an encoded form set,
+ // because the extension value may have been mutated after
+ // the last time this function was called.
+
+ ei := u.getExtElemInfo(e.desc)
+ v := e.value
+ p := toAddrPointer(&v, ei.isptr, ei.deref)
+ n += ei.sizer(p, 1) // message, tag = 3 (size=1)
+ }
+ mu.Unlock()
+ return n
+}
+
+// appendMessageSet marshals a XXX_InternalExtensions field in message set format (above)
+// to the end of byte slice b.
+func (u *marshalInfo) appendMessageSet(b []byte, ext *XXX_InternalExtensions, deterministic bool) ([]byte, error) {
+ m, mu := ext.extensionsRead()
+ if m == nil {
+ return b, nil
+ }
+ mu.Lock()
+ defer mu.Unlock()
+
+ var err error
+ var nerr nonFatal
+
+ // Fast-path for common cases: zero or one extensions.
+ // Don't bother sorting the keys.
+ if len(m) <= 1 {
+ for id, e := range m {
+ b = append(b, 1<<3|WireStartGroup)
+ b = append(b, 2<<3|WireVarint)
+ b = appendVarint(b, uint64(id))
+
+ if e.value == nil || e.desc == nil {
+ // Extension is only in its encoded form.
+ msgWithLen := skipVarint(e.enc) // skip old tag, but leave the length varint
+ b = append(b, 3<<3|WireBytes)
+ b = append(b, msgWithLen...)
+ b = append(b, 1<<3|WireEndGroup)
+ continue
+ }
+
+ // We don't skip extensions that have an encoded form set,
+ // because the extension value may have been mutated after
+ // the last time this function was called.
+
+ ei := u.getExtElemInfo(e.desc)
+ v := e.value
+ p := toAddrPointer(&v, ei.isptr, ei.deref)
+ b, err = ei.marshaler(b, p, 3<<3|WireBytes, deterministic)
+ if !nerr.Merge(err) {
+ return b, err
+ }
+ b = append(b, 1<<3|WireEndGroup)
+ }
+ return b, nerr.E
+ }
+
+ // Sort the keys to provide a deterministic encoding.
+ keys := make([]int, 0, len(m))
+ for k := range m {
+ keys = append(keys, int(k))
+ }
+ sort.Ints(keys)
+
+ for _, id := range keys {
+ e := m[int32(id)]
+ b = append(b, 1<<3|WireStartGroup)
+ b = append(b, 2<<3|WireVarint)
+ b = appendVarint(b, uint64(id))
+
+ if e.value == nil || e.desc == nil {
+ // Extension is only in its encoded form.
+ msgWithLen := skipVarint(e.enc) // skip old tag, but leave the length varint
+ b = append(b, 3<<3|WireBytes)
+ b = append(b, msgWithLen...)
+ b = append(b, 1<<3|WireEndGroup)
+ continue
+ }
+
+ // We don't skip extensions that have an encoded form set,
+ // because the extension value may have been mutated after
+ // the last time this function was called.
+
+ ei := u.getExtElemInfo(e.desc)
+ v := e.value
+ p := toAddrPointer(&v, ei.isptr, ei.deref)
+ b, err = ei.marshaler(b, p, 3<<3|WireBytes, deterministic)
+ b = append(b, 1<<3|WireEndGroup)
+ if !nerr.Merge(err) {
+ return b, err
+ }
+ }
+ return b, nerr.E
+}
+
+// sizeV1Extensions computes the size of encoded data for a V1-API extension field.
+func (u *marshalInfo) sizeV1Extensions(m map[int32]Extension) int {
+ if m == nil {
+ return 0
+ }
+
+ n := 0
+ for _, e := range m {
+ if e.value == nil || e.desc == nil {
+ // Extension is only in its encoded form.
+ n += len(e.enc)
+ continue
+ }
+
+ // We don't skip extensions that have an encoded form set,
+ // because the extension value may have been mutated after
+ // the last time this function was called.
+
+ ei := u.getExtElemInfo(e.desc)
+ v := e.value
+ p := toAddrPointer(&v, ei.isptr, ei.deref)
+ n += ei.sizer(p, ei.tagsize)
+ }
+ return n
+}
+
+// appendV1Extensions marshals a V1-API extension field to the end of byte slice b.
+func (u *marshalInfo) appendV1Extensions(b []byte, m map[int32]Extension, deterministic bool) ([]byte, error) {
+ if m == nil {
+ return b, nil
+ }
+
+ // Sort the keys to provide a deterministic encoding.
+ keys := make([]int, 0, len(m))
+ for k := range m {
+ keys = append(keys, int(k))
+ }
+ sort.Ints(keys)
+
+ var err error
+ var nerr nonFatal
+ for _, k := range keys {
+ e := m[int32(k)]
+ if e.value == nil || e.desc == nil {
+ // Extension is only in its encoded form.
+ b = append(b, e.enc...)
+ continue
+ }
+
+ // We don't skip extensions that have an encoded form set,
+ // because the extension value may have been mutated after
+ // the last time this function was called.
+
+ ei := u.getExtElemInfo(e.desc)
+ v := e.value
+ p := toAddrPointer(&v, ei.isptr, ei.deref)
+ b, err = ei.marshaler(b, p, ei.wiretag, deterministic)
+ if !nerr.Merge(err) {
+ return b, err
+ }
+ }
+ return b, nerr.E
+}
+
+// newMarshaler is the interface representing objects that can marshal themselves.
+//
+// This exists to support protoc-gen-go generated messages.
+// The proto package will stop type-asserting to this interface in the future.
+//
+// DO NOT DEPEND ON THIS.
+type newMarshaler interface {
+ XXX_Size() int
+ XXX_Marshal(b []byte, deterministic bool) ([]byte, error)
+}
+
+// Size returns the encoded size of a protocol buffer message.
+// This is the main entry point.
+func Size(pb Message) int {
+ if m, ok := pb.(newMarshaler); ok {
+ return m.XXX_Size()
+ }
+ if m, ok := pb.(Marshaler); ok {
+ // If the message can marshal itself, let it do it, for compatibility.
+ // NOTE: This is not efficient.
+ b, _ := m.Marshal()
+ return len(b)
+ }
+ // in case somehow we didn't generate the wrapper
+ if pb == nil {
+ return 0
+ }
+ var info InternalMessageInfo
+ return info.Size(pb)
+}
+
+// Marshal takes a protocol buffer message
+// and encodes it into the wire format, returning the data.
+// This is the main entry point.
+func Marshal(pb Message) ([]byte, error) {
+ if m, ok := pb.(newMarshaler); ok {
+ siz := m.XXX_Size()
+ b := make([]byte, 0, siz)
+ return m.XXX_Marshal(b, false)
+ }
+ if m, ok := pb.(Marshaler); ok {
+ // If the message can marshal itself, let it do it, for compatibility.
+ // NOTE: This is not efficient.
+ return m.Marshal()
+ }
+ // in case somehow we didn't generate the wrapper
+ if pb == nil {
+ return nil, ErrNil
+ }
+ var info InternalMessageInfo
+ siz := info.Size(pb)
+ b := make([]byte, 0, siz)
+ return info.Marshal(b, pb, false)
+}
+
+// Marshal takes a protocol buffer message
+// and encodes it into the wire format, writing the result to the
+// Buffer.
+// This is an alternative entry point. It is not necessary to use
+// a Buffer for most applications.
+func (p *Buffer) Marshal(pb Message) error {
+ var err error
+ if m, ok := pb.(newMarshaler); ok {
+ siz := m.XXX_Size()
+ p.grow(siz) // make sure buf has enough capacity
+ p.buf, err = m.XXX_Marshal(p.buf, p.deterministic)
+ return err
+ }
+ if m, ok := pb.(Marshaler); ok {
+ // If the message can marshal itself, let it do it, for compatibility.
+ // NOTE: This is not efficient.
+ b, err := m.Marshal()
+ p.buf = append(p.buf, b...)
+ return err
+ }
+ // in case somehow we didn't generate the wrapper
+ if pb == nil {
+ return ErrNil
+ }
+ var info InternalMessageInfo
+ siz := info.Size(pb)
+ p.grow(siz) // make sure buf has enough capacity
+ p.buf, err = info.Marshal(p.buf, pb, p.deterministic)
+ return err
+}
+
+// grow grows the buffer's capacity, if necessary, to guarantee space for
+// another n bytes. After grow(n), at least n bytes can be written to the
+// buffer without another allocation.
+func (p *Buffer) grow(n int) {
+ need := len(p.buf) + n
+ if need <= cap(p.buf) {
+ return
+ }
+ newCap := len(p.buf) * 2
+ if newCap < need {
+ newCap = need
+ }
+ p.buf = append(make([]byte, 0, newCap), p.buf...)
+}
diff --git a/vendor/github.com/golang/protobuf/proto/table_merge.go b/vendor/github.com/golang/protobuf/proto/table_merge.go
new file mode 100644
index 000000000..5525def6a
--- /dev/null
+++ b/vendor/github.com/golang/protobuf/proto/table_merge.go
@@ -0,0 +1,654 @@
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2016 The Go Authors. All rights reserved.
+// https://github.com/golang/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package proto
+
+import (
+ "fmt"
+ "reflect"
+ "strings"
+ "sync"
+ "sync/atomic"
+)
+
+// Merge merges the src message into dst.
+// This assumes that dst and src of the same type and are non-nil.
+func (a *InternalMessageInfo) Merge(dst, src Message) {
+ mi := atomicLoadMergeInfo(&a.merge)
+ if mi == nil {
+ mi = getMergeInfo(reflect.TypeOf(dst).Elem())
+ atomicStoreMergeInfo(&a.merge, mi)
+ }
+ mi.merge(toPointer(&dst), toPointer(&src))
+}
+
+type mergeInfo struct {
+ typ reflect.Type
+
+ initialized int32 // 0: only typ is valid, 1: everything is valid
+ lock sync.Mutex
+
+ fields []mergeFieldInfo
+ unrecognized field // Offset of XXX_unrecognized
+}
+
+type mergeFieldInfo struct {
+ field field // Offset of field, guaranteed to be valid
+
+ // isPointer reports whether the value in the field is a pointer.
+ // This is true for the following situations:
+ // * Pointer to struct
+ // * Pointer to basic type (proto2 only)
+ // * Slice (first value in slice header is a pointer)
+ // * String (first value in string header is a pointer)
+ isPointer bool
+
+ // basicWidth reports the width of the field assuming that it is directly
+ // embedded in the struct (as is the case for basic types in proto3).
+ // The possible values are:
+ // 0: invalid
+ // 1: bool
+ // 4: int32, uint32, float32
+ // 8: int64, uint64, float64
+ basicWidth int
+
+ // Where dst and src are pointers to the types being merged.
+ merge func(dst, src pointer)
+}
+
+var (
+ mergeInfoMap = map[reflect.Type]*mergeInfo{}
+ mergeInfoLock sync.Mutex
+)
+
+func getMergeInfo(t reflect.Type) *mergeInfo {
+ mergeInfoLock.Lock()
+ defer mergeInfoLock.Unlock()
+ mi := mergeInfoMap[t]
+ if mi == nil {
+ mi = &mergeInfo{typ: t}
+ mergeInfoMap[t] = mi
+ }
+ return mi
+}
+
+// merge merges src into dst assuming they are both of type *mi.typ.
+func (mi *mergeInfo) merge(dst, src pointer) {
+ if dst.isNil() {
+ panic("proto: nil destination")
+ }
+ if src.isNil() {
+ return // Nothing to do.
+ }
+
+ if atomic.LoadInt32(&mi.initialized) == 0 {
+ mi.computeMergeInfo()
+ }
+
+ for _, fi := range mi.fields {
+ sfp := src.offset(fi.field)
+
+ // As an optimization, we can avoid the merge function call cost
+ // if we know for sure that the source will have no effect
+ // by checking if it is the zero value.
+ if unsafeAllowed {
+ if fi.isPointer && sfp.getPointer().isNil() { // Could be slice or string
+ continue
+ }
+ if fi.basicWidth > 0 {
+ switch {
+ case fi.basicWidth == 1 && !*sfp.toBool():
+ continue
+ case fi.basicWidth == 4 && *sfp.toUint32() == 0:
+ continue
+ case fi.basicWidth == 8 && *sfp.toUint64() == 0:
+ continue
+ }
+ }
+ }
+
+ dfp := dst.offset(fi.field)
+ fi.merge(dfp, sfp)
+ }
+
+ // TODO: Make this faster?
+ out := dst.asPointerTo(mi.typ).Elem()
+ in := src.asPointerTo(mi.typ).Elem()
+ if emIn, err := extendable(in.Addr().Interface()); err == nil {
+ emOut, _ := extendable(out.Addr().Interface())
+ mIn, muIn := emIn.extensionsRead()
+ if mIn != nil {
+ mOut := emOut.extensionsWrite()
+ muIn.Lock()
+ mergeExtension(mOut, mIn)
+ muIn.Unlock()
+ }
+ }
+
+ if mi.unrecognized.IsValid() {
+ if b := *src.offset(mi.unrecognized).toBytes(); len(b) > 0 {
+ *dst.offset(mi.unrecognized).toBytes() = append([]byte(nil), b...)
+ }
+ }
+}
+
+func (mi *mergeInfo) computeMergeInfo() {
+ mi.lock.Lock()
+ defer mi.lock.Unlock()
+ if mi.initialized != 0 {
+ return
+ }
+ t := mi.typ
+ n := t.NumField()
+
+ props := GetProperties(t)
+ for i := 0; i < n; i++ {
+ f := t.Field(i)
+ if strings.HasPrefix(f.Name, "XXX_") {
+ continue
+ }
+
+ mfi := mergeFieldInfo{field: toField(&f)}
+ tf := f.Type
+
+ // As an optimization, we can avoid the merge function call cost
+ // if we know for sure that the source will have no effect
+ // by checking if it is the zero value.
+ if unsafeAllowed {
+ switch tf.Kind() {
+ case reflect.Ptr, reflect.Slice, reflect.String:
+ // As a special case, we assume slices and strings are pointers
+ // since we know that the first field in the SliceSlice or
+ // StringHeader is a data pointer.
+ mfi.isPointer = true
+ case reflect.Bool:
+ mfi.basicWidth = 1
+ case reflect.Int32, reflect.Uint32, reflect.Float32:
+ mfi.basicWidth = 4
+ case reflect.Int64, reflect.Uint64, reflect.Float64:
+ mfi.basicWidth = 8
+ }
+ }
+
+ // Unwrap tf to get at its most basic type.
+ var isPointer, isSlice bool
+ if tf.Kind() == reflect.Slice && tf.Elem().Kind() != reflect.Uint8 {
+ isSlice = true
+ tf = tf.Elem()
+ }
+ if tf.Kind() == reflect.Ptr {
+ isPointer = true
+ tf = tf.Elem()
+ }
+ if isPointer && isSlice && tf.Kind() != reflect.Struct {
+ panic("both pointer and slice for basic type in " + tf.Name())
+ }
+
+ switch tf.Kind() {
+ case reflect.Int32:
+ switch {
+ case isSlice: // E.g., []int32
+ mfi.merge = func(dst, src pointer) {
+ // NOTE: toInt32Slice is not defined (see pointer_reflect.go).
+ /*
+ sfsp := src.toInt32Slice()
+ if *sfsp != nil {
+ dfsp := dst.toInt32Slice()
+ *dfsp = append(*dfsp, *sfsp...)
+ if *dfsp == nil {
+ *dfsp = []int64{}
+ }
+ }
+ */
+ sfs := src.getInt32Slice()
+ if sfs != nil {
+ dfs := dst.getInt32Slice()
+ dfs = append(dfs, sfs...)
+ if dfs == nil {
+ dfs = []int32{}
+ }
+ dst.setInt32Slice(dfs)
+ }
+ }
+ case isPointer: // E.g., *int32
+ mfi.merge = func(dst, src pointer) {
+ // NOTE: toInt32Ptr is not defined (see pointer_reflect.go).
+ /*
+ sfpp := src.toInt32Ptr()
+ if *sfpp != nil {
+ dfpp := dst.toInt32Ptr()
+ if *dfpp == nil {
+ *dfpp = Int32(**sfpp)
+ } else {
+ **dfpp = **sfpp
+ }
+ }
+ */
+ sfp := src.getInt32Ptr()
+ if sfp != nil {
+ dfp := dst.getInt32Ptr()
+ if dfp == nil {
+ dst.setInt32Ptr(*sfp)
+ } else {
+ *dfp = *sfp
+ }
+ }
+ }
+ default: // E.g., int32
+ mfi.merge = func(dst, src pointer) {
+ if v := *src.toInt32(); v != 0 {
+ *dst.toInt32() = v
+ }
+ }
+ }
+ case reflect.Int64:
+ switch {
+ case isSlice: // E.g., []int64
+ mfi.merge = func(dst, src pointer) {
+ sfsp := src.toInt64Slice()
+ if *sfsp != nil {
+ dfsp := dst.toInt64Slice()
+ *dfsp = append(*dfsp, *sfsp...)
+ if *dfsp == nil {
+ *dfsp = []int64{}
+ }
+ }
+ }
+ case isPointer: // E.g., *int64
+ mfi.merge = func(dst, src pointer) {
+ sfpp := src.toInt64Ptr()
+ if *sfpp != nil {
+ dfpp := dst.toInt64Ptr()
+ if *dfpp == nil {
+ *dfpp = Int64(**sfpp)
+ } else {
+ **dfpp = **sfpp
+ }
+ }
+ }
+ default: // E.g., int64
+ mfi.merge = func(dst, src pointer) {
+ if v := *src.toInt64(); v != 0 {
+ *dst.toInt64() = v
+ }
+ }
+ }
+ case reflect.Uint32:
+ switch {
+ case isSlice: // E.g., []uint32
+ mfi.merge = func(dst, src pointer) {
+ sfsp := src.toUint32Slice()
+ if *sfsp != nil {
+ dfsp := dst.toUint32Slice()
+ *dfsp = append(*dfsp, *sfsp...)
+ if *dfsp == nil {
+ *dfsp = []uint32{}
+ }
+ }
+ }
+ case isPointer: // E.g., *uint32
+ mfi.merge = func(dst, src pointer) {
+ sfpp := src.toUint32Ptr()
+ if *sfpp != nil {
+ dfpp := dst.toUint32Ptr()
+ if *dfpp == nil {
+ *dfpp = Uint32(**sfpp)
+ } else {
+ **dfpp = **sfpp
+ }
+ }
+ }
+ default: // E.g., uint32
+ mfi.merge = func(dst, src pointer) {
+ if v := *src.toUint32(); v != 0 {
+ *dst.toUint32() = v
+ }
+ }
+ }
+ case reflect.Uint64:
+ switch {
+ case isSlice: // E.g., []uint64
+ mfi.merge = func(dst, src pointer) {
+ sfsp := src.toUint64Slice()
+ if *sfsp != nil {
+ dfsp := dst.toUint64Slice()
+ *dfsp = append(*dfsp, *sfsp...)
+ if *dfsp == nil {
+ *dfsp = []uint64{}
+ }
+ }
+ }
+ case isPointer: // E.g., *uint64
+ mfi.merge = func(dst, src pointer) {
+ sfpp := src.toUint64Ptr()
+ if *sfpp != nil {
+ dfpp := dst.toUint64Ptr()
+ if *dfpp == nil {
+ *dfpp = Uint64(**sfpp)
+ } else {
+ **dfpp = **sfpp
+ }
+ }
+ }
+ default: // E.g., uint64
+ mfi.merge = func(dst, src pointer) {
+ if v := *src.toUint64(); v != 0 {
+ *dst.toUint64() = v
+ }
+ }
+ }
+ case reflect.Float32:
+ switch {
+ case isSlice: // E.g., []float32
+ mfi.merge = func(dst, src pointer) {
+ sfsp := src.toFloat32Slice()
+ if *sfsp != nil {
+ dfsp := dst.toFloat32Slice()
+ *dfsp = append(*dfsp, *sfsp...)
+ if *dfsp == nil {
+ *dfsp = []float32{}
+ }
+ }
+ }
+ case isPointer: // E.g., *float32
+ mfi.merge = func(dst, src pointer) {
+ sfpp := src.toFloat32Ptr()
+ if *sfpp != nil {
+ dfpp := dst.toFloat32Ptr()
+ if *dfpp == nil {
+ *dfpp = Float32(**sfpp)
+ } else {
+ **dfpp = **sfpp
+ }
+ }
+ }
+ default: // E.g., float32
+ mfi.merge = func(dst, src pointer) {
+ if v := *src.toFloat32(); v != 0 {
+ *dst.toFloat32() = v
+ }
+ }
+ }
+ case reflect.Float64:
+ switch {
+ case isSlice: // E.g., []float64
+ mfi.merge = func(dst, src pointer) {
+ sfsp := src.toFloat64Slice()
+ if *sfsp != nil {
+ dfsp := dst.toFloat64Slice()
+ *dfsp = append(*dfsp, *sfsp...)
+ if *dfsp == nil {
+ *dfsp = []float64{}
+ }
+ }
+ }
+ case isPointer: // E.g., *float64
+ mfi.merge = func(dst, src pointer) {
+ sfpp := src.toFloat64Ptr()
+ if *sfpp != nil {
+ dfpp := dst.toFloat64Ptr()
+ if *dfpp == nil {
+ *dfpp = Float64(**sfpp)
+ } else {
+ **dfpp = **sfpp
+ }
+ }
+ }
+ default: // E.g., float64
+ mfi.merge = func(dst, src pointer) {
+ if v := *src.toFloat64(); v != 0 {
+ *dst.toFloat64() = v
+ }
+ }
+ }
+ case reflect.Bool:
+ switch {
+ case isSlice: // E.g., []bool
+ mfi.merge = func(dst, src pointer) {
+ sfsp := src.toBoolSlice()
+ if *sfsp != nil {
+ dfsp := dst.toBoolSlice()
+ *dfsp = append(*dfsp, *sfsp...)
+ if *dfsp == nil {
+ *dfsp = []bool{}
+ }
+ }
+ }
+ case isPointer: // E.g., *bool
+ mfi.merge = func(dst, src pointer) {
+ sfpp := src.toBoolPtr()
+ if *sfpp != nil {
+ dfpp := dst.toBoolPtr()
+ if *dfpp == nil {
+ *dfpp = Bool(**sfpp)
+ } else {
+ **dfpp = **sfpp
+ }
+ }
+ }
+ default: // E.g., bool
+ mfi.merge = func(dst, src pointer) {
+ if v := *src.toBool(); v {
+ *dst.toBool() = v
+ }
+ }
+ }
+ case reflect.String:
+ switch {
+ case isSlice: // E.g., []string
+ mfi.merge = func(dst, src pointer) {
+ sfsp := src.toStringSlice()
+ if *sfsp != nil {
+ dfsp := dst.toStringSlice()
+ *dfsp = append(*dfsp, *sfsp...)
+ if *dfsp == nil {
+ *dfsp = []string{}
+ }
+ }
+ }
+ case isPointer: // E.g., *string
+ mfi.merge = func(dst, src pointer) {
+ sfpp := src.toStringPtr()
+ if *sfpp != nil {
+ dfpp := dst.toStringPtr()
+ if *dfpp == nil {
+ *dfpp = String(**sfpp)
+ } else {
+ **dfpp = **sfpp
+ }
+ }
+ }
+ default: // E.g., string
+ mfi.merge = func(dst, src pointer) {
+ if v := *src.toString(); v != "" {
+ *dst.toString() = v
+ }
+ }
+ }
+ case reflect.Slice:
+ isProto3 := props.Prop[i].proto3
+ switch {
+ case isPointer:
+ panic("bad pointer in byte slice case in " + tf.Name())
+ case tf.Elem().Kind() != reflect.Uint8:
+ panic("bad element kind in byte slice case in " + tf.Name())
+ case isSlice: // E.g., [][]byte
+ mfi.merge = func(dst, src pointer) {
+ sbsp := src.toBytesSlice()
+ if *sbsp != nil {
+ dbsp := dst.toBytesSlice()
+ for _, sb := range *sbsp {
+ if sb == nil {
+ *dbsp = append(*dbsp, nil)
+ } else {
+ *dbsp = append(*dbsp, append([]byte{}, sb...))
+ }
+ }
+ if *dbsp == nil {
+ *dbsp = [][]byte{}
+ }
+ }
+ }
+ default: // E.g., []byte
+ mfi.merge = func(dst, src pointer) {
+ sbp := src.toBytes()
+ if *sbp != nil {
+ dbp := dst.toBytes()
+ if !isProto3 || len(*sbp) > 0 {
+ *dbp = append([]byte{}, *sbp...)
+ }
+ }
+ }
+ }
+ case reflect.Struct:
+ switch {
+ case !isPointer:
+ panic(fmt.Sprintf("message field %s without pointer", tf))
+ case isSlice: // E.g., []*pb.T
+ mi := getMergeInfo(tf)
+ mfi.merge = func(dst, src pointer) {
+ sps := src.getPointerSlice()
+ if sps != nil {
+ dps := dst.getPointerSlice()
+ for _, sp := range sps {
+ var dp pointer
+ if !sp.isNil() {
+ dp = valToPointer(reflect.New(tf))
+ mi.merge(dp, sp)
+ }
+ dps = append(dps, dp)
+ }
+ if dps == nil {
+ dps = []pointer{}
+ }
+ dst.setPointerSlice(dps)
+ }
+ }
+ default: // E.g., *pb.T
+ mi := getMergeInfo(tf)
+ mfi.merge = func(dst, src pointer) {
+ sp := src.getPointer()
+ if !sp.isNil() {
+ dp := dst.getPointer()
+ if dp.isNil() {
+ dp = valToPointer(reflect.New(tf))
+ dst.setPointer(dp)
+ }
+ mi.merge(dp, sp)
+ }
+ }
+ }
+ case reflect.Map:
+ switch {
+ case isPointer || isSlice:
+ panic("bad pointer or slice in map case in " + tf.Name())
+ default: // E.g., map[K]V
+ mfi.merge = func(dst, src pointer) {
+ sm := src.asPointerTo(tf).Elem()
+ if sm.Len() == 0 {
+ return
+ }
+ dm := dst.asPointerTo(tf).Elem()
+ if dm.IsNil() {
+ dm.Set(reflect.MakeMap(tf))
+ }
+
+ switch tf.Elem().Kind() {
+ case reflect.Ptr: // Proto struct (e.g., *T)
+ for _, key := range sm.MapKeys() {
+ val := sm.MapIndex(key)
+ val = reflect.ValueOf(Clone(val.Interface().(Message)))
+ dm.SetMapIndex(key, val)
+ }
+ case reflect.Slice: // E.g. Bytes type (e.g., []byte)
+ for _, key := range sm.MapKeys() {
+ val := sm.MapIndex(key)
+ val = reflect.ValueOf(append([]byte{}, val.Bytes()...))
+ dm.SetMapIndex(key, val)
+ }
+ default: // Basic type (e.g., string)
+ for _, key := range sm.MapKeys() {
+ val := sm.MapIndex(key)
+ dm.SetMapIndex(key, val)
+ }
+ }
+ }
+ }
+ case reflect.Interface:
+ // Must be oneof field.
+ switch {
+ case isPointer || isSlice:
+ panic("bad pointer or slice in interface case in " + tf.Name())
+ default: // E.g., interface{}
+ // TODO: Make this faster?
+ mfi.merge = func(dst, src pointer) {
+ su := src.asPointerTo(tf).Elem()
+ if !su.IsNil() {
+ du := dst.asPointerTo(tf).Elem()
+ typ := su.Elem().Type()
+ if du.IsNil() || du.Elem().Type() != typ {
+ du.Set(reflect.New(typ.Elem())) // Initialize interface if empty
+ }
+ sv := su.Elem().Elem().Field(0)
+ if sv.Kind() == reflect.Ptr && sv.IsNil() {
+ return
+ }
+ dv := du.Elem().Elem().Field(0)
+ if dv.Kind() == reflect.Ptr && dv.IsNil() {
+ dv.Set(reflect.New(sv.Type().Elem())) // Initialize proto message if empty
+ }
+ switch sv.Type().Kind() {
+ case reflect.Ptr: // Proto struct (e.g., *T)
+ Merge(dv.Interface().(Message), sv.Interface().(Message))
+ case reflect.Slice: // E.g. Bytes type (e.g., []byte)
+ dv.Set(reflect.ValueOf(append([]byte{}, sv.Bytes()...)))
+ default: // Basic type (e.g., string)
+ dv.Set(sv)
+ }
+ }
+ }
+ }
+ default:
+ panic(fmt.Sprintf("merger not found for type:%s", tf))
+ }
+ mi.fields = append(mi.fields, mfi)
+ }
+
+ mi.unrecognized = invalidField
+ if f, ok := t.FieldByName("XXX_unrecognized"); ok {
+ if f.Type != reflect.TypeOf([]byte{}) {
+ panic("expected XXX_unrecognized to be of type []byte")
+ }
+ mi.unrecognized = toField(&f)
+ }
+
+ atomic.StoreInt32(&mi.initialized, 1)
+}
diff --git a/vendor/github.com/golang/protobuf/proto/table_unmarshal.go b/vendor/github.com/golang/protobuf/proto/table_unmarshal.go
new file mode 100644
index 000000000..acee2fc52
--- /dev/null
+++ b/vendor/github.com/golang/protobuf/proto/table_unmarshal.go
@@ -0,0 +1,2053 @@
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2016 The Go Authors. All rights reserved.
+// https://github.com/golang/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package proto
+
+import (
+ "errors"
+ "fmt"
+ "io"
+ "math"
+ "reflect"
+ "strconv"
+ "strings"
+ "sync"
+ "sync/atomic"
+ "unicode/utf8"
+)
+
+// Unmarshal is the entry point from the generated .pb.go files.
+// This function is not intended to be used by non-generated code.
+// This function is not subject to any compatibility guarantee.
+// msg contains a pointer to a protocol buffer struct.
+// b is the data to be unmarshaled into the protocol buffer.
+// a is a pointer to a place to store cached unmarshal information.
+func (a *InternalMessageInfo) Unmarshal(msg Message, b []byte) error {
+ // Load the unmarshal information for this message type.
+ // The atomic load ensures memory consistency.
+ u := atomicLoadUnmarshalInfo(&a.unmarshal)
+ if u == nil {
+ // Slow path: find unmarshal info for msg, update a with it.
+ u = getUnmarshalInfo(reflect.TypeOf(msg).Elem())
+ atomicStoreUnmarshalInfo(&a.unmarshal, u)
+ }
+ // Then do the unmarshaling.
+ err := u.unmarshal(toPointer(&msg), b)
+ return err
+}
+
+type unmarshalInfo struct {
+ typ reflect.Type // type of the protobuf struct
+
+ // 0 = only typ field is initialized
+ // 1 = completely initialized
+ initialized int32
+ lock sync.Mutex // prevents double initialization
+ dense []unmarshalFieldInfo // fields indexed by tag #
+ sparse map[uint64]unmarshalFieldInfo // fields indexed by tag #
+ reqFields []string // names of required fields
+ reqMask uint64 // 1<<len(reqFields)-1
+ unrecognized field // offset of []byte to put unrecognized data (or invalidField if we should throw it away)
+ extensions field // offset of extensions field (of type proto.XXX_InternalExtensions), or invalidField if it does not exist
+ oldExtensions field // offset of old-form extensions field (of type map[int]Extension)
+ extensionRanges []ExtensionRange // if non-nil, implies extensions field is valid
+ isMessageSet bool // if true, implies extensions field is valid
+}
+
+// An unmarshaler takes a stream of bytes and a pointer to a field of a message.
+// It decodes the field, stores it at f, and returns the unused bytes.
+// w is the wire encoding.
+// b is the data after the tag and wire encoding have been read.
+type unmarshaler func(b []byte, f pointer, w int) ([]byte, error)
+
+type unmarshalFieldInfo struct {
+ // location of the field in the proto message structure.
+ field field
+
+ // function to unmarshal the data for the field.
+ unmarshal unmarshaler
+
+ // if a required field, contains a single set bit at this field's index in the required field list.
+ reqMask uint64
+
+ name string // name of the field, for error reporting
+}
+
+var (
+ unmarshalInfoMap = map[reflect.Type]*unmarshalInfo{}
+ unmarshalInfoLock sync.Mutex
+)
+
+// getUnmarshalInfo returns the data structure which can be
+// subsequently used to unmarshal a message of the given type.
+// t is the type of the message (note: not pointer to message).
+func getUnmarshalInfo(t reflect.Type) *unmarshalInfo {
+ // It would be correct to return a new unmarshalInfo
+ // unconditionally. We would end up allocating one
+ // per occurrence of that type as a message or submessage.
+ // We use a cache here just to reduce memory usage.
+ unmarshalInfoLock.Lock()
+ defer unmarshalInfoLock.Unlock()
+ u := unmarshalInfoMap[t]
+ if u == nil {
+ u = &unmarshalInfo{typ: t}
+ // Note: we just set the type here. The rest of the fields
+ // will be initialized on first use.
+ unmarshalInfoMap[t] = u
+ }
+ return u
+}
+
+// unmarshal does the main work of unmarshaling a message.
+// u provides type information used to unmarshal the message.
+// m is a pointer to a protocol buffer message.
+// b is a byte stream to unmarshal into m.
+// This is top routine used when recursively unmarshaling submessages.
+func (u *unmarshalInfo) unmarshal(m pointer, b []byte) error {
+ if atomic.LoadInt32(&u.initialized) == 0 {
+ u.computeUnmarshalInfo()
+ }
+ if u.isMessageSet {
+ return unmarshalMessageSet(b, m.offset(u.extensions).toExtensions())
+ }
+ var reqMask uint64 // bitmask of required fields we've seen.
+ var errLater error
+ for len(b) > 0 {
+ // Read tag and wire type.
+ // Special case 1 and 2 byte varints.
+ var x uint64
+ if b[0] < 128 {
+ x = uint64(b[0])
+ b = b[1:]
+ } else if len(b) >= 2 && b[1] < 128 {
+ x = uint64(b[0]&0x7f) + uint64(b[1])<<7
+ b = b[2:]
+ } else {
+ var n int
+ x, n = decodeVarint(b)
+ if n == 0 {
+ return io.ErrUnexpectedEOF
+ }
+ b = b[n:]
+ }
+ tag := x >> 3
+ wire := int(x) & 7
+
+ // Dispatch on the tag to one of the unmarshal* functions below.
+ var f unmarshalFieldInfo
+ if tag < uint64(len(u.dense)) {
+ f = u.dense[tag]
+ } else {
+ f = u.sparse[tag]
+ }
+ if fn := f.unmarshal; fn != nil {
+ var err error
+ b, err = fn(b, m.offset(f.field), wire)
+ if err == nil {
+ reqMask |= f.reqMask
+ continue
+ }
+ if r, ok := err.(*RequiredNotSetError); ok {
+ // Remember this error, but keep parsing. We need to produce
+ // a full parse even if a required field is missing.
+ if errLater == nil {
+ errLater = r
+ }
+ reqMask |= f.reqMask
+ continue
+ }
+ if err != errInternalBadWireType {
+ if err == errInvalidUTF8 {
+ if errLater == nil {
+ fullName := revProtoTypes[reflect.PtrTo(u.typ)] + "." + f.name
+ errLater = &invalidUTF8Error{fullName}
+ }
+ continue
+ }
+ return err
+ }
+ // Fragments with bad wire type are treated as unknown fields.
+ }
+
+ // Unknown tag.
+ if !u.unrecognized.IsValid() {
+ // Don't keep unrecognized data; just skip it.
+ var err error
+ b, err = skipField(b, wire)
+ if err != nil {
+ return err
+ }
+ continue
+ }
+ // Keep unrecognized data around.
+ // maybe in extensions, maybe in the unrecognized field.
+ z := m.offset(u.unrecognized).toBytes()
+ var emap map[int32]Extension
+ var e Extension
+ for _, r := range u.extensionRanges {
+ if uint64(r.Start) <= tag && tag <= uint64(r.End) {
+ if u.extensions.IsValid() {
+ mp := m.offset(u.extensions).toExtensions()
+ emap = mp.extensionsWrite()
+ e = emap[int32(tag)]
+ z = &e.enc
+ break
+ }
+ if u.oldExtensions.IsValid() {
+ p := m.offset(u.oldExtensions).toOldExtensions()
+ emap = *p
+ if emap == nil {
+ emap = map[int32]Extension{}
+ *p = emap
+ }
+ e = emap[int32(tag)]
+ z = &e.enc
+ break
+ }
+ panic("no extensions field available")
+ }
+ }
+
+ // Use wire type to skip data.
+ var err error
+ b0 := b
+ b, err = skipField(b, wire)
+ if err != nil {
+ return err
+ }
+ *z = encodeVarint(*z, tag<<3|uint64(wire))
+ *z = append(*z, b0[:len(b0)-len(b)]...)
+
+ if emap != nil {
+ emap[int32(tag)] = e
+ }
+ }
+ if reqMask != u.reqMask && errLater == nil {
+ // A required field of this message is missing.
+ for _, n := range u.reqFields {
+ if reqMask&1 == 0 {
+ errLater = &RequiredNotSetError{n}
+ }
+ reqMask >>= 1
+ }
+ }
+ return errLater
+}
+
+// computeUnmarshalInfo fills in u with information for use
+// in unmarshaling protocol buffers of type u.typ.
+func (u *unmarshalInfo) computeUnmarshalInfo() {
+ u.lock.Lock()
+ defer u.lock.Unlock()
+ if u.initialized != 0 {
+ return
+ }
+ t := u.typ
+ n := t.NumField()
+
+ // Set up the "not found" value for the unrecognized byte buffer.
+ // This is the default for proto3.
+ u.unrecognized = invalidField
+ u.extensions = invalidField
+ u.oldExtensions = invalidField
+
+ // List of the generated type and offset for each oneof field.
+ type oneofField struct {
+ ityp reflect.Type // interface type of oneof field
+ field field // offset in containing message
+ }
+ var oneofFields []oneofField
+
+ for i := 0; i < n; i++ {
+ f := t.Field(i)
+ if f.Name == "XXX_unrecognized" {
+ // The byte slice used to hold unrecognized input is special.
+ if f.Type != reflect.TypeOf(([]byte)(nil)) {
+ panic("bad type for XXX_unrecognized field: " + f.Type.Name())
+ }
+ u.unrecognized = toField(&f)
+ continue
+ }
+ if f.Name == "XXX_InternalExtensions" {
+ // Ditto here.
+ if f.Type != reflect.TypeOf(XXX_InternalExtensions{}) {
+ panic("bad type for XXX_InternalExtensions field: " + f.Type.Name())
+ }
+ u.extensions = toField(&f)
+ if f.Tag.Get("protobuf_messageset") == "1" {
+ u.isMessageSet = true
+ }
+ continue
+ }
+ if f.Name == "XXX_extensions" {
+ // An older form of the extensions field.
+ if f.Type != reflect.TypeOf((map[int32]Extension)(nil)) {
+ panic("bad type for XXX_extensions field: " + f.Type.Name())
+ }
+ u.oldExtensions = toField(&f)
+ continue
+ }
+ if f.Name == "XXX_NoUnkeyedLiteral" || f.Name == "XXX_sizecache" {
+ continue
+ }
+
+ oneof := f.Tag.Get("protobuf_oneof")
+ if oneof != "" {
+ oneofFields = append(oneofFields, oneofField{f.Type, toField(&f)})
+ // The rest of oneof processing happens below.
+ continue
+ }
+
+ tags := f.Tag.Get("protobuf")
+ tagArray := strings.Split(tags, ",")
+ if len(tagArray) < 2 {
+ panic("protobuf tag not enough fields in " + t.Name() + "." + f.Name + ": " + tags)
+ }
+ tag, err := strconv.Atoi(tagArray[1])
+ if err != nil {
+ panic("protobuf tag field not an integer: " + tagArray[1])
+ }
+
+ name := ""
+ for _, tag := range tagArray[3:] {
+ if strings.HasPrefix(tag, "name=") {
+ name = tag[5:]
+ }
+ }
+
+ // Extract unmarshaling function from the field (its type and tags).
+ unmarshal := fieldUnmarshaler(&f)
+
+ // Required field?
+ var reqMask uint64
+ if tagArray[2] == "req" {
+ bit := len(u.reqFields)
+ u.reqFields = append(u.reqFields, name)
+ reqMask = uint64(1) << uint(bit)
+ // TODO: if we have more than 64 required fields, we end up
+ // not verifying that all required fields are present.
+ // Fix this, perhaps using a count of required fields?
+ }
+
+ // Store the info in the correct slot in the message.
+ u.setTag(tag, toField(&f), unmarshal, reqMask, name)
+ }
+
+ // Find any types associated with oneof fields.
+ var oneofImplementers []interface{}
+ switch m := reflect.Zero(reflect.PtrTo(t)).Interface().(type) {
+ case oneofFuncsIface:
+ _, _, _, oneofImplementers = m.XXX_OneofFuncs()
+ case oneofWrappersIface:
+ oneofImplementers = m.XXX_OneofWrappers()
+ }
+ for _, v := range oneofImplementers {
+ tptr := reflect.TypeOf(v) // *Msg_X
+ typ := tptr.Elem() // Msg_X
+
+ f := typ.Field(0) // oneof implementers have one field
+ baseUnmarshal := fieldUnmarshaler(&f)
+ tags := strings.Split(f.Tag.Get("protobuf"), ",")
+ fieldNum, err := strconv.Atoi(tags[1])
+ if err != nil {
+ panic("protobuf tag field not an integer: " + tags[1])
+ }
+ var name string
+ for _, tag := range tags {
+ if strings.HasPrefix(tag, "name=") {
+ name = strings.TrimPrefix(tag, "name=")
+ break
+ }
+ }
+
+ // Find the oneof field that this struct implements.
+ // Might take O(n^2) to process all of the oneofs, but who cares.
+ for _, of := range oneofFields {
+ if tptr.Implements(of.ityp) {
+ // We have found the corresponding interface for this struct.
+ // That lets us know where this struct should be stored
+ // when we encounter it during unmarshaling.
+ unmarshal := makeUnmarshalOneof(typ, of.ityp, baseUnmarshal)
+ u.setTag(fieldNum, of.field, unmarshal, 0, name)
+ }
+ }
+
+ }
+
+ // Get extension ranges, if any.
+ fn := reflect.Zero(reflect.PtrTo(t)).MethodByName("ExtensionRangeArray")
+ if fn.IsValid() {
+ if !u.extensions.IsValid() && !u.oldExtensions.IsValid() {
+ panic("a message with extensions, but no extensions field in " + t.Name())
+ }
+ u.extensionRanges = fn.Call(nil)[0].Interface().([]ExtensionRange)
+ }
+
+ // Explicitly disallow tag 0. This will ensure we flag an error
+ // when decoding a buffer of all zeros. Without this code, we
+ // would decode and skip an all-zero buffer of even length.
+ // [0 0] is [tag=0/wiretype=varint varint-encoded-0].
+ u.setTag(0, zeroField, func(b []byte, f pointer, w int) ([]byte, error) {
+ return nil, fmt.Errorf("proto: %s: illegal tag 0 (wire type %d)", t, w)
+ }, 0, "")
+
+ // Set mask for required field check.
+ u.reqMask = uint64(1)<<uint(len(u.reqFields)) - 1
+
+ atomic.StoreInt32(&u.initialized, 1)
+}
+
+// setTag stores the unmarshal information for the given tag.
+// tag = tag # for field
+// field/unmarshal = unmarshal info for that field.
+// reqMask = if required, bitmask for field position in required field list. 0 otherwise.
+// name = short name of the field.
+func (u *unmarshalInfo) setTag(tag int, field field, unmarshal unmarshaler, reqMask uint64, name string) {
+ i := unmarshalFieldInfo{field: field, unmarshal: unmarshal, reqMask: reqMask, name: name}
+ n := u.typ.NumField()
+ if tag >= 0 && (tag < 16 || tag < 2*n) { // TODO: what are the right numbers here?
+ for len(u.dense) <= tag {
+ u.dense = append(u.dense, unmarshalFieldInfo{})
+ }
+ u.dense[tag] = i
+ return
+ }
+ if u.sparse == nil {
+ u.sparse = map[uint64]unmarshalFieldInfo{}
+ }
+ u.sparse[uint64(tag)] = i
+}
+
+// fieldUnmarshaler returns an unmarshaler for the given field.
+func fieldUnmarshaler(f *reflect.StructField) unmarshaler {
+ if f.Type.Kind() == reflect.Map {
+ return makeUnmarshalMap(f)
+ }
+ return typeUnmarshaler(f.Type, f.Tag.Get("protobuf"))
+}
+
+// typeUnmarshaler returns an unmarshaler for the given field type / field tag pair.
+func typeUnmarshaler(t reflect.Type, tags string) unmarshaler {
+ tagArray := strings.Split(tags, ",")
+ encoding := tagArray[0]
+ name := "unknown"
+ proto3 := false
+ validateUTF8 := true
+ for _, tag := range tagArray[3:] {
+ if strings.HasPrefix(tag, "name=") {
+ name = tag[5:]
+ }
+ if tag == "proto3" {
+ proto3 = true
+ }
+ }
+ validateUTF8 = validateUTF8 && proto3
+
+ // Figure out packaging (pointer, slice, or both)
+ slice := false
+ pointer := false
+ if t.Kind() == reflect.Slice && t.Elem().Kind() != reflect.Uint8 {
+ slice = true
+ t = t.Elem()
+ }
+ if t.Kind() == reflect.Ptr {
+ pointer = true
+ t = t.Elem()
+ }
+
+ // We'll never have both pointer and slice for basic types.
+ if pointer && slice && t.Kind() != reflect.Struct {
+ panic("both pointer and slice for basic type in " + t.Name())
+ }
+
+ switch t.Kind() {
+ case reflect.Bool:
+ if pointer {
+ return unmarshalBoolPtr
+ }
+ if slice {
+ return unmarshalBoolSlice
+ }
+ return unmarshalBoolValue
+ case reflect.Int32:
+ switch encoding {
+ case "fixed32":
+ if pointer {
+ return unmarshalFixedS32Ptr
+ }
+ if slice {
+ return unmarshalFixedS32Slice
+ }
+ return unmarshalFixedS32Value
+ case "varint":
+ // this could be int32 or enum
+ if pointer {
+ return unmarshalInt32Ptr
+ }
+ if slice {
+ return unmarshalInt32Slice
+ }
+ return unmarshalInt32Value
+ case "zigzag32":
+ if pointer {
+ return unmarshalSint32Ptr
+ }
+ if slice {
+ return unmarshalSint32Slice
+ }
+ return unmarshalSint32Value
+ }
+ case reflect.Int64:
+ switch encoding {
+ case "fixed64":
+ if pointer {
+ return unmarshalFixedS64Ptr
+ }
+ if slice {
+ return unmarshalFixedS64Slice
+ }
+ return unmarshalFixedS64Value
+ case "varint":
+ if pointer {
+ return unmarshalInt64Ptr
+ }
+ if slice {
+ return unmarshalInt64Slice
+ }
+ return unmarshalInt64Value
+ case "zigzag64":
+ if pointer {
+ return unmarshalSint64Ptr
+ }
+ if slice {
+ return unmarshalSint64Slice
+ }
+ return unmarshalSint64Value
+ }
+ case reflect.Uint32:
+ switch encoding {
+ case "fixed32":
+ if pointer {
+ return unmarshalFixed32Ptr
+ }
+ if slice {
+ return unmarshalFixed32Slice
+ }
+ return unmarshalFixed32Value
+ case "varint":
+ if pointer {
+ return unmarshalUint32Ptr
+ }
+ if slice {
+ return unmarshalUint32Slice
+ }
+ return unmarshalUint32Value
+ }
+ case reflect.Uint64:
+ switch encoding {
+ case "fixed64":
+ if pointer {
+ return unmarshalFixed64Ptr
+ }
+ if slice {
+ return unmarshalFixed64Slice
+ }
+ return unmarshalFixed64Value
+ case "varint":
+ if pointer {
+ return unmarshalUint64Ptr
+ }
+ if slice {
+ return unmarshalUint64Slice
+ }
+ return unmarshalUint64Value
+ }
+ case reflect.Float32:
+ if pointer {
+ return unmarshalFloat32Ptr
+ }
+ if slice {
+ return unmarshalFloat32Slice
+ }
+ return unmarshalFloat32Value
+ case reflect.Float64:
+ if pointer {
+ return unmarshalFloat64Ptr
+ }
+ if slice {
+ return unmarshalFloat64Slice
+ }
+ return unmarshalFloat64Value
+ case reflect.Map:
+ panic("map type in typeUnmarshaler in " + t.Name())
+ case reflect.Slice:
+ if pointer {
+ panic("bad pointer in slice case in " + t.Name())
+ }
+ if slice {
+ return unmarshalBytesSlice
+ }
+ return unmarshalBytesValue
+ case reflect.String:
+ if validateUTF8 {
+ if pointer {
+ return unmarshalUTF8StringPtr
+ }
+ if slice {
+ return unmarshalUTF8StringSlice
+ }
+ return unmarshalUTF8StringValue
+ }
+ if pointer {
+ return unmarshalStringPtr
+ }
+ if slice {
+ return unmarshalStringSlice
+ }
+ return unmarshalStringValue
+ case reflect.Struct:
+ // message or group field
+ if !pointer {
+ panic(fmt.Sprintf("message/group field %s:%s without pointer", t, encoding))
+ }
+ switch encoding {
+ case "bytes":
+ if slice {
+ return makeUnmarshalMessageSlicePtr(getUnmarshalInfo(t), name)
+ }
+ return makeUnmarshalMessagePtr(getUnmarshalInfo(t), name)
+ case "group":
+ if slice {
+ return makeUnmarshalGroupSlicePtr(getUnmarshalInfo(t), name)
+ }
+ return makeUnmarshalGroupPtr(getUnmarshalInfo(t), name)
+ }
+ }
+ panic(fmt.Sprintf("unmarshaler not found type:%s encoding:%s", t, encoding))
+}
+
+// Below are all the unmarshalers for individual fields of various types.
+
+func unmarshalInt64Value(b []byte, f pointer, w int) ([]byte, error) {
+ if w != WireVarint {
+ return b, errInternalBadWireType
+ }
+ x, n := decodeVarint(b)
+ if n == 0 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ b = b[n:]
+ v := int64(x)
+ *f.toInt64() = v
+ return b, nil
+}
+
+func unmarshalInt64Ptr(b []byte, f pointer, w int) ([]byte, error) {
+ if w != WireVarint {
+ return b, errInternalBadWireType
+ }
+ x, n := decodeVarint(b)
+ if n == 0 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ b = b[n:]
+ v := int64(x)
+ *f.toInt64Ptr() = &v
+ return b, nil
+}
+
+func unmarshalInt64Slice(b []byte, f pointer, w int) ([]byte, error) {
+ if w == WireBytes { // packed
+ x, n := decodeVarint(b)
+ if n == 0 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ b = b[n:]
+ if x > uint64(len(b)) {
+ return nil, io.ErrUnexpectedEOF
+ }
+ res := b[x:]
+ b = b[:x]
+ for len(b) > 0 {
+ x, n = decodeVarint(b)
+ if n == 0 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ b = b[n:]
+ v := int64(x)
+ s := f.toInt64Slice()
+ *s = append(*s, v)
+ }
+ return res, nil
+ }
+ if w != WireVarint {
+ return b, errInternalBadWireType
+ }
+ x, n := decodeVarint(b)
+ if n == 0 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ b = b[n:]
+ v := int64(x)
+ s := f.toInt64Slice()
+ *s = append(*s, v)
+ return b, nil
+}
+
+func unmarshalSint64Value(b []byte, f pointer, w int) ([]byte, error) {
+ if w != WireVarint {
+ return b, errInternalBadWireType
+ }
+ x, n := decodeVarint(b)
+ if n == 0 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ b = b[n:]
+ v := int64(x>>1) ^ int64(x)<<63>>63
+ *f.toInt64() = v
+ return b, nil
+}
+
+func unmarshalSint64Ptr(b []byte, f pointer, w int) ([]byte, error) {
+ if w != WireVarint {
+ return b, errInternalBadWireType
+ }
+ x, n := decodeVarint(b)
+ if n == 0 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ b = b[n:]
+ v := int64(x>>1) ^ int64(x)<<63>>63
+ *f.toInt64Ptr() = &v
+ return b, nil
+}
+
+func unmarshalSint64Slice(b []byte, f pointer, w int) ([]byte, error) {
+ if w == WireBytes { // packed
+ x, n := decodeVarint(b)
+ if n == 0 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ b = b[n:]
+ if x > uint64(len(b)) {
+ return nil, io.ErrUnexpectedEOF
+ }
+ res := b[x:]
+ b = b[:x]
+ for len(b) > 0 {
+ x, n = decodeVarint(b)
+ if n == 0 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ b = b[n:]
+ v := int64(x>>1) ^ int64(x)<<63>>63
+ s := f.toInt64Slice()
+ *s = append(*s, v)
+ }
+ return res, nil
+ }
+ if w != WireVarint {
+ return b, errInternalBadWireType
+ }
+ x, n := decodeVarint(b)
+ if n == 0 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ b = b[n:]
+ v := int64(x>>1) ^ int64(x)<<63>>63
+ s := f.toInt64Slice()
+ *s = append(*s, v)
+ return b, nil
+}
+
+func unmarshalUint64Value(b []byte, f pointer, w int) ([]byte, error) {
+ if w != WireVarint {
+ return b, errInternalBadWireType
+ }
+ x, n := decodeVarint(b)
+ if n == 0 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ b = b[n:]
+ v := uint64(x)
+ *f.toUint64() = v
+ return b, nil
+}
+
+func unmarshalUint64Ptr(b []byte, f pointer, w int) ([]byte, error) {
+ if w != WireVarint {
+ return b, errInternalBadWireType
+ }
+ x, n := decodeVarint(b)
+ if n == 0 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ b = b[n:]
+ v := uint64(x)
+ *f.toUint64Ptr() = &v
+ return b, nil
+}
+
+func unmarshalUint64Slice(b []byte, f pointer, w int) ([]byte, error) {
+ if w == WireBytes { // packed
+ x, n := decodeVarint(b)
+ if n == 0 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ b = b[n:]
+ if x > uint64(len(b)) {
+ return nil, io.ErrUnexpectedEOF
+ }
+ res := b[x:]
+ b = b[:x]
+ for len(b) > 0 {
+ x, n = decodeVarint(b)
+ if n == 0 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ b = b[n:]
+ v := uint64(x)
+ s := f.toUint64Slice()
+ *s = append(*s, v)
+ }
+ return res, nil
+ }
+ if w != WireVarint {
+ return b, errInternalBadWireType
+ }
+ x, n := decodeVarint(b)
+ if n == 0 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ b = b[n:]
+ v := uint64(x)
+ s := f.toUint64Slice()
+ *s = append(*s, v)
+ return b, nil
+}
+
+func unmarshalInt32Value(b []byte, f pointer, w int) ([]byte, error) {
+ if w != WireVarint {
+ return b, errInternalBadWireType
+ }
+ x, n := decodeVarint(b)
+ if n == 0 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ b = b[n:]
+ v := int32(x)
+ *f.toInt32() = v
+ return b, nil
+}
+
+func unmarshalInt32Ptr(b []byte, f pointer, w int) ([]byte, error) {
+ if w != WireVarint {
+ return b, errInternalBadWireType
+ }
+ x, n := decodeVarint(b)
+ if n == 0 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ b = b[n:]
+ v := int32(x)
+ f.setInt32Ptr(v)
+ return b, nil
+}
+
+func unmarshalInt32Slice(b []byte, f pointer, w int) ([]byte, error) {
+ if w == WireBytes { // packed
+ x, n := decodeVarint(b)
+ if n == 0 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ b = b[n:]
+ if x > uint64(len(b)) {
+ return nil, io.ErrUnexpectedEOF
+ }
+ res := b[x:]
+ b = b[:x]
+ for len(b) > 0 {
+ x, n = decodeVarint(b)
+ if n == 0 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ b = b[n:]
+ v := int32(x)
+ f.appendInt32Slice(v)
+ }
+ return res, nil
+ }
+ if w != WireVarint {
+ return b, errInternalBadWireType
+ }
+ x, n := decodeVarint(b)
+ if n == 0 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ b = b[n:]
+ v := int32(x)
+ f.appendInt32Slice(v)
+ return b, nil
+}
+
+func unmarshalSint32Value(b []byte, f pointer, w int) ([]byte, error) {
+ if w != WireVarint {
+ return b, errInternalBadWireType
+ }
+ x, n := decodeVarint(b)
+ if n == 0 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ b = b[n:]
+ v := int32(x>>1) ^ int32(x)<<31>>31
+ *f.toInt32() = v
+ return b, nil
+}
+
+func unmarshalSint32Ptr(b []byte, f pointer, w int) ([]byte, error) {
+ if w != WireVarint {
+ return b, errInternalBadWireType
+ }
+ x, n := decodeVarint(b)
+ if n == 0 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ b = b[n:]
+ v := int32(x>>1) ^ int32(x)<<31>>31
+ f.setInt32Ptr(v)
+ return b, nil
+}
+
+func unmarshalSint32Slice(b []byte, f pointer, w int) ([]byte, error) {
+ if w == WireBytes { // packed
+ x, n := decodeVarint(b)
+ if n == 0 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ b = b[n:]
+ if x > uint64(len(b)) {
+ return nil, io.ErrUnexpectedEOF
+ }
+ res := b[x:]
+ b = b[:x]
+ for len(b) > 0 {
+ x, n = decodeVarint(b)
+ if n == 0 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ b = b[n:]
+ v := int32(x>>1) ^ int32(x)<<31>>31
+ f.appendInt32Slice(v)
+ }
+ return res, nil
+ }
+ if w != WireVarint {
+ return b, errInternalBadWireType
+ }
+ x, n := decodeVarint(b)
+ if n == 0 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ b = b[n:]
+ v := int32(x>>1) ^ int32(x)<<31>>31
+ f.appendInt32Slice(v)
+ return b, nil
+}
+
+func unmarshalUint32Value(b []byte, f pointer, w int) ([]byte, error) {
+ if w != WireVarint {
+ return b, errInternalBadWireType
+ }
+ x, n := decodeVarint(b)
+ if n == 0 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ b = b[n:]
+ v := uint32(x)
+ *f.toUint32() = v
+ return b, nil
+}
+
+func unmarshalUint32Ptr(b []byte, f pointer, w int) ([]byte, error) {
+ if w != WireVarint {
+ return b, errInternalBadWireType
+ }
+ x, n := decodeVarint(b)
+ if n == 0 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ b = b[n:]
+ v := uint32(x)
+ *f.toUint32Ptr() = &v
+ return b, nil
+}
+
+func unmarshalUint32Slice(b []byte, f pointer, w int) ([]byte, error) {
+ if w == WireBytes { // packed
+ x, n := decodeVarint(b)
+ if n == 0 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ b = b[n:]
+ if x > uint64(len(b)) {
+ return nil, io.ErrUnexpectedEOF
+ }
+ res := b[x:]
+ b = b[:x]
+ for len(b) > 0 {
+ x, n = decodeVarint(b)
+ if n == 0 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ b = b[n:]
+ v := uint32(x)
+ s := f.toUint32Slice()
+ *s = append(*s, v)
+ }
+ return res, nil
+ }
+ if w != WireVarint {
+ return b, errInternalBadWireType
+ }
+ x, n := decodeVarint(b)
+ if n == 0 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ b = b[n:]
+ v := uint32(x)
+ s := f.toUint32Slice()
+ *s = append(*s, v)
+ return b, nil
+}
+
+func unmarshalFixed64Value(b []byte, f pointer, w int) ([]byte, error) {
+ if w != WireFixed64 {
+ return b, errInternalBadWireType
+ }
+ if len(b) < 8 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ v := uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56
+ *f.toUint64() = v
+ return b[8:], nil
+}
+
+func unmarshalFixed64Ptr(b []byte, f pointer, w int) ([]byte, error) {
+ if w != WireFixed64 {
+ return b, errInternalBadWireType
+ }
+ if len(b) < 8 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ v := uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56
+ *f.toUint64Ptr() = &v
+ return b[8:], nil
+}
+
+func unmarshalFixed64Slice(b []byte, f pointer, w int) ([]byte, error) {
+ if w == WireBytes { // packed
+ x, n := decodeVarint(b)
+ if n == 0 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ b = b[n:]
+ if x > uint64(len(b)) {
+ return nil, io.ErrUnexpectedEOF
+ }
+ res := b[x:]
+ b = b[:x]
+ for len(b) > 0 {
+ if len(b) < 8 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ v := uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56
+ s := f.toUint64Slice()
+ *s = append(*s, v)
+ b = b[8:]
+ }
+ return res, nil
+ }
+ if w != WireFixed64 {
+ return b, errInternalBadWireType
+ }
+ if len(b) < 8 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ v := uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56
+ s := f.toUint64Slice()
+ *s = append(*s, v)
+ return b[8:], nil
+}
+
+func unmarshalFixedS64Value(b []byte, f pointer, w int) ([]byte, error) {
+ if w != WireFixed64 {
+ return b, errInternalBadWireType
+ }
+ if len(b) < 8 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ v := int64(b[0]) | int64(b[1])<<8 | int64(b[2])<<16 | int64(b[3])<<24 | int64(b[4])<<32 | int64(b[5])<<40 | int64(b[6])<<48 | int64(b[7])<<56
+ *f.toInt64() = v
+ return b[8:], nil
+}
+
+func unmarshalFixedS64Ptr(b []byte, f pointer, w int) ([]byte, error) {
+ if w != WireFixed64 {
+ return b, errInternalBadWireType
+ }
+ if len(b) < 8 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ v := int64(b[0]) | int64(b[1])<<8 | int64(b[2])<<16 | int64(b[3])<<24 | int64(b[4])<<32 | int64(b[5])<<40 | int64(b[6])<<48 | int64(b[7])<<56
+ *f.toInt64Ptr() = &v
+ return b[8:], nil
+}
+
+func unmarshalFixedS64Slice(b []byte, f pointer, w int) ([]byte, error) {
+ if w == WireBytes { // packed
+ x, n := decodeVarint(b)
+ if n == 0 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ b = b[n:]
+ if x > uint64(len(b)) {
+ return nil, io.ErrUnexpectedEOF
+ }
+ res := b[x:]
+ b = b[:x]
+ for len(b) > 0 {
+ if len(b) < 8 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ v := int64(b[0]) | int64(b[1])<<8 | int64(b[2])<<16 | int64(b[3])<<24 | int64(b[4])<<32 | int64(b[5])<<40 | int64(b[6])<<48 | int64(b[7])<<56
+ s := f.toInt64Slice()
+ *s = append(*s, v)
+ b = b[8:]
+ }
+ return res, nil
+ }
+ if w != WireFixed64 {
+ return b, errInternalBadWireType
+ }
+ if len(b) < 8 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ v := int64(b[0]) | int64(b[1])<<8 | int64(b[2])<<16 | int64(b[3])<<24 | int64(b[4])<<32 | int64(b[5])<<40 | int64(b[6])<<48 | int64(b[7])<<56
+ s := f.toInt64Slice()
+ *s = append(*s, v)
+ return b[8:], nil
+}
+
+func unmarshalFixed32Value(b []byte, f pointer, w int) ([]byte, error) {
+ if w != WireFixed32 {
+ return b, errInternalBadWireType
+ }
+ if len(b) < 4 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ v := uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
+ *f.toUint32() = v
+ return b[4:], nil
+}
+
+func unmarshalFixed32Ptr(b []byte, f pointer, w int) ([]byte, error) {
+ if w != WireFixed32 {
+ return b, errInternalBadWireType
+ }
+ if len(b) < 4 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ v := uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
+ *f.toUint32Ptr() = &v
+ return b[4:], nil
+}
+
+func unmarshalFixed32Slice(b []byte, f pointer, w int) ([]byte, error) {
+ if w == WireBytes { // packed
+ x, n := decodeVarint(b)
+ if n == 0 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ b = b[n:]
+ if x > uint64(len(b)) {
+ return nil, io.ErrUnexpectedEOF
+ }
+ res := b[x:]
+ b = b[:x]
+ for len(b) > 0 {
+ if len(b) < 4 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ v := uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
+ s := f.toUint32Slice()
+ *s = append(*s, v)
+ b = b[4:]
+ }
+ return res, nil
+ }
+ if w != WireFixed32 {
+ return b, errInternalBadWireType
+ }
+ if len(b) < 4 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ v := uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
+ s := f.toUint32Slice()
+ *s = append(*s, v)
+ return b[4:], nil
+}
+
+func unmarshalFixedS32Value(b []byte, f pointer, w int) ([]byte, error) {
+ if w != WireFixed32 {
+ return b, errInternalBadWireType
+ }
+ if len(b) < 4 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ v := int32(b[0]) | int32(b[1])<<8 | int32(b[2])<<16 | int32(b[3])<<24
+ *f.toInt32() = v
+ return b[4:], nil
+}
+
+func unmarshalFixedS32Ptr(b []byte, f pointer, w int) ([]byte, error) {
+ if w != WireFixed32 {
+ return b, errInternalBadWireType
+ }
+ if len(b) < 4 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ v := int32(b[0]) | int32(b[1])<<8 | int32(b[2])<<16 | int32(b[3])<<24
+ f.setInt32Ptr(v)
+ return b[4:], nil
+}
+
+func unmarshalFixedS32Slice(b []byte, f pointer, w int) ([]byte, error) {
+ if w == WireBytes { // packed
+ x, n := decodeVarint(b)
+ if n == 0 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ b = b[n:]
+ if x > uint64(len(b)) {
+ return nil, io.ErrUnexpectedEOF
+ }
+ res := b[x:]
+ b = b[:x]
+ for len(b) > 0 {
+ if len(b) < 4 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ v := int32(b[0]) | int32(b[1])<<8 | int32(b[2])<<16 | int32(b[3])<<24
+ f.appendInt32Slice(v)
+ b = b[4:]
+ }
+ return res, nil
+ }
+ if w != WireFixed32 {
+ return b, errInternalBadWireType
+ }
+ if len(b) < 4 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ v := int32(b[0]) | int32(b[1])<<8 | int32(b[2])<<16 | int32(b[3])<<24
+ f.appendInt32Slice(v)
+ return b[4:], nil
+}
+
+func unmarshalBoolValue(b []byte, f pointer, w int) ([]byte, error) {
+ if w != WireVarint {
+ return b, errInternalBadWireType
+ }
+ // Note: any length varint is allowed, even though any sane
+ // encoder will use one byte.
+ // See https://github.com/golang/protobuf/issues/76
+ x, n := decodeVarint(b)
+ if n == 0 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ // TODO: check if x>1? Tests seem to indicate no.
+ v := x != 0
+ *f.toBool() = v
+ return b[n:], nil
+}
+
+func unmarshalBoolPtr(b []byte, f pointer, w int) ([]byte, error) {
+ if w != WireVarint {
+ return b, errInternalBadWireType
+ }
+ x, n := decodeVarint(b)
+ if n == 0 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ v := x != 0
+ *f.toBoolPtr() = &v
+ return b[n:], nil
+}
+
+func unmarshalBoolSlice(b []byte, f pointer, w int) ([]byte, error) {
+ if w == WireBytes { // packed
+ x, n := decodeVarint(b)
+ if n == 0 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ b = b[n:]
+ if x > uint64(len(b)) {
+ return nil, io.ErrUnexpectedEOF
+ }
+ res := b[x:]
+ b = b[:x]
+ for len(b) > 0 {
+ x, n = decodeVarint(b)
+ if n == 0 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ v := x != 0
+ s := f.toBoolSlice()
+ *s = append(*s, v)
+ b = b[n:]
+ }
+ return res, nil
+ }
+ if w != WireVarint {
+ return b, errInternalBadWireType
+ }
+ x, n := decodeVarint(b)
+ if n == 0 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ v := x != 0
+ s := f.toBoolSlice()
+ *s = append(*s, v)
+ return b[n:], nil
+}
+
+func unmarshalFloat64Value(b []byte, f pointer, w int) ([]byte, error) {
+ if w != WireFixed64 {
+ return b, errInternalBadWireType
+ }
+ if len(b) < 8 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ v := math.Float64frombits(uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56)
+ *f.toFloat64() = v
+ return b[8:], nil
+}
+
+func unmarshalFloat64Ptr(b []byte, f pointer, w int) ([]byte, error) {
+ if w != WireFixed64 {
+ return b, errInternalBadWireType
+ }
+ if len(b) < 8 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ v := math.Float64frombits(uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56)
+ *f.toFloat64Ptr() = &v
+ return b[8:], nil
+}
+
+func unmarshalFloat64Slice(b []byte, f pointer, w int) ([]byte, error) {
+ if w == WireBytes { // packed
+ x, n := decodeVarint(b)
+ if n == 0 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ b = b[n:]
+ if x > uint64(len(b)) {
+ return nil, io.ErrUnexpectedEOF
+ }
+ res := b[x:]
+ b = b[:x]
+ for len(b) > 0 {
+ if len(b) < 8 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ v := math.Float64frombits(uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56)
+ s := f.toFloat64Slice()
+ *s = append(*s, v)
+ b = b[8:]
+ }
+ return res, nil
+ }
+ if w != WireFixed64 {
+ return b, errInternalBadWireType
+ }
+ if len(b) < 8 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ v := math.Float64frombits(uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56)
+ s := f.toFloat64Slice()
+ *s = append(*s, v)
+ return b[8:], nil
+}
+
+func unmarshalFloat32Value(b []byte, f pointer, w int) ([]byte, error) {
+ if w != WireFixed32 {
+ return b, errInternalBadWireType
+ }
+ if len(b) < 4 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ v := math.Float32frombits(uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24)
+ *f.toFloat32() = v
+ return b[4:], nil
+}
+
+func unmarshalFloat32Ptr(b []byte, f pointer, w int) ([]byte, error) {
+ if w != WireFixed32 {
+ return b, errInternalBadWireType
+ }
+ if len(b) < 4 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ v := math.Float32frombits(uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24)
+ *f.toFloat32Ptr() = &v
+ return b[4:], nil
+}
+
+func unmarshalFloat32Slice(b []byte, f pointer, w int) ([]byte, error) {
+ if w == WireBytes { // packed
+ x, n := decodeVarint(b)
+ if n == 0 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ b = b[n:]
+ if x > uint64(len(b)) {
+ return nil, io.ErrUnexpectedEOF
+ }
+ res := b[x:]
+ b = b[:x]
+ for len(b) > 0 {
+ if len(b) < 4 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ v := math.Float32frombits(uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24)
+ s := f.toFloat32Slice()
+ *s = append(*s, v)
+ b = b[4:]
+ }
+ return res, nil
+ }
+ if w != WireFixed32 {
+ return b, errInternalBadWireType
+ }
+ if len(b) < 4 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ v := math.Float32frombits(uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24)
+ s := f.toFloat32Slice()
+ *s = append(*s, v)
+ return b[4:], nil
+}
+
+func unmarshalStringValue(b []byte, f pointer, w int) ([]byte, error) {
+ if w != WireBytes {
+ return b, errInternalBadWireType
+ }
+ x, n := decodeVarint(b)
+ if n == 0 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ b = b[n:]
+ if x > uint64(len(b)) {
+ return nil, io.ErrUnexpectedEOF
+ }
+ v := string(b[:x])
+ *f.toString() = v
+ return b[x:], nil
+}
+
+func unmarshalStringPtr(b []byte, f pointer, w int) ([]byte, error) {
+ if w != WireBytes {
+ return b, errInternalBadWireType
+ }
+ x, n := decodeVarint(b)
+ if n == 0 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ b = b[n:]
+ if x > uint64(len(b)) {
+ return nil, io.ErrUnexpectedEOF
+ }
+ v := string(b[:x])
+ *f.toStringPtr() = &v
+ return b[x:], nil
+}
+
+func unmarshalStringSlice(b []byte, f pointer, w int) ([]byte, error) {
+ if w != WireBytes {
+ return b, errInternalBadWireType
+ }
+ x, n := decodeVarint(b)
+ if n == 0 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ b = b[n:]
+ if x > uint64(len(b)) {
+ return nil, io.ErrUnexpectedEOF
+ }
+ v := string(b[:x])
+ s := f.toStringSlice()
+ *s = append(*s, v)
+ return b[x:], nil
+}
+
+func unmarshalUTF8StringValue(b []byte, f pointer, w int) ([]byte, error) {
+ if w != WireBytes {
+ return b, errInternalBadWireType
+ }
+ x, n := decodeVarint(b)
+ if n == 0 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ b = b[n:]
+ if x > uint64(len(b)) {
+ return nil, io.ErrUnexpectedEOF
+ }
+ v := string(b[:x])
+ *f.toString() = v
+ if !utf8.ValidString(v) {
+ return b[x:], errInvalidUTF8
+ }
+ return b[x:], nil
+}
+
+func unmarshalUTF8StringPtr(b []byte, f pointer, w int) ([]byte, error) {
+ if w != WireBytes {
+ return b, errInternalBadWireType
+ }
+ x, n := decodeVarint(b)
+ if n == 0 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ b = b[n:]
+ if x > uint64(len(b)) {
+ return nil, io.ErrUnexpectedEOF
+ }
+ v := string(b[:x])
+ *f.toStringPtr() = &v
+ if !utf8.ValidString(v) {
+ return b[x:], errInvalidUTF8
+ }
+ return b[x:], nil
+}
+
+func unmarshalUTF8StringSlice(b []byte, f pointer, w int) ([]byte, error) {
+ if w != WireBytes {
+ return b, errInternalBadWireType
+ }
+ x, n := decodeVarint(b)
+ if n == 0 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ b = b[n:]
+ if x > uint64(len(b)) {
+ return nil, io.ErrUnexpectedEOF
+ }
+ v := string(b[:x])
+ s := f.toStringSlice()
+ *s = append(*s, v)
+ if !utf8.ValidString(v) {
+ return b[x:], errInvalidUTF8
+ }
+ return b[x:], nil
+}
+
+var emptyBuf [0]byte
+
+func unmarshalBytesValue(b []byte, f pointer, w int) ([]byte, error) {
+ if w != WireBytes {
+ return b, errInternalBadWireType
+ }
+ x, n := decodeVarint(b)
+ if n == 0 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ b = b[n:]
+ if x > uint64(len(b)) {
+ return nil, io.ErrUnexpectedEOF
+ }
+ // The use of append here is a trick which avoids the zeroing
+ // that would be required if we used a make/copy pair.
+ // We append to emptyBuf instead of nil because we want
+ // a non-nil result even when the length is 0.
+ v := append(emptyBuf[:], b[:x]...)
+ *f.toBytes() = v
+ return b[x:], nil
+}
+
+func unmarshalBytesSlice(b []byte, f pointer, w int) ([]byte, error) {
+ if w != WireBytes {
+ return b, errInternalBadWireType
+ }
+ x, n := decodeVarint(b)
+ if n == 0 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ b = b[n:]
+ if x > uint64(len(b)) {
+ return nil, io.ErrUnexpectedEOF
+ }
+ v := append(emptyBuf[:], b[:x]...)
+ s := f.toBytesSlice()
+ *s = append(*s, v)
+ return b[x:], nil
+}
+
+func makeUnmarshalMessagePtr(sub *unmarshalInfo, name string) unmarshaler {
+ return func(b []byte, f pointer, w int) ([]byte, error) {
+ if w != WireBytes {
+ return b, errInternalBadWireType
+ }
+ x, n := decodeVarint(b)
+ if n == 0 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ b = b[n:]
+ if x > uint64(len(b)) {
+ return nil, io.ErrUnexpectedEOF
+ }
+ // First read the message field to see if something is there.
+ // The semantics of multiple submessages are weird. Instead of
+ // the last one winning (as it is for all other fields), multiple
+ // submessages are merged.
+ v := f.getPointer()
+ if v.isNil() {
+ v = valToPointer(reflect.New(sub.typ))
+ f.setPointer(v)
+ }
+ err := sub.unmarshal(v, b[:x])
+ if err != nil {
+ if r, ok := err.(*RequiredNotSetError); ok {
+ r.field = name + "." + r.field
+ } else {
+ return nil, err
+ }
+ }
+ return b[x:], err
+ }
+}
+
+func makeUnmarshalMessageSlicePtr(sub *unmarshalInfo, name string) unmarshaler {
+ return func(b []byte, f pointer, w int) ([]byte, error) {
+ if w != WireBytes {
+ return b, errInternalBadWireType
+ }
+ x, n := decodeVarint(b)
+ if n == 0 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ b = b[n:]
+ if x > uint64(len(b)) {
+ return nil, io.ErrUnexpectedEOF
+ }
+ v := valToPointer(reflect.New(sub.typ))
+ err := sub.unmarshal(v, b[:x])
+ if err != nil {
+ if r, ok := err.(*RequiredNotSetError); ok {
+ r.field = name + "." + r.field
+ } else {
+ return nil, err
+ }
+ }
+ f.appendPointer(v)
+ return b[x:], err
+ }
+}
+
+func makeUnmarshalGroupPtr(sub *unmarshalInfo, name string) unmarshaler {
+ return func(b []byte, f pointer, w int) ([]byte, error) {
+ if w != WireStartGroup {
+ return b, errInternalBadWireType
+ }
+ x, y := findEndGroup(b)
+ if x < 0 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ v := f.getPointer()
+ if v.isNil() {
+ v = valToPointer(reflect.New(sub.typ))
+ f.setPointer(v)
+ }
+ err := sub.unmarshal(v, b[:x])
+ if err != nil {
+ if r, ok := err.(*RequiredNotSetError); ok {
+ r.field = name + "." + r.field
+ } else {
+ return nil, err
+ }
+ }
+ return b[y:], err
+ }
+}
+
+func makeUnmarshalGroupSlicePtr(sub *unmarshalInfo, name string) unmarshaler {
+ return func(b []byte, f pointer, w int) ([]byte, error) {
+ if w != WireStartGroup {
+ return b, errInternalBadWireType
+ }
+ x, y := findEndGroup(b)
+ if x < 0 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ v := valToPointer(reflect.New(sub.typ))
+ err := sub.unmarshal(v, b[:x])
+ if err != nil {
+ if r, ok := err.(*RequiredNotSetError); ok {
+ r.field = name + "." + r.field
+ } else {
+ return nil, err
+ }
+ }
+ f.appendPointer(v)
+ return b[y:], err
+ }
+}
+
+func makeUnmarshalMap(f *reflect.StructField) unmarshaler {
+ t := f.Type
+ kt := t.Key()
+ vt := t.Elem()
+ unmarshalKey := typeUnmarshaler(kt, f.Tag.Get("protobuf_key"))
+ unmarshalVal := typeUnmarshaler(vt, f.Tag.Get("protobuf_val"))
+ return func(b []byte, f pointer, w int) ([]byte, error) {
+ // The map entry is a submessage. Figure out how big it is.
+ if w != WireBytes {
+ return nil, fmt.Errorf("proto: bad wiretype for map field: got %d want %d", w, WireBytes)
+ }
+ x, n := decodeVarint(b)
+ if n == 0 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ b = b[n:]
+ if x > uint64(len(b)) {
+ return nil, io.ErrUnexpectedEOF
+ }
+ r := b[x:] // unused data to return
+ b = b[:x] // data for map entry
+
+ // Note: we could use #keys * #values ~= 200 functions
+ // to do map decoding without reflection. Probably not worth it.
+ // Maps will be somewhat slow. Oh well.
+
+ // Read key and value from data.
+ var nerr nonFatal
+ k := reflect.New(kt)
+ v := reflect.New(vt)
+ for len(b) > 0 {
+ x, n := decodeVarint(b)
+ if n == 0 {
+ return nil, io.ErrUnexpectedEOF
+ }
+ wire := int(x) & 7
+ b = b[n:]
+
+ var err error
+ switch x >> 3 {
+ case 1:
+ b, err = unmarshalKey(b, valToPointer(k), wire)
+ case 2:
+ b, err = unmarshalVal(b, valToPointer(v), wire)
+ default:
+ err = errInternalBadWireType // skip unknown tag
+ }
+
+ if nerr.Merge(err) {
+ continue
+ }
+ if err != errInternalBadWireType {
+ return nil, err
+ }
+
+ // Skip past unknown fields.
+ b, err = skipField(b, wire)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ // Get map, allocate if needed.
+ m := f.asPointerTo(t).Elem() // an addressable map[K]T
+ if m.IsNil() {
+ m.Set(reflect.MakeMap(t))
+ }
+
+ // Insert into map.
+ m.SetMapIndex(k.Elem(), v.Elem())
+
+ return r, nerr.E
+ }
+}
+
+// makeUnmarshalOneof makes an unmarshaler for oneof fields.
+// for:
+// message Msg {
+// oneof F {
+// int64 X = 1;
+// float64 Y = 2;
+// }
+// }
+// typ is the type of the concrete entry for a oneof case (e.g. Msg_X).
+// ityp is the interface type of the oneof field (e.g. isMsg_F).
+// unmarshal is the unmarshaler for the base type of the oneof case (e.g. int64).
+// Note that this function will be called once for each case in the oneof.
+func makeUnmarshalOneof(typ, ityp reflect.Type, unmarshal unmarshaler) unmarshaler {
+ sf := typ.Field(0)
+ field0 := toField(&sf)
+ return func(b []byte, f pointer, w int) ([]byte, error) {
+ // Allocate holder for value.
+ v := reflect.New(typ)
+
+ // Unmarshal data into holder.
+ // We unmarshal into the first field of the holder object.
+ var err error
+ var nerr nonFatal
+ b, err = unmarshal(b, valToPointer(v).offset(field0), w)
+ if !nerr.Merge(err) {
+ return nil, err
+ }
+
+ // Write pointer to holder into target field.
+ f.asPointerTo(ityp).Elem().Set(v)
+
+ return b, nerr.E
+ }
+}
+
+// Error used by decode internally.
+var errInternalBadWireType = errors.New("proto: internal error: bad wiretype")
+
+// skipField skips past a field of type wire and returns the remaining bytes.
+func skipField(b []byte, wire int) ([]byte, error) {
+ switch wire {
+ case WireVarint:
+ _, k := decodeVarint(b)
+ if k == 0 {
+ return b, io.ErrUnexpectedEOF
+ }
+ b = b[k:]
+ case WireFixed32:
+ if len(b) < 4 {
+ return b, io.ErrUnexpectedEOF
+ }
+ b = b[4:]
+ case WireFixed64:
+ if len(b) < 8 {
+ return b, io.ErrUnexpectedEOF
+ }
+ b = b[8:]
+ case WireBytes:
+ m, k := decodeVarint(b)
+ if k == 0 || uint64(len(b)-k) < m {
+ return b, io.ErrUnexpectedEOF
+ }
+ b = b[uint64(k)+m:]
+ case WireStartGroup:
+ _, i := findEndGroup(b)
+ if i == -1 {
+ return b, io.ErrUnexpectedEOF
+ }
+ b = b[i:]
+ default:
+ return b, fmt.Errorf("proto: can't skip unknown wire type %d", wire)
+ }
+ return b, nil
+}
+
+// findEndGroup finds the index of the next EndGroup tag.
+// Groups may be nested, so the "next" EndGroup tag is the first
+// unpaired EndGroup.
+// findEndGroup returns the indexes of the start and end of the EndGroup tag.
+// Returns (-1,-1) if it can't find one.
+func findEndGroup(b []byte) (int, int) {
+ depth := 1
+ i := 0
+ for {
+ x, n := decodeVarint(b[i:])
+ if n == 0 {
+ return -1, -1
+ }
+ j := i
+ i += n
+ switch x & 7 {
+ case WireVarint:
+ _, k := decodeVarint(b[i:])
+ if k == 0 {
+ return -1, -1
+ }
+ i += k
+ case WireFixed32:
+ if len(b)-4 < i {
+ return -1, -1
+ }
+ i += 4
+ case WireFixed64:
+ if len(b)-8 < i {
+ return -1, -1
+ }
+ i += 8
+ case WireBytes:
+ m, k := decodeVarint(b[i:])
+ if k == 0 {
+ return -1, -1
+ }
+ i += k
+ if uint64(len(b)-i) < m {
+ return -1, -1
+ }
+ i += int(m)
+ case WireStartGroup:
+ depth++
+ case WireEndGroup:
+ depth--
+ if depth == 0 {
+ return j, i
+ }
+ default:
+ return -1, -1
+ }
+ }
+}
+
+// encodeVarint appends a varint-encoded integer to b and returns the result.
+func encodeVarint(b []byte, x uint64) []byte {
+ for x >= 1<<7 {
+ b = append(b, byte(x&0x7f|0x80))
+ x >>= 7
+ }
+ return append(b, byte(x))
+}
+
+// decodeVarint reads a varint-encoded integer from b.
+// Returns the decoded integer and the number of bytes read.
+// If there is an error, it returns 0,0.
+func decodeVarint(b []byte) (uint64, int) {
+ var x, y uint64
+ if len(b) == 0 {
+ goto bad
+ }
+ x = uint64(b[0])
+ if x < 0x80 {
+ return x, 1
+ }
+ x -= 0x80
+
+ if len(b) <= 1 {
+ goto bad
+ }
+ y = uint64(b[1])
+ x += y << 7
+ if y < 0x80 {
+ return x, 2
+ }
+ x -= 0x80 << 7
+
+ if len(b) <= 2 {
+ goto bad
+ }
+ y = uint64(b[2])
+ x += y << 14
+ if y < 0x80 {
+ return x, 3
+ }
+ x -= 0x80 << 14
+
+ if len(b) <= 3 {
+ goto bad
+ }
+ y = uint64(b[3])
+ x += y << 21
+ if y < 0x80 {
+ return x, 4
+ }
+ x -= 0x80 << 21
+
+ if len(b) <= 4 {
+ goto bad
+ }
+ y = uint64(b[4])
+ x += y << 28
+ if y < 0x80 {
+ return x, 5
+ }
+ x -= 0x80 << 28
+
+ if len(b) <= 5 {
+ goto bad
+ }
+ y = uint64(b[5])
+ x += y << 35
+ if y < 0x80 {
+ return x, 6
+ }
+ x -= 0x80 << 35
+
+ if len(b) <= 6 {
+ goto bad
+ }
+ y = uint64(b[6])
+ x += y << 42
+ if y < 0x80 {
+ return x, 7
+ }
+ x -= 0x80 << 42
+
+ if len(b) <= 7 {
+ goto bad
+ }
+ y = uint64(b[7])
+ x += y << 49
+ if y < 0x80 {
+ return x, 8
+ }
+ x -= 0x80 << 49
+
+ if len(b) <= 8 {
+ goto bad
+ }
+ y = uint64(b[8])
+ x += y << 56
+ if y < 0x80 {
+ return x, 9
+ }
+ x -= 0x80 << 56
+
+ if len(b) <= 9 {
+ goto bad
+ }
+ y = uint64(b[9])
+ x += y << 63
+ if y < 2 {
+ return x, 10
+ }
+
+bad:
+ return 0, 0
+}
diff --git a/vendor/github.com/golang/protobuf/proto/text.go b/vendor/github.com/golang/protobuf/proto/text.go
index 965876bf0..1aaee725b 100644
--- a/vendor/github.com/golang/protobuf/proto/text.go
+++ b/vendor/github.com/golang/protobuf/proto/text.go
@@ -50,7 +50,6 @@ import (
var (
newline = []byte("\n")
spaces = []byte(" ")
- gtNewline = []byte(">\n")
endBraceNewline = []byte("}\n")
backslashN = []byte{'\\', 'n'}
backslashR = []byte{'\\', 'r'}
@@ -170,11 +169,6 @@ func writeName(w *textWriter, props *Properties) error {
return nil
}
-// raw is the interface satisfied by RawMessage.
-type raw interface {
- Bytes() []byte
-}
-
func requiresQuotes(u string) bool {
// When type URL contains any characters except [0-9A-Za-z./\-]*, it must be quoted.
for _, ch := range u {
@@ -269,6 +263,10 @@ func (tm *TextMarshaler) writeStruct(w *textWriter, sv reflect.Value) error {
props := sprops.Prop[i]
name := st.Field(i).Name
+ if name == "XXX_NoUnkeyedLiteral" {
+ continue
+ }
+
if strings.HasPrefix(name, "XXX_") {
// There are two XXX_ fields:
// XXX_unrecognized []byte
@@ -355,7 +353,7 @@ func (tm *TextMarshaler) writeStruct(w *textWriter, sv reflect.Value) error {
return err
}
}
- if err := tm.writeAny(w, key, props.mkeyprop); err != nil {
+ if err := tm.writeAny(w, key, props.MapKeyProp); err != nil {
return err
}
if err := w.WriteByte('\n'); err != nil {
@@ -372,7 +370,7 @@ func (tm *TextMarshaler) writeStruct(w *textWriter, sv reflect.Value) error {
return err
}
}
- if err := tm.writeAny(w, val, props.mvalprop); err != nil {
+ if err := tm.writeAny(w, val, props.MapValProp); err != nil {
return err
}
if err := w.WriteByte('\n'); err != nil {
@@ -436,12 +434,6 @@ func (tm *TextMarshaler) writeStruct(w *textWriter, sv reflect.Value) error {
return err
}
}
- if b, ok := fv.Interface().(raw); ok {
- if err := writeRaw(w, b.Bytes()); err != nil {
- return err
- }
- continue
- }
// Enums have a String method, so writeAny will work fine.
if err := tm.writeAny(w, fv, props); err != nil {
@@ -455,7 +447,7 @@ func (tm *TextMarshaler) writeStruct(w *textWriter, sv reflect.Value) error {
// Extensions (the XXX_extensions field).
pv := sv.Addr()
- if _, ok := extendable(pv.Interface()); ok {
+ if _, err := extendable(pv.Interface()); err == nil {
if err := tm.writeExtensions(w, pv); err != nil {
return err
}
@@ -464,27 +456,6 @@ func (tm *TextMarshaler) writeStruct(w *textWriter, sv reflect.Value) error {
return nil
}
-// writeRaw writes an uninterpreted raw message.
-func writeRaw(w *textWriter, b []byte) error {
- if err := w.WriteByte('<'); err != nil {
- return err
- }
- if !w.compact {
- if err := w.WriteByte('\n'); err != nil {
- return err
- }
- }
- w.indent()
- if err := writeUnknownStruct(w, b); err != nil {
- return err
- }
- w.unindent()
- if err := w.WriteByte('>'); err != nil {
- return err
- }
- return nil
-}
-
// writeAny writes an arbitrary field.
func (tm *TextMarshaler) writeAny(w *textWriter, v reflect.Value, props *Properties) error {
v = reflect.Indirect(v)
@@ -535,6 +506,19 @@ func (tm *TextMarshaler) writeAny(w *textWriter, v reflect.Value, props *Propert
}
}
w.indent()
+ if v.CanAddr() {
+ // Calling v.Interface on a struct causes the reflect package to
+ // copy the entire struct. This is racy with the new Marshaler
+ // since we atomically update the XXX_sizecache.
+ //
+ // Thus, we retrieve a pointer to the struct if possible to avoid
+ // a race since v.Interface on the pointer doesn't copy the struct.
+ //
+ // If v is not addressable, then we are not worried about a race
+ // since it implies that the binary Marshaler cannot possibly be
+ // mutating this value.
+ v = v.Addr()
+ }
if etm, ok := v.Interface().(encoding.TextMarshaler); ok {
text, err := etm.MarshalText()
if err != nil {
@@ -543,8 +527,13 @@ func (tm *TextMarshaler) writeAny(w *textWriter, v reflect.Value, props *Propert
if _, err = w.Write(text); err != nil {
return err
}
- } else if err := tm.writeStruct(w, v); err != nil {
- return err
+ } else {
+ if v.Kind() == reflect.Ptr {
+ v = v.Elem()
+ }
+ if err := tm.writeStruct(w, v); err != nil {
+ return err
+ }
}
w.unindent()
if err := w.WriteByte(ket); err != nil {
diff --git a/vendor/github.com/golang/protobuf/proto/text_parser.go b/vendor/github.com/golang/protobuf/proto/text_parser.go
index 5e14513f2..bb55a3af2 100644
--- a/vendor/github.com/golang/protobuf/proto/text_parser.go
+++ b/vendor/github.com/golang/protobuf/proto/text_parser.go
@@ -206,7 +206,6 @@ func (p *textParser) advance() {
var (
errBadUTF8 = errors.New("proto: bad UTF-8")
- errBadHex = errors.New("proto: bad hexadecimal")
)
func unquoteC(s string, quote rune) (string, error) {
@@ -277,60 +276,47 @@ func unescape(s string) (ch string, tail string, err error) {
return "?", s, nil // trigraph workaround
case '\'', '"', '\\':
return string(r), s, nil
- case '0', '1', '2', '3', '4', '5', '6', '7', 'x', 'X':
+ case '0', '1', '2', '3', '4', '5', '6', '7':
if len(s) < 2 {
return "", "", fmt.Errorf(`\%c requires 2 following digits`, r)
}
- base := 8
- ss := s[:2]
+ ss := string(r) + s[:2]
s = s[2:]
- if r == 'x' || r == 'X' {
- base = 16
- } else {
- ss = string(r) + ss
- }
- i, err := strconv.ParseUint(ss, base, 8)
+ i, err := strconv.ParseUint(ss, 8, 8)
if err != nil {
- return "", "", err
+ return "", "", fmt.Errorf(`\%s contains non-octal digits`, ss)
}
return string([]byte{byte(i)}), s, nil
- case 'u', 'U':
- n := 4
- if r == 'U' {
+ case 'x', 'X', 'u', 'U':
+ var n int
+ switch r {
+ case 'x', 'X':
+ n = 2
+ case 'u':
+ n = 4
+ case 'U':
n = 8
}
if len(s) < n {
- return "", "", fmt.Errorf(`\%c requires %d digits`, r, n)
- }
-
- bs := make([]byte, n/2)
- for i := 0; i < n; i += 2 {
- a, ok1 := unhex(s[i])
- b, ok2 := unhex(s[i+1])
- if !ok1 || !ok2 {
- return "", "", errBadHex
- }
- bs[i/2] = a<<4 | b
+ return "", "", fmt.Errorf(`\%c requires %d following digits`, r, n)
}
+ ss := s[:n]
s = s[n:]
- return string(bs), s, nil
+ i, err := strconv.ParseUint(ss, 16, 64)
+ if err != nil {
+ return "", "", fmt.Errorf(`\%c%s contains non-hexadecimal digits`, r, ss)
+ }
+ if r == 'x' || r == 'X' {
+ return string([]byte{byte(i)}), s, nil
+ }
+ if i > utf8.MaxRune {
+ return "", "", fmt.Errorf(`\%c%s is not a valid Unicode code point`, r, ss)
+ }
+ return string(i), s, nil
}
return "", "", fmt.Errorf(`unknown escape \%c`, r)
}
-// Adapted from src/pkg/strconv/quote.go.
-func unhex(b byte) (v byte, ok bool) {
- switch {
- case '0' <= b && b <= '9':
- return b - '0', true
- case 'a' <= b && b <= 'f':
- return b - 'a' + 10, true
- case 'A' <= b && b <= 'F':
- return b - 'A' + 10, true
- }
- return 0, false
-}
-
// Back off the parser by one token. Can only be done between calls to next().
// It makes the next advance() a no-op.
func (p *textParser) back() { p.backed = true }
@@ -644,17 +630,17 @@ func (p *textParser) readStruct(sv reflect.Value, terminator string) error {
if err := p.consumeToken(":"); err != nil {
return err
}
- if err := p.readAny(key, props.mkeyprop); err != nil {
+ if err := p.readAny(key, props.MapKeyProp); err != nil {
return err
}
if err := p.consumeOptionalSeparator(); err != nil {
return err
}
case "value":
- if err := p.checkForColon(props.mvalprop, dst.Type().Elem()); err != nil {
+ if err := p.checkForColon(props.MapValProp, dst.Type().Elem()); err != nil {
return err
}
- if err := p.readAny(val, props.mvalprop); err != nil {
+ if err := p.readAny(val, props.MapValProp); err != nil {
return err
}
if err := p.consumeOptionalSeparator(); err != nil {
@@ -728,6 +714,9 @@ func (p *textParser) consumeExtName() (string, error) {
if tok.err != nil {
return "", p.errorf("unrecognized type_url or extension name: %s", tok.err)
}
+ if p.done && tok.value != "]" {
+ return "", p.errorf("unclosed type_url or extension name")
+ }
}
return strings.Join(parts, ""), nil
}
@@ -865,7 +854,7 @@ func (p *textParser) readAny(v reflect.Value, props *Properties) error {
return p.readStruct(fv, terminator)
case reflect.Uint32:
if x, err := strconv.ParseUint(tok.value, 0, 32); err == nil {
- fv.SetUint(x)
+ fv.SetUint(uint64(x))
return nil
}
case reflect.Uint64:
@@ -883,13 +872,9 @@ func (p *textParser) readAny(v reflect.Value, props *Properties) error {
// UnmarshalText returns *RequiredNotSetError.
func UnmarshalText(s string, pb Message) error {
if um, ok := pb.(encoding.TextUnmarshaler); ok {
- err := um.UnmarshalText([]byte(s))
- return err
+ return um.UnmarshalText([]byte(s))
}
pb.Reset()
v := reflect.ValueOf(pb)
- if pe := newTextParser(s).readStruct(v.Elem(), ""); pe != nil {
- return pe
- }
- return nil
+ return newTextParser(s).readStruct(v.Elem(), "")
}
diff --git a/vendor/github.com/golang/protobuf/ptypes/any.go b/vendor/github.com/golang/protobuf/ptypes/any.go
new file mode 100644
index 000000000..b2af97f4a
--- /dev/null
+++ b/vendor/github.com/golang/protobuf/ptypes/any.go
@@ -0,0 +1,139 @@
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2016 The Go Authors. All rights reserved.
+// https://github.com/golang/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package ptypes
+
+// This file implements functions to marshal proto.Message to/from
+// google.protobuf.Any message.
+
+import (
+ "fmt"
+ "reflect"
+ "strings"
+
+ "github.com/golang/protobuf/proto"
+ "github.com/golang/protobuf/ptypes/any"
+)
+
+const googleApis = "type.googleapis.com/"
+
+// AnyMessageName returns the name of the message contained in a google.protobuf.Any message.
+//
+// Note that regular type assertions should be done using the Is
+// function. AnyMessageName is provided for less common use cases like filtering a
+// sequence of Any messages based on a set of allowed message type names.
+func AnyMessageName(any *any.Any) (string, error) {
+ if any == nil {
+ return "", fmt.Errorf("message is nil")
+ }
+ slash := strings.LastIndex(any.TypeUrl, "/")
+ if slash < 0 {
+ return "", fmt.Errorf("message type url %q is invalid", any.TypeUrl)
+ }
+ return any.TypeUrl[slash+1:], nil
+}
+
+// MarshalAny takes the protocol buffer and encodes it into google.protobuf.Any.
+func MarshalAny(pb proto.Message) (*any.Any, error) {
+ value, err := proto.Marshal(pb)
+ if err != nil {
+ return nil, err
+ }
+ return &any.Any{TypeUrl: googleApis + proto.MessageName(pb), Value: value}, nil
+}
+
+// DynamicAny is a value that can be passed to UnmarshalAny to automatically
+// allocate a proto.Message for the type specified in a google.protobuf.Any
+// message. The allocated message is stored in the embedded proto.Message.
+//
+// Example:
+//
+// var x ptypes.DynamicAny
+// if err := ptypes.UnmarshalAny(a, &x); err != nil { ... }
+// fmt.Printf("unmarshaled message: %v", x.Message)
+type DynamicAny struct {
+ proto.Message
+}
+
+// Empty returns a new proto.Message of the type specified in a
+// google.protobuf.Any message. It returns an error if corresponding message
+// type isn't linked in.
+func Empty(any *any.Any) (proto.Message, error) {
+ aname, err := AnyMessageName(any)
+ if err != nil {
+ return nil, err
+ }
+
+ t := proto.MessageType(aname)
+ if t == nil {
+ return nil, fmt.Errorf("any: message type %q isn't linked in", aname)
+ }
+ return reflect.New(t.Elem()).Interface().(proto.Message), nil
+}
+
+// UnmarshalAny parses the protocol buffer representation in a google.protobuf.Any
+// message and places the decoded result in pb. It returns an error if type of
+// contents of Any message does not match type of pb message.
+//
+// pb can be a proto.Message, or a *DynamicAny.
+func UnmarshalAny(any *any.Any, pb proto.Message) error {
+ if d, ok := pb.(*DynamicAny); ok {
+ if d.Message == nil {
+ var err error
+ d.Message, err = Empty(any)
+ if err != nil {
+ return err
+ }
+ }
+ return UnmarshalAny(any, d.Message)
+ }
+
+ aname, err := AnyMessageName(any)
+ if err != nil {
+ return err
+ }
+
+ mname := proto.MessageName(pb)
+ if aname != mname {
+ return fmt.Errorf("mismatched message type: got %q want %q", aname, mname)
+ }
+ return proto.Unmarshal(any.Value, pb)
+}
+
+// Is returns true if any value contains a given message type.
+func Is(any *any.Any, pb proto.Message) bool {
+ aname, err := AnyMessageName(any)
+ if err != nil {
+ return false
+ }
+
+ return aname == proto.MessageName(pb)
+}
diff --git a/vendor/github.com/golang/protobuf/ptypes/any/any.pb.go b/vendor/github.com/golang/protobuf/ptypes/any/any.pb.go
new file mode 100644
index 000000000..78ee52334
--- /dev/null
+++ b/vendor/github.com/golang/protobuf/ptypes/any/any.pb.go
@@ -0,0 +1,200 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// source: google/protobuf/any.proto
+
+package any
+
+import (
+ fmt "fmt"
+ proto "github.com/golang/protobuf/proto"
+ math "math"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
+
+// `Any` contains an arbitrary serialized protocol buffer message along with a
+// URL that describes the type of the serialized message.
+//
+// Protobuf library provides support to pack/unpack Any values in the form
+// of utility functions or additional generated methods of the Any type.
+//
+// Example 1: Pack and unpack a message in C++.
+//
+// Foo foo = ...;
+// Any any;
+// any.PackFrom(foo);
+// ...
+// if (any.UnpackTo(&foo)) {
+// ...
+// }
+//
+// Example 2: Pack and unpack a message in Java.
+//
+// Foo foo = ...;
+// Any any = Any.pack(foo);
+// ...
+// if (any.is(Foo.class)) {
+// foo = any.unpack(Foo.class);
+// }
+//
+// Example 3: Pack and unpack a message in Python.
+//
+// foo = Foo(...)
+// any = Any()
+// any.Pack(foo)
+// ...
+// if any.Is(Foo.DESCRIPTOR):
+// any.Unpack(foo)
+// ...
+//
+// Example 4: Pack and unpack a message in Go
+//
+// foo := &pb.Foo{...}
+// any, err := ptypes.MarshalAny(foo)
+// ...
+// foo := &pb.Foo{}
+// if err := ptypes.UnmarshalAny(any, foo); err != nil {
+// ...
+// }
+//
+// The pack methods provided by protobuf library will by default use
+// 'type.googleapis.com/full.type.name' as the type URL and the unpack
+// methods only use the fully qualified type name after the last '/'
+// in the type URL, for example "foo.bar.com/x/y.z" will yield type
+// name "y.z".
+//
+//
+// JSON
+// ====
+// The JSON representation of an `Any` value uses the regular
+// representation of the deserialized, embedded message, with an
+// additional field `@type` which contains the type URL. Example:
+//
+// package google.profile;
+// message Person {
+// string first_name = 1;
+// string last_name = 2;
+// }
+//
+// {
+// "@type": "type.googleapis.com/google.profile.Person",
+// "firstName": <string>,
+// "lastName": <string>
+// }
+//
+// If the embedded message type is well-known and has a custom JSON
+// representation, that representation will be embedded adding a field
+// `value` which holds the custom JSON in addition to the `@type`
+// field. Example (for message [google.protobuf.Duration][]):
+//
+// {
+// "@type": "type.googleapis.com/google.protobuf.Duration",
+// "value": "1.212s"
+// }
+//
+type Any struct {
+ // A URL/resource name that uniquely identifies the type of the serialized
+ // protocol buffer message. The last segment of the URL's path must represent
+ // the fully qualified name of the type (as in
+ // `path/google.protobuf.Duration`). The name should be in a canonical form
+ // (e.g., leading "." is not accepted).
+ //
+ // In practice, teams usually precompile into the binary all types that they
+ // expect it to use in the context of Any. However, for URLs which use the
+ // scheme `http`, `https`, or no scheme, one can optionally set up a type
+ // server that maps type URLs to message definitions as follows:
+ //
+ // * If no scheme is provided, `https` is assumed.
+ // * An HTTP GET on the URL must yield a [google.protobuf.Type][]
+ // value in binary format, or produce an error.
+ // * Applications are allowed to cache lookup results based on the
+ // URL, or have them precompiled into a binary to avoid any
+ // lookup. Therefore, binary compatibility needs to be preserved
+ // on changes to types. (Use versioned type names to manage
+ // breaking changes.)
+ //
+ // Note: this functionality is not currently available in the official
+ // protobuf release, and it is not used for type URLs beginning with
+ // type.googleapis.com.
+ //
+ // Schemes other than `http`, `https` (or the empty scheme) might be
+ // used with implementation specific semantics.
+ //
+ TypeUrl string `protobuf:"bytes,1,opt,name=type_url,json=typeUrl,proto3" json:"type_url,omitempty"`
+ // Must be a valid serialized protocol buffer of the above specified type.
+ Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *Any) Reset() { *m = Any{} }
+func (m *Any) String() string { return proto.CompactTextString(m) }
+func (*Any) ProtoMessage() {}
+func (*Any) Descriptor() ([]byte, []int) {
+ return fileDescriptor_b53526c13ae22eb4, []int{0}
+}
+
+func (*Any) XXX_WellKnownType() string { return "Any" }
+
+func (m *Any) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_Any.Unmarshal(m, b)
+}
+func (m *Any) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_Any.Marshal(b, m, deterministic)
+}
+func (m *Any) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_Any.Merge(m, src)
+}
+func (m *Any) XXX_Size() int {
+ return xxx_messageInfo_Any.Size(m)
+}
+func (m *Any) XXX_DiscardUnknown() {
+ xxx_messageInfo_Any.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Any proto.InternalMessageInfo
+
+func (m *Any) GetTypeUrl() string {
+ if m != nil {
+ return m.TypeUrl
+ }
+ return ""
+}
+
+func (m *Any) GetValue() []byte {
+ if m != nil {
+ return m.Value
+ }
+ return nil
+}
+
+func init() {
+ proto.RegisterType((*Any)(nil), "google.protobuf.Any")
+}
+
+func init() { proto.RegisterFile("google/protobuf/any.proto", fileDescriptor_b53526c13ae22eb4) }
+
+var fileDescriptor_b53526c13ae22eb4 = []byte{
+ // 185 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4c, 0xcf, 0xcf, 0x4f,
+ 0xcf, 0x49, 0xd5, 0x2f, 0x28, 0xca, 0x2f, 0xc9, 0x4f, 0x2a, 0x4d, 0xd3, 0x4f, 0xcc, 0xab, 0xd4,
+ 0x03, 0x73, 0x84, 0xf8, 0x21, 0x52, 0x7a, 0x30, 0x29, 0x25, 0x33, 0x2e, 0x66, 0xc7, 0xbc, 0x4a,
+ 0x21, 0x49, 0x2e, 0x8e, 0x92, 0xca, 0x82, 0xd4, 0xf8, 0xd2, 0xa2, 0x1c, 0x09, 0x46, 0x05, 0x46,
+ 0x0d, 0xce, 0x20, 0x76, 0x10, 0x3f, 0xb4, 0x28, 0x47, 0x48, 0x84, 0x8b, 0xb5, 0x2c, 0x31, 0xa7,
+ 0x34, 0x55, 0x82, 0x49, 0x81, 0x51, 0x83, 0x27, 0x08, 0xc2, 0x71, 0xca, 0xe7, 0x12, 0x4e, 0xce,
+ 0xcf, 0xd5, 0x43, 0x33, 0xce, 0x89, 0xc3, 0x31, 0xaf, 0x32, 0x00, 0xc4, 0x09, 0x60, 0x8c, 0x52,
+ 0x4d, 0xcf, 0x2c, 0xc9, 0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xcf, 0xcf, 0x49, 0xcc,
+ 0x4b, 0x47, 0xb8, 0xa8, 0x00, 0x64, 0x7a, 0x31, 0xc8, 0x61, 0x8b, 0x98, 0x98, 0xdd, 0x03, 0x9c,
+ 0x56, 0x31, 0xc9, 0xb9, 0x43, 0x8c, 0x0a, 0x80, 0x2a, 0xd1, 0x0b, 0x4f, 0xcd, 0xc9, 0xf1, 0xce,
+ 0xcb, 0x2f, 0xcf, 0x0b, 0x01, 0x29, 0x4d, 0x62, 0x03, 0xeb, 0x35, 0x06, 0x04, 0x00, 0x00, 0xff,
+ 0xff, 0x13, 0xf8, 0xe8, 0x42, 0xdd, 0x00, 0x00, 0x00,
+}
diff --git a/vendor/github.com/golang/protobuf/ptypes/any/any.proto b/vendor/github.com/golang/protobuf/ptypes/any/any.proto
new file mode 100644
index 000000000..493294255
--- /dev/null
+++ b/vendor/github.com/golang/protobuf/ptypes/any/any.proto
@@ -0,0 +1,154 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+syntax = "proto3";
+
+package google.protobuf;
+
+option csharp_namespace = "Google.Protobuf.WellKnownTypes";
+option go_package = "github.com/golang/protobuf/ptypes/any";
+option java_package = "com.google.protobuf";
+option java_outer_classname = "AnyProto";
+option java_multiple_files = true;
+option objc_class_prefix = "GPB";
+
+// `Any` contains an arbitrary serialized protocol buffer message along with a
+// URL that describes the type of the serialized message.
+//
+// Protobuf library provides support to pack/unpack Any values in the form
+// of utility functions or additional generated methods of the Any type.
+//
+// Example 1: Pack and unpack a message in C++.
+//
+// Foo foo = ...;
+// Any any;
+// any.PackFrom(foo);
+// ...
+// if (any.UnpackTo(&foo)) {
+// ...
+// }
+//
+// Example 2: Pack and unpack a message in Java.
+//
+// Foo foo = ...;
+// Any any = Any.pack(foo);
+// ...
+// if (any.is(Foo.class)) {
+// foo = any.unpack(Foo.class);
+// }
+//
+// Example 3: Pack and unpack a message in Python.
+//
+// foo = Foo(...)
+// any = Any()
+// any.Pack(foo)
+// ...
+// if any.Is(Foo.DESCRIPTOR):
+// any.Unpack(foo)
+// ...
+//
+// Example 4: Pack and unpack a message in Go
+//
+// foo := &pb.Foo{...}
+// any, err := ptypes.MarshalAny(foo)
+// ...
+// foo := &pb.Foo{}
+// if err := ptypes.UnmarshalAny(any, foo); err != nil {
+// ...
+// }
+//
+// The pack methods provided by protobuf library will by default use
+// 'type.googleapis.com/full.type.name' as the type URL and the unpack
+// methods only use the fully qualified type name after the last '/'
+// in the type URL, for example "foo.bar.com/x/y.z" will yield type
+// name "y.z".
+//
+//
+// JSON
+// ====
+// The JSON representation of an `Any` value uses the regular
+// representation of the deserialized, embedded message, with an
+// additional field `@type` which contains the type URL. Example:
+//
+// package google.profile;
+// message Person {
+// string first_name = 1;
+// string last_name = 2;
+// }
+//
+// {
+// "@type": "type.googleapis.com/google.profile.Person",
+// "firstName": <string>,
+// "lastName": <string>
+// }
+//
+// If the embedded message type is well-known and has a custom JSON
+// representation, that representation will be embedded adding a field
+// `value` which holds the custom JSON in addition to the `@type`
+// field. Example (for message [google.protobuf.Duration][]):
+//
+// {
+// "@type": "type.googleapis.com/google.protobuf.Duration",
+// "value": "1.212s"
+// }
+//
+message Any {
+ // A URL/resource name that uniquely identifies the type of the serialized
+ // protocol buffer message. The last segment of the URL's path must represent
+ // the fully qualified name of the type (as in
+ // `path/google.protobuf.Duration`). The name should be in a canonical form
+ // (e.g., leading "." is not accepted).
+ //
+ // In practice, teams usually precompile into the binary all types that they
+ // expect it to use in the context of Any. However, for URLs which use the
+ // scheme `http`, `https`, or no scheme, one can optionally set up a type
+ // server that maps type URLs to message definitions as follows:
+ //
+ // * If no scheme is provided, `https` is assumed.
+ // * An HTTP GET on the URL must yield a [google.protobuf.Type][]
+ // value in binary format, or produce an error.
+ // * Applications are allowed to cache lookup results based on the
+ // URL, or have them precompiled into a binary to avoid any
+ // lookup. Therefore, binary compatibility needs to be preserved
+ // on changes to types. (Use versioned type names to manage
+ // breaking changes.)
+ //
+ // Note: this functionality is not currently available in the official
+ // protobuf release, and it is not used for type URLs beginning with
+ // type.googleapis.com.
+ //
+ // Schemes other than `http`, `https` (or the empty scheme) might be
+ // used with implementation specific semantics.
+ //
+ string type_url = 1;
+
+ // Must be a valid serialized protocol buffer of the above specified type.
+ bytes value = 2;
+}
diff --git a/vendor/github.com/golang/protobuf/ptypes/doc.go b/vendor/github.com/golang/protobuf/ptypes/doc.go
new file mode 100644
index 000000000..c0d595da7
--- /dev/null
+++ b/vendor/github.com/golang/protobuf/ptypes/doc.go
@@ -0,0 +1,35 @@
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2016 The Go Authors. All rights reserved.
+// https://github.com/golang/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+/*
+Package ptypes contains code for interacting with well-known types.
+*/
+package ptypes
diff --git a/vendor/github.com/golang/protobuf/ptypes/duration.go b/vendor/github.com/golang/protobuf/ptypes/duration.go
new file mode 100644
index 000000000..65cb0f8eb
--- /dev/null
+++ b/vendor/github.com/golang/protobuf/ptypes/duration.go
@@ -0,0 +1,102 @@
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2016 The Go Authors. All rights reserved.
+// https://github.com/golang/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package ptypes
+
+// This file implements conversions between google.protobuf.Duration
+// and time.Duration.
+
+import (
+ "errors"
+ "fmt"
+ "time"
+
+ durpb "github.com/golang/protobuf/ptypes/duration"
+)
+
+const (
+ // Range of a durpb.Duration in seconds, as specified in
+ // google/protobuf/duration.proto. This is about 10,000 years in seconds.
+ maxSeconds = int64(10000 * 365.25 * 24 * 60 * 60)
+ minSeconds = -maxSeconds
+)
+
+// validateDuration determines whether the durpb.Duration is valid according to the
+// definition in google/protobuf/duration.proto. A valid durpb.Duration
+// may still be too large to fit into a time.Duration (the range of durpb.Duration
+// is about 10,000 years, and the range of time.Duration is about 290).
+func validateDuration(d *durpb.Duration) error {
+ if d == nil {
+ return errors.New("duration: nil Duration")
+ }
+ if d.Seconds < minSeconds || d.Seconds > maxSeconds {
+ return fmt.Errorf("duration: %v: seconds out of range", d)
+ }
+ if d.Nanos <= -1e9 || d.Nanos >= 1e9 {
+ return fmt.Errorf("duration: %v: nanos out of range", d)
+ }
+ // Seconds and Nanos must have the same sign, unless d.Nanos is zero.
+ if (d.Seconds < 0 && d.Nanos > 0) || (d.Seconds > 0 && d.Nanos < 0) {
+ return fmt.Errorf("duration: %v: seconds and nanos have different signs", d)
+ }
+ return nil
+}
+
+// Duration converts a durpb.Duration to a time.Duration. Duration
+// returns an error if the durpb.Duration is invalid or is too large to be
+// represented in a time.Duration.
+func Duration(p *durpb.Duration) (time.Duration, error) {
+ if err := validateDuration(p); err != nil {
+ return 0, err
+ }
+ d := time.Duration(p.Seconds) * time.Second
+ if int64(d/time.Second) != p.Seconds {
+ return 0, fmt.Errorf("duration: %v is out of range for time.Duration", p)
+ }
+ if p.Nanos != 0 {
+ d += time.Duration(p.Nanos)
+ if (d < 0) != (p.Nanos < 0) {
+ return 0, fmt.Errorf("duration: %v is out of range for time.Duration", p)
+ }
+ }
+ return d, nil
+}
+
+// DurationProto converts a time.Duration to a durpb.Duration.
+func DurationProto(d time.Duration) *durpb.Duration {
+ nanos := d.Nanoseconds()
+ secs := nanos / 1e9
+ nanos -= secs * 1e9
+ return &durpb.Duration{
+ Seconds: secs,
+ Nanos: int32(nanos),
+ }
+}
diff --git a/vendor/github.com/golang/protobuf/ptypes/duration/duration.pb.go b/vendor/github.com/golang/protobuf/ptypes/duration/duration.pb.go
new file mode 100644
index 000000000..0d681ee21
--- /dev/null
+++ b/vendor/github.com/golang/protobuf/ptypes/duration/duration.pb.go
@@ -0,0 +1,161 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// source: google/protobuf/duration.proto
+
+package duration
+
+import (
+ fmt "fmt"
+ proto "github.com/golang/protobuf/proto"
+ math "math"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
+
+// A Duration represents a signed, fixed-length span of time represented
+// as a count of seconds and fractions of seconds at nanosecond
+// resolution. It is independent of any calendar and concepts like "day"
+// or "month". It is related to Timestamp in that the difference between
+// two Timestamp values is a Duration and it can be added or subtracted
+// from a Timestamp. Range is approximately +-10,000 years.
+//
+// # Examples
+//
+// Example 1: Compute Duration from two Timestamps in pseudo code.
+//
+// Timestamp start = ...;
+// Timestamp end = ...;
+// Duration duration = ...;
+//
+// duration.seconds = end.seconds - start.seconds;
+// duration.nanos = end.nanos - start.nanos;
+//
+// if (duration.seconds < 0 && duration.nanos > 0) {
+// duration.seconds += 1;
+// duration.nanos -= 1000000000;
+// } else if (durations.seconds > 0 && duration.nanos < 0) {
+// duration.seconds -= 1;
+// duration.nanos += 1000000000;
+// }
+//
+// Example 2: Compute Timestamp from Timestamp + Duration in pseudo code.
+//
+// Timestamp start = ...;
+// Duration duration = ...;
+// Timestamp end = ...;
+//
+// end.seconds = start.seconds + duration.seconds;
+// end.nanos = start.nanos + duration.nanos;
+//
+// if (end.nanos < 0) {
+// end.seconds -= 1;
+// end.nanos += 1000000000;
+// } else if (end.nanos >= 1000000000) {
+// end.seconds += 1;
+// end.nanos -= 1000000000;
+// }
+//
+// Example 3: Compute Duration from datetime.timedelta in Python.
+//
+// td = datetime.timedelta(days=3, minutes=10)
+// duration = Duration()
+// duration.FromTimedelta(td)
+//
+// # JSON Mapping
+//
+// In JSON format, the Duration type is encoded as a string rather than an
+// object, where the string ends in the suffix "s" (indicating seconds) and
+// is preceded by the number of seconds, with nanoseconds expressed as
+// fractional seconds. For example, 3 seconds with 0 nanoseconds should be
+// encoded in JSON format as "3s", while 3 seconds and 1 nanosecond should
+// be expressed in JSON format as "3.000000001s", and 3 seconds and 1
+// microsecond should be expressed in JSON format as "3.000001s".
+//
+//
+type Duration struct {
+ // Signed seconds of the span of time. Must be from -315,576,000,000
+ // to +315,576,000,000 inclusive. Note: these bounds are computed from:
+ // 60 sec/min * 60 min/hr * 24 hr/day * 365.25 days/year * 10000 years
+ Seconds int64 `protobuf:"varint,1,opt,name=seconds,proto3" json:"seconds,omitempty"`
+ // Signed fractions of a second at nanosecond resolution of the span
+ // of time. Durations less than one second are represented with a 0
+ // `seconds` field and a positive or negative `nanos` field. For durations
+ // of one second or more, a non-zero value for the `nanos` field must be
+ // of the same sign as the `seconds` field. Must be from -999,999,999
+ // to +999,999,999 inclusive.
+ Nanos int32 `protobuf:"varint,2,opt,name=nanos,proto3" json:"nanos,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *Duration) Reset() { *m = Duration{} }
+func (m *Duration) String() string { return proto.CompactTextString(m) }
+func (*Duration) ProtoMessage() {}
+func (*Duration) Descriptor() ([]byte, []int) {
+ return fileDescriptor_23597b2ebd7ac6c5, []int{0}
+}
+
+func (*Duration) XXX_WellKnownType() string { return "Duration" }
+
+func (m *Duration) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_Duration.Unmarshal(m, b)
+}
+func (m *Duration) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_Duration.Marshal(b, m, deterministic)
+}
+func (m *Duration) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_Duration.Merge(m, src)
+}
+func (m *Duration) XXX_Size() int {
+ return xxx_messageInfo_Duration.Size(m)
+}
+func (m *Duration) XXX_DiscardUnknown() {
+ xxx_messageInfo_Duration.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Duration proto.InternalMessageInfo
+
+func (m *Duration) GetSeconds() int64 {
+ if m != nil {
+ return m.Seconds
+ }
+ return 0
+}
+
+func (m *Duration) GetNanos() int32 {
+ if m != nil {
+ return m.Nanos
+ }
+ return 0
+}
+
+func init() {
+ proto.RegisterType((*Duration)(nil), "google.protobuf.Duration")
+}
+
+func init() { proto.RegisterFile("google/protobuf/duration.proto", fileDescriptor_23597b2ebd7ac6c5) }
+
+var fileDescriptor_23597b2ebd7ac6c5 = []byte{
+ // 190 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4b, 0xcf, 0xcf, 0x4f,
+ 0xcf, 0x49, 0xd5, 0x2f, 0x28, 0xca, 0x2f, 0xc9, 0x4f, 0x2a, 0x4d, 0xd3, 0x4f, 0x29, 0x2d, 0x4a,
+ 0x2c, 0xc9, 0xcc, 0xcf, 0xd3, 0x03, 0x8b, 0x08, 0xf1, 0x43, 0xe4, 0xf5, 0x60, 0xf2, 0x4a, 0x56,
+ 0x5c, 0x1c, 0x2e, 0x50, 0x25, 0x42, 0x12, 0x5c, 0xec, 0xc5, 0xa9, 0xc9, 0xf9, 0x79, 0x29, 0xc5,
+ 0x12, 0x8c, 0x0a, 0x8c, 0x1a, 0xcc, 0x41, 0x30, 0xae, 0x90, 0x08, 0x17, 0x6b, 0x5e, 0x62, 0x5e,
+ 0x7e, 0xb1, 0x04, 0x93, 0x02, 0xa3, 0x06, 0x6b, 0x10, 0x84, 0xe3, 0x54, 0xc3, 0x25, 0x9c, 0x9c,
+ 0x9f, 0xab, 0x87, 0x66, 0xa4, 0x13, 0x2f, 0xcc, 0xc0, 0x00, 0x90, 0x48, 0x00, 0x63, 0x94, 0x56,
+ 0x7a, 0x66, 0x49, 0x46, 0x69, 0x92, 0x5e, 0x72, 0x7e, 0xae, 0x7e, 0x7a, 0x7e, 0x4e, 0x62, 0x5e,
+ 0x3a, 0xc2, 0x7d, 0x05, 0x25, 0x95, 0x05, 0xa9, 0xc5, 0x70, 0x67, 0xfe, 0x60, 0x64, 0x5c, 0xc4,
+ 0xc4, 0xec, 0x1e, 0xe0, 0xb4, 0x8a, 0x49, 0xce, 0x1d, 0x62, 0x6e, 0x00, 0x54, 0xa9, 0x5e, 0x78,
+ 0x6a, 0x4e, 0x8e, 0x77, 0x5e, 0x7e, 0x79, 0x5e, 0x08, 0x48, 0x4b, 0x12, 0x1b, 0xd8, 0x0c, 0x63,
+ 0x40, 0x00, 0x00, 0x00, 0xff, 0xff, 0xdc, 0x84, 0x30, 0xff, 0xf3, 0x00, 0x00, 0x00,
+}
diff --git a/vendor/github.com/golang/protobuf/ptypes/duration/duration.proto b/vendor/github.com/golang/protobuf/ptypes/duration/duration.proto
new file mode 100644
index 000000000..975fce41a
--- /dev/null
+++ b/vendor/github.com/golang/protobuf/ptypes/duration/duration.proto
@@ -0,0 +1,117 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+syntax = "proto3";
+
+package google.protobuf;
+
+option csharp_namespace = "Google.Protobuf.WellKnownTypes";
+option cc_enable_arenas = true;
+option go_package = "github.com/golang/protobuf/ptypes/duration";
+option java_package = "com.google.protobuf";
+option java_outer_classname = "DurationProto";
+option java_multiple_files = true;
+option objc_class_prefix = "GPB";
+
+// A Duration represents a signed, fixed-length span of time represented
+// as a count of seconds and fractions of seconds at nanosecond
+// resolution. It is independent of any calendar and concepts like "day"
+// or "month". It is related to Timestamp in that the difference between
+// two Timestamp values is a Duration and it can be added or subtracted
+// from a Timestamp. Range is approximately +-10,000 years.
+//
+// # Examples
+//
+// Example 1: Compute Duration from two Timestamps in pseudo code.
+//
+// Timestamp start = ...;
+// Timestamp end = ...;
+// Duration duration = ...;
+//
+// duration.seconds = end.seconds - start.seconds;
+// duration.nanos = end.nanos - start.nanos;
+//
+// if (duration.seconds < 0 && duration.nanos > 0) {
+// duration.seconds += 1;
+// duration.nanos -= 1000000000;
+// } else if (durations.seconds > 0 && duration.nanos < 0) {
+// duration.seconds -= 1;
+// duration.nanos += 1000000000;
+// }
+//
+// Example 2: Compute Timestamp from Timestamp + Duration in pseudo code.
+//
+// Timestamp start = ...;
+// Duration duration = ...;
+// Timestamp end = ...;
+//
+// end.seconds = start.seconds + duration.seconds;
+// end.nanos = start.nanos + duration.nanos;
+//
+// if (end.nanos < 0) {
+// end.seconds -= 1;
+// end.nanos += 1000000000;
+// } else if (end.nanos >= 1000000000) {
+// end.seconds += 1;
+// end.nanos -= 1000000000;
+// }
+//
+// Example 3: Compute Duration from datetime.timedelta in Python.
+//
+// td = datetime.timedelta(days=3, minutes=10)
+// duration = Duration()
+// duration.FromTimedelta(td)
+//
+// # JSON Mapping
+//
+// In JSON format, the Duration type is encoded as a string rather than an
+// object, where the string ends in the suffix "s" (indicating seconds) and
+// is preceded by the number of seconds, with nanoseconds expressed as
+// fractional seconds. For example, 3 seconds with 0 nanoseconds should be
+// encoded in JSON format as "3s", while 3 seconds and 1 nanosecond should
+// be expressed in JSON format as "3.000000001s", and 3 seconds and 1
+// microsecond should be expressed in JSON format as "3.000001s".
+//
+//
+message Duration {
+
+ // Signed seconds of the span of time. Must be from -315,576,000,000
+ // to +315,576,000,000 inclusive. Note: these bounds are computed from:
+ // 60 sec/min * 60 min/hr * 24 hr/day * 365.25 days/year * 10000 years
+ int64 seconds = 1;
+
+ // Signed fractions of a second at nanosecond resolution of the span
+ // of time. Durations less than one second are represented with a 0
+ // `seconds` field and a positive or negative `nanos` field. For durations
+ // of one second or more, a non-zero value for the `nanos` field must be
+ // of the same sign as the `seconds` field. Must be from -999,999,999
+ // to +999,999,999 inclusive.
+ int32 nanos = 2;
+}
diff --git a/vendor/github.com/golang/protobuf/ptypes/timestamp.go b/vendor/github.com/golang/protobuf/ptypes/timestamp.go
new file mode 100644
index 000000000..47f10dbc2
--- /dev/null
+++ b/vendor/github.com/golang/protobuf/ptypes/timestamp.go
@@ -0,0 +1,134 @@
+// Go support for Protocol Buffers - Google's data interchange format
+//
+// Copyright 2016 The Go Authors. All rights reserved.
+// https://github.com/golang/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package ptypes
+
+// This file implements operations on google.protobuf.Timestamp.
+
+import (
+ "errors"
+ "fmt"
+ "time"
+
+ tspb "github.com/golang/protobuf/ptypes/timestamp"
+)
+
+const (
+ // Seconds field of the earliest valid Timestamp.
+ // This is time.Date(1, 1, 1, 0, 0, 0, 0, time.UTC).Unix().
+ minValidSeconds = -62135596800
+ // Seconds field just after the latest valid Timestamp.
+ // This is time.Date(10000, 1, 1, 0, 0, 0, 0, time.UTC).Unix().
+ maxValidSeconds = 253402300800
+)
+
+// validateTimestamp determines whether a Timestamp is valid.
+// A valid timestamp represents a time in the range
+// [0001-01-01, 10000-01-01) and has a Nanos field
+// in the range [0, 1e9).
+//
+// If the Timestamp is valid, validateTimestamp returns nil.
+// Otherwise, it returns an error that describes
+// the problem.
+//
+// Every valid Timestamp can be represented by a time.Time, but the converse is not true.
+func validateTimestamp(ts *tspb.Timestamp) error {
+ if ts == nil {
+ return errors.New("timestamp: nil Timestamp")
+ }
+ if ts.Seconds < minValidSeconds {
+ return fmt.Errorf("timestamp: %v before 0001-01-01", ts)
+ }
+ if ts.Seconds >= maxValidSeconds {
+ return fmt.Errorf("timestamp: %v after 10000-01-01", ts)
+ }
+ if ts.Nanos < 0 || ts.Nanos >= 1e9 {
+ return fmt.Errorf("timestamp: %v: nanos not in range [0, 1e9)", ts)
+ }
+ return nil
+}
+
+// Timestamp converts a google.protobuf.Timestamp proto to a time.Time.
+// It returns an error if the argument is invalid.
+//
+// Unlike most Go functions, if Timestamp returns an error, the first return value
+// is not the zero time.Time. Instead, it is the value obtained from the
+// time.Unix function when passed the contents of the Timestamp, in the UTC
+// locale. This may or may not be a meaningful time; many invalid Timestamps
+// do map to valid time.Times.
+//
+// A nil Timestamp returns an error. The first return value in that case is
+// undefined.
+func Timestamp(ts *tspb.Timestamp) (time.Time, error) {
+ // Don't return the zero value on error, because corresponds to a valid
+ // timestamp. Instead return whatever time.Unix gives us.
+ var t time.Time
+ if ts == nil {
+ t = time.Unix(0, 0).UTC() // treat nil like the empty Timestamp
+ } else {
+ t = time.Unix(ts.Seconds, int64(ts.Nanos)).UTC()
+ }
+ return t, validateTimestamp(ts)
+}
+
+// TimestampNow returns a google.protobuf.Timestamp for the current time.
+func TimestampNow() *tspb.Timestamp {
+ ts, err := TimestampProto(time.Now())
+ if err != nil {
+ panic("ptypes: time.Now() out of Timestamp range")
+ }
+ return ts
+}
+
+// TimestampProto converts the time.Time to a google.protobuf.Timestamp proto.
+// It returns an error if the resulting Timestamp is invalid.
+func TimestampProto(t time.Time) (*tspb.Timestamp, error) {
+ seconds := t.Unix()
+ nanos := int32(t.Sub(time.Unix(seconds, 0)))
+ ts := &tspb.Timestamp{
+ Seconds: seconds,
+ Nanos: nanos,
+ }
+ if err := validateTimestamp(ts); err != nil {
+ return nil, err
+ }
+ return ts, nil
+}
+
+// TimestampString returns the RFC 3339 string for valid Timestamps. For invalid
+// Timestamps, it returns an error message in parentheses.
+func TimestampString(ts *tspb.Timestamp) string {
+ t, err := Timestamp(ts)
+ if err != nil {
+ return fmt.Sprintf("(%v)", err)
+ }
+ return t.Format(time.RFC3339Nano)
+}
diff --git a/vendor/github.com/golang/protobuf/ptypes/timestamp/timestamp.pb.go b/vendor/github.com/golang/protobuf/ptypes/timestamp/timestamp.pb.go
new file mode 100644
index 000000000..31cd846de
--- /dev/null
+++ b/vendor/github.com/golang/protobuf/ptypes/timestamp/timestamp.pb.go
@@ -0,0 +1,179 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// source: google/protobuf/timestamp.proto
+
+package timestamp
+
+import (
+ fmt "fmt"
+ proto "github.com/golang/protobuf/proto"
+ math "math"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
+
+// A Timestamp represents a point in time independent of any time zone
+// or calendar, represented as seconds and fractions of seconds at
+// nanosecond resolution in UTC Epoch time. It is encoded using the
+// Proleptic Gregorian Calendar which extends the Gregorian calendar
+// backwards to year one. It is encoded assuming all minutes are 60
+// seconds long, i.e. leap seconds are "smeared" so that no leap second
+// table is needed for interpretation. Range is from
+// 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z.
+// By restricting to that range, we ensure that we can convert to
+// and from RFC 3339 date strings.
+// See [https://www.ietf.org/rfc/rfc3339.txt](https://www.ietf.org/rfc/rfc3339.txt).
+//
+// # Examples
+//
+// Example 1: Compute Timestamp from POSIX `time()`.
+//
+// Timestamp timestamp;
+// timestamp.set_seconds(time(NULL));
+// timestamp.set_nanos(0);
+//
+// Example 2: Compute Timestamp from POSIX `gettimeofday()`.
+//
+// struct timeval tv;
+// gettimeofday(&tv, NULL);
+//
+// Timestamp timestamp;
+// timestamp.set_seconds(tv.tv_sec);
+// timestamp.set_nanos(tv.tv_usec * 1000);
+//
+// Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`.
+//
+// FILETIME ft;
+// GetSystemTimeAsFileTime(&ft);
+// UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
+//
+// // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z
+// // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z.
+// Timestamp timestamp;
+// timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL));
+// timestamp.set_nanos((INT32) ((ticks % 10000000) * 100));
+//
+// Example 4: Compute Timestamp from Java `System.currentTimeMillis()`.
+//
+// long millis = System.currentTimeMillis();
+//
+// Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000)
+// .setNanos((int) ((millis % 1000) * 1000000)).build();
+//
+//
+// Example 5: Compute Timestamp from current time in Python.
+//
+// timestamp = Timestamp()
+// timestamp.GetCurrentTime()
+//
+// # JSON Mapping
+//
+// In JSON format, the Timestamp type is encoded as a string in the
+// [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format. That is, the
+// format is "{year}-{month}-{day}T{hour}:{min}:{sec}[.{frac_sec}]Z"
+// where {year} is always expressed using four digits while {month}, {day},
+// {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional
+// seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution),
+// are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone
+// is required. A proto3 JSON serializer should always use UTC (as indicated by
+// "Z") when printing the Timestamp type and a proto3 JSON parser should be
+// able to accept both UTC and other timezones (as indicated by an offset).
+//
+// For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past
+// 01:30 UTC on January 15, 2017.
+//
+// In JavaScript, one can convert a Date object to this format using the
+// standard [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString]
+// method. In Python, a standard `datetime.datetime` object can be converted
+// to this format using [`strftime`](https://docs.python.org/2/library/time.html#time.strftime)
+// with the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one
+// can use the Joda Time's [`ISODateTimeFormat.dateTime()`](
+// http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime--
+// ) to obtain a formatter capable of generating timestamps in this format.
+//
+//
+type Timestamp struct {
+ // Represents seconds of UTC time since Unix epoch
+ // 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to
+ // 9999-12-31T23:59:59Z inclusive.
+ Seconds int64 `protobuf:"varint,1,opt,name=seconds,proto3" json:"seconds,omitempty"`
+ // Non-negative fractions of a second at nanosecond resolution. Negative
+ // second values with fractions must still have non-negative nanos values
+ // that count forward in time. Must be from 0 to 999,999,999
+ // inclusive.
+ Nanos int32 `protobuf:"varint,2,opt,name=nanos,proto3" json:"nanos,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *Timestamp) Reset() { *m = Timestamp{} }
+func (m *Timestamp) String() string { return proto.CompactTextString(m) }
+func (*Timestamp) ProtoMessage() {}
+func (*Timestamp) Descriptor() ([]byte, []int) {
+ return fileDescriptor_292007bbfe81227e, []int{0}
+}
+
+func (*Timestamp) XXX_WellKnownType() string { return "Timestamp" }
+
+func (m *Timestamp) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_Timestamp.Unmarshal(m, b)
+}
+func (m *Timestamp) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_Timestamp.Marshal(b, m, deterministic)
+}
+func (m *Timestamp) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_Timestamp.Merge(m, src)
+}
+func (m *Timestamp) XXX_Size() int {
+ return xxx_messageInfo_Timestamp.Size(m)
+}
+func (m *Timestamp) XXX_DiscardUnknown() {
+ xxx_messageInfo_Timestamp.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Timestamp proto.InternalMessageInfo
+
+func (m *Timestamp) GetSeconds() int64 {
+ if m != nil {
+ return m.Seconds
+ }
+ return 0
+}
+
+func (m *Timestamp) GetNanos() int32 {
+ if m != nil {
+ return m.Nanos
+ }
+ return 0
+}
+
+func init() {
+ proto.RegisterType((*Timestamp)(nil), "google.protobuf.Timestamp")
+}
+
+func init() { proto.RegisterFile("google/protobuf/timestamp.proto", fileDescriptor_292007bbfe81227e) }
+
+var fileDescriptor_292007bbfe81227e = []byte{
+ // 191 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4f, 0xcf, 0xcf, 0x4f,
+ 0xcf, 0x49, 0xd5, 0x2f, 0x28, 0xca, 0x2f, 0xc9, 0x4f, 0x2a, 0x4d, 0xd3, 0x2f, 0xc9, 0xcc, 0x4d,
+ 0x2d, 0x2e, 0x49, 0xcc, 0x2d, 0xd0, 0x03, 0x0b, 0x09, 0xf1, 0x43, 0x14, 0xe8, 0xc1, 0x14, 0x28,
+ 0x59, 0x73, 0x71, 0x86, 0xc0, 0xd4, 0x08, 0x49, 0x70, 0xb1, 0x17, 0xa7, 0x26, 0xe7, 0xe7, 0xa5,
+ 0x14, 0x4b, 0x30, 0x2a, 0x30, 0x6a, 0x30, 0x07, 0xc1, 0xb8, 0x42, 0x22, 0x5c, 0xac, 0x79, 0x89,
+ 0x79, 0xf9, 0xc5, 0x12, 0x4c, 0x0a, 0x8c, 0x1a, 0xac, 0x41, 0x10, 0x8e, 0x53, 0x1d, 0x97, 0x70,
+ 0x72, 0x7e, 0xae, 0x1e, 0x9a, 0x99, 0x4e, 0x7c, 0x70, 0x13, 0x03, 0x40, 0x42, 0x01, 0x8c, 0x51,
+ 0xda, 0xe9, 0x99, 0x25, 0x19, 0xa5, 0x49, 0x7a, 0xc9, 0xf9, 0xb9, 0xfa, 0xe9, 0xf9, 0x39, 0x89,
+ 0x79, 0xe9, 0x08, 0x27, 0x16, 0x94, 0x54, 0x16, 0xa4, 0x16, 0x23, 0x5c, 0xfa, 0x83, 0x91, 0x71,
+ 0x11, 0x13, 0xb3, 0x7b, 0x80, 0xd3, 0x2a, 0x26, 0x39, 0x77, 0x88, 0xc9, 0x01, 0x50, 0xb5, 0x7a,
+ 0xe1, 0xa9, 0x39, 0x39, 0xde, 0x79, 0xf9, 0xe5, 0x79, 0x21, 0x20, 0x3d, 0x49, 0x6c, 0x60, 0x43,
+ 0x8c, 0x01, 0x01, 0x00, 0x00, 0xff, 0xff, 0xbc, 0x77, 0x4a, 0x07, 0xf7, 0x00, 0x00, 0x00,
+}
diff --git a/vendor/github.com/golang/protobuf/ptypes/timestamp/timestamp.proto b/vendor/github.com/golang/protobuf/ptypes/timestamp/timestamp.proto
new file mode 100644
index 000000000..eafb3fa03
--- /dev/null
+++ b/vendor/github.com/golang/protobuf/ptypes/timestamp/timestamp.proto
@@ -0,0 +1,135 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+syntax = "proto3";
+
+package google.protobuf;
+
+option csharp_namespace = "Google.Protobuf.WellKnownTypes";
+option cc_enable_arenas = true;
+option go_package = "github.com/golang/protobuf/ptypes/timestamp";
+option java_package = "com.google.protobuf";
+option java_outer_classname = "TimestampProto";
+option java_multiple_files = true;
+option objc_class_prefix = "GPB";
+
+// A Timestamp represents a point in time independent of any time zone
+// or calendar, represented as seconds and fractions of seconds at
+// nanosecond resolution in UTC Epoch time. It is encoded using the
+// Proleptic Gregorian Calendar which extends the Gregorian calendar
+// backwards to year one. It is encoded assuming all minutes are 60
+// seconds long, i.e. leap seconds are "smeared" so that no leap second
+// table is needed for interpretation. Range is from
+// 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z.
+// By restricting to that range, we ensure that we can convert to
+// and from RFC 3339 date strings.
+// See [https://www.ietf.org/rfc/rfc3339.txt](https://www.ietf.org/rfc/rfc3339.txt).
+//
+// # Examples
+//
+// Example 1: Compute Timestamp from POSIX `time()`.
+//
+// Timestamp timestamp;
+// timestamp.set_seconds(time(NULL));
+// timestamp.set_nanos(0);
+//
+// Example 2: Compute Timestamp from POSIX `gettimeofday()`.
+//
+// struct timeval tv;
+// gettimeofday(&tv, NULL);
+//
+// Timestamp timestamp;
+// timestamp.set_seconds(tv.tv_sec);
+// timestamp.set_nanos(tv.tv_usec * 1000);
+//
+// Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`.
+//
+// FILETIME ft;
+// GetSystemTimeAsFileTime(&ft);
+// UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
+//
+// // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z
+// // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z.
+// Timestamp timestamp;
+// timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL));
+// timestamp.set_nanos((INT32) ((ticks % 10000000) * 100));
+//
+// Example 4: Compute Timestamp from Java `System.currentTimeMillis()`.
+//
+// long millis = System.currentTimeMillis();
+//
+// Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000)
+// .setNanos((int) ((millis % 1000) * 1000000)).build();
+//
+//
+// Example 5: Compute Timestamp from current time in Python.
+//
+// timestamp = Timestamp()
+// timestamp.GetCurrentTime()
+//
+// # JSON Mapping
+//
+// In JSON format, the Timestamp type is encoded as a string in the
+// [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format. That is, the
+// format is "{year}-{month}-{day}T{hour}:{min}:{sec}[.{frac_sec}]Z"
+// where {year} is always expressed using four digits while {month}, {day},
+// {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional
+// seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution),
+// are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone
+// is required. A proto3 JSON serializer should always use UTC (as indicated by
+// "Z") when printing the Timestamp type and a proto3 JSON parser should be
+// able to accept both UTC and other timezones (as indicated by an offset).
+//
+// For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past
+// 01:30 UTC on January 15, 2017.
+//
+// In JavaScript, one can convert a Date object to this format using the
+// standard [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString]
+// method. In Python, a standard `datetime.datetime` object can be converted
+// to this format using [`strftime`](https://docs.python.org/2/library/time.html#time.strftime)
+// with the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one
+// can use the Joda Time's [`ISODateTimeFormat.dateTime()`](
+// http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime--
+// ) to obtain a formatter capable of generating timestamps in this format.
+//
+//
+message Timestamp {
+
+ // Represents seconds of UTC time since Unix epoch
+ // 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to
+ // 9999-12-31T23:59:59Z inclusive.
+ int64 seconds = 1;
+
+ // Non-negative fractions of a second at nanosecond resolution. Negative
+ // second values with fractions must still have non-negative nanos values
+ // that count forward in time. Must be from 0 to 999,999,999
+ // inclusive.
+ int32 nanos = 2;
+}
diff --git a/vendor/github.com/googleapis/gax-go/CODE_OF_CONDUCT.md b/vendor/github.com/googleapis/gax-go/CODE_OF_CONDUCT.md
new file mode 100644
index 000000000..46b2a08ea
--- /dev/null
+++ b/vendor/github.com/googleapis/gax-go/CODE_OF_CONDUCT.md
@@ -0,0 +1,43 @@
+# Contributor Code of Conduct
+
+As contributors and maintainers of this project,
+and in the interest of fostering an open and welcoming community,
+we pledge to respect all people who contribute through reporting issues,
+posting feature requests, updating documentation,
+submitting pull requests or patches, and other activities.
+
+We are committed to making participation in this project
+a harassment-free experience for everyone,
+regardless of level of experience, gender, gender identity and expression,
+sexual orientation, disability, personal appearance,
+body size, race, ethnicity, age, religion, or nationality.
+
+Examples of unacceptable behavior by participants include:
+
+* The use of sexualized language or imagery
+* Personal attacks
+* Trolling or insulting/derogatory comments
+* Public or private harassment
+* Publishing other's private information,
+such as physical or electronic
+addresses, without explicit permission
+* Other unethical or unprofessional conduct.
+
+Project maintainers have the right and responsibility to remove, edit, or reject
+comments, commits, code, wiki edits, issues, and other contributions
+that are not aligned to this Code of Conduct.
+By adopting this Code of Conduct,
+project maintainers commit themselves to fairly and consistently
+applying these principles to every aspect of managing this project.
+Project maintainers who do not follow or enforce the Code of Conduct
+may be permanently removed from the project team.
+
+This code of conduct applies both within project spaces and in public spaces
+when an individual is representing the project or its community.
+
+Instances of abusive, harassing, or otherwise unacceptable behavior
+may be reported by opening an issue
+or contacting one or more of the project maintainers.
+
+This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.2.0,
+available at [http://contributor-covenant.org/version/1/2/0/](http://contributor-covenant.org/version/1/2/0/)
diff --git a/vendor/github.com/googleapis/gax-go/CONTRIBUTING.md b/vendor/github.com/googleapis/gax-go/CONTRIBUTING.md
new file mode 100644
index 000000000..2827b7d3f
--- /dev/null
+++ b/vendor/github.com/googleapis/gax-go/CONTRIBUTING.md
@@ -0,0 +1,27 @@
+Want to contribute? Great! First, read this page (including the small print at the end).
+
+### Before you contribute
+Before we can use your code, you must sign the
+[Google Individual Contributor License Agreement]
+(https://cla.developers.google.com/about/google-individual)
+(CLA), which you can do online. The CLA is necessary mainly because you own the
+copyright to your changes, even after your contribution becomes part of our
+codebase, so we need your permission to use and distribute your code. We also
+need to be sure of various other things—for instance that you'll tell us if you
+know that your code infringes on other people's patents. You don't have to sign
+the CLA until after you've submitted your code for review and a member has
+approved it, but you must do it before we can put your code into our codebase.
+Before you start working on a larger contribution, you should get in touch with
+us first through the issue tracker with your idea so that we can help out and
+possibly guide you. Coordinating up front makes it much easier to avoid
+frustration later on.
+
+### Code reviews
+All submissions, including submissions by project members, require review. We
+use Github pull requests for this purpose.
+
+### The small print
+Contributions made by corporations are covered by a different agreement than
+the one above, the
+[Software Grant and Corporate Contributor License Agreement]
+(https://cla.developers.google.com/about/google-corporate).
diff --git a/vendor/github.com/googleapis/gax-go/LICENSE b/vendor/github.com/googleapis/gax-go/LICENSE
new file mode 100644
index 000000000..6d16b6578
--- /dev/null
+++ b/vendor/github.com/googleapis/gax-go/LICENSE
@@ -0,0 +1,27 @@
+Copyright 2016, Google Inc.
+All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/vendor/github.com/googleapis/gax-go/README.md b/vendor/github.com/googleapis/gax-go/README.md
new file mode 100644
index 000000000..c3bb2e187
--- /dev/null
+++ b/vendor/github.com/googleapis/gax-go/README.md
@@ -0,0 +1,27 @@
+Google API Extensions for Go
+============================
+
+[![GoDoc](https://godoc.org/github.com/googleapis/gax-go?status.svg)](https://godoc.org/github.com/googleapis/gax-go)
+
+Google API Extensions for Go (gax-go) is a set of modules which aids the
+development of APIs for clients and servers based on `gRPC` and Google API
+conventions.
+
+To install the API extensions, use:
+
+```
+go get -u github.com/googleapis/gax-go
+```
+
+**Note:** Application code will rarely need to use this library directly,
+but the code generated automatically from API definition files can use it
+to simplify code generation and to provide more convenient and idiomatic API surface.
+
+Go Versions
+===========
+This library requires Go 1.6 or above.
+
+License
+=======
+BSD - please see [LICENSE](https://github.com/googleapis/gax-go/blob/master/LICENSE)
+for more information.
diff --git a/vendor/github.com/googleapis/gax-go/call_option.go b/vendor/github.com/googleapis/gax-go/call_option.go
new file mode 100644
index 000000000..5bd48972b
--- /dev/null
+++ b/vendor/github.com/googleapis/gax-go/call_option.go
@@ -0,0 +1,71 @@
+// Copyright 2016, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package gax
+
+import (
+ v2 "github.com/googleapis/gax-go/v2"
+ "google.golang.org/grpc"
+ "google.golang.org/grpc/codes"
+)
+
+// CallOption is an option used by Invoke to control behaviors of RPC calls.
+// CallOption works by modifying relevant fields of CallSettings.
+type CallOption = v2.CallOption
+
+// Retryer is used by Invoke to determine retry behavior.
+type Retryer = v2.Retryer
+
+// WithRetry sets CallSettings.Retry to fn.
+func WithRetry(fn func() Retryer) CallOption {
+ return v2.WithRetry(fn)
+}
+
+// OnCodes returns a Retryer that retries if and only if
+// the previous attempt returns a GRPC error whose error code is stored in cc.
+// Pause times between retries are specified by bo.
+//
+// bo is only used for its parameters; each Retryer has its own copy.
+func OnCodes(cc []codes.Code, bo Backoff) Retryer {
+ return v2.OnCodes(cc, bo)
+}
+
+// Backoff implements exponential backoff.
+// The wait time between retries is a random value between 0 and the "retry envelope".
+// The envelope starts at Initial and increases by the factor of Multiplier every retry,
+// but is capped at Max.
+type Backoff = v2.Backoff
+
+// WithGRPCOptions allows passing gRPC call options during client creation.
+func WithGRPCOptions(opt ...grpc.CallOption) CallOption {
+ return v2.WithGRPCOptions(opt...)
+}
+
+// CallSettings allow fine-grained control over how calls are made.
+type CallSettings = v2.CallSettings
diff --git a/vendor/github.com/googleapis/gax-go/gax.go b/vendor/github.com/googleapis/gax-go/gax.go
new file mode 100644
index 000000000..006739804
--- /dev/null
+++ b/vendor/github.com/googleapis/gax-go/gax.go
@@ -0,0 +1,39 @@
+// Copyright 2016, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Package gax contains a set of modules which aid the development of APIs
+// for clients and servers based on gRPC and Google API conventions.
+//
+// Application code will rarely need to use this library directly.
+// However, code generated automatically from API definition files can use it
+// to simplify code generation and to provide more convenient and idiomatic API surfaces.
+package gax
+
+// Version specifies the gax version.
+const Version = "1.0.1"
diff --git a/vendor/github.com/googleapis/gax-go/go.mod b/vendor/github.com/googleapis/gax-go/go.mod
new file mode 100644
index 000000000..dc69a07c9
--- /dev/null
+++ b/vendor/github.com/googleapis/gax-go/go.mod
@@ -0,0 +1,6 @@
+module github.com/googleapis/gax-go
+
+require (
+ github.com/googleapis/gax-go/v2 v2.0.2
+ google.golang.org/grpc v1.16.0
+)
diff --git a/vendor/github.com/googleapis/gax-go/go.sum b/vendor/github.com/googleapis/gax-go/go.sum
new file mode 100644
index 000000000..2fb5cc0a3
--- /dev/null
+++ b/vendor/github.com/googleapis/gax-go/go.sum
@@ -0,0 +1,28 @@
+cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
+github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
+github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
+github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E=
+github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
+github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
+github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/googleapis/gax-go/v2 v2.0.2 h1:/rNgUniLy2vDXiK2xyJOcirGpC3G99dtK1NWx26WZ8Y=
+github.com/googleapis/gax-go/v2 v2.0.2/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg=
+github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
+golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
+golang.org/x/net v0.0.0-20180826012351-8a410e7b638d h1:g9qWBGx4puODJTMVyoPrpoxPFgVGd+z1DZwjfRu4d0I=
+golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
+golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA=
+golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20180830151530-49385e6e1522 h1:Ve1ORMCxvRmSXBwJK+t3Oy+V2vRW2OetUQBq4rJIkZE=
+golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
+google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0NQvRW8DG4Yk3Q6T9cu9RcFQDu1tc=
+google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
+google.golang.org/grpc v1.16.0 h1:dz5IJGuC2BB7qXR5AyHNwAUBhZscK2xVez7mznh72sY=
+google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
+honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
diff --git a/vendor/github.com/googleapis/gax-go/header.go b/vendor/github.com/googleapis/gax-go/header.go
new file mode 100644
index 000000000..e1a0af1ba
--- /dev/null
+++ b/vendor/github.com/googleapis/gax-go/header.go
@@ -0,0 +1,40 @@
+// Copyright 2018, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package gax
+
+import v2 "github.com/googleapis/gax-go/v2"
+
+// XGoogHeader is for use by the Google Cloud Libraries only.
+//
+// XGoogHeader formats key-value pairs.
+// The resulting string is suitable for x-goog-api-client header.
+func XGoogHeader(keyval ...string) string {
+ return v2.XGoogHeader(keyval...)
+}
diff --git a/vendor/github.com/googleapis/gax-go/invoke.go b/vendor/github.com/googleapis/gax-go/invoke.go
new file mode 100644
index 000000000..6422d3f73
--- /dev/null
+++ b/vendor/github.com/googleapis/gax-go/invoke.go
@@ -0,0 +1,52 @@
+// Copyright 2016, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package gax
+
+import (
+ "context"
+ "time"
+
+ v2 "github.com/googleapis/gax-go/v2"
+)
+
+// APICall is a user defined call stub.
+type APICall = v2.APICall
+
+// Invoke calls the given APICall,
+// performing retries as specified by opts, if any.
+func Invoke(ctx context.Context, call APICall, opts ...CallOption) error {
+ return v2.Invoke(ctx, call, opts...)
+}
+
+// Sleep is similar to time.Sleep, but it can be interrupted by ctx.Done() closing.
+// If interrupted, Sleep returns ctx.Err().
+func Sleep(ctx context.Context, d time.Duration) error {
+ return v2.Sleep(ctx, d)
+}
diff --git a/vendor/github.com/googleapis/gax-go/v2/call_option.go b/vendor/github.com/googleapis/gax-go/v2/call_option.go
new file mode 100644
index 000000000..b1d53dd19
--- /dev/null
+++ b/vendor/github.com/googleapis/gax-go/v2/call_option.go
@@ -0,0 +1,161 @@
+// Copyright 2016, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package gax
+
+import (
+ "math/rand"
+ "time"
+
+ "google.golang.org/grpc"
+ "google.golang.org/grpc/codes"
+ "google.golang.org/grpc/status"
+)
+
+// CallOption is an option used by Invoke to control behaviors of RPC calls.
+// CallOption works by modifying relevant fields of CallSettings.
+type CallOption interface {
+ // Resolve applies the option by modifying cs.
+ Resolve(cs *CallSettings)
+}
+
+// Retryer is used by Invoke to determine retry behavior.
+type Retryer interface {
+ // Retry reports whether a request should be retriedand how long to pause before retrying
+ // if the previous attempt returned with err. Invoke never calls Retry with nil error.
+ Retry(err error) (pause time.Duration, shouldRetry bool)
+}
+
+type retryerOption func() Retryer
+
+func (o retryerOption) Resolve(s *CallSettings) {
+ s.Retry = o
+}
+
+// WithRetry sets CallSettings.Retry to fn.
+func WithRetry(fn func() Retryer) CallOption {
+ return retryerOption(fn)
+}
+
+// OnCodes returns a Retryer that retries if and only if
+// the previous attempt returns a GRPC error whose error code is stored in cc.
+// Pause times between retries are specified by bo.
+//
+// bo is only used for its parameters; each Retryer has its own copy.
+func OnCodes(cc []codes.Code, bo Backoff) Retryer {
+ return &boRetryer{
+ backoff: bo,
+ codes: append([]codes.Code(nil), cc...),
+ }
+}
+
+type boRetryer struct {
+ backoff Backoff
+ codes []codes.Code
+}
+
+func (r *boRetryer) Retry(err error) (time.Duration, bool) {
+ st, ok := status.FromError(err)
+ if !ok {
+ return 0, false
+ }
+ c := st.Code()
+ for _, rc := range r.codes {
+ if c == rc {
+ return r.backoff.Pause(), true
+ }
+ }
+ return 0, false
+}
+
+// Backoff implements exponential backoff.
+// The wait time between retries is a random value between 0 and the "retry envelope".
+// The envelope starts at Initial and increases by the factor of Multiplier every retry,
+// but is capped at Max.
+type Backoff struct {
+ // Initial is the initial value of the retry envelope, defaults to 1 second.
+ Initial time.Duration
+
+ // Max is the maximum value of the retry envelope, defaults to 30 seconds.
+ Max time.Duration
+
+ // Multiplier is the factor by which the retry envelope increases.
+ // It should be greater than 1 and defaults to 2.
+ Multiplier float64
+
+ // cur is the current retry envelope
+ cur time.Duration
+}
+
+// Pause returns the next time.Duration that the caller should use to backoff.
+func (bo *Backoff) Pause() time.Duration {
+ if bo.Initial == 0 {
+ bo.Initial = time.Second
+ }
+ if bo.cur == 0 {
+ bo.cur = bo.Initial
+ }
+ if bo.Max == 0 {
+ bo.Max = 30 * time.Second
+ }
+ if bo.Multiplier < 1 {
+ bo.Multiplier = 2
+ }
+ // Select a duration between 1ns and the current max. It might seem
+ // counterintuitive to have so much jitter, but
+ // https://www.awsarchitectureblog.com/2015/03/backoff.html argues that
+ // that is the best strategy.
+ d := time.Duration(1 + rand.Int63n(int64(bo.cur)))
+ bo.cur = time.Duration(float64(bo.cur) * bo.Multiplier)
+ if bo.cur > bo.Max {
+ bo.cur = bo.Max
+ }
+ return d
+}
+
+type grpcOpt []grpc.CallOption
+
+func (o grpcOpt) Resolve(s *CallSettings) {
+ s.GRPC = o
+}
+
+// WithGRPCOptions allows passing gRPC call options during client creation.
+func WithGRPCOptions(opt ...grpc.CallOption) CallOption {
+ return grpcOpt(append([]grpc.CallOption(nil), opt...))
+}
+
+// CallSettings allow fine-grained control over how calls are made.
+type CallSettings struct {
+ // Retry returns a Retryer to be used to control retry logic of a method call.
+ // If Retry is nil or the returned Retryer is nil, the call will not be retried.
+ Retry func() Retryer
+
+ // CallOptions to be forwarded to GRPC.
+ GRPC []grpc.CallOption
+}
diff --git a/vendor/github.com/googleapis/gax-go/v2/gax.go b/vendor/github.com/googleapis/gax-go/v2/gax.go
new file mode 100644
index 000000000..1ba4629a4
--- /dev/null
+++ b/vendor/github.com/googleapis/gax-go/v2/gax.go
@@ -0,0 +1,39 @@
+// Copyright 2016, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Package gax contains a set of modules which aid the development of APIs
+// for clients and servers based on gRPC and Google API conventions.
+//
+// Application code will rarely need to use this library directly.
+// However, code generated automatically from API definition files can use it
+// to simplify code generation and to provide more convenient and idiomatic API surfaces.
+package gax
+
+// Version specifies the gax-go version being used.
+const Version = "2.0.1"
diff --git a/vendor/github.com/googleapis/gax-go/v2/go.mod b/vendor/github.com/googleapis/gax-go/v2/go.mod
new file mode 100644
index 000000000..c88c20526
--- /dev/null
+++ b/vendor/github.com/googleapis/gax-go/v2/go.mod
@@ -0,0 +1,3 @@
+module github.com/googleapis/gax-go/v2
+
+require google.golang.org/grpc v1.16.0
diff --git a/vendor/github.com/googleapis/gax-go/v2/go.sum b/vendor/github.com/googleapis/gax-go/v2/go.sum
new file mode 100644
index 000000000..bad34abcd
--- /dev/null
+++ b/vendor/github.com/googleapis/gax-go/v2/go.sum
@@ -0,0 +1,26 @@
+cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
+github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
+github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
+github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E=
+github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
+github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
+github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
+golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
+golang.org/x/net v0.0.0-20180826012351-8a410e7b638d h1:g9qWBGx4puODJTMVyoPrpoxPFgVGd+z1DZwjfRu4d0I=
+golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
+golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA=
+golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20180830151530-49385e6e1522 h1:Ve1ORMCxvRmSXBwJK+t3Oy+V2vRW2OetUQBq4rJIkZE=
+golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
+google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0NQvRW8DG4Yk3Q6T9cu9RcFQDu1tc=
+google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
+google.golang.org/grpc v1.16.0 h1:dz5IJGuC2BB7qXR5AyHNwAUBhZscK2xVez7mznh72sY=
+google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
+honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
diff --git a/vendor/github.com/googleapis/gax-go/v2/header.go b/vendor/github.com/googleapis/gax-go/v2/header.go
new file mode 100644
index 000000000..139371a0b
--- /dev/null
+++ b/vendor/github.com/googleapis/gax-go/v2/header.go
@@ -0,0 +1,53 @@
+// Copyright 2018, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package gax
+
+import "bytes"
+
+// XGoogHeader is for use by the Google Cloud Libraries only.
+//
+// XGoogHeader formats key-value pairs.
+// The resulting string is suitable for x-goog-api-client header.
+func XGoogHeader(keyval ...string) string {
+ if len(keyval) == 0 {
+ return ""
+ }
+ if len(keyval)%2 != 0 {
+ panic("gax.Header: odd argument count")
+ }
+ var buf bytes.Buffer
+ for i := 0; i < len(keyval); i += 2 {
+ buf.WriteByte(' ')
+ buf.WriteString(keyval[i])
+ buf.WriteByte('/')
+ buf.WriteString(keyval[i+1])
+ }
+ return buf.String()[1:]
+}
diff --git a/vendor/github.com/googleapis/gax-go/v2/invoke.go b/vendor/github.com/googleapis/gax-go/v2/invoke.go
new file mode 100644
index 000000000..a24046718
--- /dev/null
+++ b/vendor/github.com/googleapis/gax-go/v2/invoke.go
@@ -0,0 +1,89 @@
+// Copyright 2016, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+package gax
+
+import (
+ "context"
+ "time"
+)
+
+// APICall is a user defined call stub.
+type APICall func(context.Context, CallSettings) error
+
+// Invoke calls the given APICall,
+// performing retries as specified by opts, if any.
+func Invoke(ctx context.Context, call APICall, opts ...CallOption) error {
+ var settings CallSettings
+ for _, opt := range opts {
+ opt.Resolve(&settings)
+ }
+ return invoke(ctx, call, settings, Sleep)
+}
+
+// Sleep is similar to time.Sleep, but it can be interrupted by ctx.Done() closing.
+// If interrupted, Sleep returns ctx.Err().
+func Sleep(ctx context.Context, d time.Duration) error {
+ t := time.NewTimer(d)
+ select {
+ case <-ctx.Done():
+ t.Stop()
+ return ctx.Err()
+ case <-t.C:
+ return nil
+ }
+}
+
+type sleeper func(ctx context.Context, d time.Duration) error
+
+// invoke implements Invoke, taking an additional sleeper argument for testing.
+func invoke(ctx context.Context, call APICall, settings CallSettings, sp sleeper) error {
+ var retryer Retryer
+ for {
+ err := call(ctx, settings)
+ if err == nil {
+ return nil
+ }
+ if settings.Retry == nil {
+ return err
+ }
+ if retryer == nil {
+ if r := settings.Retry(); r != nil {
+ retryer = r
+ } else {
+ return err
+ }
+ }
+ if d, ok := retryer.Retry(err); !ok {
+ return err
+ } else if err = sp(ctx, d); err != nil {
+ return err
+ }
+ }
+}
diff --git a/vendor/github.com/influxdata/influxdb/LICENSE_OF_DEPENDENCIES.md b/vendor/github.com/influxdata/influxdb/LICENSE_OF_DEPENDENCIES.md
index ea6fc69f3..da4ff1d04 100644
--- a/vendor/github.com/influxdata/influxdb/LICENSE_OF_DEPENDENCIES.md
+++ b/vendor/github.com/influxdata/influxdb/LICENSE_OF_DEPENDENCIES.md
@@ -1,9 +1,7 @@
-- # List
+# List
- bootstrap 3.3.5 [MIT LICENSE](https://github.com/twbs/bootstrap/blob/master/LICENSE)
- collectd.org [ISC LICENSE](https://github.com/collectd/go-collectd/blob/master/LICENSE)
- github.com/BurntSushi/toml [MIT LICENSE](https://github.com/BurntSushi/toml/blob/master/COPYING)
-- github.com/RoaringBitmap/roaring [APACHE LICENSE](https://github.com/RoaringBitmap/roaring/blob/master/LICENSE)
-- github.com/beorn7/perks [MIT LICENSE](https://github.com/beorn7/perks/blob/master/LICENSE)
- github.com/bmizerany/pat [MIT LICENSE](https://github.com/bmizerany/pat#license)
- github.com/boltdb/bolt [MIT LICENSE](https://github.com/boltdb/bolt/blob/master/LICENSE)
- github.com/cespare/xxhash [MIT LICENSE](https://github.com/cespare/xxhash/blob/master/LICENSE.txt)
@@ -12,51 +10,18 @@
- github.com/dgrijalva/jwt-go [MIT LICENSE](https://github.com/dgrijalva/jwt-go/blob/master/LICENSE)
- github.com/dgryski/go-bits [MIT LICENSE](https://github.com/dgryski/go-bits/blob/master/LICENSE)
- github.com/dgryski/go-bitstream [MIT LICENSE](https://github.com/dgryski/go-bitstream/blob/master/LICENSE)
-- github.com/glycerine/go-unsnap-stream [MIT LICENSE](https://github.com/glycerine/go-unsnap-stream/blob/master/LICENSE)
- github.com/gogo/protobuf/proto [BSD LICENSE](https://github.com/gogo/protobuf/blob/master/LICENSE)
-- github.com/golang/protobuf [BSD LICENSE](https://github.com/golang/protobuf/blob/master/LICENSE)
- github.com/golang/snappy [BSD LICENSE](https://github.com/golang/snappy/blob/master/LICENSE)
- github.com/google/go-cmp [BSD LICENSE](https://github.com/google/go-cmp/blob/master/LICENSE)
-- github.com/influxdata/influxql [MIT LICENSE](https://github.com/influxdata/influxql/blob/master/LICENSE)
- github.com/influxdata/usage-client [MIT LICENSE](https://github.com/influxdata/usage-client/blob/master/LICENSE.txt)
-- github.com/influxdata/yamux [MOZILLA PUBLIC LICENSE](https://github.com/influxdata/yamux/blob/master/LICENSE)
-- github.com/influxdata/yarpc [MIT LICENSE](https://github.com/influxdata/yarpc/blob/master/LICENSE)
-- github.com/jsternberg/zap-logfmt [MIT LICENSE](https://github.com/jsternberg/zap-logfmt/blob/master/LICENSE)
- github.com/jwilder/encoding [MIT LICENSE](https://github.com/jwilder/encoding/blob/master/LICENSE)
-- github.com/mattn/go-isatty [MIT LICENSE](https://github.com/mattn/go-isatty/blob/master/LICENSE)
-- github.com/matttproud/golang_protobuf_extensions [APACHE LICENSE](https://github.com/matttproud/golang_protobuf_extensions/blob/master/LICENSE)
-- github.com/opentracing/opentracing-go [MIT LICENSE](https://github.com/opentracing/opentracing-go/blob/master/LICENSE)
+- github.com/philhofer/fwd [MIT LICENSE](https://github.com/philhofer/fwd/blob/master/LICENSE.md)
- github.com/paulbellamy/ratecounter [MIT LICENSE](https://github.com/paulbellamy/ratecounter/blob/master/LICENSE)
- github.com/peterh/liner [MIT LICENSE](https://github.com/peterh/liner/blob/master/COPYING)
-- github.com/philhofer/fwd [MIT LICENSE](https://github.com/philhofer/fwd/blob/master/LICENSE.md)
-- github.com/prometheus/client_golang [MIT LICENSE](https://github.com/prometheus/client_golang/blob/master/LICENSE)
-- github.com/prometheus/client_model [MIT LICENSE](https://github.com/prometheus/client_model/blob/master/LICENSE)
-- github.com/prometheus/common [APACHE LICENSE](https://github.com/prometheus/common/blob/master/LICENSE)
-- github.com/prometheus/procfs [APACHE LICENSE](https://github.com/prometheus/procfs/blob/master/LICENSE)
+- github.com/tinylib/msgp [MIT LICENSE](https://github.com/tinylib/msgp/blob/master/LICENSE)
- github.com/rakyll/statik [APACHE LICENSE](https://github.com/rakyll/statik/blob/master/LICENSE)
- github.com/retailnext/hllpp [BSD LICENSE](https://github.com/retailnext/hllpp/blob/master/LICENSE)
-- github.com/tinylib/msgp [MIT LICENSE](https://github.com/tinylib/msgp/blob/master/LICENSE)
-- go.uber.org/atomic [MIT LICENSE](https://github.com/uber-go/atomic/blob/master/LICENSE.txt)
-- go.uber.org/multierr [MIT LICENSE](https://github.com/uber-go/multierr/blob/master/LICENSE.txt)
-- go.uber.org/zap [MIT LICENSE](https://github.com/uber-go/zap/blob/master/LICENSE.txt)
+- github.com/uber-go/atomic [MIT LICENSE](https://github.com/uber-go/atomic/blob/master/LICENSE.txt)
+- github.com/uber-go/zap [MIT LICENSE](https://github.com/uber-go/zap/blob/master/LICENSE.txt)
- golang.org/x/crypto [BSD LICENSE](https://github.com/golang/crypto/blob/master/LICENSE)
-- golang.org/x/net [BSD LICENSE](https://github.com/golang/net/blob/master/LICENSE)
-- golang.org/x/sys [BSD LICENSE](https://github.com/golang/sys/blob/master/LICENSE)
-- golang.org/x/text [BSD LICENSE](https://github.com/golang/text/blob/master/LICENSE)
-- golang.org/x/time [BSD LICENSE](https://github.com/golang/time/blob/master/LICENSE)
- jquery 2.1.4 [MIT LICENSE](https://github.com/jquery/jquery/blob/master/LICENSE.txt)
-- github.com/xlab/treeprint [MIT LICENSE](https://github.com/xlab/treeprint/blob/master/LICENSE)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/vendor/github.com/influxdata/influxdb/client/influxdb.go b/vendor/github.com/influxdata/influxdb/client/influxdb.go
index 98d362d50..36c526d99 100644
--- a/vendor/github.com/influxdata/influxdb/client/influxdb.go
+++ b/vendor/github.com/influxdata/influxdb/client/influxdb.go
@@ -306,7 +306,7 @@ func (c *Client) Write(bp BatchPoints) (*Response, error) {
precision := bp.Precision
if precision == "" {
- precision = "ns"
+ precision = c.precision
}
params := req.URL.Query()
diff --git a/vendor/github.com/mattn/go-colorable/colorable_appengine.go b/vendor/github.com/mattn/go-colorable/colorable_appengine.go
new file mode 100644
index 000000000..1f28d773d
--- /dev/null
+++ b/vendor/github.com/mattn/go-colorable/colorable_appengine.go
@@ -0,0 +1,29 @@
+// +build appengine
+
+package colorable
+
+import (
+ "io"
+ "os"
+
+ _ "github.com/mattn/go-isatty"
+)
+
+// NewColorable return new instance of Writer which handle escape sequence.
+func NewColorable(file *os.File) io.Writer {
+ if file == nil {
+ panic("nil passed instead of *os.File to NewColorable()")
+ }
+
+ return file
+}
+
+// NewColorableStdout return new instance of Writer which handle escape sequence for stdout.
+func NewColorableStdout() io.Writer {
+ return os.Stdout
+}
+
+// NewColorableStderr return new instance of Writer which handle escape sequence for stderr.
+func NewColorableStderr() io.Writer {
+ return os.Stderr
+}
diff --git a/vendor/go.opencensus.io/AUTHORS b/vendor/go.opencensus.io/AUTHORS
new file mode 100644
index 000000000..e491a9e7f
--- /dev/null
+++ b/vendor/go.opencensus.io/AUTHORS
@@ -0,0 +1 @@
+Google Inc.
diff --git a/vendor/go.opencensus.io/CONTRIBUTING.md b/vendor/go.opencensus.io/CONTRIBUTING.md
new file mode 100644
index 000000000..3f3aed396
--- /dev/null
+++ b/vendor/go.opencensus.io/CONTRIBUTING.md
@@ -0,0 +1,56 @@
+# How to contribute
+
+We'd love to accept your patches and contributions to this project. There are
+just a few small guidelines you need to follow.
+
+## Contributor License Agreement
+
+Contributions to this project must be accompanied by a Contributor License
+Agreement. You (or your employer) retain the copyright to your contribution,
+this simply gives us permission to use and redistribute your contributions as
+part of the project. Head over to <https://cla.developers.google.com/> to see
+your current agreements on file or to sign a new one.
+
+You generally only need to submit a CLA once, so if you've already submitted one
+(even if it was for a different project), you probably don't need to do it
+again.
+
+## Code reviews
+
+All submissions, including submissions by project members, require review. We
+use GitHub pull requests for this purpose. Consult [GitHub Help] for more
+information on using pull requests.
+
+[GitHub Help]: https://help.github.com/articles/about-pull-requests/
+
+## Instructions
+
+Fork the repo, checkout the upstream repo to your GOPATH by:
+
+```
+$ go get -d go.opencensus.io
+```
+
+Add your fork as an origin:
+
+```
+cd $(go env GOPATH)/src/go.opencensus.io
+git remote add fork git@github.com:YOUR_GITHUB_USERNAME/opencensus-go.git
+```
+
+Run tests:
+
+```
+$ go test ./...
+```
+
+Checkout a new branch, make modifications and push the branch to your fork:
+
+```
+$ git checkout -b feature
+# edit files
+$ git commit
+$ git push fork feature
+```
+
+Open a pull request against the main opencensus-go repo.
diff --git a/vendor/go.opencensus.io/Gopkg.lock b/vendor/go.opencensus.io/Gopkg.lock
new file mode 100644
index 000000000..3be12ac8f
--- /dev/null
+++ b/vendor/go.opencensus.io/Gopkg.lock
@@ -0,0 +1,231 @@
+# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
+
+
+[[projects]]
+ branch = "master"
+ digest = "1:eee9386329f4fcdf8d6c0def0c9771b634bdd5ba460d888aa98c17d59b37a76c"
+ name = "git.apache.org/thrift.git"
+ packages = ["lib/go/thrift"]
+ pruneopts = "UT"
+ revision = "6e67faa92827ece022380b211c2caaadd6145bf5"
+ source = "github.com/apache/thrift"
+
+[[projects]]
+ branch = "master"
+ digest = "1:d6afaeed1502aa28e80a4ed0981d570ad91b2579193404256ce672ed0a609e0d"
+ name = "github.com/beorn7/perks"
+ packages = ["quantile"]
+ pruneopts = "UT"
+ revision = "3a771d992973f24aa725d07868b467d1ddfceafb"
+
+[[projects]]
+ digest = "1:4c0989ca0bcd10799064318923b9bc2db6b4d6338dd75f3f2d86c3511aaaf5cf"
+ name = "github.com/golang/protobuf"
+ packages = [
+ "proto",
+ "ptypes",
+ "ptypes/any",
+ "ptypes/duration",
+ "ptypes/timestamp",
+ ]
+ pruneopts = "UT"
+ revision = "aa810b61a9c79d51363740d207bb46cf8e620ed5"
+ version = "v1.2.0"
+
+[[projects]]
+ digest = "1:ff5ebae34cfbf047d505ee150de27e60570e8c394b3b8fdbb720ff6ac71985fc"
+ name = "github.com/matttproud/golang_protobuf_extensions"
+ packages = ["pbutil"]
+ pruneopts = "UT"
+ revision = "c12348ce28de40eed0136aa2b644d0ee0650e56c"
+ version = "v1.0.1"
+
+[[projects]]
+ digest = "1:824c8f3aa4c5f23928fa84ebbd5ed2e9443b3f0cb958a40c1f2fbed5cf5e64b1"
+ name = "github.com/openzipkin/zipkin-go"
+ packages = [
+ ".",
+ "idgenerator",
+ "model",
+ "propagation",
+ "reporter",
+ "reporter/http",
+ ]
+ pruneopts = "UT"
+ revision = "d455a5674050831c1e187644faa4046d653433c2"
+ version = "v0.1.1"
+
+[[projects]]
+ digest = "1:d14a5f4bfecf017cb780bdde1b6483e5deb87e12c332544d2c430eda58734bcb"
+ name = "github.com/prometheus/client_golang"
+ packages = [
+ "prometheus",
+ "prometheus/promhttp",
+ ]
+ pruneopts = "UT"
+ revision = "c5b7fccd204277076155f10851dad72b76a49317"
+ version = "v0.8.0"
+
+[[projects]]
+ branch = "master"
+ digest = "1:2d5cd61daa5565187e1d96bae64dbbc6080dacf741448e9629c64fd93203b0d4"
+ name = "github.com/prometheus/client_model"
+ packages = ["go"]
+ pruneopts = "UT"
+ revision = "5c3871d89910bfb32f5fcab2aa4b9ec68e65a99f"
+
+[[projects]]
+ branch = "master"
+ digest = "1:63b68062b8968092eb86bedc4e68894bd096ea6b24920faca8b9dcf451f54bb5"
+ name = "github.com/prometheus/common"
+ packages = [
+ "expfmt",
+ "internal/bitbucket.org/ww/goautoneg",
+ "model",
+ ]
+ pruneopts = "UT"
+ revision = "c7de2306084e37d54b8be01f3541a8464345e9a5"
+
+[[projects]]
+ branch = "master"
+ digest = "1:8c49953a1414305f2ff5465147ee576dd705487c35b15918fcd4efdc0cb7a290"
+ name = "github.com/prometheus/procfs"
+ packages = [
+ ".",
+ "internal/util",
+ "nfs",
+ "xfs",
+ ]
+ pruneopts = "UT"
+ revision = "05ee40e3a273f7245e8777337fc7b46e533a9a92"
+
+[[projects]]
+ branch = "master"
+ digest = "1:deafe4ab271911fec7de5b693d7faae3f38796d9eb8622e2b9e7df42bb3dfea9"
+ name = "golang.org/x/net"
+ packages = [
+ "context",
+ "http/httpguts",
+ "http2",
+ "http2/hpack",
+ "idna",
+ "internal/timeseries",
+ "trace",
+ ]
+ pruneopts = "UT"
+ revision = "922f4815f713f213882e8ef45e0d315b164d705c"
+
+[[projects]]
+ branch = "master"
+ digest = "1:e0140c0c868c6e0f01c0380865194592c011fe521d6e12d78bfd33e756fe018a"
+ name = "golang.org/x/sync"
+ packages = ["semaphore"]
+ pruneopts = "UT"
+ revision = "1d60e4601c6fd243af51cc01ddf169918a5407ca"
+
+[[projects]]
+ branch = "master"
+ digest = "1:a3f00ac457c955fe86a41e1495e8f4c54cb5399d609374c5cc26aa7d72e542c8"
+ name = "golang.org/x/sys"
+ packages = ["unix"]
+ pruneopts = "UT"
+ revision = "3b58ed4ad3395d483fc92d5d14123ce2c3581fec"
+
+[[projects]]
+ digest = "1:a2ab62866c75542dd18d2b069fec854577a20211d7c0ea6ae746072a1dccdd18"
+ name = "golang.org/x/text"
+ packages = [
+ "collate",
+ "collate/build",
+ "internal/colltab",
+ "internal/gen",
+ "internal/tag",
+ "internal/triegen",
+ "internal/ucd",
+ "language",
+ "secure/bidirule",
+ "transform",
+ "unicode/bidi",
+ "unicode/cldr",
+ "unicode/norm",
+ "unicode/rangetable",
+ ]
+ pruneopts = "UT"
+ revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0"
+ version = "v0.3.0"
+
+[[projects]]
+ branch = "master"
+ digest = "1:c0c17c94fe8bc1ab34e7f586a4a8b788c5e1f4f9f750ff23395b8b2f5a523530"
+ name = "google.golang.org/api"
+ packages = ["support/bundler"]
+ pruneopts = "UT"
+ revision = "e21acd801f91da814261b938941d193bb036441a"
+
+[[projects]]
+ branch = "master"
+ digest = "1:077c1c599507b3b3e9156d17d36e1e61928ee9b53a5b420f10f28ebd4a0b275c"
+ name = "google.golang.org/genproto"
+ packages = ["googleapis/rpc/status"]
+ pruneopts = "UT"
+ revision = "c66870c02cf823ceb633bcd05be3c7cda29976f4"
+
+[[projects]]
+ digest = "1:3dd7996ce6bf52dec6a2f69fa43e7c4cefea1d4dfa3c8ab7a5f8a9f7434e239d"
+ name = "google.golang.org/grpc"
+ packages = [
+ ".",
+ "balancer",
+ "balancer/base",
+ "balancer/roundrobin",
+ "codes",
+ "connectivity",
+ "credentials",
+ "encoding",
+ "encoding/proto",
+ "grpclog",
+ "internal",
+ "internal/backoff",
+ "internal/channelz",
+ "internal/envconfig",
+ "internal/grpcrand",
+ "internal/transport",
+ "keepalive",
+ "metadata",
+ "naming",
+ "peer",
+ "resolver",
+ "resolver/dns",
+ "resolver/passthrough",
+ "stats",
+ "status",
+ "tap",
+ ]
+ pruneopts = "UT"
+ revision = "32fb0ac620c32ba40a4626ddf94d90d12cce3455"
+ version = "v1.14.0"
+
+[solve-meta]
+ analyzer-name = "dep"
+ analyzer-version = 1
+ input-imports = [
+ "git.apache.org/thrift.git/lib/go/thrift",
+ "github.com/golang/protobuf/proto",
+ "github.com/openzipkin/zipkin-go",
+ "github.com/openzipkin/zipkin-go/model",
+ "github.com/openzipkin/zipkin-go/reporter",
+ "github.com/openzipkin/zipkin-go/reporter/http",
+ "github.com/prometheus/client_golang/prometheus",
+ "github.com/prometheus/client_golang/prometheus/promhttp",
+ "golang.org/x/net/context",
+ "golang.org/x/net/http2",
+ "google.golang.org/api/support/bundler",
+ "google.golang.org/grpc",
+ "google.golang.org/grpc/codes",
+ "google.golang.org/grpc/grpclog",
+ "google.golang.org/grpc/metadata",
+ "google.golang.org/grpc/stats",
+ "google.golang.org/grpc/status",
+ ]
+ solver-name = "gps-cdcl"
+ solver-version = 1
diff --git a/vendor/go.opencensus.io/Gopkg.toml b/vendor/go.opencensus.io/Gopkg.toml
new file mode 100644
index 000000000..a9f3cd68e
--- /dev/null
+++ b/vendor/go.opencensus.io/Gopkg.toml
@@ -0,0 +1,36 @@
+# For v0.x.y dependencies, prefer adding a constraints of the form: version=">= 0.x.y"
+# to avoid locking to a particular minor version which can cause dep to not be
+# able to find a satisfying dependency graph.
+
+[[constraint]]
+ branch = "master"
+ name = "git.apache.org/thrift.git"
+ source = "github.com/apache/thrift"
+
+[[constraint]]
+ name = "github.com/golang/protobuf"
+ version = "1.0.0"
+
+[[constraint]]
+ name = "github.com/openzipkin/zipkin-go"
+ version = ">=0.1.0"
+
+[[constraint]]
+ name = "github.com/prometheus/client_golang"
+ version = ">=0.8.0"
+
+[[constraint]]
+ branch = "master"
+ name = "golang.org/x/net"
+
+[[constraint]]
+ branch = "master"
+ name = "google.golang.org/api"
+
+[[constraint]]
+ name = "google.golang.org/grpc"
+ version = "1.11.3"
+
+[prune]
+ go-tests = true
+ unused-packages = true
diff --git a/vendor/go.opencensus.io/LICENSE b/vendor/go.opencensus.io/LICENSE
new file mode 100644
index 000000000..7a4a3ea24
--- /dev/null
+++ b/vendor/go.opencensus.io/LICENSE
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License. \ No newline at end of file
diff --git a/vendor/go.opencensus.io/README.md b/vendor/go.opencensus.io/README.md
new file mode 100644
index 000000000..b8a5107bf
--- /dev/null
+++ b/vendor/go.opencensus.io/README.md
@@ -0,0 +1,263 @@
+# OpenCensus Libraries for Go
+
+[![Build Status][travis-image]][travis-url]
+[![Windows Build Status][appveyor-image]][appveyor-url]
+[![GoDoc][godoc-image]][godoc-url]
+[![Gitter chat][gitter-image]][gitter-url]
+
+OpenCensus Go is a Go implementation of OpenCensus, a toolkit for
+collecting application performance and behavior monitoring data.
+Currently it consists of three major components: tags, stats and tracing.
+
+## Installation
+
+```
+$ go get -u go.opencensus.io
+```
+
+The API of this project is still evolving, see: [Deprecation Policy](#deprecation-policy).
+The use of vendoring or a dependency management tool is recommended.
+
+## Prerequisites
+
+OpenCensus Go libraries require Go 1.8 or later.
+
+## Getting Started
+
+The easiest way to get started using OpenCensus in your application is to use an existing
+integration with your RPC framework:
+
+* [net/http](https://godoc.org/go.opencensus.io/plugin/ochttp)
+* [gRPC](https://godoc.org/go.opencensus.io/plugin/ocgrpc)
+* [database/sql](https://godoc.org/github.com/opencensus-integrations/ocsql)
+* [Go kit](https://godoc.org/github.com/go-kit/kit/tracing/opencensus)
+* [Groupcache](https://godoc.org/github.com/orijtech/groupcache)
+* [Caddy webserver](https://godoc.org/github.com/orijtech/caddy)
+* [MongoDB](https://godoc.org/github.com/orijtech/mongo-go-driver)
+* [Redis gomodule/redigo](https://godoc.org/github.com/orijtech/redigo)
+* [Redis goredis/redis](https://godoc.org/github.com/orijtech/redis)
+* [Memcache](https://godoc.org/github.com/orijtech/gomemcache)
+
+If you're using a framework not listed here, you could either implement your own middleware for your
+framework or use [custom stats](#stats) and [spans](#spans) directly in your application.
+
+## Exporters
+
+OpenCensus can export instrumentation data to various backends.
+OpenCensus has exporter implementations for the following, users
+can implement their own exporters by implementing the exporter interfaces
+([stats](https://godoc.org/go.opencensus.io/stats/view#Exporter),
+[trace](https://godoc.org/go.opencensus.io/trace#Exporter)):
+
+* [Prometheus][exporter-prom] for stats
+* [OpenZipkin][exporter-zipkin] for traces
+* [Stackdriver][exporter-stackdriver] Monitoring for stats and Trace for traces
+* [Jaeger][exporter-jaeger] for traces
+* [AWS X-Ray][exporter-xray] for traces
+* [Datadog][exporter-datadog] for stats and traces
+* [Graphite][exporter-graphite] for stats
+* [Honeycomb][exporter-honeycomb] for traces
+
+## Overview
+
+![OpenCensus Overview](https://i.imgur.com/cf4ElHE.jpg)
+
+In a microservices environment, a user request may go through
+multiple services until there is a response. OpenCensus allows
+you to instrument your services and collect diagnostics data all
+through your services end-to-end.
+
+## Tags
+
+Tags represent propagated key-value pairs. They are propagated using `context.Context`
+in the same process or can be encoded to be transmitted on the wire. Usually, this will
+be handled by an integration plugin, e.g. `ocgrpc.ServerHandler` and `ocgrpc.ClientHandler`
+for gRPC.
+
+Package `tag` allows adding or modifying tags in the current context.
+
+[embedmd]:# (internal/readme/tags.go new)
+```go
+ctx, err = tag.New(ctx,
+ tag.Insert(osKey, "macOS-10.12.5"),
+ tag.Upsert(userIDKey, "cde36753ed"),
+)
+if err != nil {
+ log.Fatal(err)
+}
+```
+
+## Stats
+
+OpenCensus is a low-overhead framework even if instrumentation is always enabled.
+In order to be so, it is optimized to make recording of data points fast
+and separate from the data aggregation.
+
+OpenCensus stats collection happens in two stages:
+
+* Definition of measures and recording of data points
+* Definition of views and aggregation of the recorded data
+
+### Recording
+
+Measurements are data points associated with a measure.
+Recording implicitly tags the set of Measurements with the tags from the
+provided context:
+
+[embedmd]:# (internal/readme/stats.go record)
+```go
+stats.Record(ctx, videoSize.M(102478))
+```
+
+### Views
+
+Views are how Measures are aggregated. You can think of them as queries over the
+set of recorded data points (measurements).
+
+Views have two parts: the tags to group by and the aggregation type used.
+
+Currently three types of aggregations are supported:
+* CountAggregation is used to count the number of times a sample was recorded.
+* DistributionAggregation is used to provide a histogram of the values of the samples.
+* SumAggregation is used to sum up all sample values.
+
+[embedmd]:# (internal/readme/stats.go aggs)
+```go
+distAgg := view.Distribution(0, 1<<32, 2<<32, 3<<32)
+countAgg := view.Count()
+sumAgg := view.Sum()
+```
+
+Here we create a view with the DistributionAggregation over our measure.
+
+[embedmd]:# (internal/readme/stats.go view)
+```go
+if err := view.Register(&view.View{
+ Name: "example.com/video_size_distribution",
+ Description: "distribution of processed video size over time",
+ Measure: videoSize,
+ Aggregation: view.Distribution(0, 1<<32, 2<<32, 3<<32),
+}); err != nil {
+ log.Fatalf("Failed to register view: %v", err)
+}
+```
+
+Register begins collecting data for the view. Registered views' data will be
+exported via the registered exporters.
+
+## Traces
+
+A distributed trace tracks the progression of a single user request as
+it is handled by the services and processes that make up an application.
+Each step is called a span in the trace. Spans include metadata about the step,
+including especially the time spent in the step, called the span’s latency.
+
+Below you see a trace and several spans underneath it.
+
+![Traces and spans](https://i.imgur.com/7hZwRVj.png)
+
+### Spans
+
+Span is the unit step in a trace. Each span has a name, latency, status and
+additional metadata.
+
+Below we are starting a span for a cache read and ending it
+when we are done:
+
+[embedmd]:# (internal/readme/trace.go startend)
+```go
+ctx, span := trace.StartSpan(ctx, "cache.Get")
+defer span.End()
+
+// Do work to get from cache.
+```
+
+### Propagation
+
+Spans can have parents or can be root spans if they don't have any parents.
+The current span is propagated in-process and across the network to allow associating
+new child spans with the parent.
+
+In the same process, `context.Context` is used to propagate spans.
+`trace.StartSpan` creates a new span as a root if the current context
+doesn't contain a span. Or, it creates a child of the span that is
+already in current context. The returned context can be used to keep
+propagating the newly created span in the current context.
+
+[embedmd]:# (internal/readme/trace.go startend)
+```go
+ctx, span := trace.StartSpan(ctx, "cache.Get")
+defer span.End()
+
+// Do work to get from cache.
+```
+
+Across the network, OpenCensus provides different propagation
+methods for different protocols.
+
+* gRPC integrations use the OpenCensus' [binary propagation format](https://godoc.org/go.opencensus.io/trace/propagation).
+* HTTP integrations use Zipkin's [B3](https://github.com/openzipkin/b3-propagation)
+ by default but can be configured to use a custom propagation method by setting another
+ [propagation.HTTPFormat](https://godoc.org/go.opencensus.io/trace/propagation#HTTPFormat).
+
+## Execution Tracer
+
+With Go 1.11, OpenCensus Go will support integration with the Go execution tracer.
+See [Debugging Latency in Go](https://medium.com/observability/debugging-latency-in-go-1-11-9f97a7910d68)
+for an example of their mutual use.
+
+## Profiles
+
+OpenCensus tags can be applied as profiler labels
+for users who are on Go 1.9 and above.
+
+[embedmd]:# (internal/readme/tags.go profiler)
+```go
+ctx, err = tag.New(ctx,
+ tag.Insert(osKey, "macOS-10.12.5"),
+ tag.Insert(userIDKey, "fff0989878"),
+)
+if err != nil {
+ log.Fatal(err)
+}
+tag.Do(ctx, func(ctx context.Context) {
+ // Do work.
+ // When profiling is on, samples will be
+ // recorded with the key/values from the tag map.
+})
+```
+
+A screenshot of the CPU profile from the program above:
+
+![CPU profile](https://i.imgur.com/jBKjlkw.png)
+
+## Deprecation Policy
+
+Before version 1.0.0, the following deprecation policy will be observed:
+
+No backwards-incompatible changes will be made except for the removal of symbols that have
+been marked as *Deprecated* for at least one minor release (e.g. 0.9.0 to 0.10.0). A release
+removing the *Deprecated* functionality will be made no sooner than 28 days after the first
+release in which the functionality was marked *Deprecated*.
+
+[travis-image]: https://travis-ci.org/census-instrumentation/opencensus-go.svg?branch=master
+[travis-url]: https://travis-ci.org/census-instrumentation/opencensus-go
+[appveyor-image]: https://ci.appveyor.com/api/projects/status/vgtt29ps1783ig38?svg=true
+[appveyor-url]: https://ci.appveyor.com/project/opencensusgoteam/opencensus-go/branch/master
+[godoc-image]: https://godoc.org/go.opencensus.io?status.svg
+[godoc-url]: https://godoc.org/go.opencensus.io
+[gitter-image]: https://badges.gitter.im/census-instrumentation/lobby.svg
+[gitter-url]: https://gitter.im/census-instrumentation/lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge
+
+
+[new-ex]: https://godoc.org/go.opencensus.io/tag#example-NewMap
+[new-replace-ex]: https://godoc.org/go.opencensus.io/tag#example-NewMap--Replace
+
+[exporter-prom]: https://godoc.org/go.opencensus.io/exporter/prometheus
+[exporter-stackdriver]: https://godoc.org/contrib.go.opencensus.io/exporter/stackdriver
+[exporter-zipkin]: https://godoc.org/go.opencensus.io/exporter/zipkin
+[exporter-jaeger]: https://godoc.org/go.opencensus.io/exporter/jaeger
+[exporter-xray]: https://github.com/census-ecosystem/opencensus-go-exporter-aws
+[exporter-datadog]: https://github.com/DataDog/opencensus-go-exporter-datadog
+[exporter-graphite]: https://github.com/census-ecosystem/opencensus-go-exporter-graphite
+[exporter-honeycomb]: https://github.com/honeycombio/opencensus-exporter
diff --git a/vendor/go.opencensus.io/appveyor.yml b/vendor/go.opencensus.io/appveyor.yml
new file mode 100644
index 000000000..98057888a
--- /dev/null
+++ b/vendor/go.opencensus.io/appveyor.yml
@@ -0,0 +1,24 @@
+version: "{build}"
+
+platform: x64
+
+clone_folder: c:\gopath\src\go.opencensus.io
+
+environment:
+ GOPATH: 'c:\gopath'
+ GOVERSION: '1.11'
+ GO111MODULE: 'on'
+ CGO_ENABLED: '0' # See: https://github.com/appveyor/ci/issues/2613
+
+install:
+ - set PATH=%GOPATH%\bin;c:\go\bin;%PATH%
+ - go version
+ - go env
+
+build: false
+deploy: false
+
+test_script:
+ - cd %APPVEYOR_BUILD_FOLDER%
+ - go build -v .\...
+ - go test -v .\... # No -race because cgo is disabled
diff --git a/vendor/go.opencensus.io/exemplar/exemplar.go b/vendor/go.opencensus.io/exemplar/exemplar.go
new file mode 100644
index 000000000..e676df837
--- /dev/null
+++ b/vendor/go.opencensus.io/exemplar/exemplar.go
@@ -0,0 +1,78 @@
+// Copyright 2018, OpenCensus Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package exemplar implements support for exemplars. Exemplars are additional
+// data associated with each measurement.
+//
+// Their purpose it to provide an example of the kind of thing
+// (request, RPC, trace span, etc.) that resulted in that measurement.
+package exemplar
+
+import (
+ "context"
+ "time"
+)
+
+const (
+ KeyTraceID = "trace_id"
+ KeySpanID = "span_id"
+ KeyPrefixTag = "tag:"
+)
+
+// Exemplar is an example data point associated with each bucket of a
+// distribution type aggregation.
+type Exemplar struct {
+ Value float64 // the value that was recorded
+ Timestamp time.Time // the time the value was recorded
+ Attachments Attachments // attachments (if any)
+}
+
+// Attachments is a map of extra values associated with a recorded data point.
+// The map should only be mutated from AttachmentExtractor functions.
+type Attachments map[string]string
+
+// AttachmentExtractor is a function capable of extracting exemplar attachments
+// from the context used to record measurements.
+// The map passed to the function should be mutated and returned. It will
+// initially be nil: the first AttachmentExtractor that would like to add keys to the
+// map is responsible for initializing it.
+type AttachmentExtractor func(ctx context.Context, a Attachments) Attachments
+
+var extractors []AttachmentExtractor
+
+// RegisterAttachmentExtractor registers the given extractor associated with the exemplar
+// type name.
+//
+// Extractors will be used to attempt to extract exemplars from the context
+// associated with each recorded measurement.
+//
+// Packages that support exemplars should register their extractor functions on
+// initialization.
+//
+// RegisterAttachmentExtractor should not be called after any measurements have
+// been recorded.
+func RegisterAttachmentExtractor(e AttachmentExtractor) {
+ extractors = append(extractors, e)
+}
+
+// NewFromContext extracts exemplars from the given context.
+// Each registered AttachmentExtractor (see RegisterAttachmentExtractor) is called in an
+// unspecified order to add attachments to the exemplar.
+func AttachmentsFromContext(ctx context.Context) Attachments {
+ var a Attachments
+ for _, extractor := range extractors {
+ a = extractor(ctx, a)
+ }
+ return a
+}
diff --git a/vendor/go.opencensus.io/go.mod b/vendor/go.opencensus.io/go.mod
new file mode 100644
index 000000000..1236f4c2f
--- /dev/null
+++ b/vendor/go.opencensus.io/go.mod
@@ -0,0 +1,25 @@
+module go.opencensus.io
+
+require (
+ git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999
+ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973
+ github.com/ghodss/yaml v1.0.0 // indirect
+ github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b // indirect
+ github.com/golang/protobuf v1.2.0
+ github.com/google/go-cmp v0.2.0
+ github.com/grpc-ecosystem/grpc-gateway v1.5.0 // indirect
+ github.com/matttproud/golang_protobuf_extensions v1.0.1
+ github.com/openzipkin/zipkin-go v0.1.1
+ github.com/prometheus/client_golang v0.8.0
+ github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910
+ github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e
+ github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273
+ golang.org/x/net v0.0.0-20180906233101-161cd47e91fd
+ golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f
+ golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e
+ golang.org/x/text v0.3.0
+ google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf
+ google.golang.org/genproto v0.0.0-20180831171423-11092d34479b
+ google.golang.org/grpc v1.14.0
+ gopkg.in/yaml.v2 v2.2.1 // indirect
+)
diff --git a/vendor/go.opencensus.io/go.sum b/vendor/go.opencensus.io/go.sum
new file mode 100644
index 000000000..3e0bab884
--- /dev/null
+++ b/vendor/go.opencensus.io/go.sum
@@ -0,0 +1,48 @@
+git.apache.org/thrift.git v0.0.0-20180807212849-6e67faa92827/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg=
+git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999 h1:sihTnRgTOUSCQz0iS0pjZuFQy/z7GXCJgSBg3+rZKHw=
+git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg=
+github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0=
+github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
+github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
+github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
+github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
+github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
+github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
+github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ=
+github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
+github.com/grpc-ecosystem/grpc-gateway v1.5.0 h1:WcmKMm43DR7RdtlkEXQJyo5ws8iTp98CyhCCbOHMvNI=
+github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw=
+github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
+github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
+github.com/openzipkin/zipkin-go v0.1.1 h1:A/ADD6HaPnAKj3yS7HjGHRK77qi41Hi0DirOOIQAeIw=
+github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
+github.com/prometheus/client_golang v0.8.0 h1:1921Yw9Gc3iSc4VQh3PIoOqgPCZS7G/4xQNVUp8Mda8=
+github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
+github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910 h1:idejC8f05m9MGOsuEi1ATq9shN03HrxNkD/luQvxCv8=
+github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
+github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e h1:n/3MEhJQjQxrOUCzh1Y3Re6aJUUWRp2M9+Oc3eVn/54=
+github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
+github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273 h1:agujYaXJSxSo18YNX3jzl+4G6Bstwt+kqv47GS12uL0=
+github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
+golang.org/x/net v0.0.0-20180821023952-922f4815f713/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20180906233101-161cd47e91fd h1:nTDtHvHSdCn1m6ITfMRqtOd/9+7a3s8RBNOZ3eYZzJA=
+golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA=
+golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20180821140842-3b58ed4ad339/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e h1:o3PsSEY8E4eXWkXrIP9YJALUkVZqzHJT5DOasTyn8Vs=
+golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+google.golang.org/api v0.0.0-20180818000503-e21acd801f91/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
+google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf h1:rjxqQmxjyqerRKEj+tZW+MCm4LgpFXu18bsEoCMgDsk=
+google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
+google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
+google.golang.org/genproto v0.0.0-20180831171423-11092d34479b h1:lohp5blsw53GBXtLyLNaTXPXS9pJ1tiTw61ZHUoE9Qw=
+google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
+google.golang.org/grpc v1.14.0 h1:ArxJuB1NWfPY6r9Gp9gqwplT0Ge7nqv9msgu03lHLmo=
+google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=
+gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
diff --git a/vendor/go.opencensus.io/internal/internal.go b/vendor/go.opencensus.io/internal/internal.go
new file mode 100644
index 000000000..2d6baf177
--- /dev/null
+++ b/vendor/go.opencensus.io/internal/internal.go
@@ -0,0 +1,37 @@
+// Copyright 2017, OpenCensus Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package internal // import "go.opencensus.io/internal"
+
+import (
+ "fmt"
+ "time"
+
+ "go.opencensus.io"
+)
+
+// UserAgent is the user agent to be added to the outgoing
+// requests from the exporters.
+var UserAgent = fmt.Sprintf("opencensus-go/%s", opencensus.Version())
+
+// MonotonicEndTime returns the end time at present
+// but offset from start, monotonically.
+//
+// The monotonic clock is used in subtractions hence
+// the duration since start added back to start gives
+// end as a monotonic time.
+// See https://golang.org/pkg/time/#hdr-Monotonic_Clocks
+func MonotonicEndTime(start time.Time) time.Time {
+ return start.Add(time.Now().Sub(start))
+}
diff --git a/vendor/go.opencensus.io/internal/sanitize.go b/vendor/go.opencensus.io/internal/sanitize.go
new file mode 100644
index 000000000..de8ccf236
--- /dev/null
+++ b/vendor/go.opencensus.io/internal/sanitize.go
@@ -0,0 +1,50 @@
+// Copyright 2017, OpenCensus Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package internal
+
+import (
+ "strings"
+ "unicode"
+)
+
+const labelKeySizeLimit = 100
+
+// Sanitize returns a string that is trunacated to 100 characters if it's too
+// long, and replaces non-alphanumeric characters to underscores.
+func Sanitize(s string) string {
+ if len(s) == 0 {
+ return s
+ }
+ if len(s) > labelKeySizeLimit {
+ s = s[:labelKeySizeLimit]
+ }
+ s = strings.Map(sanitizeRune, s)
+ if unicode.IsDigit(rune(s[0])) {
+ s = "key_" + s
+ }
+ if s[0] == '_' {
+ s = "key" + s
+ }
+ return s
+}
+
+// converts anything that is not a letter or digit to an underscore
+func sanitizeRune(r rune) rune {
+ if unicode.IsLetter(r) || unicode.IsDigit(r) {
+ return r
+ }
+ // Everything else turns into an underscore
+ return '_'
+}
diff --git a/vendor/go.opencensus.io/internal/tagencoding/tagencoding.go b/vendor/go.opencensus.io/internal/tagencoding/tagencoding.go
new file mode 100644
index 000000000..3b1af8b4b
--- /dev/null
+++ b/vendor/go.opencensus.io/internal/tagencoding/tagencoding.go
@@ -0,0 +1,72 @@
+// Copyright 2017, OpenCensus Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// Package tagencoding contains the tag encoding
+// used interally by the stats collector.
+package tagencoding // import "go.opencensus.io/internal/tagencoding"
+
+type Values struct {
+ Buffer []byte
+ WriteIndex int
+ ReadIndex int
+}
+
+func (vb *Values) growIfRequired(expected int) {
+ if len(vb.Buffer)-vb.WriteIndex < expected {
+ tmp := make([]byte, 2*(len(vb.Buffer)+1)+expected)
+ copy(tmp, vb.Buffer)
+ vb.Buffer = tmp
+ }
+}
+
+func (vb *Values) WriteValue(v []byte) {
+ length := len(v) & 0xff
+ vb.growIfRequired(1 + length)
+
+ // writing length of v
+ vb.Buffer[vb.WriteIndex] = byte(length)
+ vb.WriteIndex++
+
+ if length == 0 {
+ // No value was encoded for this key
+ return
+ }
+
+ // writing v
+ copy(vb.Buffer[vb.WriteIndex:], v[:length])
+ vb.WriteIndex += length
+}
+
+// ReadValue is the helper method to read the values when decoding valuesBytes to a map[Key][]byte.
+func (vb *Values) ReadValue() []byte {
+ // read length of v
+ length := int(vb.Buffer[vb.ReadIndex])
+ vb.ReadIndex++
+ if length == 0 {
+ // No value was encoded for this key
+ return nil
+ }
+
+ // read value of v
+ v := make([]byte, length)
+ endIdx := vb.ReadIndex + length
+ copy(v, vb.Buffer[vb.ReadIndex:endIdx])
+ vb.ReadIndex = endIdx
+ return v
+}
+
+func (vb *Values) Bytes() []byte {
+ return vb.Buffer[:vb.WriteIndex]
+}
diff --git a/vendor/go.opencensus.io/internal/traceinternals.go b/vendor/go.opencensus.io/internal/traceinternals.go
new file mode 100644
index 000000000..553ca68dc
--- /dev/null
+++ b/vendor/go.opencensus.io/internal/traceinternals.go
@@ -0,0 +1,52 @@
+// Copyright 2017, OpenCensus Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package internal
+
+import (
+ "time"
+)
+
+// Trace allows internal access to some trace functionality.
+// TODO(#412): remove this
+var Trace interface{}
+
+var LocalSpanStoreEnabled bool
+
+// BucketConfiguration stores the number of samples to store for span buckets
+// for successful and failed spans for a particular span name.
+type BucketConfiguration struct {
+ Name string
+ MaxRequestsSucceeded int
+ MaxRequestsErrors int
+}
+
+// PerMethodSummary is a summary of the spans stored for a single span name.
+type PerMethodSummary struct {
+ Active int
+ LatencyBuckets []LatencyBucketSummary
+ ErrorBuckets []ErrorBucketSummary
+}
+
+// LatencyBucketSummary is a summary of a latency bucket.
+type LatencyBucketSummary struct {
+ MinLatency, MaxLatency time.Duration
+ Size int
+}
+
+// ErrorBucketSummary is a summary of an error bucket.
+type ErrorBucketSummary struct {
+ ErrorCode int32
+ Size int
+}
diff --git a/vendor/go.opencensus.io/opencensus.go b/vendor/go.opencensus.io/opencensus.go
new file mode 100644
index 000000000..7faf9e821
--- /dev/null
+++ b/vendor/go.opencensus.io/opencensus.go
@@ -0,0 +1,21 @@
+// Copyright 2017, OpenCensus Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package opencensus contains Go support for OpenCensus.
+package opencensus // import "go.opencensus.io"
+
+// Version is the current release version of OpenCensus in use.
+func Version() string {
+ return "0.19.0"
+}
diff --git a/vendor/go.opencensus.io/plugin/ochttp/client.go b/vendor/go.opencensus.io/plugin/ochttp/client.go
new file mode 100644
index 000000000..da815b2a7
--- /dev/null
+++ b/vendor/go.opencensus.io/plugin/ochttp/client.go
@@ -0,0 +1,117 @@
+// Copyright 2018, OpenCensus Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package ochttp
+
+import (
+ "net/http"
+ "net/http/httptrace"
+
+ "go.opencensus.io/trace"
+ "go.opencensus.io/trace/propagation"
+)
+
+// Transport is an http.RoundTripper that instruments all outgoing requests with
+// OpenCensus stats and tracing.
+//
+// The zero value is intended to be a useful default, but for
+// now it's recommended that you explicitly set Propagation, since the default
+// for this may change.
+type Transport struct {
+ // Base may be set to wrap another http.RoundTripper that does the actual
+ // requests. By default http.DefaultTransport is used.
+ //
+ // If base HTTP roundtripper implements CancelRequest,
+ // the returned round tripper will be cancelable.
+ Base http.RoundTripper
+
+ // Propagation defines how traces are propagated. If unspecified, a default
+ // (currently B3 format) will be used.
+ Propagation propagation.HTTPFormat
+
+ // StartOptions are applied to the span started by this Transport around each
+ // request.
+ //
+ // StartOptions.SpanKind will always be set to trace.SpanKindClient
+ // for spans started by this transport.
+ StartOptions trace.StartOptions
+
+ // GetStartOptions allows to set start options per request. If set,
+ // StartOptions is going to be ignored.
+ GetStartOptions func(*http.Request) trace.StartOptions
+
+ // NameFromRequest holds the function to use for generating the span name
+ // from the information found in the outgoing HTTP Request. By default the
+ // name equals the URL Path.
+ FormatSpanName func(*http.Request) string
+
+ // NewClientTrace may be set to a function allowing the current *trace.Span
+ // to be annotated with HTTP request event information emitted by the
+ // httptrace package.
+ NewClientTrace func(*http.Request, *trace.Span) *httptrace.ClientTrace
+
+ // TODO: Implement tag propagation for HTTP.
+}
+
+// RoundTrip implements http.RoundTripper, delegating to Base and recording stats and traces for the request.
+func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error) {
+ rt := t.base()
+ if isHealthEndpoint(req.URL.Path) {
+ return rt.RoundTrip(req)
+ }
+ // TODO: remove excessive nesting of http.RoundTrippers here.
+ format := t.Propagation
+ if format == nil {
+ format = defaultFormat
+ }
+ spanNameFormatter := t.FormatSpanName
+ if spanNameFormatter == nil {
+ spanNameFormatter = spanNameFromURL
+ }
+
+ startOpts := t.StartOptions
+ if t.GetStartOptions != nil {
+ startOpts = t.GetStartOptions(req)
+ }
+
+ rt = &traceTransport{
+ base: rt,
+ format: format,
+ startOptions: trace.StartOptions{
+ Sampler: startOpts.Sampler,
+ SpanKind: trace.SpanKindClient,
+ },
+ formatSpanName: spanNameFormatter,
+ newClientTrace: t.NewClientTrace,
+ }
+ rt = statsTransport{base: rt}
+ return rt.RoundTrip(req)
+}
+
+func (t *Transport) base() http.RoundTripper {
+ if t.Base != nil {
+ return t.Base
+ }
+ return http.DefaultTransport
+}
+
+// CancelRequest cancels an in-flight request by closing its connection.
+func (t *Transport) CancelRequest(req *http.Request) {
+ type canceler interface {
+ CancelRequest(*http.Request)
+ }
+ if cr, ok := t.base().(canceler); ok {
+ cr.CancelRequest(req)
+ }
+}
diff --git a/vendor/go.opencensus.io/plugin/ochttp/client_stats.go b/vendor/go.opencensus.io/plugin/ochttp/client_stats.go
new file mode 100644
index 000000000..066ebb87f
--- /dev/null
+++ b/vendor/go.opencensus.io/plugin/ochttp/client_stats.go
@@ -0,0 +1,135 @@
+// Copyright 2018, OpenCensus Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package ochttp
+
+import (
+ "context"
+ "io"
+ "net/http"
+ "strconv"
+ "sync"
+ "time"
+
+ "go.opencensus.io/stats"
+ "go.opencensus.io/tag"
+)
+
+// statsTransport is an http.RoundTripper that collects stats for the outgoing requests.
+type statsTransport struct {
+ base http.RoundTripper
+}
+
+// RoundTrip implements http.RoundTripper, delegating to Base and recording stats for the request.
+func (t statsTransport) RoundTrip(req *http.Request) (*http.Response, error) {
+ ctx, _ := tag.New(req.Context(),
+ tag.Upsert(KeyClientHost, req.URL.Host),
+ tag.Upsert(Host, req.URL.Host),
+ tag.Upsert(KeyClientPath, req.URL.Path),
+ tag.Upsert(Path, req.URL.Path),
+ tag.Upsert(KeyClientMethod, req.Method),
+ tag.Upsert(Method, req.Method))
+ req = req.WithContext(ctx)
+ track := &tracker{
+ start: time.Now(),
+ ctx: ctx,
+ }
+ if req.Body == nil {
+ // TODO: Handle cases where ContentLength is not set.
+ track.reqSize = -1
+ } else if req.ContentLength > 0 {
+ track.reqSize = req.ContentLength
+ }
+ stats.Record(ctx, ClientRequestCount.M(1))
+
+ // Perform request.
+ resp, err := t.base.RoundTrip(req)
+
+ if err != nil {
+ track.statusCode = http.StatusInternalServerError
+ track.end()
+ } else {
+ track.statusCode = resp.StatusCode
+ if resp.Body == nil {
+ track.end()
+ } else {
+ track.body = resp.Body
+ resp.Body = track
+ }
+ }
+ return resp, err
+}
+
+// CancelRequest cancels an in-flight request by closing its connection.
+func (t statsTransport) CancelRequest(req *http.Request) {
+ type canceler interface {
+ CancelRequest(*http.Request)
+ }
+ if cr, ok := t.base.(canceler); ok {
+ cr.CancelRequest(req)
+ }
+}
+
+type tracker struct {
+ ctx context.Context
+ respSize int64
+ reqSize int64
+ start time.Time
+ body io.ReadCloser
+ statusCode int
+ endOnce sync.Once
+}
+
+var _ io.ReadCloser = (*tracker)(nil)
+
+func (t *tracker) end() {
+ t.endOnce.Do(func() {
+ latencyMs := float64(time.Since(t.start)) / float64(time.Millisecond)
+ m := []stats.Measurement{
+ ClientSentBytes.M(t.reqSize),
+ ClientReceivedBytes.M(t.respSize),
+ ClientRoundtripLatency.M(latencyMs),
+ ClientLatency.M(latencyMs),
+ ClientResponseBytes.M(t.respSize),
+ }
+ if t.reqSize >= 0 {
+ m = append(m, ClientRequestBytes.M(t.reqSize))
+ }
+
+ stats.RecordWithTags(t.ctx, []tag.Mutator{
+ tag.Upsert(StatusCode, strconv.Itoa(t.statusCode)),
+ tag.Upsert(KeyClientStatus, strconv.Itoa(t.statusCode)),
+ }, m...)
+ })
+}
+
+func (t *tracker) Read(b []byte) (int, error) {
+ n, err := t.body.Read(b)
+ switch err {
+ case nil:
+ t.respSize += int64(n)
+ return n, nil
+ case io.EOF:
+ t.end()
+ }
+ return n, err
+}
+
+func (t *tracker) Close() error {
+ // Invoking endSpan on Close will help catch the cases
+ // in which a read returned a non-nil error, we set the
+ // span status but didn't end the span.
+ t.end()
+ return t.body.Close()
+}
diff --git a/vendor/go.opencensus.io/plugin/ochttp/doc.go b/vendor/go.opencensus.io/plugin/ochttp/doc.go
new file mode 100644
index 000000000..10e626b16
--- /dev/null
+++ b/vendor/go.opencensus.io/plugin/ochttp/doc.go
@@ -0,0 +1,19 @@
+// Copyright 2018, OpenCensus Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package ochttp provides OpenCensus instrumentation for net/http package.
+//
+// For server instrumentation, see Handler. For client-side instrumentation,
+// see Transport.
+package ochttp // import "go.opencensus.io/plugin/ochttp"
diff --git a/vendor/go.opencensus.io/plugin/ochttp/propagation/b3/b3.go b/vendor/go.opencensus.io/plugin/ochttp/propagation/b3/b3.go
new file mode 100644
index 000000000..f777772ec
--- /dev/null
+++ b/vendor/go.opencensus.io/plugin/ochttp/propagation/b3/b3.go
@@ -0,0 +1,123 @@
+// Copyright 2018, OpenCensus Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package b3 contains a propagation.HTTPFormat implementation
+// for B3 propagation. See https://github.com/openzipkin/b3-propagation
+// for more details.
+package b3 // import "go.opencensus.io/plugin/ochttp/propagation/b3"
+
+import (
+ "encoding/hex"
+ "net/http"
+
+ "go.opencensus.io/trace"
+ "go.opencensus.io/trace/propagation"
+)
+
+// B3 headers that OpenCensus understands.
+const (
+ TraceIDHeader = "X-B3-TraceId"
+ SpanIDHeader = "X-B3-SpanId"
+ SampledHeader = "X-B3-Sampled"
+)
+
+// HTTPFormat implements propagation.HTTPFormat to propagate
+// traces in HTTP headers in B3 propagation format.
+// HTTPFormat skips the X-B3-ParentId and X-B3-Flags headers
+// because there are additional fields not represented in the
+// OpenCensus span context. Spans created from the incoming
+// header will be the direct children of the client-side span.
+// Similarly, reciever of the outgoing spans should use client-side
+// span created by OpenCensus as the parent.
+type HTTPFormat struct{}
+
+var _ propagation.HTTPFormat = (*HTTPFormat)(nil)
+
+// SpanContextFromRequest extracts a B3 span context from incoming requests.
+func (f *HTTPFormat) SpanContextFromRequest(req *http.Request) (sc trace.SpanContext, ok bool) {
+ tid, ok := ParseTraceID(req.Header.Get(TraceIDHeader))
+ if !ok {
+ return trace.SpanContext{}, false
+ }
+ sid, ok := ParseSpanID(req.Header.Get(SpanIDHeader))
+ if !ok {
+ return trace.SpanContext{}, false
+ }
+ sampled, _ := ParseSampled(req.Header.Get(SampledHeader))
+ return trace.SpanContext{
+ TraceID: tid,
+ SpanID: sid,
+ TraceOptions: sampled,
+ }, true
+}
+
+// ParseTraceID parses the value of the X-B3-TraceId header.
+func ParseTraceID(tid string) (trace.TraceID, bool) {
+ if tid == "" {
+ return trace.TraceID{}, false
+ }
+ b, err := hex.DecodeString(tid)
+ if err != nil {
+ return trace.TraceID{}, false
+ }
+ var traceID trace.TraceID
+ if len(b) <= 8 {
+ // The lower 64-bits.
+ start := 8 + (8 - len(b))
+ copy(traceID[start:], b)
+ } else {
+ start := 16 - len(b)
+ copy(traceID[start:], b)
+ }
+
+ return traceID, true
+}
+
+// ParseSpanID parses the value of the X-B3-SpanId or X-B3-ParentSpanId headers.
+func ParseSpanID(sid string) (spanID trace.SpanID, ok bool) {
+ if sid == "" {
+ return trace.SpanID{}, false
+ }
+ b, err := hex.DecodeString(sid)
+ if err != nil {
+ return trace.SpanID{}, false
+ }
+ start := 8 - len(b)
+ copy(spanID[start:], b)
+ return spanID, true
+}
+
+// ParseSampled parses the value of the X-B3-Sampled header.
+func ParseSampled(sampled string) (trace.TraceOptions, bool) {
+ switch sampled {
+ case "true", "1":
+ return trace.TraceOptions(1), true
+ default:
+ return trace.TraceOptions(0), false
+ }
+}
+
+// SpanContextToRequest modifies the given request to include B3 headers.
+func (f *HTTPFormat) SpanContextToRequest(sc trace.SpanContext, req *http.Request) {
+ req.Header.Set(TraceIDHeader, hex.EncodeToString(sc.TraceID[:]))
+ req.Header.Set(SpanIDHeader, hex.EncodeToString(sc.SpanID[:]))
+
+ var sampled string
+ if sc.IsSampled() {
+ sampled = "1"
+ } else {
+ sampled = "0"
+ }
+ req.Header.Set(SampledHeader, sampled)
+}
diff --git a/vendor/go.opencensus.io/plugin/ochttp/route.go b/vendor/go.opencensus.io/plugin/ochttp/route.go
new file mode 100644
index 000000000..dbe22d586
--- /dev/null
+++ b/vendor/go.opencensus.io/plugin/ochttp/route.go
@@ -0,0 +1,51 @@
+// Copyright 2018, OpenCensus Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package ochttp
+
+import (
+ "net/http"
+
+ "go.opencensus.io/tag"
+)
+
+// WithRouteTag returns an http.Handler that records stats with the
+// http_server_route tag set to the given value.
+func WithRouteTag(handler http.Handler, route string) http.Handler {
+ return taggedHandlerFunc(func(w http.ResponseWriter, r *http.Request) []tag.Mutator {
+ addRoute := []tag.Mutator{tag.Upsert(KeyServerRoute, route)}
+ ctx, _ := tag.New(r.Context(), addRoute...)
+ r = r.WithContext(ctx)
+ handler.ServeHTTP(w, r)
+ return addRoute
+ })
+}
+
+// taggedHandlerFunc is a http.Handler that returns tags describing the
+// processing of the request. These tags will be recorded along with the
+// measures in this package at the end of the request.
+type taggedHandlerFunc func(w http.ResponseWriter, r *http.Request) []tag.Mutator
+
+func (h taggedHandlerFunc) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+ tags := h(w, r)
+ if a, ok := r.Context().Value(addedTagsKey{}).(*addedTags); ok {
+ a.t = append(a.t, tags...)
+ }
+}
+
+type addedTagsKey struct{}
+
+type addedTags struct {
+ t []tag.Mutator
+}
diff --git a/vendor/go.opencensus.io/plugin/ochttp/server.go b/vendor/go.opencensus.io/plugin/ochttp/server.go
new file mode 100644
index 000000000..ff72de97a
--- /dev/null
+++ b/vendor/go.opencensus.io/plugin/ochttp/server.go
@@ -0,0 +1,440 @@
+// Copyright 2018, OpenCensus Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package ochttp
+
+import (
+ "context"
+ "io"
+ "net/http"
+ "strconv"
+ "sync"
+ "time"
+
+ "go.opencensus.io/stats"
+ "go.opencensus.io/tag"
+ "go.opencensus.io/trace"
+ "go.opencensus.io/trace/propagation"
+)
+
+// Handler is an http.Handler wrapper to instrument your HTTP server with
+// OpenCensus. It supports both stats and tracing.
+//
+// Tracing
+//
+// This handler is aware of the incoming request's span, reading it from request
+// headers as configured using the Propagation field.
+// The extracted span can be accessed from the incoming request's
+// context.
+//
+// span := trace.FromContext(r.Context())
+//
+// The server span will be automatically ended at the end of ServeHTTP.
+type Handler struct {
+ // Propagation defines how traces are propagated. If unspecified,
+ // B3 propagation will be used.
+ Propagation propagation.HTTPFormat
+
+ // Handler is the handler used to handle the incoming request.
+ Handler http.Handler
+
+ // StartOptions are applied to the span started by this Handler around each
+ // request.
+ //
+ // StartOptions.SpanKind will always be set to trace.SpanKindServer
+ // for spans started by this transport.
+ StartOptions trace.StartOptions
+
+ // GetStartOptions allows to set start options per request. If set,
+ // StartOptions is going to be ignored.
+ GetStartOptions func(*http.Request) trace.StartOptions
+
+ // IsPublicEndpoint should be set to true for publicly accessible HTTP(S)
+ // servers. If true, any trace metadata set on the incoming request will
+ // be added as a linked trace instead of being added as a parent of the
+ // current trace.
+ IsPublicEndpoint bool
+
+ // FormatSpanName holds the function to use for generating the span name
+ // from the information found in the incoming HTTP Request. By default the
+ // name equals the URL Path.
+ FormatSpanName func(*http.Request) string
+}
+
+func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+ var tags addedTags
+ r, traceEnd := h.startTrace(w, r)
+ defer traceEnd()
+ w, statsEnd := h.startStats(w, r)
+ defer statsEnd(&tags)
+ handler := h.Handler
+ if handler == nil {
+ handler = http.DefaultServeMux
+ }
+ r = r.WithContext(context.WithValue(r.Context(), addedTagsKey{}, &tags))
+ handler.ServeHTTP(w, r)
+}
+
+func (h *Handler) startTrace(w http.ResponseWriter, r *http.Request) (*http.Request, func()) {
+ if isHealthEndpoint(r.URL.Path) {
+ return r, func() {}
+ }
+ var name string
+ if h.FormatSpanName == nil {
+ name = spanNameFromURL(r)
+ } else {
+ name = h.FormatSpanName(r)
+ }
+ ctx := r.Context()
+
+ startOpts := h.StartOptions
+ if h.GetStartOptions != nil {
+ startOpts = h.GetStartOptions(r)
+ }
+
+ var span *trace.Span
+ sc, ok := h.extractSpanContext(r)
+ if ok && !h.IsPublicEndpoint {
+ ctx, span = trace.StartSpanWithRemoteParent(ctx, name, sc,
+ trace.WithSampler(startOpts.Sampler),
+ trace.WithSpanKind(trace.SpanKindServer))
+ } else {
+ ctx, span = trace.StartSpan(ctx, name,
+ trace.WithSampler(startOpts.Sampler),
+ trace.WithSpanKind(trace.SpanKindServer),
+ )
+ if ok {
+ span.AddLink(trace.Link{
+ TraceID: sc.TraceID,
+ SpanID: sc.SpanID,
+ Type: trace.LinkTypeChild,
+ Attributes: nil,
+ })
+ }
+ }
+ span.AddAttributes(requestAttrs(r)...)
+ return r.WithContext(ctx), span.End
+}
+
+func (h *Handler) extractSpanContext(r *http.Request) (trace.SpanContext, bool) {
+ if h.Propagation == nil {
+ return defaultFormat.SpanContextFromRequest(r)
+ }
+ return h.Propagation.SpanContextFromRequest(r)
+}
+
+func (h *Handler) startStats(w http.ResponseWriter, r *http.Request) (http.ResponseWriter, func(tags *addedTags)) {
+ ctx, _ := tag.New(r.Context(),
+ tag.Upsert(Host, r.URL.Host),
+ tag.Upsert(Path, r.URL.Path),
+ tag.Upsert(Method, r.Method))
+ track := &trackingResponseWriter{
+ start: time.Now(),
+ ctx: ctx,
+ writer: w,
+ }
+ if r.Body == nil {
+ // TODO: Handle cases where ContentLength is not set.
+ track.reqSize = -1
+ } else if r.ContentLength > 0 {
+ track.reqSize = r.ContentLength
+ }
+ stats.Record(ctx, ServerRequestCount.M(1))
+ return track.wrappedResponseWriter(), track.end
+}
+
+type trackingResponseWriter struct {
+ ctx context.Context
+ reqSize int64
+ respSize int64
+ start time.Time
+ statusCode int
+ statusLine string
+ endOnce sync.Once
+ writer http.ResponseWriter
+}
+
+// Compile time assertion for ResponseWriter interface
+var _ http.ResponseWriter = (*trackingResponseWriter)(nil)
+
+var logTagsErrorOnce sync.Once
+
+func (t *trackingResponseWriter) end(tags *addedTags) {
+ t.endOnce.Do(func() {
+ if t.statusCode == 0 {
+ t.statusCode = 200
+ }
+
+ span := trace.FromContext(t.ctx)
+ span.SetStatus(TraceStatus(t.statusCode, t.statusLine))
+ span.AddAttributes(trace.Int64Attribute(StatusCodeAttribute, int64(t.statusCode)))
+
+ m := []stats.Measurement{
+ ServerLatency.M(float64(time.Since(t.start)) / float64(time.Millisecond)),
+ ServerResponseBytes.M(t.respSize),
+ }
+ if t.reqSize >= 0 {
+ m = append(m, ServerRequestBytes.M(t.reqSize))
+ }
+ allTags := make([]tag.Mutator, len(tags.t)+1)
+ allTags[0] = tag.Upsert(StatusCode, strconv.Itoa(t.statusCode))
+ copy(allTags[1:], tags.t)
+ stats.RecordWithTags(t.ctx, allTags, m...)
+ })
+}
+
+func (t *trackingResponseWriter) Header() http.Header {
+ return t.writer.Header()
+}
+
+func (t *trackingResponseWriter) Write(data []byte) (int, error) {
+ n, err := t.writer.Write(data)
+ t.respSize += int64(n)
+ return n, err
+}
+
+func (t *trackingResponseWriter) WriteHeader(statusCode int) {
+ t.writer.WriteHeader(statusCode)
+ t.statusCode = statusCode
+ t.statusLine = http.StatusText(t.statusCode)
+}
+
+// wrappedResponseWriter returns a wrapped version of the original
+// ResponseWriter and only implements the same combination of additional
+// interfaces as the original.
+// This implementation is based on https://github.com/felixge/httpsnoop.
+func (t *trackingResponseWriter) wrappedResponseWriter() http.ResponseWriter {
+ var (
+ hj, i0 = t.writer.(http.Hijacker)
+ cn, i1 = t.writer.(http.CloseNotifier)
+ pu, i2 = t.writer.(http.Pusher)
+ fl, i3 = t.writer.(http.Flusher)
+ rf, i4 = t.writer.(io.ReaderFrom)
+ )
+
+ switch {
+ case !i0 && !i1 && !i2 && !i3 && !i4:
+ return struct {
+ http.ResponseWriter
+ }{t}
+ case !i0 && !i1 && !i2 && !i3 && i4:
+ return struct {
+ http.ResponseWriter
+ io.ReaderFrom
+ }{t, rf}
+ case !i0 && !i1 && !i2 && i3 && !i4:
+ return struct {
+ http.ResponseWriter
+ http.Flusher
+ }{t, fl}
+ case !i0 && !i1 && !i2 && i3 && i4:
+ return struct {
+ http.ResponseWriter
+ http.Flusher
+ io.ReaderFrom
+ }{t, fl, rf}
+ case !i0 && !i1 && i2 && !i3 && !i4:
+ return struct {
+ http.ResponseWriter
+ http.Pusher
+ }{t, pu}
+ case !i0 && !i1 && i2 && !i3 && i4:
+ return struct {
+ http.ResponseWriter
+ http.Pusher
+ io.ReaderFrom
+ }{t, pu, rf}
+ case !i0 && !i1 && i2 && i3 && !i4:
+ return struct {
+ http.ResponseWriter
+ http.Pusher
+ http.Flusher
+ }{t, pu, fl}
+ case !i0 && !i1 && i2 && i3 && i4:
+ return struct {
+ http.ResponseWriter
+ http.Pusher
+ http.Flusher
+ io.ReaderFrom
+ }{t, pu, fl, rf}
+ case !i0 && i1 && !i2 && !i3 && !i4:
+ return struct {
+ http.ResponseWriter
+ http.CloseNotifier
+ }{t, cn}
+ case !i0 && i1 && !i2 && !i3 && i4:
+ return struct {
+ http.ResponseWriter
+ http.CloseNotifier
+ io.ReaderFrom
+ }{t, cn, rf}
+ case !i0 && i1 && !i2 && i3 && !i4:
+ return struct {
+ http.ResponseWriter
+ http.CloseNotifier
+ http.Flusher
+ }{t, cn, fl}
+ case !i0 && i1 && !i2 && i3 && i4:
+ return struct {
+ http.ResponseWriter
+ http.CloseNotifier
+ http.Flusher
+ io.ReaderFrom
+ }{t, cn, fl, rf}
+ case !i0 && i1 && i2 && !i3 && !i4:
+ return struct {
+ http.ResponseWriter
+ http.CloseNotifier
+ http.Pusher
+ }{t, cn, pu}
+ case !i0 && i1 && i2 && !i3 && i4:
+ return struct {
+ http.ResponseWriter
+ http.CloseNotifier
+ http.Pusher
+ io.ReaderFrom
+ }{t, cn, pu, rf}
+ case !i0 && i1 && i2 && i3 && !i4:
+ return struct {
+ http.ResponseWriter
+ http.CloseNotifier
+ http.Pusher
+ http.Flusher
+ }{t, cn, pu, fl}
+ case !i0 && i1 && i2 && i3 && i4:
+ return struct {
+ http.ResponseWriter
+ http.CloseNotifier
+ http.Pusher
+ http.Flusher
+ io.ReaderFrom
+ }{t, cn, pu, fl, rf}
+ case i0 && !i1 && !i2 && !i3 && !i4:
+ return struct {
+ http.ResponseWriter
+ http.Hijacker
+ }{t, hj}
+ case i0 && !i1 && !i2 && !i3 && i4:
+ return struct {
+ http.ResponseWriter
+ http.Hijacker
+ io.ReaderFrom
+ }{t, hj, rf}
+ case i0 && !i1 && !i2 && i3 && !i4:
+ return struct {
+ http.ResponseWriter
+ http.Hijacker
+ http.Flusher
+ }{t, hj, fl}
+ case i0 && !i1 && !i2 && i3 && i4:
+ return struct {
+ http.ResponseWriter
+ http.Hijacker
+ http.Flusher
+ io.ReaderFrom
+ }{t, hj, fl, rf}
+ case i0 && !i1 && i2 && !i3 && !i4:
+ return struct {
+ http.ResponseWriter
+ http.Hijacker
+ http.Pusher
+ }{t, hj, pu}
+ case i0 && !i1 && i2 && !i3 && i4:
+ return struct {
+ http.ResponseWriter
+ http.Hijacker
+ http.Pusher
+ io.ReaderFrom
+ }{t, hj, pu, rf}
+ case i0 && !i1 && i2 && i3 && !i4:
+ return struct {
+ http.ResponseWriter
+ http.Hijacker
+ http.Pusher
+ http.Flusher
+ }{t, hj, pu, fl}
+ case i0 && !i1 && i2 && i3 && i4:
+ return struct {
+ http.ResponseWriter
+ http.Hijacker
+ http.Pusher
+ http.Flusher
+ io.ReaderFrom
+ }{t, hj, pu, fl, rf}
+ case i0 && i1 && !i2 && !i3 && !i4:
+ return struct {
+ http.ResponseWriter
+ http.Hijacker
+ http.CloseNotifier
+ }{t, hj, cn}
+ case i0 && i1 && !i2 && !i3 && i4:
+ return struct {
+ http.ResponseWriter
+ http.Hijacker
+ http.CloseNotifier
+ io.ReaderFrom
+ }{t, hj, cn, rf}
+ case i0 && i1 && !i2 && i3 && !i4:
+ return struct {
+ http.ResponseWriter
+ http.Hijacker
+ http.CloseNotifier
+ http.Flusher
+ }{t, hj, cn, fl}
+ case i0 && i1 && !i2 && i3 && i4:
+ return struct {
+ http.ResponseWriter
+ http.Hijacker
+ http.CloseNotifier
+ http.Flusher
+ io.ReaderFrom
+ }{t, hj, cn, fl, rf}
+ case i0 && i1 && i2 && !i3 && !i4:
+ return struct {
+ http.ResponseWriter
+ http.Hijacker
+ http.CloseNotifier
+ http.Pusher
+ }{t, hj, cn, pu}
+ case i0 && i1 && i2 && !i3 && i4:
+ return struct {
+ http.ResponseWriter
+ http.Hijacker
+ http.CloseNotifier
+ http.Pusher
+ io.ReaderFrom
+ }{t, hj, cn, pu, rf}
+ case i0 && i1 && i2 && i3 && !i4:
+ return struct {
+ http.ResponseWriter
+ http.Hijacker
+ http.CloseNotifier
+ http.Pusher
+ http.Flusher
+ }{t, hj, cn, pu, fl}
+ case i0 && i1 && i2 && i3 && i4:
+ return struct {
+ http.ResponseWriter
+ http.Hijacker
+ http.CloseNotifier
+ http.Pusher
+ http.Flusher
+ io.ReaderFrom
+ }{t, hj, cn, pu, fl, rf}
+ default:
+ return struct {
+ http.ResponseWriter
+ }{t}
+ }
+}
diff --git a/vendor/go.opencensus.io/plugin/ochttp/span_annotating_client_trace.go b/vendor/go.opencensus.io/plugin/ochttp/span_annotating_client_trace.go
new file mode 100644
index 000000000..05c6c56cc
--- /dev/null
+++ b/vendor/go.opencensus.io/plugin/ochttp/span_annotating_client_trace.go
@@ -0,0 +1,169 @@
+// Copyright 2018, OpenCensus Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package ochttp
+
+import (
+ "crypto/tls"
+ "net/http"
+ "net/http/httptrace"
+ "strings"
+
+ "go.opencensus.io/trace"
+)
+
+type spanAnnotator struct {
+ sp *trace.Span
+}
+
+// TODO: Remove NewSpanAnnotator at the next release.
+
+// NewSpanAnnotator returns a httptrace.ClientTrace which annotates
+// all emitted httptrace events on the provided Span.
+// Deprecated: Use NewSpanAnnotatingClientTrace instead
+func NewSpanAnnotator(r *http.Request, s *trace.Span) *httptrace.ClientTrace {
+ return NewSpanAnnotatingClientTrace(r, s)
+}
+
+// NewSpanAnnotatingClientTrace returns a httptrace.ClientTrace which annotates
+// all emitted httptrace events on the provided Span.
+func NewSpanAnnotatingClientTrace(_ *http.Request, s *trace.Span) *httptrace.ClientTrace {
+ sa := spanAnnotator{sp: s}
+
+ return &httptrace.ClientTrace{
+ GetConn: sa.getConn,
+ GotConn: sa.gotConn,
+ PutIdleConn: sa.putIdleConn,
+ GotFirstResponseByte: sa.gotFirstResponseByte,
+ Got100Continue: sa.got100Continue,
+ DNSStart: sa.dnsStart,
+ DNSDone: sa.dnsDone,
+ ConnectStart: sa.connectStart,
+ ConnectDone: sa.connectDone,
+ TLSHandshakeStart: sa.tlsHandshakeStart,
+ TLSHandshakeDone: sa.tlsHandshakeDone,
+ WroteHeaders: sa.wroteHeaders,
+ Wait100Continue: sa.wait100Continue,
+ WroteRequest: sa.wroteRequest,
+ }
+}
+
+func (s spanAnnotator) getConn(hostPort string) {
+ attrs := []trace.Attribute{
+ trace.StringAttribute("httptrace.get_connection.host_port", hostPort),
+ }
+ s.sp.Annotate(attrs, "GetConn")
+}
+
+func (s spanAnnotator) gotConn(info httptrace.GotConnInfo) {
+ attrs := []trace.Attribute{
+ trace.BoolAttribute("httptrace.got_connection.reused", info.Reused),
+ trace.BoolAttribute("httptrace.got_connection.was_idle", info.WasIdle),
+ }
+ if info.WasIdle {
+ attrs = append(attrs,
+ trace.StringAttribute("httptrace.got_connection.idle_time", info.IdleTime.String()))
+ }
+ s.sp.Annotate(attrs, "GotConn")
+}
+
+// PutIdleConn implements a httptrace.ClientTrace hook
+func (s spanAnnotator) putIdleConn(err error) {
+ var attrs []trace.Attribute
+ if err != nil {
+ attrs = append(attrs,
+ trace.StringAttribute("httptrace.put_idle_connection.error", err.Error()))
+ }
+ s.sp.Annotate(attrs, "PutIdleConn")
+}
+
+func (s spanAnnotator) gotFirstResponseByte() {
+ s.sp.Annotate(nil, "GotFirstResponseByte")
+}
+
+func (s spanAnnotator) got100Continue() {
+ s.sp.Annotate(nil, "Got100Continue")
+}
+
+func (s spanAnnotator) dnsStart(info httptrace.DNSStartInfo) {
+ attrs := []trace.Attribute{
+ trace.StringAttribute("httptrace.dns_start.host", info.Host),
+ }
+ s.sp.Annotate(attrs, "DNSStart")
+}
+
+func (s spanAnnotator) dnsDone(info httptrace.DNSDoneInfo) {
+ var addrs []string
+ for _, addr := range info.Addrs {
+ addrs = append(addrs, addr.String())
+ }
+ attrs := []trace.Attribute{
+ trace.StringAttribute("httptrace.dns_done.addrs", strings.Join(addrs, " , ")),
+ }
+ if info.Err != nil {
+ attrs = append(attrs,
+ trace.StringAttribute("httptrace.dns_done.error", info.Err.Error()))
+ }
+ s.sp.Annotate(attrs, "DNSDone")
+}
+
+func (s spanAnnotator) connectStart(network, addr string) {
+ attrs := []trace.Attribute{
+ trace.StringAttribute("httptrace.connect_start.network", network),
+ trace.StringAttribute("httptrace.connect_start.addr", addr),
+ }
+ s.sp.Annotate(attrs, "ConnectStart")
+}
+
+func (s spanAnnotator) connectDone(network, addr string, err error) {
+ attrs := []trace.Attribute{
+ trace.StringAttribute("httptrace.connect_done.network", network),
+ trace.StringAttribute("httptrace.connect_done.addr", addr),
+ }
+ if err != nil {
+ attrs = append(attrs,
+ trace.StringAttribute("httptrace.connect_done.error", err.Error()))
+ }
+ s.sp.Annotate(attrs, "ConnectDone")
+}
+
+func (s spanAnnotator) tlsHandshakeStart() {
+ s.sp.Annotate(nil, "TLSHandshakeStart")
+}
+
+func (s spanAnnotator) tlsHandshakeDone(_ tls.ConnectionState, err error) {
+ var attrs []trace.Attribute
+ if err != nil {
+ attrs = append(attrs,
+ trace.StringAttribute("httptrace.tls_handshake_done.error", err.Error()))
+ }
+ s.sp.Annotate(attrs, "TLSHandshakeDone")
+}
+
+func (s spanAnnotator) wroteHeaders() {
+ s.sp.Annotate(nil, "WroteHeaders")
+}
+
+func (s spanAnnotator) wait100Continue() {
+ s.sp.Annotate(nil, "Wait100Continue")
+}
+
+func (s spanAnnotator) wroteRequest(info httptrace.WroteRequestInfo) {
+ var attrs []trace.Attribute
+ if info.Err != nil {
+ attrs = append(attrs,
+ trace.StringAttribute("httptrace.wrote_request.error", info.Err.Error()))
+ }
+ s.sp.Annotate(attrs, "WroteRequest")
+}
diff --git a/vendor/go.opencensus.io/plugin/ochttp/stats.go b/vendor/go.opencensus.io/plugin/ochttp/stats.go
new file mode 100644
index 000000000..46dcc8e57
--- /dev/null
+++ b/vendor/go.opencensus.io/plugin/ochttp/stats.go
@@ -0,0 +1,265 @@
+// Copyright 2018, OpenCensus Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package ochttp
+
+import (
+ "go.opencensus.io/stats"
+ "go.opencensus.io/stats/view"
+ "go.opencensus.io/tag"
+)
+
+// The following client HTTP measures are supported for use in custom views.
+var (
+ // Deprecated: Use a Count aggregation over one of the other client measures to achieve the same effect.
+ ClientRequestCount = stats.Int64("opencensus.io/http/client/request_count", "Number of HTTP requests started", stats.UnitDimensionless)
+ // Deprecated: Use ClientSentBytes.
+ ClientRequestBytes = stats.Int64("opencensus.io/http/client/request_bytes", "HTTP request body size if set as ContentLength (uncompressed)", stats.UnitBytes)
+ // Deprecated: Use ClientReceivedBytes.
+ ClientResponseBytes = stats.Int64("opencensus.io/http/client/response_bytes", "HTTP response body size (uncompressed)", stats.UnitBytes)
+ // Deprecated: Use ClientRoundtripLatency.
+ ClientLatency = stats.Float64("opencensus.io/http/client/latency", "End-to-end latency", stats.UnitMilliseconds)
+)
+
+// Client measures supported for use in custom views.
+var (
+ ClientSentBytes = stats.Int64(
+ "opencensus.io/http/client/sent_bytes",
+ "Total bytes sent in request body (not including headers)",
+ stats.UnitBytes,
+ )
+ ClientReceivedBytes = stats.Int64(
+ "opencensus.io/http/client/received_bytes",
+ "Total bytes received in response bodies (not including headers but including error responses with bodies)",
+ stats.UnitBytes,
+ )
+ ClientRoundtripLatency = stats.Float64(
+ "opencensus.io/http/client/roundtrip_latency",
+ "Time between first byte of request headers sent to last byte of response received, or terminal error",
+ stats.UnitMilliseconds,
+ )
+)
+
+// The following server HTTP measures are supported for use in custom views:
+var (
+ ServerRequestCount = stats.Int64("opencensus.io/http/server/request_count", "Number of HTTP requests started", stats.UnitDimensionless)
+ ServerRequestBytes = stats.Int64("opencensus.io/http/server/request_bytes", "HTTP request body size if set as ContentLength (uncompressed)", stats.UnitBytes)
+ ServerResponseBytes = stats.Int64("opencensus.io/http/server/response_bytes", "HTTP response body size (uncompressed)", stats.UnitBytes)
+ ServerLatency = stats.Float64("opencensus.io/http/server/latency", "End-to-end latency", stats.UnitMilliseconds)
+)
+
+// The following tags are applied to stats recorded by this package. Host, Path
+// and Method are applied to all measures. StatusCode is not applied to
+// ClientRequestCount or ServerRequestCount, since it is recorded before the status is known.
+var (
+ // Host is the value of the HTTP Host header.
+ //
+ // The value of this tag can be controlled by the HTTP client, so you need
+ // to watch out for potentially generating high-cardinality labels in your
+ // metrics backend if you use this tag in views.
+ Host, _ = tag.NewKey("http.host")
+
+ // StatusCode is the numeric HTTP response status code,
+ // or "error" if a transport error occurred and no status code was read.
+ StatusCode, _ = tag.NewKey("http.status")
+
+ // Path is the URL path (not including query string) in the request.
+ //
+ // The value of this tag can be controlled by the HTTP client, so you need
+ // to watch out for potentially generating high-cardinality labels in your
+ // metrics backend if you use this tag in views.
+ Path, _ = tag.NewKey("http.path")
+
+ // Method is the HTTP method of the request, capitalized (GET, POST, etc.).
+ Method, _ = tag.NewKey("http.method")
+
+ // KeyServerRoute is a low cardinality string representing the logical
+ // handler of the request. This is usually the pattern registered on the a
+ // ServeMux (or similar string).
+ KeyServerRoute, _ = tag.NewKey("http_server_route")
+)
+
+// Client tag keys.
+var (
+ // KeyClientMethod is the HTTP method, capitalized (i.e. GET, POST, PUT, DELETE, etc.).
+ KeyClientMethod, _ = tag.NewKey("http_client_method")
+ // KeyClientPath is the URL path (not including query string).
+ KeyClientPath, _ = tag.NewKey("http_client_path")
+ // KeyClientStatus is the HTTP status code as an integer (e.g. 200, 404, 500.), or "error" if no response status line was received.
+ KeyClientStatus, _ = tag.NewKey("http_client_status")
+ // KeyClientHost is the value of the request Host header.
+ KeyClientHost, _ = tag.NewKey("http_client_host")
+)
+
+// Default distributions used by views in this package.
+var (
+ DefaultSizeDistribution = view.Distribution(0, 1024, 2048, 4096, 16384, 65536, 262144, 1048576, 4194304, 16777216, 67108864, 268435456, 1073741824, 4294967296)
+ DefaultLatencyDistribution = view.Distribution(0, 1, 2, 3, 4, 5, 6, 8, 10, 13, 16, 20, 25, 30, 40, 50, 65, 80, 100, 130, 160, 200, 250, 300, 400, 500, 650, 800, 1000, 2000, 5000, 10000, 20000, 50000, 100000)
+)
+
+// Package ochttp provides some convenience views.
+// You still need to register these views for data to actually be collected.
+var (
+ ClientSentBytesDistribution = &view.View{
+ Name: "opencensus.io/http/client/sent_bytes",
+ Measure: ClientSentBytes,
+ Aggregation: DefaultSizeDistribution,
+ Description: "Total bytes sent in request body (not including headers), by HTTP method and response status",
+ TagKeys: []tag.Key{KeyClientMethod, KeyClientStatus},
+ }
+
+ ClientReceivedBytesDistribution = &view.View{
+ Name: "opencensus.io/http/client/received_bytes",
+ Measure: ClientReceivedBytes,
+ Aggregation: DefaultSizeDistribution,
+ Description: "Total bytes received in response bodies (not including headers but including error responses with bodies), by HTTP method and response status",
+ TagKeys: []tag.Key{KeyClientMethod, KeyClientStatus},
+ }
+
+ ClientRoundtripLatencyDistribution = &view.View{
+ Name: "opencensus.io/http/client/roundtrip_latency",
+ Measure: ClientRoundtripLatency,
+ Aggregation: DefaultLatencyDistribution,
+ Description: "End-to-end latency, by HTTP method and response status",
+ TagKeys: []tag.Key{KeyClientMethod, KeyClientStatus},
+ }
+
+ ClientCompletedCount = &view.View{
+ Name: "opencensus.io/http/client/completed_count",
+ Measure: ClientRoundtripLatency,
+ Aggregation: view.Count(),
+ Description: "Count of completed requests, by HTTP method and response status",
+ TagKeys: []tag.Key{KeyClientMethod, KeyClientStatus},
+ }
+)
+
+var (
+ // Deprecated: No direct replacement, but see ClientCompletedCount.
+ ClientRequestCountView = &view.View{
+ Name: "opencensus.io/http/client/request_count",
+ Description: "Count of HTTP requests started",
+ Measure: ClientRequestCount,
+ Aggregation: view.Count(),
+ }
+
+ // Deprecated: Use ClientSentBytesDistribution.
+ ClientRequestBytesView = &view.View{
+ Name: "opencensus.io/http/client/request_bytes",
+ Description: "Size distribution of HTTP request body",
+ Measure: ClientSentBytes,
+ Aggregation: DefaultSizeDistribution,
+ }
+
+ // Deprecated: Use ClientReceivedBytesDistribution.
+ ClientResponseBytesView = &view.View{
+ Name: "opencensus.io/http/client/response_bytes",
+ Description: "Size distribution of HTTP response body",
+ Measure: ClientReceivedBytes,
+ Aggregation: DefaultSizeDistribution,
+ }
+
+ // Deprecated: Use ClientRoundtripLatencyDistribution.
+ ClientLatencyView = &view.View{
+ Name: "opencensus.io/http/client/latency",
+ Description: "Latency distribution of HTTP requests",
+ Measure: ClientRoundtripLatency,
+ Aggregation: DefaultLatencyDistribution,
+ }
+
+ // Deprecated: Use ClientCompletedCount.
+ ClientRequestCountByMethod = &view.View{
+ Name: "opencensus.io/http/client/request_count_by_method",
+ Description: "Client request count by HTTP method",
+ TagKeys: []tag.Key{Method},
+ Measure: ClientSentBytes,
+ Aggregation: view.Count(),
+ }
+
+ // Deprecated: Use ClientCompletedCount.
+ ClientResponseCountByStatusCode = &view.View{
+ Name: "opencensus.io/http/client/response_count_by_status_code",
+ Description: "Client response count by status code",
+ TagKeys: []tag.Key{StatusCode},
+ Measure: ClientRoundtripLatency,
+ Aggregation: view.Count(),
+ }
+)
+
+var (
+ ServerRequestCountView = &view.View{
+ Name: "opencensus.io/http/server/request_count",
+ Description: "Count of HTTP requests started",
+ Measure: ServerRequestCount,
+ Aggregation: view.Count(),
+ }
+
+ ServerRequestBytesView = &view.View{
+ Name: "opencensus.io/http/server/request_bytes",
+ Description: "Size distribution of HTTP request body",
+ Measure: ServerRequestBytes,
+ Aggregation: DefaultSizeDistribution,
+ }
+
+ ServerResponseBytesView = &view.View{
+ Name: "opencensus.io/http/server/response_bytes",
+ Description: "Size distribution of HTTP response body",
+ Measure: ServerResponseBytes,
+ Aggregation: DefaultSizeDistribution,
+ }
+
+ ServerLatencyView = &view.View{
+ Name: "opencensus.io/http/server/latency",
+ Description: "Latency distribution of HTTP requests",
+ Measure: ServerLatency,
+ Aggregation: DefaultLatencyDistribution,
+ }
+
+ ServerRequestCountByMethod = &view.View{
+ Name: "opencensus.io/http/server/request_count_by_method",
+ Description: "Server request count by HTTP method",
+ TagKeys: []tag.Key{Method},
+ Measure: ServerRequestCount,
+ Aggregation: view.Count(),
+ }
+
+ ServerResponseCountByStatusCode = &view.View{
+ Name: "opencensus.io/http/server/response_count_by_status_code",
+ Description: "Server response count by status code",
+ TagKeys: []tag.Key{StatusCode},
+ Measure: ServerLatency,
+ Aggregation: view.Count(),
+ }
+)
+
+// DefaultClientViews are the default client views provided by this package.
+// Deprecated: No replacement. Register the views you would like individually.
+var DefaultClientViews = []*view.View{
+ ClientRequestCountView,
+ ClientRequestBytesView,
+ ClientResponseBytesView,
+ ClientLatencyView,
+ ClientRequestCountByMethod,
+ ClientResponseCountByStatusCode,
+}
+
+// DefaultServerViews are the default server views provided by this package.
+// Deprecated: No replacement. Register the views you would like individually.
+var DefaultServerViews = []*view.View{
+ ServerRequestCountView,
+ ServerRequestBytesView,
+ ServerResponseBytesView,
+ ServerLatencyView,
+ ServerRequestCountByMethod,
+ ServerResponseCountByStatusCode,
+}
diff --git a/vendor/go.opencensus.io/plugin/ochttp/trace.go b/vendor/go.opencensus.io/plugin/ochttp/trace.go
new file mode 100644
index 000000000..819a2d5ff
--- /dev/null
+++ b/vendor/go.opencensus.io/plugin/ochttp/trace.go
@@ -0,0 +1,228 @@
+// Copyright 2018, OpenCensus Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package ochttp
+
+import (
+ "io"
+ "net/http"
+ "net/http/httptrace"
+
+ "go.opencensus.io/plugin/ochttp/propagation/b3"
+ "go.opencensus.io/trace"
+ "go.opencensus.io/trace/propagation"
+)
+
+// TODO(jbd): Add godoc examples.
+
+var defaultFormat propagation.HTTPFormat = &b3.HTTPFormat{}
+
+// Attributes recorded on the span for the requests.
+// Only trace exporters will need them.
+const (
+ HostAttribute = "http.host"
+ MethodAttribute = "http.method"
+ PathAttribute = "http.path"
+ UserAgentAttribute = "http.user_agent"
+ StatusCodeAttribute = "http.status_code"
+)
+
+type traceTransport struct {
+ base http.RoundTripper
+ startOptions trace.StartOptions
+ format propagation.HTTPFormat
+ formatSpanName func(*http.Request) string
+ newClientTrace func(*http.Request, *trace.Span) *httptrace.ClientTrace
+}
+
+// TODO(jbd): Add message events for request and response size.
+
+// RoundTrip creates a trace.Span and inserts it into the outgoing request's headers.
+// The created span can follow a parent span, if a parent is presented in
+// the request's context.
+func (t *traceTransport) RoundTrip(req *http.Request) (*http.Response, error) {
+ name := t.formatSpanName(req)
+ // TODO(jbd): Discuss whether we want to prefix
+ // outgoing requests with Sent.
+ ctx, span := trace.StartSpan(req.Context(), name,
+ trace.WithSampler(t.startOptions.Sampler),
+ trace.WithSpanKind(trace.SpanKindClient))
+
+ if t.newClientTrace != nil {
+ req = req.WithContext(httptrace.WithClientTrace(ctx, t.newClientTrace(req, span)))
+ } else {
+ req = req.WithContext(ctx)
+ }
+
+ if t.format != nil {
+ // SpanContextToRequest will modify its Request argument, which is
+ // contrary to the contract for http.RoundTripper, so we need to
+ // pass it a copy of the Request.
+ // However, the Request struct itself was already copied by
+ // the WithContext calls above and so we just need to copy the header.
+ header := make(http.Header)
+ for k, v := range req.Header {
+ header[k] = v
+ }
+ req.Header = header
+ t.format.SpanContextToRequest(span.SpanContext(), req)
+ }
+
+ span.AddAttributes(requestAttrs(req)...)
+ resp, err := t.base.RoundTrip(req)
+ if err != nil {
+ span.SetStatus(trace.Status{Code: trace.StatusCodeUnknown, Message: err.Error()})
+ span.End()
+ return resp, err
+ }
+
+ span.AddAttributes(responseAttrs(resp)...)
+ span.SetStatus(TraceStatus(resp.StatusCode, resp.Status))
+
+ // span.End() will be invoked after
+ // a read from resp.Body returns io.EOF or when
+ // resp.Body.Close() is invoked.
+ resp.Body = &bodyTracker{rc: resp.Body, span: span}
+ return resp, err
+}
+
+// bodyTracker wraps a response.Body and invokes
+// trace.EndSpan on encountering io.EOF on reading
+// the body of the original response.
+type bodyTracker struct {
+ rc io.ReadCloser
+ span *trace.Span
+}
+
+var _ io.ReadCloser = (*bodyTracker)(nil)
+
+func (bt *bodyTracker) Read(b []byte) (int, error) {
+ n, err := bt.rc.Read(b)
+
+ switch err {
+ case nil:
+ return n, nil
+ case io.EOF:
+ bt.span.End()
+ default:
+ // For all other errors, set the span status
+ bt.span.SetStatus(trace.Status{
+ // Code 2 is the error code for Internal server error.
+ Code: 2,
+ Message: err.Error(),
+ })
+ }
+ return n, err
+}
+
+func (bt *bodyTracker) Close() error {
+ // Invoking endSpan on Close will help catch the cases
+ // in which a read returned a non-nil error, we set the
+ // span status but didn't end the span.
+ bt.span.End()
+ return bt.rc.Close()
+}
+
+// CancelRequest cancels an in-flight request by closing its connection.
+func (t *traceTransport) CancelRequest(req *http.Request) {
+ type canceler interface {
+ CancelRequest(*http.Request)
+ }
+ if cr, ok := t.base.(canceler); ok {
+ cr.CancelRequest(req)
+ }
+}
+
+func spanNameFromURL(req *http.Request) string {
+ return req.URL.Path
+}
+
+func requestAttrs(r *http.Request) []trace.Attribute {
+ return []trace.Attribute{
+ trace.StringAttribute(PathAttribute, r.URL.Path),
+ trace.StringAttribute(HostAttribute, r.URL.Host),
+ trace.StringAttribute(MethodAttribute, r.Method),
+ trace.StringAttribute(UserAgentAttribute, r.UserAgent()),
+ }
+}
+
+func responseAttrs(resp *http.Response) []trace.Attribute {
+ return []trace.Attribute{
+ trace.Int64Attribute(StatusCodeAttribute, int64(resp.StatusCode)),
+ }
+}
+
+// TraceStatus is a utility to convert the HTTP status code to a trace.Status that
+// represents the outcome as closely as possible.
+func TraceStatus(httpStatusCode int, statusLine string) trace.Status {
+ var code int32
+ if httpStatusCode < 200 || httpStatusCode >= 400 {
+ code = trace.StatusCodeUnknown
+ }
+ switch httpStatusCode {
+ case 499:
+ code = trace.StatusCodeCancelled
+ case http.StatusBadRequest:
+ code = trace.StatusCodeInvalidArgument
+ case http.StatusGatewayTimeout:
+ code = trace.StatusCodeDeadlineExceeded
+ case http.StatusNotFound:
+ code = trace.StatusCodeNotFound
+ case http.StatusForbidden:
+ code = trace.StatusCodePermissionDenied
+ case http.StatusUnauthorized: // 401 is actually unauthenticated.
+ code = trace.StatusCodeUnauthenticated
+ case http.StatusTooManyRequests:
+ code = trace.StatusCodeResourceExhausted
+ case http.StatusNotImplemented:
+ code = trace.StatusCodeUnimplemented
+ case http.StatusServiceUnavailable:
+ code = trace.StatusCodeUnavailable
+ case http.StatusOK:
+ code = trace.StatusCodeOK
+ }
+ return trace.Status{Code: code, Message: codeToStr[code]}
+}
+
+var codeToStr = map[int32]string{
+ trace.StatusCodeOK: `OK`,
+ trace.StatusCodeCancelled: `CANCELLED`,
+ trace.StatusCodeUnknown: `UNKNOWN`,
+ trace.StatusCodeInvalidArgument: `INVALID_ARGUMENT`,
+ trace.StatusCodeDeadlineExceeded: `DEADLINE_EXCEEDED`,
+ trace.StatusCodeNotFound: `NOT_FOUND`,
+ trace.StatusCodeAlreadyExists: `ALREADY_EXISTS`,
+ trace.StatusCodePermissionDenied: `PERMISSION_DENIED`,
+ trace.StatusCodeResourceExhausted: `RESOURCE_EXHAUSTED`,
+ trace.StatusCodeFailedPrecondition: `FAILED_PRECONDITION`,
+ trace.StatusCodeAborted: `ABORTED`,
+ trace.StatusCodeOutOfRange: `OUT_OF_RANGE`,
+ trace.StatusCodeUnimplemented: `UNIMPLEMENTED`,
+ trace.StatusCodeInternal: `INTERNAL`,
+ trace.StatusCodeUnavailable: `UNAVAILABLE`,
+ trace.StatusCodeDataLoss: `DATA_LOSS`,
+ trace.StatusCodeUnauthenticated: `UNAUTHENTICATED`,
+}
+
+func isHealthEndpoint(path string) bool {
+ // Health checking is pretty frequent and
+ // traces collected for health endpoints
+ // can be extremely noisy and expensive.
+ // Disable canonical health checking endpoints
+ // like /healthz and /_ah/health for now.
+ if path == "/healthz" || path == "/_ah/health" {
+ return true
+ }
+ return false
+}
diff --git a/vendor/go.opencensus.io/stats/doc.go b/vendor/go.opencensus.io/stats/doc.go
new file mode 100644
index 000000000..00d473ee0
--- /dev/null
+++ b/vendor/go.opencensus.io/stats/doc.go
@@ -0,0 +1,69 @@
+// Copyright 2017, OpenCensus Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/*
+Package stats contains support for OpenCensus stats recording.
+
+OpenCensus allows users to create typed measures, record measurements,
+aggregate the collected data, and export the aggregated data.
+
+Measures
+
+A measure represents a type of data point to be tracked and recorded.
+For example, latency, request Mb/s, and response Mb/s are measures
+to collect from a server.
+
+Measure constructors such as Int64 and Float64 automatically
+register the measure by the given name. Each registered measure needs
+to be unique by name. Measures also have a description and a unit.
+
+Libraries can define and export measures. Application authors can then
+create views and collect and break down measures by the tags they are
+interested in.
+
+Recording measurements
+
+Measurement is a data point to be collected for a measure. For example,
+for a latency (ms) measure, 100 is a measurement that represents a 100ms
+latency event. Measurements are created from measures with
+the current context. Tags from the current context are recorded with the
+measurements if they are any.
+
+Recorded measurements are dropped immediately if no views are registered for them.
+There is usually no need to conditionally enable and disable
+recording to reduce cost. Recording of measurements is cheap.
+
+Libraries can always record measurements, and applications can later decide
+on which measurements they want to collect by registering views. This allows
+libraries to turn on the instrumentation by default.
+
+Exemplars
+
+For a given recorded measurement, the associated exemplar is a diagnostic map
+that gives more information about the measurement.
+
+When aggregated using a Distribution aggregation, an exemplar is kept for each
+bucket in the Distribution. This allows you to easily find an example of a
+measurement that fell into each bucket.
+
+For example, if you also use the OpenCensus trace package and you
+record a measurement with a context that contains a sampled trace span,
+then the trace span will be added to the exemplar associated with the measurement.
+
+When exported to a supporting back end, you should be able to easily navigate
+to example traces that fell into each bucket in the Distribution.
+
+*/
+package stats // import "go.opencensus.io/stats"
diff --git a/vendor/go.opencensus.io/stats/internal/record.go b/vendor/go.opencensus.io/stats/internal/record.go
new file mode 100644
index 000000000..ed5455205
--- /dev/null
+++ b/vendor/go.opencensus.io/stats/internal/record.go
@@ -0,0 +1,25 @@
+// Copyright 2018, OpenCensus Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package internal
+
+import (
+ "go.opencensus.io/tag"
+)
+
+// DefaultRecorder will be called for each Record call.
+var DefaultRecorder func(tags *tag.Map, measurement interface{}, attachments map[string]string)
+
+// SubscriptionReporter reports when a view subscribed with a measure.
+var SubscriptionReporter func(measure string)
diff --git a/vendor/go.opencensus.io/stats/internal/validation.go b/vendor/go.opencensus.io/stats/internal/validation.go
new file mode 100644
index 000000000..b946667f9
--- /dev/null
+++ b/vendor/go.opencensus.io/stats/internal/validation.go
@@ -0,0 +1,28 @@
+// Copyright 2018, OpenCensus Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package internal // import "go.opencensus.io/stats/internal"
+
+const (
+ MaxNameLength = 255
+)
+
+func IsPrintable(str string) bool {
+ for _, r := range str {
+ if !(r >= ' ' && r <= '~') {
+ return false
+ }
+ }
+ return true
+}
diff --git a/vendor/go.opencensus.io/stats/measure.go b/vendor/go.opencensus.io/stats/measure.go
new file mode 100644
index 000000000..1ffd3cefc
--- /dev/null
+++ b/vendor/go.opencensus.io/stats/measure.go
@@ -0,0 +1,109 @@
+// Copyright 2017, OpenCensus Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package stats
+
+import (
+ "sync"
+ "sync/atomic"
+)
+
+// Measure represents a single numeric value to be tracked and recorded.
+// For example, latency, request bytes, and response bytes could be measures
+// to collect from a server.
+//
+// Measures by themselves have no outside effects. In order to be exported,
+// the measure needs to be used in a View. If no Views are defined over a
+// measure, there is very little cost in recording it.
+type Measure interface {
+ // Name returns the name of this measure.
+ //
+ // Measure names are globally unique (among all libraries linked into your program).
+ // We recommend prefixing the measure name with a domain name relevant to your
+ // project or application.
+ //
+ // Measure names are never sent over the wire or exported to backends.
+ // They are only used to create Views.
+ Name() string
+
+ // Description returns the human-readable description of this measure.
+ Description() string
+
+ // Unit returns the units for the values this measure takes on.
+ //
+ // Units are encoded according to the case-sensitive abbreviations from the
+ // Unified Code for Units of Measure: http://unitsofmeasure.org/ucum.html
+ Unit() string
+}
+
+// measureDescriptor is the untyped descriptor associated with each measure.
+// Int64Measure and Float64Measure wrap measureDescriptor to provide typed
+// recording APIs.
+// Two Measures with the same name will have the same measureDescriptor.
+type measureDescriptor struct {
+ subs int32 // access atomically
+
+ name string
+ description string
+ unit string
+}
+
+func (m *measureDescriptor) subscribe() {
+ atomic.StoreInt32(&m.subs, 1)
+}
+
+func (m *measureDescriptor) subscribed() bool {
+ return atomic.LoadInt32(&m.subs) == 1
+}
+
+var (
+ mu sync.RWMutex
+ measures = make(map[string]*measureDescriptor)
+)
+
+func registerMeasureHandle(name, desc, unit string) *measureDescriptor {
+ mu.Lock()
+ defer mu.Unlock()
+
+ if stored, ok := measures[name]; ok {
+ return stored
+ }
+ m := &measureDescriptor{
+ name: name,
+ description: desc,
+ unit: unit,
+ }
+ measures[name] = m
+ return m
+}
+
+// Measurement is the numeric value measured when recording stats. Each measure
+// provides methods to create measurements of their kind. For example, Int64Measure
+// provides M to convert an int64 into a measurement.
+type Measurement struct {
+ v float64
+ m Measure
+ desc *measureDescriptor
+}
+
+// Value returns the value of the Measurement as a float64.
+func (m Measurement) Value() float64 {
+ return m.v
+}
+
+// Measure returns the Measure from which this Measurement was created.
+func (m Measurement) Measure() Measure {
+ return m.m
+}
diff --git a/vendor/go.opencensus.io/stats/measure_float64.go b/vendor/go.opencensus.io/stats/measure_float64.go
new file mode 100644
index 000000000..f02c1eda8
--- /dev/null
+++ b/vendor/go.opencensus.io/stats/measure_float64.go
@@ -0,0 +1,55 @@
+// Copyright 2017, OpenCensus Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package stats
+
+// Float64Measure is a measure for float64 values.
+type Float64Measure struct {
+ desc *measureDescriptor
+}
+
+// M creates a new float64 measurement.
+// Use Record to record measurements.
+func (m *Float64Measure) M(v float64) Measurement {
+ return Measurement{
+ m: m,
+ desc: m.desc,
+ v: v,
+ }
+}
+
+// Float64 creates a new measure for float64 values.
+//
+// See the documentation for interface Measure for more guidance on the
+// parameters of this function.
+func Float64(name, description, unit string) *Float64Measure {
+ mi := registerMeasureHandle(name, description, unit)
+ return &Float64Measure{mi}
+}
+
+// Name returns the name of the measure.
+func (m *Float64Measure) Name() string {
+ return m.desc.name
+}
+
+// Description returns the description of the measure.
+func (m *Float64Measure) Description() string {
+ return m.desc.description
+}
+
+// Unit returns the unit of the measure.
+func (m *Float64Measure) Unit() string {
+ return m.desc.unit
+}
diff --git a/vendor/go.opencensus.io/stats/measure_int64.go b/vendor/go.opencensus.io/stats/measure_int64.go
new file mode 100644
index 000000000..d101d7973
--- /dev/null
+++ b/vendor/go.opencensus.io/stats/measure_int64.go
@@ -0,0 +1,55 @@
+// Copyright 2017, OpenCensus Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package stats
+
+// Int64Measure is a measure for int64 values.
+type Int64Measure struct {
+ desc *measureDescriptor
+}
+
+// M creates a new int64 measurement.
+// Use Record to record measurements.
+func (m *Int64Measure) M(v int64) Measurement {
+ return Measurement{
+ m: m,
+ desc: m.desc,
+ v: float64(v),
+ }
+}
+
+// Int64 creates a new measure for int64 values.
+//
+// See the documentation for interface Measure for more guidance on the
+// parameters of this function.
+func Int64(name, description, unit string) *Int64Measure {
+ mi := registerMeasureHandle(name, description, unit)
+ return &Int64Measure{mi}
+}
+
+// Name returns the name of the measure.
+func (m *Int64Measure) Name() string {
+ return m.desc.name
+}
+
+// Description returns the description of the measure.
+func (m *Int64Measure) Description() string {
+ return m.desc.description
+}
+
+// Unit returns the unit of the measure.
+func (m *Int64Measure) Unit() string {
+ return m.desc.unit
+}
diff --git a/vendor/go.opencensus.io/stats/record.go b/vendor/go.opencensus.io/stats/record.go
new file mode 100644
index 000000000..86f491e22
--- /dev/null
+++ b/vendor/go.opencensus.io/stats/record.go
@@ -0,0 +1,69 @@
+// Copyright 2018, OpenCensus Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package stats
+
+import (
+ "context"
+
+ "go.opencensus.io/exemplar"
+ "go.opencensus.io/stats/internal"
+ "go.opencensus.io/tag"
+)
+
+func init() {
+ internal.SubscriptionReporter = func(measure string) {
+ mu.Lock()
+ measures[measure].subscribe()
+ mu.Unlock()
+ }
+}
+
+// Record records one or multiple measurements with the same context at once.
+// If there are any tags in the context, measurements will be tagged with them.
+func Record(ctx context.Context, ms ...Measurement) {
+ recorder := internal.DefaultRecorder
+ if recorder == nil {
+ return
+ }
+ if len(ms) == 0 {
+ return
+ }
+ record := false
+ for _, m := range ms {
+ if m.desc.subscribed() {
+ record = true
+ break
+ }
+ }
+ if !record {
+ return
+ }
+ recorder(tag.FromContext(ctx), ms, exemplar.AttachmentsFromContext(ctx))
+}
+
+// RecordWithTags records one or multiple measurements at once.
+//
+// Measurements will be tagged with the tags in the context mutated by the mutators.
+// RecordWithTags is useful if you want to record with tag mutations but don't want
+// to propagate the mutations in the context.
+func RecordWithTags(ctx context.Context, mutators []tag.Mutator, ms ...Measurement) error {
+ ctx, err := tag.New(ctx, mutators...)
+ if err != nil {
+ return err
+ }
+ Record(ctx, ms...)
+ return nil
+}
diff --git a/vendor/go.opencensus.io/stats/units.go b/vendor/go.opencensus.io/stats/units.go
new file mode 100644
index 000000000..6931a5f29
--- /dev/null
+++ b/vendor/go.opencensus.io/stats/units.go
@@ -0,0 +1,25 @@
+// Copyright 2018, OpenCensus Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package stats
+
+// Units are encoded according to the case-sensitive abbreviations from the
+// Unified Code for Units of Measure: http://unitsofmeasure.org/ucum.html
+const (
+ UnitNone = "1" // Deprecated: Use UnitDimensionless.
+ UnitDimensionless = "1"
+ UnitBytes = "By"
+ UnitMilliseconds = "ms"
+)
diff --git a/vendor/go.opencensus.io/stats/view/aggregation.go b/vendor/go.opencensus.io/stats/view/aggregation.go
new file mode 100644
index 000000000..b7f169b4a
--- /dev/null
+++ b/vendor/go.opencensus.io/stats/view/aggregation.go
@@ -0,0 +1,120 @@
+// Copyright 2017, OpenCensus Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package view
+
+// AggType represents the type of aggregation function used on a View.
+type AggType int
+
+// All available aggregation types.
+const (
+ AggTypeNone AggType = iota // no aggregation; reserved for future use.
+ AggTypeCount // the count aggregation, see Count.
+ AggTypeSum // the sum aggregation, see Sum.
+ AggTypeDistribution // the distribution aggregation, see Distribution.
+ AggTypeLastValue // the last value aggregation, see LastValue.
+)
+
+func (t AggType) String() string {
+ return aggTypeName[t]
+}
+
+var aggTypeName = map[AggType]string{
+ AggTypeNone: "None",
+ AggTypeCount: "Count",
+ AggTypeSum: "Sum",
+ AggTypeDistribution: "Distribution",
+ AggTypeLastValue: "LastValue",
+}
+
+// Aggregation represents a data aggregation method. Use one of the functions:
+// Count, Sum, or Distribution to construct an Aggregation.
+type Aggregation struct {
+ Type AggType // Type is the AggType of this Aggregation.
+ Buckets []float64 // Buckets are the bucket endpoints if this Aggregation represents a distribution, see Distribution.
+
+ newData func() AggregationData
+}
+
+var (
+ aggCount = &Aggregation{
+ Type: AggTypeCount,
+ newData: func() AggregationData {
+ return &CountData{}
+ },
+ }
+ aggSum = &Aggregation{
+ Type: AggTypeSum,
+ newData: func() AggregationData {
+ return &SumData{}
+ },
+ }
+)
+
+// Count indicates that data collected and aggregated
+// with this method will be turned into a count value.
+// For example, total number of accepted requests can be
+// aggregated by using Count.
+func Count() *Aggregation {
+ return aggCount
+}
+
+// Sum indicates that data collected and aggregated
+// with this method will be summed up.
+// For example, accumulated request bytes can be aggregated by using
+// Sum.
+func Sum() *Aggregation {
+ return aggSum
+}
+
+// Distribution indicates that the desired aggregation is
+// a histogram distribution.
+//
+// An distribution aggregation may contain a histogram of the values in the
+// population. The bucket boundaries for that histogram are described
+// by the bounds. This defines len(bounds)+1 buckets.
+//
+// If len(bounds) >= 2 then the boundaries for bucket index i are:
+//
+// [-infinity, bounds[i]) for i = 0
+// [bounds[i-1], bounds[i]) for 0 < i < length
+// [bounds[i-1], +infinity) for i = length
+//
+// If len(bounds) is 0 then there is no histogram associated with the
+// distribution. There will be a single bucket with boundaries
+// (-infinity, +infinity).
+//
+// If len(bounds) is 1 then there is no finite buckets, and that single
+// element is the common boundary of the overflow and underflow buckets.
+func Distribution(bounds ...float64) *Aggregation {
+ return &Aggregation{
+ Type: AggTypeDistribution,
+ Buckets: bounds,
+ newData: func() AggregationData {
+ return newDistributionData(bounds)
+ },
+ }
+}
+
+// LastValue only reports the last value recorded using this
+// aggregation. All other measurements will be dropped.
+func LastValue() *Aggregation {
+ return &Aggregation{
+ Type: AggTypeLastValue,
+ newData: func() AggregationData {
+ return &LastValueData{}
+ },
+ }
+}
diff --git a/vendor/go.opencensus.io/stats/view/aggregation_data.go b/vendor/go.opencensus.io/stats/view/aggregation_data.go
new file mode 100644
index 000000000..960b94601
--- /dev/null
+++ b/vendor/go.opencensus.io/stats/view/aggregation_data.go
@@ -0,0 +1,235 @@
+// Copyright 2017, OpenCensus Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package view
+
+import (
+ "math"
+
+ "go.opencensus.io/exemplar"
+)
+
+// AggregationData represents an aggregated value from a collection.
+// They are reported on the view data during exporting.
+// Mosts users won't directly access aggregration data.
+type AggregationData interface {
+ isAggregationData() bool
+ addSample(e *exemplar.Exemplar)
+ clone() AggregationData
+ equal(other AggregationData) bool
+}
+
+const epsilon = 1e-9
+
+// CountData is the aggregated data for the Count aggregation.
+// A count aggregation processes data and counts the recordings.
+//
+// Most users won't directly access count data.
+type CountData struct {
+ Value int64
+}
+
+func (a *CountData) isAggregationData() bool { return true }
+
+func (a *CountData) addSample(_ *exemplar.Exemplar) {
+ a.Value = a.Value + 1
+}
+
+func (a *CountData) clone() AggregationData {
+ return &CountData{Value: a.Value}
+}
+
+func (a *CountData) equal(other AggregationData) bool {
+ a2, ok := other.(*CountData)
+ if !ok {
+ return false
+ }
+
+ return a.Value == a2.Value
+}
+
+// SumData is the aggregated data for the Sum aggregation.
+// A sum aggregation processes data and sums up the recordings.
+//
+// Most users won't directly access sum data.
+type SumData struct {
+ Value float64
+}
+
+func (a *SumData) isAggregationData() bool { return true }
+
+func (a *SumData) addSample(e *exemplar.Exemplar) {
+ a.Value += e.Value
+}
+
+func (a *SumData) clone() AggregationData {
+ return &SumData{Value: a.Value}
+}
+
+func (a *SumData) equal(other AggregationData) bool {
+ a2, ok := other.(*SumData)
+ if !ok {
+ return false
+ }
+ return math.Pow(a.Value-a2.Value, 2) < epsilon
+}
+
+// DistributionData is the aggregated data for the
+// Distribution aggregation.
+//
+// Most users won't directly access distribution data.
+//
+// For a distribution with N bounds, the associated DistributionData will have
+// N+1 buckets.
+type DistributionData struct {
+ Count int64 // number of data points aggregated
+ Min float64 // minimum value in the distribution
+ Max float64 // max value in the distribution
+ Mean float64 // mean of the distribution
+ SumOfSquaredDev float64 // sum of the squared deviation from the mean
+ CountPerBucket []int64 // number of occurrences per bucket
+ // ExemplarsPerBucket is slice the same length as CountPerBucket containing
+ // an exemplar for the associated bucket, or nil.
+ ExemplarsPerBucket []*exemplar.Exemplar
+ bounds []float64 // histogram distribution of the values
+}
+
+func newDistributionData(bounds []float64) *DistributionData {
+ bucketCount := len(bounds) + 1
+ return &DistributionData{
+ CountPerBucket: make([]int64, bucketCount),
+ ExemplarsPerBucket: make([]*exemplar.Exemplar, bucketCount),
+ bounds: bounds,
+ Min: math.MaxFloat64,
+ Max: math.SmallestNonzeroFloat64,
+ }
+}
+
+// Sum returns the sum of all samples collected.
+func (a *DistributionData) Sum() float64 { return a.Mean * float64(a.Count) }
+
+func (a *DistributionData) variance() float64 {
+ if a.Count <= 1 {
+ return 0
+ }
+ return a.SumOfSquaredDev / float64(a.Count-1)
+}
+
+func (a *DistributionData) isAggregationData() bool { return true }
+
+func (a *DistributionData) addSample(e *exemplar.Exemplar) {
+ f := e.Value
+ if f < a.Min {
+ a.Min = f
+ }
+ if f > a.Max {
+ a.Max = f
+ }
+ a.Count++
+ a.addToBucket(e)
+
+ if a.Count == 1 {
+ a.Mean = f
+ return
+ }
+
+ oldMean := a.Mean
+ a.Mean = a.Mean + (f-a.Mean)/float64(a.Count)
+ a.SumOfSquaredDev = a.SumOfSquaredDev + (f-oldMean)*(f-a.Mean)
+}
+
+func (a *DistributionData) addToBucket(e *exemplar.Exemplar) {
+ var count *int64
+ var ex **exemplar.Exemplar
+ for i, b := range a.bounds {
+ if e.Value < b {
+ count = &a.CountPerBucket[i]
+ ex = &a.ExemplarsPerBucket[i]
+ break
+ }
+ }
+ if count == nil {
+ count = &a.CountPerBucket[len(a.bounds)]
+ ex = &a.ExemplarsPerBucket[len(a.bounds)]
+ }
+ *count++
+ *ex = maybeRetainExemplar(*ex, e)
+}
+
+func maybeRetainExemplar(old, cur *exemplar.Exemplar) *exemplar.Exemplar {
+ if old == nil {
+ return cur
+ }
+
+ // Heuristic to pick the "better" exemplar: first keep the one with a
+ // sampled trace attachment, if neither have a trace attachment, pick the
+ // one with more attachments.
+ _, haveTraceID := cur.Attachments[exemplar.KeyTraceID]
+ if haveTraceID || len(cur.Attachments) >= len(old.Attachments) {
+ return cur
+ }
+ return old
+}
+
+func (a *DistributionData) clone() AggregationData {
+ c := *a
+ c.CountPerBucket = append([]int64(nil), a.CountPerBucket...)
+ c.ExemplarsPerBucket = append([]*exemplar.Exemplar(nil), a.ExemplarsPerBucket...)
+ return &c
+}
+
+func (a *DistributionData) equal(other AggregationData) bool {
+ a2, ok := other.(*DistributionData)
+ if !ok {
+ return false
+ }
+ if a2 == nil {
+ return false
+ }
+ if len(a.CountPerBucket) != len(a2.CountPerBucket) {
+ return false
+ }
+ for i := range a.CountPerBucket {
+ if a.CountPerBucket[i] != a2.CountPerBucket[i] {
+ return false
+ }
+ }
+ return a.Count == a2.Count && a.Min == a2.Min && a.Max == a2.Max && math.Pow(a.Mean-a2.Mean, 2) < epsilon && math.Pow(a.variance()-a2.variance(), 2) < epsilon
+}
+
+// LastValueData returns the last value recorded for LastValue aggregation.
+type LastValueData struct {
+ Value float64
+}
+
+func (l *LastValueData) isAggregationData() bool {
+ return true
+}
+
+func (l *LastValueData) addSample(e *exemplar.Exemplar) {
+ l.Value = e.Value
+}
+
+func (l *LastValueData) clone() AggregationData {
+ return &LastValueData{l.Value}
+}
+
+func (l *LastValueData) equal(other AggregationData) bool {
+ a2, ok := other.(*LastValueData)
+ if !ok {
+ return false
+ }
+ return l.Value == a2.Value
+}
diff --git a/vendor/go.opencensus.io/stats/view/collector.go b/vendor/go.opencensus.io/stats/view/collector.go
new file mode 100644
index 000000000..32415d485
--- /dev/null
+++ b/vendor/go.opencensus.io/stats/view/collector.go
@@ -0,0 +1,87 @@
+// Copyright 2017, OpenCensus Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package view
+
+import (
+ "sort"
+
+ "go.opencensus.io/exemplar"
+
+ "go.opencensus.io/internal/tagencoding"
+ "go.opencensus.io/tag"
+)
+
+type collector struct {
+ // signatures holds the aggregations values for each unique tag signature
+ // (values for all keys) to its aggregator.
+ signatures map[string]AggregationData
+ // Aggregation is the description of the aggregation to perform for this
+ // view.
+ a *Aggregation
+}
+
+func (c *collector) addSample(s string, e *exemplar.Exemplar) {
+ aggregator, ok := c.signatures[s]
+ if !ok {
+ aggregator = c.a.newData()
+ c.signatures[s] = aggregator
+ }
+ aggregator.addSample(e)
+}
+
+// collectRows returns a snapshot of the collected Row values.
+func (c *collector) collectedRows(keys []tag.Key) []*Row {
+ rows := make([]*Row, 0, len(c.signatures))
+ for sig, aggregator := range c.signatures {
+ tags := decodeTags([]byte(sig), keys)
+ row := &Row{Tags: tags, Data: aggregator.clone()}
+ rows = append(rows, row)
+ }
+ return rows
+}
+
+func (c *collector) clearRows() {
+ c.signatures = make(map[string]AggregationData)
+}
+
+// encodeWithKeys encodes the map by using values
+// only associated with the keys provided.
+func encodeWithKeys(m *tag.Map, keys []tag.Key) []byte {
+ vb := &tagencoding.Values{
+ Buffer: make([]byte, len(keys)),
+ }
+ for _, k := range keys {
+ v, _ := m.Value(k)
+ vb.WriteValue([]byte(v))
+ }
+ return vb.Bytes()
+}
+
+// decodeTags decodes tags from the buffer and
+// orders them by the keys.
+func decodeTags(buf []byte, keys []tag.Key) []tag.Tag {
+ vb := &tagencoding.Values{Buffer: buf}
+ var tags []tag.Tag
+ for _, k := range keys {
+ v := vb.ReadValue()
+ if v != nil {
+ tags = append(tags, tag.Tag{Key: k, Value: string(v)})
+ }
+ }
+ vb.ReadIndex = 0
+ sort.Slice(tags, func(i, j int) bool { return tags[i].Key.Name() < tags[j].Key.Name() })
+ return tags
+}
diff --git a/vendor/go.opencensus.io/stats/view/doc.go b/vendor/go.opencensus.io/stats/view/doc.go
new file mode 100644
index 000000000..dced225c3
--- /dev/null
+++ b/vendor/go.opencensus.io/stats/view/doc.go
@@ -0,0 +1,47 @@
+// Copyright 2017, OpenCensus Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// Package view contains support for collecting and exposing aggregates over stats.
+//
+// In order to collect measurements, views need to be defined and registered.
+// A view allows recorded measurements to be filtered and aggregated.
+//
+// All recorded measurements can be grouped by a list of tags.
+//
+// OpenCensus provides several aggregation methods: Count, Distribution and Sum.
+//
+// Count only counts the number of measurement points recorded.
+// Distribution provides statistical summary of the aggregated data by counting
+// how many recorded measurements fall into each bucket.
+// Sum adds up the measurement values.
+// LastValue just keeps track of the most recently recorded measurement value.
+// All aggregations are cumulative.
+//
+// Views can be registerd and unregistered at any time during program execution.
+//
+// Libraries can define views but it is recommended that in most cases registering
+// views be left up to applications.
+//
+// Exporting
+//
+// Collected and aggregated data can be exported to a metric collection
+// backend by registering its exporter.
+//
+// Multiple exporters can be registered to upload the data to various
+// different back ends.
+package view // import "go.opencensus.io/stats/view"
+
+// TODO(acetechnologist): Add a link to the language independent OpenCensus
+// spec when it is available.
diff --git a/vendor/go.opencensus.io/stats/view/export.go b/vendor/go.opencensus.io/stats/view/export.go
new file mode 100644
index 000000000..7cb59718f
--- /dev/null
+++ b/vendor/go.opencensus.io/stats/view/export.go
@@ -0,0 +1,58 @@
+// Copyright 2017, OpenCensus Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package view
+
+import "sync"
+
+var (
+ exportersMu sync.RWMutex // guards exporters
+ exporters = make(map[Exporter]struct{})
+)
+
+// Exporter exports the collected records as view data.
+//
+// The ExportView method should return quickly; if an
+// Exporter takes a significant amount of time to
+// process a Data, that work should be done on another goroutine.
+//
+// It is safe to assume that ExportView will not be called concurrently from
+// multiple goroutines.
+//
+// The Data should not be modified.
+type Exporter interface {
+ ExportView(viewData *Data)
+}
+
+// RegisterExporter registers an exporter.
+// Collected data will be reported via all the
+// registered exporters. Once you no longer
+// want data to be exported, invoke UnregisterExporter
+// with the previously registered exporter.
+//
+// Binaries can register exporters, libraries shouldn't register exporters.
+func RegisterExporter(e Exporter) {
+ exportersMu.Lock()
+ defer exportersMu.Unlock()
+
+ exporters[e] = struct{}{}
+}
+
+// UnregisterExporter unregisters an exporter.
+func UnregisterExporter(e Exporter) {
+ exportersMu.Lock()
+ defer exportersMu.Unlock()
+
+ delete(exporters, e)
+}
diff --git a/vendor/go.opencensus.io/stats/view/view.go b/vendor/go.opencensus.io/stats/view/view.go
new file mode 100644
index 000000000..c2a08af67
--- /dev/null
+++ b/vendor/go.opencensus.io/stats/view/view.go
@@ -0,0 +1,185 @@
+// Copyright 2017, OpenCensus Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package view
+
+import (
+ "bytes"
+ "fmt"
+ "reflect"
+ "sort"
+ "sync/atomic"
+ "time"
+
+ "go.opencensus.io/exemplar"
+
+ "go.opencensus.io/stats"
+ "go.opencensus.io/stats/internal"
+ "go.opencensus.io/tag"
+)
+
+// View allows users to aggregate the recorded stats.Measurements.
+// Views need to be passed to the Register function to be before data will be
+// collected and sent to Exporters.
+type View struct {
+ Name string // Name of View. Must be unique. If unset, will default to the name of the Measure.
+ Description string // Description is a human-readable description for this view.
+
+ // TagKeys are the tag keys describing the grouping of this view.
+ // A single Row will be produced for each combination of associated tag values.
+ TagKeys []tag.Key
+
+ // Measure is a stats.Measure to aggregate in this view.
+ Measure stats.Measure
+
+ // Aggregation is the aggregation function tp apply to the set of Measurements.
+ Aggregation *Aggregation
+}
+
+// WithName returns a copy of the View with a new name. This is useful for
+// renaming views to cope with limitations placed on metric names by various
+// backends.
+func (v *View) WithName(name string) *View {
+ vNew := *v
+ vNew.Name = name
+ return &vNew
+}
+
+// same compares two views and returns true if they represent the same aggregation.
+func (v *View) same(other *View) bool {
+ if v == other {
+ return true
+ }
+ if v == nil {
+ return false
+ }
+ return reflect.DeepEqual(v.Aggregation, other.Aggregation) &&
+ v.Measure.Name() == other.Measure.Name()
+}
+
+// canonicalize canonicalizes v by setting explicit
+// defaults for Name and Description and sorting the TagKeys
+func (v *View) canonicalize() error {
+ if v.Measure == nil {
+ return fmt.Errorf("cannot register view %q: measure not set", v.Name)
+ }
+ if v.Aggregation == nil {
+ return fmt.Errorf("cannot register view %q: aggregation not set", v.Name)
+ }
+ if v.Name == "" {
+ v.Name = v.Measure.Name()
+ }
+ if v.Description == "" {
+ v.Description = v.Measure.Description()
+ }
+ if err := checkViewName(v.Name); err != nil {
+ return err
+ }
+ sort.Slice(v.TagKeys, func(i, j int) bool {
+ return v.TagKeys[i].Name() < v.TagKeys[j].Name()
+ })
+ return nil
+}
+
+// viewInternal is the internal representation of a View.
+type viewInternal struct {
+ view *View // view is the canonicalized View definition associated with this view.
+ subscribed uint32 // 1 if someone is subscribed and data need to be exported, use atomic to access
+ collector *collector
+}
+
+func newViewInternal(v *View) (*viewInternal, error) {
+ return &viewInternal{
+ view: v,
+ collector: &collector{make(map[string]AggregationData), v.Aggregation},
+ }, nil
+}
+
+func (v *viewInternal) subscribe() {
+ atomic.StoreUint32(&v.subscribed, 1)
+}
+
+func (v *viewInternal) unsubscribe() {
+ atomic.StoreUint32(&v.subscribed, 0)
+}
+
+// isSubscribed returns true if the view is exporting
+// data by subscription.
+func (v *viewInternal) isSubscribed() bool {
+ return atomic.LoadUint32(&v.subscribed) == 1
+}
+
+func (v *viewInternal) clearRows() {
+ v.collector.clearRows()
+}
+
+func (v *viewInternal) collectedRows() []*Row {
+ return v.collector.collectedRows(v.view.TagKeys)
+}
+
+func (v *viewInternal) addSample(m *tag.Map, e *exemplar.Exemplar) {
+ if !v.isSubscribed() {
+ return
+ }
+ sig := string(encodeWithKeys(m, v.view.TagKeys))
+ v.collector.addSample(sig, e)
+}
+
+// A Data is a set of rows about usage of the single measure associated
+// with the given view. Each row is specific to a unique set of tags.
+type Data struct {
+ View *View
+ Start, End time.Time
+ Rows []*Row
+}
+
+// Row is the collected value for a specific set of key value pairs a.k.a tags.
+type Row struct {
+ Tags []tag.Tag
+ Data AggregationData
+}
+
+func (r *Row) String() string {
+ var buffer bytes.Buffer
+ buffer.WriteString("{ ")
+ buffer.WriteString("{ ")
+ for _, t := range r.Tags {
+ buffer.WriteString(fmt.Sprintf("{%v %v}", t.Key.Name(), t.Value))
+ }
+ buffer.WriteString(" }")
+ buffer.WriteString(fmt.Sprintf("%v", r.Data))
+ buffer.WriteString(" }")
+ return buffer.String()
+}
+
+// Equal returns true if both rows are equal. Tags are expected to be ordered
+// by the key name. Even both rows have the same tags but the tags appear in
+// different orders it will return false.
+func (r *Row) Equal(other *Row) bool {
+ if r == other {
+ return true
+ }
+ return reflect.DeepEqual(r.Tags, other.Tags) && r.Data.equal(other.Data)
+}
+
+func checkViewName(name string) error {
+ if len(name) > internal.MaxNameLength {
+ return fmt.Errorf("view name cannot be larger than %v", internal.MaxNameLength)
+ }
+ if !internal.IsPrintable(name) {
+ return fmt.Errorf("view name needs to be an ASCII string")
+ }
+ return nil
+}
diff --git a/vendor/go.opencensus.io/stats/view/worker.go b/vendor/go.opencensus.io/stats/view/worker.go
new file mode 100644
index 000000000..63b0ee3cc
--- /dev/null
+++ b/vendor/go.opencensus.io/stats/view/worker.go
@@ -0,0 +1,229 @@
+// Copyright 2017, OpenCensus Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package view
+
+import (
+ "fmt"
+ "time"
+
+ "go.opencensus.io/stats"
+ "go.opencensus.io/stats/internal"
+ "go.opencensus.io/tag"
+)
+
+func init() {
+ defaultWorker = newWorker()
+ go defaultWorker.start()
+ internal.DefaultRecorder = record
+}
+
+type measureRef struct {
+ measure string
+ views map[*viewInternal]struct{}
+}
+
+type worker struct {
+ measures map[string]*measureRef
+ views map[string]*viewInternal
+ startTimes map[*viewInternal]time.Time
+
+ timer *time.Ticker
+ c chan command
+ quit, done chan bool
+}
+
+var defaultWorker *worker
+
+var defaultReportingDuration = 10 * time.Second
+
+// Find returns a registered view associated with this name.
+// If no registered view is found, nil is returned.
+func Find(name string) (v *View) {
+ req := &getViewByNameReq{
+ name: name,
+ c: make(chan *getViewByNameResp),
+ }
+ defaultWorker.c <- req
+ resp := <-req.c
+ return resp.v
+}
+
+// Register begins collecting data for the given views.
+// Once a view is registered, it reports data to the registered exporters.
+func Register(views ...*View) error {
+ for _, v := range views {
+ if err := v.canonicalize(); err != nil {
+ return err
+ }
+ }
+ req := &registerViewReq{
+ views: views,
+ err: make(chan error),
+ }
+ defaultWorker.c <- req
+ return <-req.err
+}
+
+// Unregister the given views. Data will not longer be exported for these views
+// after Unregister returns.
+// It is not necessary to unregister from views you expect to collect for the
+// duration of your program execution.
+func Unregister(views ...*View) {
+ names := make([]string, len(views))
+ for i := range views {
+ names[i] = views[i].Name
+ }
+ req := &unregisterFromViewReq{
+ views: names,
+ done: make(chan struct{}),
+ }
+ defaultWorker.c <- req
+ <-req.done
+}
+
+// RetrieveData gets a snapshot of the data collected for the the view registered
+// with the given name. It is intended for testing only.
+func RetrieveData(viewName string) ([]*Row, error) {
+ req := &retrieveDataReq{
+ now: time.Now(),
+ v: viewName,
+ c: make(chan *retrieveDataResp),
+ }
+ defaultWorker.c <- req
+ resp := <-req.c
+ return resp.rows, resp.err
+}
+
+func record(tags *tag.Map, ms interface{}, attachments map[string]string) {
+ req := &recordReq{
+ tm: tags,
+ ms: ms.([]stats.Measurement),
+ attachments: attachments,
+ t: time.Now(),
+ }
+ defaultWorker.c <- req
+}
+
+// SetReportingPeriod sets the interval between reporting aggregated views in
+// the program. If duration is less than or equal to zero, it enables the
+// default behavior.
+//
+// Note: each exporter makes different promises about what the lowest supported
+// duration is. For example, the Stackdriver exporter recommends a value no
+// lower than 1 minute. Consult each exporter per your needs.
+func SetReportingPeriod(d time.Duration) {
+ // TODO(acetechnologist): ensure that the duration d is more than a certain
+ // value. e.g. 1s
+ req := &setReportingPeriodReq{
+ d: d,
+ c: make(chan bool),
+ }
+ defaultWorker.c <- req
+ <-req.c // don't return until the timer is set to the new duration.
+}
+
+func newWorker() *worker {
+ return &worker{
+ measures: make(map[string]*measureRef),
+ views: make(map[string]*viewInternal),
+ startTimes: make(map[*viewInternal]time.Time),
+ timer: time.NewTicker(defaultReportingDuration),
+ c: make(chan command, 1024),
+ quit: make(chan bool),
+ done: make(chan bool),
+ }
+}
+
+func (w *worker) start() {
+ for {
+ select {
+ case cmd := <-w.c:
+ cmd.handleCommand(w)
+ case <-w.timer.C:
+ w.reportUsage(time.Now())
+ case <-w.quit:
+ w.timer.Stop()
+ close(w.c)
+ w.done <- true
+ return
+ }
+ }
+}
+
+func (w *worker) stop() {
+ w.quit <- true
+ <-w.done
+}
+
+func (w *worker) getMeasureRef(name string) *measureRef {
+ if mr, ok := w.measures[name]; ok {
+ return mr
+ }
+ mr := &measureRef{
+ measure: name,
+ views: make(map[*viewInternal]struct{}),
+ }
+ w.measures[name] = mr
+ return mr
+}
+
+func (w *worker) tryRegisterView(v *View) (*viewInternal, error) {
+ vi, err := newViewInternal(v)
+ if err != nil {
+ return nil, err
+ }
+ if x, ok := w.views[vi.view.Name]; ok {
+ if !x.view.same(vi.view) {
+ return nil, fmt.Errorf("cannot register view %q; a different view with the same name is already registered", v.Name)
+ }
+
+ // the view is already registered so there is nothing to do and the
+ // command is considered successful.
+ return x, nil
+ }
+ w.views[vi.view.Name] = vi
+ ref := w.getMeasureRef(vi.view.Measure.Name())
+ ref.views[vi] = struct{}{}
+ return vi, nil
+}
+
+func (w *worker) reportView(v *viewInternal, now time.Time) {
+ if !v.isSubscribed() {
+ return
+ }
+ rows := v.collectedRows()
+ _, ok := w.startTimes[v]
+ if !ok {
+ w.startTimes[v] = now
+ }
+ viewData := &Data{
+ View: v.view,
+ Start: w.startTimes[v],
+ End: time.Now(),
+ Rows: rows,
+ }
+ exportersMu.Lock()
+ for e := range exporters {
+ e.ExportView(viewData)
+ }
+ exportersMu.Unlock()
+}
+
+func (w *worker) reportUsage(now time.Time) {
+ for _, v := range w.views {
+ w.reportView(v, now)
+ }
+}
diff --git a/vendor/go.opencensus.io/stats/view/worker_commands.go b/vendor/go.opencensus.io/stats/view/worker_commands.go
new file mode 100644
index 000000000..b38f26f42
--- /dev/null
+++ b/vendor/go.opencensus.io/stats/view/worker_commands.go
@@ -0,0 +1,183 @@
+// Copyright 2017, OpenCensus Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package view
+
+import (
+ "errors"
+ "fmt"
+ "strings"
+ "time"
+
+ "go.opencensus.io/exemplar"
+
+ "go.opencensus.io/stats"
+ "go.opencensus.io/stats/internal"
+ "go.opencensus.io/tag"
+)
+
+type command interface {
+ handleCommand(w *worker)
+}
+
+// getViewByNameReq is the command to get a view given its name.
+type getViewByNameReq struct {
+ name string
+ c chan *getViewByNameResp
+}
+
+type getViewByNameResp struct {
+ v *View
+}
+
+func (cmd *getViewByNameReq) handleCommand(w *worker) {
+ v := w.views[cmd.name]
+ if v == nil {
+ cmd.c <- &getViewByNameResp{nil}
+ return
+ }
+ cmd.c <- &getViewByNameResp{v.view}
+}
+
+// registerViewReq is the command to register a view.
+type registerViewReq struct {
+ views []*View
+ err chan error
+}
+
+func (cmd *registerViewReq) handleCommand(w *worker) {
+ var errstr []string
+ for _, view := range cmd.views {
+ vi, err := w.tryRegisterView(view)
+ if err != nil {
+ errstr = append(errstr, fmt.Sprintf("%s: %v", view.Name, err))
+ continue
+ }
+ internal.SubscriptionReporter(view.Measure.Name())
+ vi.subscribe()
+ }
+ if len(errstr) > 0 {
+ cmd.err <- errors.New(strings.Join(errstr, "\n"))
+ } else {
+ cmd.err <- nil
+ }
+}
+
+// unregisterFromViewReq is the command to unregister to a view. Has no
+// impact on the data collection for client that are pulling data from the
+// library.
+type unregisterFromViewReq struct {
+ views []string
+ done chan struct{}
+}
+
+func (cmd *unregisterFromViewReq) handleCommand(w *worker) {
+ for _, name := range cmd.views {
+ vi, ok := w.views[name]
+ if !ok {
+ continue
+ }
+
+ // Report pending data for this view before removing it.
+ w.reportView(vi, time.Now())
+
+ vi.unsubscribe()
+ if !vi.isSubscribed() {
+ // this was the last subscription and view is not collecting anymore.
+ // The collected data can be cleared.
+ vi.clearRows()
+ }
+ delete(w.views, name)
+ }
+ cmd.done <- struct{}{}
+}
+
+// retrieveDataReq is the command to retrieve data for a view.
+type retrieveDataReq struct {
+ now time.Time
+ v string
+ c chan *retrieveDataResp
+}
+
+type retrieveDataResp struct {
+ rows []*Row
+ err error
+}
+
+func (cmd *retrieveDataReq) handleCommand(w *worker) {
+ vi, ok := w.views[cmd.v]
+ if !ok {
+ cmd.c <- &retrieveDataResp{
+ nil,
+ fmt.Errorf("cannot retrieve data; view %q is not registered", cmd.v),
+ }
+ return
+ }
+
+ if !vi.isSubscribed() {
+ cmd.c <- &retrieveDataResp{
+ nil,
+ fmt.Errorf("cannot retrieve data; view %q has no subscriptions or collection is not forcibly started", cmd.v),
+ }
+ return
+ }
+ cmd.c <- &retrieveDataResp{
+ vi.collectedRows(),
+ nil,
+ }
+}
+
+// recordReq is the command to record data related to multiple measures
+// at once.
+type recordReq struct {
+ tm *tag.Map
+ ms []stats.Measurement
+ attachments map[string]string
+ t time.Time
+}
+
+func (cmd *recordReq) handleCommand(w *worker) {
+ for _, m := range cmd.ms {
+ if (m == stats.Measurement{}) { // not registered
+ continue
+ }
+ ref := w.getMeasureRef(m.Measure().Name())
+ for v := range ref.views {
+ e := &exemplar.Exemplar{
+ Value: m.Value(),
+ Timestamp: cmd.t,
+ Attachments: cmd.attachments,
+ }
+ v.addSample(cmd.tm, e)
+ }
+ }
+}
+
+// setReportingPeriodReq is the command to modify the duration between
+// reporting the collected data to the registered clients.
+type setReportingPeriodReq struct {
+ d time.Duration
+ c chan bool
+}
+
+func (cmd *setReportingPeriodReq) handleCommand(w *worker) {
+ w.timer.Stop()
+ if cmd.d <= 0 {
+ w.timer = time.NewTicker(defaultReportingDuration)
+ } else {
+ w.timer = time.NewTicker(cmd.d)
+ }
+ cmd.c <- true
+}
diff --git a/vendor/go.opencensus.io/tag/context.go b/vendor/go.opencensus.io/tag/context.go
new file mode 100644
index 000000000..dcc13f498
--- /dev/null
+++ b/vendor/go.opencensus.io/tag/context.go
@@ -0,0 +1,67 @@
+// Copyright 2017, OpenCensus Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package tag
+
+import (
+ "context"
+
+ "go.opencensus.io/exemplar"
+)
+
+// FromContext returns the tag map stored in the context.
+func FromContext(ctx context.Context) *Map {
+ // The returned tag map shouldn't be mutated.
+ ts := ctx.Value(mapCtxKey)
+ if ts == nil {
+ return nil
+ }
+ return ts.(*Map)
+}
+
+// NewContext creates a new context with the given tag map.
+// To propagate a tag map to downstream methods and downstream RPCs, add a tag map
+// to the current context. NewContext will return a copy of the current context,
+// and put the tag map into the returned one.
+// If there is already a tag map in the current context, it will be replaced with m.
+func NewContext(ctx context.Context, m *Map) context.Context {
+ return context.WithValue(ctx, mapCtxKey, m)
+}
+
+type ctxKey struct{}
+
+var mapCtxKey = ctxKey{}
+
+func init() {
+ exemplar.RegisterAttachmentExtractor(extractTagsAttachments)
+}
+
+func extractTagsAttachments(ctx context.Context, a exemplar.Attachments) exemplar.Attachments {
+ m := FromContext(ctx)
+ if m == nil {
+ return a
+ }
+ if len(m.m) == 0 {
+ return a
+ }
+ if a == nil {
+ a = make(map[string]string)
+ }
+
+ for k, v := range m.m {
+ a[exemplar.KeyPrefixTag+k.Name()] = v
+ }
+ return a
+}
diff --git a/vendor/go.opencensus.io/tag/doc.go b/vendor/go.opencensus.io/tag/doc.go
new file mode 100644
index 000000000..da16b74e4
--- /dev/null
+++ b/vendor/go.opencensus.io/tag/doc.go
@@ -0,0 +1,26 @@
+// Copyright 2017, OpenCensus Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/*
+Package tag contains OpenCensus tags.
+
+Tags are key-value pairs. Tags provide additional cardinality to
+the OpenCensus instrumentation data.
+
+Tags can be propagated on the wire and in the same
+process via context.Context. Encode and Decode should be
+used to represent tags into their binary propagation form.
+*/
+package tag // import "go.opencensus.io/tag"
diff --git a/vendor/go.opencensus.io/tag/key.go b/vendor/go.opencensus.io/tag/key.go
new file mode 100644
index 000000000..ebbed9500
--- /dev/null
+++ b/vendor/go.opencensus.io/tag/key.go
@@ -0,0 +1,35 @@
+// Copyright 2017, OpenCensus Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package tag
+
+// Key represents a tag key.
+type Key struct {
+ name string
+}
+
+// NewKey creates or retrieves a string key identified by name.
+// Calling NewKey consequently with the same name returns the same key.
+func NewKey(name string) (Key, error) {
+ if !checkKeyName(name) {
+ return Key{}, errInvalidKeyName
+ }
+ return Key{name: name}, nil
+}
+
+// Name returns the name of the key.
+func (k Key) Name() string {
+ return k.name
+}
diff --git a/vendor/go.opencensus.io/tag/map.go b/vendor/go.opencensus.io/tag/map.go
new file mode 100644
index 000000000..5b72ba6ad
--- /dev/null
+++ b/vendor/go.opencensus.io/tag/map.go
@@ -0,0 +1,197 @@
+// Copyright 2017, OpenCensus Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package tag
+
+import (
+ "bytes"
+ "context"
+ "fmt"
+ "sort"
+)
+
+// Tag is a key value pair that can be propagated on wire.
+type Tag struct {
+ Key Key
+ Value string
+}
+
+// Map is a map of tags. Use New to create a context containing
+// a new Map.
+type Map struct {
+ m map[Key]string
+}
+
+// Value returns the value for the key if a value for the key exists.
+func (m *Map) Value(k Key) (string, bool) {
+ if m == nil {
+ return "", false
+ }
+ v, ok := m.m[k]
+ return v, ok
+}
+
+func (m *Map) String() string {
+ if m == nil {
+ return "nil"
+ }
+ keys := make([]Key, 0, len(m.m))
+ for k := range m.m {
+ keys = append(keys, k)
+ }
+ sort.Slice(keys, func(i, j int) bool { return keys[i].Name() < keys[j].Name() })
+
+ var buffer bytes.Buffer
+ buffer.WriteString("{ ")
+ for _, k := range keys {
+ buffer.WriteString(fmt.Sprintf("{%v %v}", k.name, m.m[k]))
+ }
+ buffer.WriteString(" }")
+ return buffer.String()
+}
+
+func (m *Map) insert(k Key, v string) {
+ if _, ok := m.m[k]; ok {
+ return
+ }
+ m.m[k] = v
+}
+
+func (m *Map) update(k Key, v string) {
+ if _, ok := m.m[k]; ok {
+ m.m[k] = v
+ }
+}
+
+func (m *Map) upsert(k Key, v string) {
+ m.m[k] = v
+}
+
+func (m *Map) delete(k Key) {
+ delete(m.m, k)
+}
+
+func newMap() *Map {
+ return &Map{m: make(map[Key]string)}
+}
+
+// Mutator modifies a tag map.
+type Mutator interface {
+ Mutate(t *Map) (*Map, error)
+}
+
+// Insert returns a mutator that inserts a
+// value associated with k. If k already exists in the tag map,
+// mutator doesn't update the value.
+func Insert(k Key, v string) Mutator {
+ return &mutator{
+ fn: func(m *Map) (*Map, error) {
+ if !checkValue(v) {
+ return nil, errInvalidValue
+ }
+ m.insert(k, v)
+ return m, nil
+ },
+ }
+}
+
+// Update returns a mutator that updates the
+// value of the tag associated with k with v. If k doesn't
+// exists in the tag map, the mutator doesn't insert the value.
+func Update(k Key, v string) Mutator {
+ return &mutator{
+ fn: func(m *Map) (*Map, error) {
+ if !checkValue(v) {
+ return nil, errInvalidValue
+ }
+ m.update(k, v)
+ return m, nil
+ },
+ }
+}
+
+// Upsert returns a mutator that upserts the
+// value of the tag associated with k with v. It inserts the
+// value if k doesn't exist already. It mutates the value
+// if k already exists.
+func Upsert(k Key, v string) Mutator {
+ return &mutator{
+ fn: func(m *Map) (*Map, error) {
+ if !checkValue(v) {
+ return nil, errInvalidValue
+ }
+ m.upsert(k, v)
+ return m, nil
+ },
+ }
+}
+
+// Delete returns a mutator that deletes
+// the value associated with k.
+func Delete(k Key) Mutator {
+ return &mutator{
+ fn: func(m *Map) (*Map, error) {
+ m.delete(k)
+ return m, nil
+ },
+ }
+}
+
+// New returns a new context that contains a tag map
+// originated from the incoming context and modified
+// with the provided mutators.
+func New(ctx context.Context, mutator ...Mutator) (context.Context, error) {
+ m := newMap()
+ orig := FromContext(ctx)
+ if orig != nil {
+ for k, v := range orig.m {
+ if !checkKeyName(k.Name()) {
+ return ctx, fmt.Errorf("key:%q: %v", k, errInvalidKeyName)
+ }
+ if !checkValue(v) {
+ return ctx, fmt.Errorf("key:%q value:%q: %v", k.Name(), v, errInvalidValue)
+ }
+ m.insert(k, v)
+ }
+ }
+ var err error
+ for _, mod := range mutator {
+ m, err = mod.Mutate(m)
+ if err != nil {
+ return ctx, err
+ }
+ }
+ return NewContext(ctx, m), nil
+}
+
+// Do is similar to pprof.Do: a convenience for installing the tags
+// from the context as Go profiler labels. This allows you to
+// correlated runtime profiling with stats.
+//
+// It converts the key/values from the given map to Go profiler labels
+// and calls pprof.Do.
+//
+// Do is going to do nothing if your Go version is below 1.9.
+func Do(ctx context.Context, f func(ctx context.Context)) {
+ do(ctx, f)
+}
+
+type mutator struct {
+ fn func(t *Map) (*Map, error)
+}
+
+func (m *mutator) Mutate(t *Map) (*Map, error) {
+ return m.fn(t)
+}
diff --git a/vendor/go.opencensus.io/tag/map_codec.go b/vendor/go.opencensus.io/tag/map_codec.go
new file mode 100644
index 000000000..3e998950c
--- /dev/null
+++ b/vendor/go.opencensus.io/tag/map_codec.go
@@ -0,0 +1,234 @@
+// Copyright 2017, OpenCensus Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+package tag
+
+import (
+ "encoding/binary"
+ "fmt"
+)
+
+// KeyType defines the types of keys allowed. Currently only keyTypeString is
+// supported.
+type keyType byte
+
+const (
+ keyTypeString keyType = iota
+ keyTypeInt64
+ keyTypeTrue
+ keyTypeFalse
+
+ tagsVersionID = byte(0)
+)
+
+type encoderGRPC struct {
+ buf []byte
+ writeIdx, readIdx int
+}
+
+// writeKeyString writes the fieldID '0' followed by the key string and value
+// string.
+func (eg *encoderGRPC) writeTagString(k, v string) {
+ eg.writeByte(byte(keyTypeString))
+ eg.writeStringWithVarintLen(k)
+ eg.writeStringWithVarintLen(v)
+}
+
+func (eg *encoderGRPC) writeTagUint64(k string, i uint64) {
+ eg.writeByte(byte(keyTypeInt64))
+ eg.writeStringWithVarintLen(k)
+ eg.writeUint64(i)
+}
+
+func (eg *encoderGRPC) writeTagTrue(k string) {
+ eg.writeByte(byte(keyTypeTrue))
+ eg.writeStringWithVarintLen(k)
+}
+
+func (eg *encoderGRPC) writeTagFalse(k string) {
+ eg.writeByte(byte(keyTypeFalse))
+ eg.writeStringWithVarintLen(k)
+}
+
+func (eg *encoderGRPC) writeBytesWithVarintLen(bytes []byte) {
+ length := len(bytes)
+
+ eg.growIfRequired(binary.MaxVarintLen64 + length)
+ eg.writeIdx += binary.PutUvarint(eg.buf[eg.writeIdx:], uint64(length))
+ copy(eg.buf[eg.writeIdx:], bytes)
+ eg.writeIdx += length
+}
+
+func (eg *encoderGRPC) writeStringWithVarintLen(s string) {
+ length := len(s)
+
+ eg.growIfRequired(binary.MaxVarintLen64 + length)
+ eg.writeIdx += binary.PutUvarint(eg.buf[eg.writeIdx:], uint64(length))
+ copy(eg.buf[eg.writeIdx:], s)
+ eg.writeIdx += length
+}
+
+func (eg *encoderGRPC) writeByte(v byte) {
+ eg.growIfRequired(1)
+ eg.buf[eg.writeIdx] = v
+ eg.writeIdx++
+}
+
+func (eg *encoderGRPC) writeUint32(i uint32) {
+ eg.growIfRequired(4)
+ binary.LittleEndian.PutUint32(eg.buf[eg.writeIdx:], i)
+ eg.writeIdx += 4
+}
+
+func (eg *encoderGRPC) writeUint64(i uint64) {
+ eg.growIfRequired(8)
+ binary.LittleEndian.PutUint64(eg.buf[eg.writeIdx:], i)
+ eg.writeIdx += 8
+}
+
+func (eg *encoderGRPC) readByte() byte {
+ b := eg.buf[eg.readIdx]
+ eg.readIdx++
+ return b
+}
+
+func (eg *encoderGRPC) readUint32() uint32 {
+ i := binary.LittleEndian.Uint32(eg.buf[eg.readIdx:])
+ eg.readIdx += 4
+ return i
+}
+
+func (eg *encoderGRPC) readUint64() uint64 {
+ i := binary.LittleEndian.Uint64(eg.buf[eg.readIdx:])
+ eg.readIdx += 8
+ return i
+}
+
+func (eg *encoderGRPC) readBytesWithVarintLen() ([]byte, error) {
+ if eg.readEnded() {
+ return nil, fmt.Errorf("unexpected end while readBytesWithVarintLen '%x' starting at idx '%v'", eg.buf, eg.readIdx)
+ }
+ length, valueStart := binary.Uvarint(eg.buf[eg.readIdx:])
+ if valueStart <= 0 {
+ return nil, fmt.Errorf("unexpected end while readBytesWithVarintLen '%x' starting at idx '%v'", eg.buf, eg.readIdx)
+ }
+
+ valueStart += eg.readIdx
+ valueEnd := valueStart + int(length)
+ if valueEnd > len(eg.buf) {
+ return nil, fmt.Errorf("malformed encoding: length:%v, upper:%v, maxLength:%v", length, valueEnd, len(eg.buf))
+ }
+
+ eg.readIdx = valueEnd
+ return eg.buf[valueStart:valueEnd], nil
+}
+
+func (eg *encoderGRPC) readStringWithVarintLen() (string, error) {
+ bytes, err := eg.readBytesWithVarintLen()
+ if err != nil {
+ return "", err
+ }
+ return string(bytes), nil
+}
+
+func (eg *encoderGRPC) growIfRequired(expected int) {
+ if len(eg.buf)-eg.writeIdx < expected {
+ tmp := make([]byte, 2*(len(eg.buf)+1)+expected)
+ copy(tmp, eg.buf)
+ eg.buf = tmp
+ }
+}
+
+func (eg *encoderGRPC) readEnded() bool {
+ return eg.readIdx >= len(eg.buf)
+}
+
+func (eg *encoderGRPC) bytes() []byte {
+ return eg.buf[:eg.writeIdx]
+}
+
+// Encode encodes the tag map into a []byte. It is useful to propagate
+// the tag maps on wire in binary format.
+func Encode(m *Map) []byte {
+ eg := &encoderGRPC{
+ buf: make([]byte, len(m.m)),
+ }
+ eg.writeByte(byte(tagsVersionID))
+ for k, v := range m.m {
+ eg.writeByte(byte(keyTypeString))
+ eg.writeStringWithVarintLen(k.name)
+ eg.writeBytesWithVarintLen([]byte(v))
+ }
+ return eg.bytes()
+}
+
+// Decode decodes the given []byte into a tag map.
+func Decode(bytes []byte) (*Map, error) {
+ ts := newMap()
+ err := DecodeEach(bytes, ts.upsert)
+ if err != nil {
+ // no partial failures
+ return nil, err
+ }
+ return ts, nil
+}
+
+// DecodeEach decodes the given serialized tag map, calling handler for each
+// tag key and value decoded.
+func DecodeEach(bytes []byte, fn func(key Key, val string)) error {
+ eg := &encoderGRPC{
+ buf: bytes,
+ }
+ if len(eg.buf) == 0 {
+ return nil
+ }
+
+ version := eg.readByte()
+ if version > tagsVersionID {
+ return fmt.Errorf("cannot decode: unsupported version: %q; supports only up to: %q", version, tagsVersionID)
+ }
+
+ for !eg.readEnded() {
+ typ := keyType(eg.readByte())
+
+ if typ != keyTypeString {
+ return fmt.Errorf("cannot decode: invalid key type: %q", typ)
+ }
+
+ k, err := eg.readBytesWithVarintLen()
+ if err != nil {
+ return err
+ }
+
+ v, err := eg.readBytesWithVarintLen()
+ if err != nil {
+ return err
+ }
+
+ key, err := NewKey(string(k))
+ if err != nil {
+ return err
+ }
+ val := string(v)
+ if !checkValue(val) {
+ return errInvalidValue
+ }
+ fn(key, val)
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
diff --git a/vendor/go.opencensus.io/tag/profile_19.go b/vendor/go.opencensus.io/tag/profile_19.go
new file mode 100644
index 000000000..f81cd0b4a
--- /dev/null
+++ b/vendor/go.opencensus.io/tag/profile_19.go
@@ -0,0 +1,31 @@
+// Copyright 2018, OpenCensus Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// +build go1.9
+
+package tag
+
+import (
+ "context"
+ "runtime/pprof"
+)
+
+func do(ctx context.Context, f func(ctx context.Context)) {
+ m := FromContext(ctx)
+ keyvals := make([]string, 0, 2*len(m.m))
+ for k, v := range m.m {
+ keyvals = append(keyvals, k.Name(), v)
+ }
+ pprof.Do(ctx, pprof.Labels(keyvals...), f)
+}
diff --git a/vendor/go.opencensus.io/tag/profile_not19.go b/vendor/go.opencensus.io/tag/profile_not19.go
new file mode 100644
index 000000000..83adbce56
--- /dev/null
+++ b/vendor/go.opencensus.io/tag/profile_not19.go
@@ -0,0 +1,23 @@
+// Copyright 2018, OpenCensus Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// +build !go1.9
+
+package tag
+
+import "context"
+
+func do(ctx context.Context, f func(ctx context.Context)) {
+ f(ctx)
+}
diff --git a/vendor/go.opencensus.io/tag/validate.go b/vendor/go.opencensus.io/tag/validate.go
new file mode 100644
index 000000000..0939fc674
--- /dev/null
+++ b/vendor/go.opencensus.io/tag/validate.go
@@ -0,0 +1,56 @@
+// Copyright 2017, OpenCensus Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package tag
+
+import "errors"
+
+const (
+ maxKeyLength = 255
+
+ // valid are restricted to US-ASCII subset (range 0x20 (' ') to 0x7e ('~')).
+ validKeyValueMin = 32
+ validKeyValueMax = 126
+)
+
+var (
+ errInvalidKeyName = errors.New("invalid key name: only ASCII characters accepted; max length must be 255 characters")
+ errInvalidValue = errors.New("invalid value: only ASCII characters accepted; max length must be 255 characters")
+)
+
+func checkKeyName(name string) bool {
+ if len(name) == 0 {
+ return false
+ }
+ if len(name) > maxKeyLength {
+ return false
+ }
+ return isASCII(name)
+}
+
+func isASCII(s string) bool {
+ for _, c := range s {
+ if (c < validKeyValueMin) || (c > validKeyValueMax) {
+ return false
+ }
+ }
+ return true
+}
+
+func checkValue(v string) bool {
+ if len(v) > maxKeyLength {
+ return false
+ }
+ return isASCII(v)
+}
diff --git a/vendor/go.opencensus.io/trace/basetypes.go b/vendor/go.opencensus.io/trace/basetypes.go
new file mode 100644
index 000000000..ed59bfbde
--- /dev/null
+++ b/vendor/go.opencensus.io/trace/basetypes.go
@@ -0,0 +1,119 @@
+// Copyright 2017, OpenCensus Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package trace
+
+import (
+ "fmt"
+ "time"
+)
+
+type (
+ // TraceID is a 16-byte identifier for a set of spans.
+ TraceID [16]byte
+
+ // SpanID is an 8-byte identifier for a single span.
+ SpanID [8]byte
+)
+
+func (t TraceID) String() string {
+ return fmt.Sprintf("%02x", t[:])
+}
+
+func (s SpanID) String() string {
+ return fmt.Sprintf("%02x", s[:])
+}
+
+// Annotation represents a text annotation with a set of attributes and a timestamp.
+type Annotation struct {
+ Time time.Time
+ Message string
+ Attributes map[string]interface{}
+}
+
+// Attribute represents a key-value pair on a span, link or annotation.
+// Construct with one of: BoolAttribute, Int64Attribute, or StringAttribute.
+type Attribute struct {
+ key string
+ value interface{}
+}
+
+// BoolAttribute returns a bool-valued attribute.
+func BoolAttribute(key string, value bool) Attribute {
+ return Attribute{key: key, value: value}
+}
+
+// Int64Attribute returns an int64-valued attribute.
+func Int64Attribute(key string, value int64) Attribute {
+ return Attribute{key: key, value: value}
+}
+
+// Float64Attribute returns a float64-valued attribute.
+func Float64Attribute(key string, value float64) Attribute {
+ return Attribute{key: key, value: value}
+}
+
+// StringAttribute returns a string-valued attribute.
+func StringAttribute(key string, value string) Attribute {
+ return Attribute{key: key, value: value}
+}
+
+// LinkType specifies the relationship between the span that had the link
+// added, and the linked span.
+type LinkType int32
+
+// LinkType values.
+const (
+ LinkTypeUnspecified LinkType = iota // The relationship of the two spans is unknown.
+ LinkTypeChild // The current span is a child of the linked span.
+ LinkTypeParent // The current span is the parent of the linked span.
+)
+
+// Link represents a reference from one span to another span.
+type Link struct {
+ TraceID TraceID
+ SpanID SpanID
+ Type LinkType
+ // Attributes is a set of attributes on the link.
+ Attributes map[string]interface{}
+}
+
+// MessageEventType specifies the type of message event.
+type MessageEventType int32
+
+// MessageEventType values.
+const (
+ MessageEventTypeUnspecified MessageEventType = iota // Unknown event type.
+ MessageEventTypeSent // Indicates a sent RPC message.
+ MessageEventTypeRecv // Indicates a received RPC message.
+)
+
+// MessageEvent represents an event describing a message sent or received on the network.
+type MessageEvent struct {
+ Time time.Time
+ EventType MessageEventType
+ MessageID int64
+ UncompressedByteSize int64
+ CompressedByteSize int64
+}
+
+// Status is the status of a Span.
+type Status struct {
+ // Code is a status code. Zero indicates success.
+ //
+ // If Code will be propagated to Google APIs, it ideally should be a value from
+ // https://github.com/googleapis/googleapis/blob/master/google/rpc/code.proto .
+ Code int32
+ Message string
+}
diff --git a/vendor/go.opencensus.io/trace/config.go b/vendor/go.opencensus.io/trace/config.go
new file mode 100644
index 000000000..775f8274f
--- /dev/null
+++ b/vendor/go.opencensus.io/trace/config.go
@@ -0,0 +1,86 @@
+// Copyright 2018, OpenCensus Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package trace
+
+import (
+ "sync"
+
+ "go.opencensus.io/trace/internal"
+)
+
+// Config represents the global tracing configuration.
+type Config struct {
+ // DefaultSampler is the default sampler used when creating new spans.
+ DefaultSampler Sampler
+
+ // IDGenerator is for internal use only.
+ IDGenerator internal.IDGenerator
+
+ // MaxAnnotationEventsPerSpan is max number of annotation events per span
+ MaxAnnotationEventsPerSpan int
+
+ // MaxMessageEventsPerSpan is max number of message events per span
+ MaxMessageEventsPerSpan int
+
+ // MaxAnnotationEventsPerSpan is max number of attributes per span
+ MaxAttributesPerSpan int
+
+ // MaxLinksPerSpan is max number of links per span
+ MaxLinksPerSpan int
+}
+
+var configWriteMu sync.Mutex
+
+const (
+ // DefaultMaxAnnotationEventsPerSpan is default max number of annotation events per span
+ DefaultMaxAnnotationEventsPerSpan = 32
+
+ // DefaultMaxMessageEventsPerSpan is default max number of message events per span
+ DefaultMaxMessageEventsPerSpan = 128
+
+ // DefaultMaxAttributesPerSpan is default max number of attributes per span
+ DefaultMaxAttributesPerSpan = 32
+
+ // DefaultMaxLinksPerSpan is default max number of links per span
+ DefaultMaxLinksPerSpan = 32
+)
+
+// ApplyConfig applies changes to the global tracing configuration.
+//
+// Fields not provided in the given config are going to be preserved.
+func ApplyConfig(cfg Config) {
+ configWriteMu.Lock()
+ defer configWriteMu.Unlock()
+ c := *config.Load().(*Config)
+ if cfg.DefaultSampler != nil {
+ c.DefaultSampler = cfg.DefaultSampler
+ }
+ if cfg.IDGenerator != nil {
+ c.IDGenerator = cfg.IDGenerator
+ }
+ if cfg.MaxAnnotationEventsPerSpan > 0 {
+ c.MaxAnnotationEventsPerSpan = cfg.MaxAnnotationEventsPerSpan
+ }
+ if cfg.MaxMessageEventsPerSpan > 0 {
+ c.MaxMessageEventsPerSpan = cfg.MaxMessageEventsPerSpan
+ }
+ if cfg.MaxAttributesPerSpan > 0 {
+ c.MaxAttributesPerSpan = cfg.MaxAttributesPerSpan
+ }
+ if cfg.MaxLinksPerSpan > 0 {
+ c.MaxLinksPerSpan = cfg.MaxLinksPerSpan
+ }
+ config.Store(&c)
+}
diff --git a/vendor/go.opencensus.io/trace/doc.go b/vendor/go.opencensus.io/trace/doc.go
new file mode 100644
index 000000000..04b1ee4f3
--- /dev/null
+++ b/vendor/go.opencensus.io/trace/doc.go
@@ -0,0 +1,53 @@
+// Copyright 2017, OpenCensus Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/*
+Package trace contains support for OpenCensus distributed tracing.
+
+The following assumes a basic familiarity with OpenCensus concepts.
+See http://opencensus.io
+
+
+Exporting Traces
+
+To export collected tracing data, register at least one exporter. You can use
+one of the provided exporters or write your own.
+
+ trace.RegisterExporter(exporter)
+
+By default, traces will be sampled relatively rarely. To change the sampling
+frequency for your entire program, call ApplyConfig. Use a ProbabilitySampler
+to sample a subset of traces, or use AlwaysSample to collect a trace on every run:
+
+ trace.ApplyConfig(trace.Config{DefaultSampler: trace.AlwaysSample()})
+
+Be careful about using trace.AlwaysSample in a production application with
+significant traffic: a new trace will be started and exported for every request.
+
+Adding Spans to a Trace
+
+A trace consists of a tree of spans. In Go, the current span is carried in a
+context.Context.
+
+It is common to want to capture all the activity of a function call in a span. For
+this to work, the function must take a context.Context as a parameter. Add these two
+lines to the top of the function:
+
+ ctx, span := trace.StartSpan(ctx, "example.com/Run")
+ defer span.End()
+
+StartSpan will create a new top-level span if the context
+doesn't contain another span, otherwise it will create a child span.
+*/
+package trace // import "go.opencensus.io/trace"
diff --git a/vendor/go.opencensus.io/trace/evictedqueue.go b/vendor/go.opencensus.io/trace/evictedqueue.go
new file mode 100644
index 000000000..ffc264f23
--- /dev/null
+++ b/vendor/go.opencensus.io/trace/evictedqueue.go
@@ -0,0 +1,38 @@
+// Copyright 2019, OpenCensus Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package trace
+
+type evictedQueue struct {
+ queue []interface{}
+ capacity int
+ droppedCount int
+}
+
+func newEvictedQueue(capacity int) *evictedQueue {
+ eq := &evictedQueue{
+ capacity: capacity,
+ queue: make([]interface{}, 0),
+ }
+
+ return eq
+}
+
+func (eq *evictedQueue) add(value interface{}) {
+ if len(eq.queue) == eq.capacity {
+ eq.queue = eq.queue[1:]
+ eq.droppedCount++
+ }
+ eq.queue = append(eq.queue, value)
+}
diff --git a/vendor/go.opencensus.io/trace/exemplar.go b/vendor/go.opencensus.io/trace/exemplar.go
new file mode 100644
index 000000000..416d80590
--- /dev/null
+++ b/vendor/go.opencensus.io/trace/exemplar.go
@@ -0,0 +1,43 @@
+// Copyright 2018, OpenCensus Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package trace
+
+import (
+ "context"
+ "encoding/hex"
+
+ "go.opencensus.io/exemplar"
+)
+
+func init() {
+ exemplar.RegisterAttachmentExtractor(attachSpanContext)
+}
+
+func attachSpanContext(ctx context.Context, a exemplar.Attachments) exemplar.Attachments {
+ span := FromContext(ctx)
+ if span == nil {
+ return a
+ }
+ sc := span.SpanContext()
+ if !sc.IsSampled() {
+ return a
+ }
+ if a == nil {
+ a = make(exemplar.Attachments)
+ }
+ a[exemplar.KeyTraceID] = hex.EncodeToString(sc.TraceID[:])
+ a[exemplar.KeySpanID] = hex.EncodeToString(sc.SpanID[:])
+ return a
+}
diff --git a/vendor/go.opencensus.io/trace/export.go b/vendor/go.opencensus.io/trace/export.go
new file mode 100644
index 000000000..e0d9a4b99
--- /dev/null
+++ b/vendor/go.opencensus.io/trace/export.go
@@ -0,0 +1,97 @@
+// Copyright 2017, OpenCensus Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package trace
+
+import (
+ "sync"
+ "sync/atomic"
+ "time"
+)
+
+// Exporter is a type for functions that receive sampled trace spans.
+//
+// The ExportSpan method should be safe for concurrent use and should return
+// quickly; if an Exporter takes a significant amount of time to process a
+// SpanData, that work should be done on another goroutine.
+//
+// The SpanData should not be modified, but a pointer to it can be kept.
+type Exporter interface {
+ ExportSpan(s *SpanData)
+}
+
+type exportersMap map[Exporter]struct{}
+
+var (
+ exporterMu sync.Mutex
+ exporters atomic.Value
+)
+
+// RegisterExporter adds to the list of Exporters that will receive sampled
+// trace spans.
+//
+// Binaries can register exporters, libraries shouldn't register exporters.
+func RegisterExporter(e Exporter) {
+ exporterMu.Lock()
+ new := make(exportersMap)
+ if old, ok := exporters.Load().(exportersMap); ok {
+ for k, v := range old {
+ new[k] = v
+ }
+ }
+ new[e] = struct{}{}
+ exporters.Store(new)
+ exporterMu.Unlock()
+}
+
+// UnregisterExporter removes from the list of Exporters the Exporter that was
+// registered with the given name.
+func UnregisterExporter(e Exporter) {
+ exporterMu.Lock()
+ new := make(exportersMap)
+ if old, ok := exporters.Load().(exportersMap); ok {
+ for k, v := range old {
+ new[k] = v
+ }
+ }
+ delete(new, e)
+ exporters.Store(new)
+ exporterMu.Unlock()
+}
+
+// SpanData contains all the information collected by a Span.
+type SpanData struct {
+ SpanContext
+ ParentSpanID SpanID
+ SpanKind int
+ Name string
+ StartTime time.Time
+ // The wall clock time of EndTime will be adjusted to always be offset
+ // from StartTime by the duration of the span.
+ EndTime time.Time
+ // The values of Attributes each have type string, bool, or int64.
+ Attributes map[string]interface{}
+ Annotations []Annotation
+ MessageEvents []MessageEvent
+ Status
+ Links []Link
+ HasRemoteParent bool
+ DroppedAttributeCount int
+ DroppedAnnotationCount int
+ DroppedMessageEventCount int
+ DroppedLinkCount int
+
+ // ChildSpanCount holds the number of child span created for this span.
+ ChildSpanCount int
+}
diff --git a/vendor/go.opencensus.io/trace/internal/internal.go b/vendor/go.opencensus.io/trace/internal/internal.go
new file mode 100644
index 000000000..1c8b9b34b
--- /dev/null
+++ b/vendor/go.opencensus.io/trace/internal/internal.go
@@ -0,0 +1,21 @@
+// Copyright 2018, OpenCensus Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package internal provides trace internals.
+package internal
+
+type IDGenerator interface {
+ NewTraceID() [16]byte
+ NewSpanID() [8]byte
+}
diff --git a/vendor/go.opencensus.io/trace/lrumap.go b/vendor/go.opencensus.io/trace/lrumap.go
new file mode 100644
index 000000000..3f80a3368
--- /dev/null
+++ b/vendor/go.opencensus.io/trace/lrumap.go
@@ -0,0 +1,37 @@
+// Copyright 2019, OpenCensus Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package trace
+
+import (
+ "github.com/hashicorp/golang-lru/simplelru"
+)
+
+type lruMap struct {
+ simpleLruMap *simplelru.LRU
+ droppedCount int
+}
+
+func newLruMap(size int) *lruMap {
+ lm := &lruMap{}
+ lm.simpleLruMap, _ = simplelru.NewLRU(size, nil)
+ return lm
+}
+
+func (lm *lruMap) add(key, value interface{}) {
+ evicted := lm.simpleLruMap.Add(key, value)
+ if evicted {
+ lm.droppedCount++
+ }
+}
diff --git a/vendor/go.opencensus.io/trace/propagation/propagation.go b/vendor/go.opencensus.io/trace/propagation/propagation.go
new file mode 100644
index 000000000..1eb190a96
--- /dev/null
+++ b/vendor/go.opencensus.io/trace/propagation/propagation.go
@@ -0,0 +1,108 @@
+// Copyright 2017, OpenCensus Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package propagation implements the binary trace context format.
+package propagation // import "go.opencensus.io/trace/propagation"
+
+// TODO: link to external spec document.
+
+// BinaryFormat format:
+//
+// Binary value: <version_id><version_format>
+// version_id: 1 byte representing the version id.
+//
+// For version_id = 0:
+//
+// version_format: <field><field>
+// field_format: <field_id><field_format>
+//
+// Fields:
+//
+// TraceId: (field_id = 0, len = 16, default = "0000000000000000") - 16-byte array representing the trace_id.
+// SpanId: (field_id = 1, len = 8, default = "00000000") - 8-byte array representing the span_id.
+// TraceOptions: (field_id = 2, len = 1, default = "0") - 1-byte array representing the trace_options.
+//
+// Fields MUST be encoded using the field id order (smaller to higher).
+//
+// Valid value example:
+//
+// {0, 0, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 1, 97,
+// 98, 99, 100, 101, 102, 103, 104, 2, 1}
+//
+// version_id = 0;
+// trace_id = {64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79}
+// span_id = {97, 98, 99, 100, 101, 102, 103, 104};
+// trace_options = {1};
+
+import (
+ "net/http"
+
+ "go.opencensus.io/trace"
+)
+
+// Binary returns the binary format representation of a SpanContext.
+//
+// If sc is the zero value, Binary returns nil.
+func Binary(sc trace.SpanContext) []byte {
+ if sc == (trace.SpanContext{}) {
+ return nil
+ }
+ var b [29]byte
+ copy(b[2:18], sc.TraceID[:])
+ b[18] = 1
+ copy(b[19:27], sc.SpanID[:])
+ b[27] = 2
+ b[28] = uint8(sc.TraceOptions)
+ return b[:]
+}
+
+// FromBinary returns the SpanContext represented by b.
+//
+// If b has an unsupported version ID or contains no TraceID, FromBinary
+// returns with ok==false.
+func FromBinary(b []byte) (sc trace.SpanContext, ok bool) {
+ if len(b) == 0 || b[0] != 0 {
+ return trace.SpanContext{}, false
+ }
+ b = b[1:]
+ if len(b) >= 17 && b[0] == 0 {
+ copy(sc.TraceID[:], b[1:17])
+ b = b[17:]
+ } else {
+ return trace.SpanContext{}, false
+ }
+ if len(b) >= 9 && b[0] == 1 {
+ copy(sc.SpanID[:], b[1:9])
+ b = b[9:]
+ }
+ if len(b) >= 2 && b[0] == 2 {
+ sc.TraceOptions = trace.TraceOptions(b[1])
+ }
+ return sc, true
+}
+
+// HTTPFormat implementations propagate span contexts
+// in HTTP requests.
+//
+// SpanContextFromRequest extracts a span context from incoming
+// requests.
+//
+// SpanContextToRequest modifies the given request to include the given
+// span context.
+type HTTPFormat interface {
+ SpanContextFromRequest(req *http.Request) (sc trace.SpanContext, ok bool)
+ SpanContextToRequest(sc trace.SpanContext, req *http.Request)
+}
+
+// TODO(jbd): Find a more representative but short name for HTTPFormat.
diff --git a/vendor/go.opencensus.io/trace/sampling.go b/vendor/go.opencensus.io/trace/sampling.go
new file mode 100644
index 000000000..71c10f9e3
--- /dev/null
+++ b/vendor/go.opencensus.io/trace/sampling.go
@@ -0,0 +1,75 @@
+// Copyright 2017, OpenCensus Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package trace
+
+import (
+ "encoding/binary"
+)
+
+const defaultSamplingProbability = 1e-4
+
+// Sampler decides whether a trace should be sampled and exported.
+type Sampler func(SamplingParameters) SamplingDecision
+
+// SamplingParameters contains the values passed to a Sampler.
+type SamplingParameters struct {
+ ParentContext SpanContext
+ TraceID TraceID
+ SpanID SpanID
+ Name string
+ HasRemoteParent bool
+}
+
+// SamplingDecision is the value returned by a Sampler.
+type SamplingDecision struct {
+ Sample bool
+}
+
+// ProbabilitySampler returns a Sampler that samples a given fraction of traces.
+//
+// It also samples spans whose parents are sampled.
+func ProbabilitySampler(fraction float64) Sampler {
+ if !(fraction >= 0) {
+ fraction = 0
+ } else if fraction >= 1 {
+ return AlwaysSample()
+ }
+
+ traceIDUpperBound := uint64(fraction * (1 << 63))
+ return Sampler(func(p SamplingParameters) SamplingDecision {
+ if p.ParentContext.IsSampled() {
+ return SamplingDecision{Sample: true}
+ }
+ x := binary.BigEndian.Uint64(p.TraceID[0:8]) >> 1
+ return SamplingDecision{Sample: x < traceIDUpperBound}
+ })
+}
+
+// AlwaysSample returns a Sampler that samples every trace.
+// Be careful about using this sampler in a production application with
+// significant traffic: a new trace will be started and exported for every
+// request.
+func AlwaysSample() Sampler {
+ return func(p SamplingParameters) SamplingDecision {
+ return SamplingDecision{Sample: true}
+ }
+}
+
+// NeverSample returns a Sampler that samples no traces.
+func NeverSample() Sampler {
+ return func(p SamplingParameters) SamplingDecision {
+ return SamplingDecision{Sample: false}
+ }
+}
diff --git a/vendor/go.opencensus.io/trace/spanbucket.go b/vendor/go.opencensus.io/trace/spanbucket.go
new file mode 100644
index 000000000..fbabad34c
--- /dev/null
+++ b/vendor/go.opencensus.io/trace/spanbucket.go
@@ -0,0 +1,130 @@
+// Copyright 2017, OpenCensus Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package trace
+
+import (
+ "time"
+)
+
+// samplePeriod is the minimum time between accepting spans in a single bucket.
+const samplePeriod = time.Second
+
+// defaultLatencies contains the default latency bucket bounds.
+// TODO: consider defaults, make configurable
+var defaultLatencies = [...]time.Duration{
+ 10 * time.Microsecond,
+ 100 * time.Microsecond,
+ time.Millisecond,
+ 10 * time.Millisecond,
+ 100 * time.Millisecond,
+ time.Second,
+ 10 * time.Second,
+ time.Minute,
+}
+
+// bucket is a container for a set of spans for a particular error code or latency range.
+type bucket struct {
+ nextTime time.Time // next time we can accept a span
+ buffer []*SpanData // circular buffer of spans
+ nextIndex int // location next SpanData should be placed in buffer
+ overflow bool // whether the circular buffer has wrapped around
+}
+
+func makeBucket(bufferSize int) bucket {
+ return bucket{
+ buffer: make([]*SpanData, bufferSize),
+ }
+}
+
+// add adds a span to the bucket, if nextTime has been reached.
+func (b *bucket) add(s *SpanData) {
+ if s.EndTime.Before(b.nextTime) {
+ return
+ }
+ if len(b.buffer) == 0 {
+ return
+ }
+ b.nextTime = s.EndTime.Add(samplePeriod)
+ b.buffer[b.nextIndex] = s
+ b.nextIndex++
+ if b.nextIndex == len(b.buffer) {
+ b.nextIndex = 0
+ b.overflow = true
+ }
+}
+
+// size returns the number of spans in the bucket.
+func (b *bucket) size() int {
+ if b.overflow {
+ return len(b.buffer)
+ }
+ return b.nextIndex
+}
+
+// span returns the ith span in the bucket.
+func (b *bucket) span(i int) *SpanData {
+ if !b.overflow {
+ return b.buffer[i]
+ }
+ if i < len(b.buffer)-b.nextIndex {
+ return b.buffer[b.nextIndex+i]
+ }
+ return b.buffer[b.nextIndex+i-len(b.buffer)]
+}
+
+// resize changes the size of the bucket to n, keeping up to n existing spans.
+func (b *bucket) resize(n int) {
+ cur := b.size()
+ newBuffer := make([]*SpanData, n)
+ if cur < n {
+ for i := 0; i < cur; i++ {
+ newBuffer[i] = b.span(i)
+ }
+ b.buffer = newBuffer
+ b.nextIndex = cur
+ b.overflow = false
+ return
+ }
+ for i := 0; i < n; i++ {
+ newBuffer[i] = b.span(i + cur - n)
+ }
+ b.buffer = newBuffer
+ b.nextIndex = 0
+ b.overflow = true
+}
+
+// latencyBucket returns the appropriate bucket number for a given latency.
+func latencyBucket(latency time.Duration) int {
+ i := 0
+ for i < len(defaultLatencies) && latency >= defaultLatencies[i] {
+ i++
+ }
+ return i
+}
+
+// latencyBucketBounds returns the lower and upper bounds for a latency bucket
+// number.
+//
+// The lower bound is inclusive, the upper bound is exclusive (except for the
+// last bucket.)
+func latencyBucketBounds(index int) (lower time.Duration, upper time.Duration) {
+ if index == 0 {
+ return 0, defaultLatencies[index]
+ }
+ if index == len(defaultLatencies) {
+ return defaultLatencies[index-1], 1<<63 - 1
+ }
+ return defaultLatencies[index-1], defaultLatencies[index]
+}
diff --git a/vendor/go.opencensus.io/trace/spanstore.go b/vendor/go.opencensus.io/trace/spanstore.go
new file mode 100644
index 000000000..c442d9902
--- /dev/null
+++ b/vendor/go.opencensus.io/trace/spanstore.go
@@ -0,0 +1,306 @@
+// Copyright 2017, OpenCensus Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package trace
+
+import (
+ "sync"
+ "time"
+
+ "go.opencensus.io/internal"
+)
+
+const (
+ maxBucketSize = 100000
+ defaultBucketSize = 10
+)
+
+var (
+ ssmu sync.RWMutex // protects spanStores
+ spanStores = make(map[string]*spanStore)
+)
+
+// This exists purely to avoid exposing internal methods used by z-Pages externally.
+type internalOnly struct{}
+
+func init() {
+ //TODO(#412): remove
+ internal.Trace = &internalOnly{}
+}
+
+// ReportActiveSpans returns the active spans for the given name.
+func (i internalOnly) ReportActiveSpans(name string) []*SpanData {
+ s := spanStoreForName(name)
+ if s == nil {
+ return nil
+ }
+ var out []*SpanData
+ s.mu.Lock()
+ defer s.mu.Unlock()
+ for span := range s.active {
+ out = append(out, span.makeSpanData())
+ }
+ return out
+}
+
+// ReportSpansByError returns a sample of error spans.
+//
+// If code is nonzero, only spans with that status code are returned.
+func (i internalOnly) ReportSpansByError(name string, code int32) []*SpanData {
+ s := spanStoreForName(name)
+ if s == nil {
+ return nil
+ }
+ var out []*SpanData
+ s.mu.Lock()
+ defer s.mu.Unlock()
+ if code != 0 {
+ if b, ok := s.errors[code]; ok {
+ for _, sd := range b.buffer {
+ if sd == nil {
+ break
+ }
+ out = append(out, sd)
+ }
+ }
+ } else {
+ for _, b := range s.errors {
+ for _, sd := range b.buffer {
+ if sd == nil {
+ break
+ }
+ out = append(out, sd)
+ }
+ }
+ }
+ return out
+}
+
+// ConfigureBucketSizes sets the number of spans to keep per latency and error
+// bucket for different span names.
+func (i internalOnly) ConfigureBucketSizes(bcs []internal.BucketConfiguration) {
+ for _, bc := range bcs {
+ latencyBucketSize := bc.MaxRequestsSucceeded
+ if latencyBucketSize < 0 {
+ latencyBucketSize = 0
+ }
+ if latencyBucketSize > maxBucketSize {
+ latencyBucketSize = maxBucketSize
+ }
+ errorBucketSize := bc.MaxRequestsErrors
+ if errorBucketSize < 0 {
+ errorBucketSize = 0
+ }
+ if errorBucketSize > maxBucketSize {
+ errorBucketSize = maxBucketSize
+ }
+ spanStoreSetSize(bc.Name, latencyBucketSize, errorBucketSize)
+ }
+}
+
+// ReportSpansPerMethod returns a summary of what spans are being stored for each span name.
+func (i internalOnly) ReportSpansPerMethod() map[string]internal.PerMethodSummary {
+ out := make(map[string]internal.PerMethodSummary)
+ ssmu.RLock()
+ defer ssmu.RUnlock()
+ for name, s := range spanStores {
+ s.mu.Lock()
+ p := internal.PerMethodSummary{
+ Active: len(s.active),
+ }
+ for code, b := range s.errors {
+ p.ErrorBuckets = append(p.ErrorBuckets, internal.ErrorBucketSummary{
+ ErrorCode: code,
+ Size: b.size(),
+ })
+ }
+ for i, b := range s.latency {
+ min, max := latencyBucketBounds(i)
+ p.LatencyBuckets = append(p.LatencyBuckets, internal.LatencyBucketSummary{
+ MinLatency: min,
+ MaxLatency: max,
+ Size: b.size(),
+ })
+ }
+ s.mu.Unlock()
+ out[name] = p
+ }
+ return out
+}
+
+// ReportSpansByLatency returns a sample of successful spans.
+//
+// minLatency is the minimum latency of spans to be returned.
+// maxLatency, if nonzero, is the maximum latency of spans to be returned.
+func (i internalOnly) ReportSpansByLatency(name string, minLatency, maxLatency time.Duration) []*SpanData {
+ s := spanStoreForName(name)
+ if s == nil {
+ return nil
+ }
+ var out []*SpanData
+ s.mu.Lock()
+ defer s.mu.Unlock()
+ for i, b := range s.latency {
+ min, max := latencyBucketBounds(i)
+ if i+1 != len(s.latency) && max <= minLatency {
+ continue
+ }
+ if maxLatency != 0 && maxLatency < min {
+ continue
+ }
+ for _, sd := range b.buffer {
+ if sd == nil {
+ break
+ }
+ if minLatency != 0 || maxLatency != 0 {
+ d := sd.EndTime.Sub(sd.StartTime)
+ if d < minLatency {
+ continue
+ }
+ if maxLatency != 0 && d > maxLatency {
+ continue
+ }
+ }
+ out = append(out, sd)
+ }
+ }
+ return out
+}
+
+// spanStore keeps track of spans stored for a particular span name.
+//
+// It contains all active spans; a sample of spans for failed requests,
+// categorized by error code; and a sample of spans for successful requests,
+// bucketed by latency.
+type spanStore struct {
+ mu sync.Mutex // protects everything below.
+ active map[*Span]struct{}
+ errors map[int32]*bucket
+ latency []bucket
+ maxSpansPerErrorBucket int
+}
+
+// newSpanStore creates a span store.
+func newSpanStore(name string, latencyBucketSize int, errorBucketSize int) *spanStore {
+ s := &spanStore{
+ active: make(map[*Span]struct{}),
+ latency: make([]bucket, len(defaultLatencies)+1),
+ maxSpansPerErrorBucket: errorBucketSize,
+ }
+ for i := range s.latency {
+ s.latency[i] = makeBucket(latencyBucketSize)
+ }
+ return s
+}
+
+// spanStoreForName returns the spanStore for the given name.
+//
+// It returns nil if it doesn't exist.
+func spanStoreForName(name string) *spanStore {
+ var s *spanStore
+ ssmu.RLock()
+ s, _ = spanStores[name]
+ ssmu.RUnlock()
+ return s
+}
+
+// spanStoreForNameCreateIfNew returns the spanStore for the given name.
+//
+// It creates it if it didn't exist.
+func spanStoreForNameCreateIfNew(name string) *spanStore {
+ ssmu.RLock()
+ s, ok := spanStores[name]
+ ssmu.RUnlock()
+ if ok {
+ return s
+ }
+ ssmu.Lock()
+ defer ssmu.Unlock()
+ s, ok = spanStores[name]
+ if ok {
+ return s
+ }
+ s = newSpanStore(name, defaultBucketSize, defaultBucketSize)
+ spanStores[name] = s
+ return s
+}
+
+// spanStoreSetSize resizes the spanStore for the given name.
+//
+// It creates it if it didn't exist.
+func spanStoreSetSize(name string, latencyBucketSize int, errorBucketSize int) {
+ ssmu.RLock()
+ s, ok := spanStores[name]
+ ssmu.RUnlock()
+ if ok {
+ s.resize(latencyBucketSize, errorBucketSize)
+ return
+ }
+ ssmu.Lock()
+ defer ssmu.Unlock()
+ s, ok = spanStores[name]
+ if ok {
+ s.resize(latencyBucketSize, errorBucketSize)
+ return
+ }
+ s = newSpanStore(name, latencyBucketSize, errorBucketSize)
+ spanStores[name] = s
+}
+
+func (s *spanStore) resize(latencyBucketSize int, errorBucketSize int) {
+ s.mu.Lock()
+ for i := range s.latency {
+ s.latency[i].resize(latencyBucketSize)
+ }
+ for _, b := range s.errors {
+ b.resize(errorBucketSize)
+ }
+ s.maxSpansPerErrorBucket = errorBucketSize
+ s.mu.Unlock()
+}
+
+// add adds a span to the active bucket of the spanStore.
+func (s *spanStore) add(span *Span) {
+ s.mu.Lock()
+ s.active[span] = struct{}{}
+ s.mu.Unlock()
+}
+
+// finished removes a span from the active set, and adds a corresponding
+// SpanData to a latency or error bucket.
+func (s *spanStore) finished(span *Span, sd *SpanData) {
+ latency := sd.EndTime.Sub(sd.StartTime)
+ if latency < 0 {
+ latency = 0
+ }
+ code := sd.Status.Code
+
+ s.mu.Lock()
+ delete(s.active, span)
+ if code == 0 {
+ s.latency[latencyBucket(latency)].add(sd)
+ } else {
+ if s.errors == nil {
+ s.errors = make(map[int32]*bucket)
+ }
+ if b := s.errors[code]; b != nil {
+ b.add(sd)
+ } else {
+ b := makeBucket(s.maxSpansPerErrorBucket)
+ s.errors[code] = &b
+ b.add(sd)
+ }
+ }
+ s.mu.Unlock()
+}
diff --git a/vendor/go.opencensus.io/trace/status_codes.go b/vendor/go.opencensus.io/trace/status_codes.go
new file mode 100644
index 000000000..ec60effd1
--- /dev/null
+++ b/vendor/go.opencensus.io/trace/status_codes.go
@@ -0,0 +1,37 @@
+// Copyright 2018, OpenCensus Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package trace
+
+// Status codes for use with Span.SetStatus. These correspond to the status
+// codes used by gRPC defined here: https://github.com/googleapis/googleapis/blob/master/google/rpc/code.proto
+const (
+ StatusCodeOK = 0
+ StatusCodeCancelled = 1
+ StatusCodeUnknown = 2
+ StatusCodeInvalidArgument = 3
+ StatusCodeDeadlineExceeded = 4
+ StatusCodeNotFound = 5
+ StatusCodeAlreadyExists = 6
+ StatusCodePermissionDenied = 7
+ StatusCodeResourceExhausted = 8
+ StatusCodeFailedPrecondition = 9
+ StatusCodeAborted = 10
+ StatusCodeOutOfRange = 11
+ StatusCodeUnimplemented = 12
+ StatusCodeInternal = 13
+ StatusCodeUnavailable = 14
+ StatusCodeDataLoss = 15
+ StatusCodeUnauthenticated = 16
+)
diff --git a/vendor/go.opencensus.io/trace/trace.go b/vendor/go.opencensus.io/trace/trace.go
new file mode 100644
index 000000000..38ead7bf0
--- /dev/null
+++ b/vendor/go.opencensus.io/trace/trace.go
@@ -0,0 +1,598 @@
+// Copyright 2017, OpenCensus Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package trace
+
+import (
+ "context"
+ crand "crypto/rand"
+ "encoding/binary"
+ "fmt"
+ "math/rand"
+ "sync"
+ "sync/atomic"
+ "time"
+
+ "go.opencensus.io/internal"
+ "go.opencensus.io/trace/tracestate"
+)
+
+// Span represents a span of a trace. It has an associated SpanContext, and
+// stores data accumulated while the span is active.
+//
+// Ideally users should interact with Spans by calling the functions in this
+// package that take a Context parameter.
+type Span struct {
+ // data contains information recorded about the span.
+ //
+ // It will be non-nil if we are exporting the span or recording events for it.
+ // Otherwise, data is nil, and the Span is simply a carrier for the
+ // SpanContext, so that the trace ID is propagated.
+ data *SpanData
+ mu sync.Mutex // protects the contents of *data (but not the pointer value.)
+ spanContext SpanContext
+
+ // lruAttributes are capped at configured limit. When the capacity is reached an oldest entry
+ // is removed to create room for a new entry.
+ lruAttributes *lruMap
+
+ // annotations are stored in FIFO queue capped by configured limit.
+ annotations *evictedQueue
+
+ // messageEvents are stored in FIFO queue capped by configured limit.
+ messageEvents *evictedQueue
+
+ // links are stored in FIFO queue capped by configured limit.
+ links *evictedQueue
+
+ // spanStore is the spanStore this span belongs to, if any, otherwise it is nil.
+ *spanStore
+ endOnce sync.Once
+
+ executionTracerTaskEnd func() // ends the execution tracer span
+}
+
+// IsRecordingEvents returns true if events are being recorded for this span.
+// Use this check to avoid computing expensive annotations when they will never
+// be used.
+func (s *Span) IsRecordingEvents() bool {
+ if s == nil {
+ return false
+ }
+ return s.data != nil
+}
+
+// TraceOptions contains options associated with a trace span.
+type TraceOptions uint32
+
+// IsSampled returns true if the span will be exported.
+func (sc SpanContext) IsSampled() bool {
+ return sc.TraceOptions.IsSampled()
+}
+
+// setIsSampled sets the TraceOptions bit that determines whether the span will be exported.
+func (sc *SpanContext) setIsSampled(sampled bool) {
+ if sampled {
+ sc.TraceOptions |= 1
+ } else {
+ sc.TraceOptions &= ^TraceOptions(1)
+ }
+}
+
+// IsSampled returns true if the span will be exported.
+func (t TraceOptions) IsSampled() bool {
+ return t&1 == 1
+}
+
+// SpanContext contains the state that must propagate across process boundaries.
+//
+// SpanContext is not an implementation of context.Context.
+// TODO: add reference to external Census docs for SpanContext.
+type SpanContext struct {
+ TraceID TraceID
+ SpanID SpanID
+ TraceOptions TraceOptions
+ Tracestate *tracestate.Tracestate
+}
+
+type contextKey struct{}
+
+// FromContext returns the Span stored in a context, or nil if there isn't one.
+func FromContext(ctx context.Context) *Span {
+ s, _ := ctx.Value(contextKey{}).(*Span)
+ return s
+}
+
+// NewContext returns a new context with the given Span attached.
+func NewContext(parent context.Context, s *Span) context.Context {
+ return context.WithValue(parent, contextKey{}, s)
+}
+
+// All available span kinds. Span kind must be either one of these values.
+const (
+ SpanKindUnspecified = iota
+ SpanKindServer
+ SpanKindClient
+)
+
+// StartOptions contains options concerning how a span is started.
+type StartOptions struct {
+ // Sampler to consult for this Span. If provided, it is always consulted.
+ //
+ // If not provided, then the behavior differs based on whether
+ // the parent of this Span is remote, local, or there is no parent.
+ // In the case of a remote parent or no parent, the
+ // default sampler (see Config) will be consulted. Otherwise,
+ // when there is a non-remote parent, no new sampling decision will be made:
+ // we will preserve the sampling of the parent.
+ Sampler Sampler
+
+ // SpanKind represents the kind of a span. If none is set,
+ // SpanKindUnspecified is used.
+ SpanKind int
+}
+
+// StartOption apply changes to StartOptions.
+type StartOption func(*StartOptions)
+
+// WithSpanKind makes new spans to be created with the given kind.
+func WithSpanKind(spanKind int) StartOption {
+ return func(o *StartOptions) {
+ o.SpanKind = spanKind
+ }
+}
+
+// WithSampler makes new spans to be be created with a custom sampler.
+// Otherwise, the global sampler is used.
+func WithSampler(sampler Sampler) StartOption {
+ return func(o *StartOptions) {
+ o.Sampler = sampler
+ }
+}
+
+// StartSpan starts a new child span of the current span in the context. If
+// there is no span in the context, creates a new trace and span.
+//
+// Returned context contains the newly created span. You can use it to
+// propagate the returned span in process.
+func StartSpan(ctx context.Context, name string, o ...StartOption) (context.Context, *Span) {
+ var opts StartOptions
+ var parent SpanContext
+ if p := FromContext(ctx); p != nil {
+ p.addChild()
+ parent = p.spanContext
+ }
+ for _, op := range o {
+ op(&opts)
+ }
+ span := startSpanInternal(name, parent != SpanContext{}, parent, false, opts)
+
+ ctx, end := startExecutionTracerTask(ctx, name)
+ span.executionTracerTaskEnd = end
+ return NewContext(ctx, span), span
+}
+
+// StartSpanWithRemoteParent starts a new child span of the span from the given parent.
+//
+// If the incoming context contains a parent, it ignores. StartSpanWithRemoteParent is
+// preferred for cases where the parent is propagated via an incoming request.
+//
+// Returned context contains the newly created span. You can use it to
+// propagate the returned span in process.
+func StartSpanWithRemoteParent(ctx context.Context, name string, parent SpanContext, o ...StartOption) (context.Context, *Span) {
+ var opts StartOptions
+ for _, op := range o {
+ op(&opts)
+ }
+ span := startSpanInternal(name, parent != SpanContext{}, parent, true, opts)
+ ctx, end := startExecutionTracerTask(ctx, name)
+ span.executionTracerTaskEnd = end
+ return NewContext(ctx, span), span
+}
+
+func startSpanInternal(name string, hasParent bool, parent SpanContext, remoteParent bool, o StartOptions) *Span {
+ span := &Span{}
+ span.spanContext = parent
+
+ cfg := config.Load().(*Config)
+
+ if !hasParent {
+ span.spanContext.TraceID = cfg.IDGenerator.NewTraceID()
+ }
+ span.spanContext.SpanID = cfg.IDGenerator.NewSpanID()
+ sampler := cfg.DefaultSampler
+
+ if !hasParent || remoteParent || o.Sampler != nil {
+ // If this span is the child of a local span and no Sampler is set in the
+ // options, keep the parent's TraceOptions.
+ //
+ // Otherwise, consult the Sampler in the options if it is non-nil, otherwise
+ // the default sampler.
+ if o.Sampler != nil {
+ sampler = o.Sampler
+ }
+ span.spanContext.setIsSampled(sampler(SamplingParameters{
+ ParentContext: parent,
+ TraceID: span.spanContext.TraceID,
+ SpanID: span.spanContext.SpanID,
+ Name: name,
+ HasRemoteParent: remoteParent}).Sample)
+ }
+
+ if !internal.LocalSpanStoreEnabled && !span.spanContext.IsSampled() {
+ return span
+ }
+
+ span.data = &SpanData{
+ SpanContext: span.spanContext,
+ StartTime: time.Now(),
+ SpanKind: o.SpanKind,
+ Name: name,
+ HasRemoteParent: remoteParent,
+ }
+ span.lruAttributes = newLruMap(cfg.MaxAttributesPerSpan)
+ span.annotations = newEvictedQueue(cfg.MaxAnnotationEventsPerSpan)
+ span.messageEvents = newEvictedQueue(cfg.MaxMessageEventsPerSpan)
+ span.links = newEvictedQueue(cfg.MaxLinksPerSpan)
+
+ if hasParent {
+ span.data.ParentSpanID = parent.SpanID
+ }
+ if internal.LocalSpanStoreEnabled {
+ var ss *spanStore
+ ss = spanStoreForNameCreateIfNew(name)
+ if ss != nil {
+ span.spanStore = ss
+ ss.add(span)
+ }
+ }
+
+ return span
+}
+
+// End ends the span.
+func (s *Span) End() {
+ if s == nil {
+ return
+ }
+ if s.executionTracerTaskEnd != nil {
+ s.executionTracerTaskEnd()
+ }
+ if !s.IsRecordingEvents() {
+ return
+ }
+ s.endOnce.Do(func() {
+ exp, _ := exporters.Load().(exportersMap)
+ mustExport := s.spanContext.IsSampled() && len(exp) > 0
+ if s.spanStore != nil || mustExport {
+ sd := s.makeSpanData()
+ sd.EndTime = internal.MonotonicEndTime(sd.StartTime)
+ if s.spanStore != nil {
+ s.spanStore.finished(s, sd)
+ }
+ if mustExport {
+ for e := range exp {
+ e.ExportSpan(sd)
+ }
+ }
+ }
+ })
+}
+
+// makeSpanData produces a SpanData representing the current state of the Span.
+// It requires that s.data is non-nil.
+func (s *Span) makeSpanData() *SpanData {
+ var sd SpanData
+ s.mu.Lock()
+ sd = *s.data
+ if s.lruAttributes.simpleLruMap.Len() > 0 {
+ sd.Attributes = s.lruAttributesToAttributeMap()
+ sd.DroppedAttributeCount = s.lruAttributes.droppedCount
+ }
+ if len(s.annotations.queue) > 0 {
+ sd.Annotations = s.interfaceArrayToAnnotationArray()
+ sd.DroppedAnnotationCount = s.annotations.droppedCount
+ }
+ if len(s.messageEvents.queue) > 0 {
+ sd.MessageEvents = s.interfaceArrayToMessageEventArray()
+ sd.DroppedMessageEventCount = s.messageEvents.droppedCount
+ }
+ if len(s.links.queue) > 0 {
+ sd.Links = s.interfaceArrayToLinksArray()
+ sd.DroppedLinkCount = s.links.droppedCount
+ }
+ s.mu.Unlock()
+ return &sd
+}
+
+// SpanContext returns the SpanContext of the span.
+func (s *Span) SpanContext() SpanContext {
+ if s == nil {
+ return SpanContext{}
+ }
+ return s.spanContext
+}
+
+// SetName sets the name of the span, if it is recording events.
+func (s *Span) SetName(name string) {
+ if !s.IsRecordingEvents() {
+ return
+ }
+ s.mu.Lock()
+ s.data.Name = name
+ s.mu.Unlock()
+}
+
+// SetStatus sets the status of the span, if it is recording events.
+func (s *Span) SetStatus(status Status) {
+ if !s.IsRecordingEvents() {
+ return
+ }
+ s.mu.Lock()
+ s.data.Status = status
+ s.mu.Unlock()
+}
+
+func (s *Span) interfaceArrayToLinksArray() []Link {
+ linksArr := make([]Link, 0)
+ for _, value := range s.links.queue {
+ linksArr = append(linksArr, value.(Link))
+ }
+ return linksArr
+}
+
+func (s *Span) interfaceArrayToMessageEventArray() []MessageEvent {
+ messageEventArr := make([]MessageEvent, 0)
+ for _, value := range s.messageEvents.queue {
+ messageEventArr = append(messageEventArr, value.(MessageEvent))
+ }
+ return messageEventArr
+}
+
+func (s *Span) interfaceArrayToAnnotationArray() []Annotation {
+ annotationArr := make([]Annotation, 0)
+ for _, value := range s.annotations.queue {
+ annotationArr = append(annotationArr, value.(Annotation))
+ }
+ return annotationArr
+}
+
+func (s *Span) lruAttributesToAttributeMap() map[string]interface{} {
+ attributes := make(map[string]interface{})
+ for _, key := range s.lruAttributes.simpleLruMap.Keys() {
+ value, ok := s.lruAttributes.simpleLruMap.Get(key)
+ if ok {
+ keyStr := key.(string)
+ attributes[keyStr] = value
+ }
+ }
+ return attributes
+}
+
+func (s *Span) copyToCappedAttributes(attributes []Attribute) {
+ for _, a := range attributes {
+ s.lruAttributes.add(a.key, a.value)
+ }
+}
+
+func (s *Span) addChild() {
+ if !s.IsRecordingEvents() {
+ return
+ }
+ s.mu.Lock()
+ s.data.ChildSpanCount++
+ s.mu.Unlock()
+}
+
+// AddAttributes sets attributes in the span.
+//
+// Existing attributes whose keys appear in the attributes parameter are overwritten.
+func (s *Span) AddAttributes(attributes ...Attribute) {
+ if !s.IsRecordingEvents() {
+ return
+ }
+ s.mu.Lock()
+ s.copyToCappedAttributes(attributes)
+ s.mu.Unlock()
+}
+
+// copyAttributes copies a slice of Attributes into a map.
+func copyAttributes(m map[string]interface{}, attributes []Attribute) {
+ for _, a := range attributes {
+ m[a.key] = a.value
+ }
+}
+
+func (s *Span) lazyPrintfInternal(attributes []Attribute, format string, a ...interface{}) {
+ now := time.Now()
+ msg := fmt.Sprintf(format, a...)
+ var m map[string]interface{}
+ s.mu.Lock()
+ if len(attributes) != 0 {
+ m = make(map[string]interface{})
+ copyAttributes(m, attributes)
+ }
+ s.annotations.add(Annotation{
+ Time: now,
+ Message: msg,
+ Attributes: m,
+ })
+ s.mu.Unlock()
+}
+
+func (s *Span) printStringInternal(attributes []Attribute, str string) {
+ now := time.Now()
+ var a map[string]interface{}
+ s.mu.Lock()
+ if len(attributes) != 0 {
+ a = make(map[string]interface{})
+ copyAttributes(a, attributes)
+ }
+ s.annotations.add(Annotation{
+ Time: now,
+ Message: str,
+ Attributes: a,
+ })
+ s.mu.Unlock()
+}
+
+// Annotate adds an annotation with attributes.
+// Attributes can be nil.
+func (s *Span) Annotate(attributes []Attribute, str string) {
+ if !s.IsRecordingEvents() {
+ return
+ }
+ s.printStringInternal(attributes, str)
+}
+
+// Annotatef adds an annotation with attributes.
+func (s *Span) Annotatef(attributes []Attribute, format string, a ...interface{}) {
+ if !s.IsRecordingEvents() {
+ return
+ }
+ s.lazyPrintfInternal(attributes, format, a...)
+}
+
+// AddMessageSendEvent adds a message send event to the span.
+//
+// messageID is an identifier for the message, which is recommended to be
+// unique in this span and the same between the send event and the receive
+// event (this allows to identify a message between the sender and receiver).
+// For example, this could be a sequence id.
+func (s *Span) AddMessageSendEvent(messageID, uncompressedByteSize, compressedByteSize int64) {
+ if !s.IsRecordingEvents() {
+ return
+ }
+ now := time.Now()
+ s.mu.Lock()
+ s.messageEvents.add(MessageEvent{
+ Time: now,
+ EventType: MessageEventTypeSent,
+ MessageID: messageID,
+ UncompressedByteSize: uncompressedByteSize,
+ CompressedByteSize: compressedByteSize,
+ })
+ s.mu.Unlock()
+}
+
+// AddMessageReceiveEvent adds a message receive event to the span.
+//
+// messageID is an identifier for the message, which is recommended to be
+// unique in this span and the same between the send event and the receive
+// event (this allows to identify a message between the sender and receiver).
+// For example, this could be a sequence id.
+func (s *Span) AddMessageReceiveEvent(messageID, uncompressedByteSize, compressedByteSize int64) {
+ if !s.IsRecordingEvents() {
+ return
+ }
+ now := time.Now()
+ s.mu.Lock()
+ s.messageEvents.add(MessageEvent{
+ Time: now,
+ EventType: MessageEventTypeRecv,
+ MessageID: messageID,
+ UncompressedByteSize: uncompressedByteSize,
+ CompressedByteSize: compressedByteSize,
+ })
+ s.mu.Unlock()
+}
+
+// AddLink adds a link to the span.
+func (s *Span) AddLink(l Link) {
+ if !s.IsRecordingEvents() {
+ return
+ }
+ s.mu.Lock()
+ s.links.add(l)
+ s.mu.Unlock()
+}
+
+func (s *Span) String() string {
+ if s == nil {
+ return "<nil>"
+ }
+ if s.data == nil {
+ return fmt.Sprintf("span %s", s.spanContext.SpanID)
+ }
+ s.mu.Lock()
+ str := fmt.Sprintf("span %s %q", s.spanContext.SpanID, s.data.Name)
+ s.mu.Unlock()
+ return str
+}
+
+var config atomic.Value // access atomically
+
+func init() {
+ gen := &defaultIDGenerator{}
+ // initialize traceID and spanID generators.
+ var rngSeed int64
+ for _, p := range []interface{}{
+ &rngSeed, &gen.traceIDAdd, &gen.nextSpanID, &gen.spanIDInc,
+ } {
+ binary.Read(crand.Reader, binary.LittleEndian, p)
+ }
+ gen.traceIDRand = rand.New(rand.NewSource(rngSeed))
+ gen.spanIDInc |= 1
+
+ config.Store(&Config{
+ DefaultSampler: ProbabilitySampler(defaultSamplingProbability),
+ IDGenerator: gen,
+ MaxAttributesPerSpan: DefaultMaxAttributesPerSpan,
+ MaxAnnotationEventsPerSpan: DefaultMaxAnnotationEventsPerSpan,
+ MaxMessageEventsPerSpan: DefaultMaxMessageEventsPerSpan,
+ MaxLinksPerSpan: DefaultMaxLinksPerSpan,
+ })
+}
+
+type defaultIDGenerator struct {
+ sync.Mutex
+
+ // Please keep these as the first fields
+ // so that these 8 byte fields will be aligned on addresses
+ // divisible by 8, on both 32-bit and 64-bit machines when
+ // performing atomic increments and accesses.
+ // See:
+ // * https://github.com/census-instrumentation/opencensus-go/issues/587
+ // * https://github.com/census-instrumentation/opencensus-go/issues/865
+ // * https://golang.org/pkg/sync/atomic/#pkg-note-BUG
+ nextSpanID uint64
+ spanIDInc uint64
+
+ traceIDAdd [2]uint64
+ traceIDRand *rand.Rand
+}
+
+// NewSpanID returns a non-zero span ID from a randomly-chosen sequence.
+func (gen *defaultIDGenerator) NewSpanID() [8]byte {
+ var id uint64
+ for id == 0 {
+ id = atomic.AddUint64(&gen.nextSpanID, gen.spanIDInc)
+ }
+ var sid [8]byte
+ binary.LittleEndian.PutUint64(sid[:], id)
+ return sid
+}
+
+// NewTraceID returns a non-zero trace ID from a randomly-chosen sequence.
+// mu should be held while this function is called.
+func (gen *defaultIDGenerator) NewTraceID() [16]byte {
+ var tid [16]byte
+ // Construct the trace ID from two outputs of traceIDRand, with a constant
+ // added to each half for additional entropy.
+ gen.Lock()
+ binary.LittleEndian.PutUint64(tid[0:8], gen.traceIDRand.Uint64()+gen.traceIDAdd[0])
+ binary.LittleEndian.PutUint64(tid[8:16], gen.traceIDRand.Uint64()+gen.traceIDAdd[1])
+ gen.Unlock()
+ return tid
+}
diff --git a/vendor/go.opencensus.io/trace/trace_go11.go b/vendor/go.opencensus.io/trace/trace_go11.go
new file mode 100644
index 000000000..b7d8aaf28
--- /dev/null
+++ b/vendor/go.opencensus.io/trace/trace_go11.go
@@ -0,0 +1,32 @@
+// Copyright 2018, OpenCensus Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// +build go1.11
+
+package trace
+
+import (
+ "context"
+ t "runtime/trace"
+)
+
+func startExecutionTracerTask(ctx context.Context, name string) (context.Context, func()) {
+ if !t.IsEnabled() {
+ // Avoid additional overhead if
+ // runtime/trace is not enabled.
+ return ctx, func() {}
+ }
+ nctx, task := t.NewTask(ctx, name)
+ return nctx, task.End
+}
diff --git a/vendor/go.opencensus.io/trace/trace_nongo11.go b/vendor/go.opencensus.io/trace/trace_nongo11.go
new file mode 100644
index 000000000..e25419859
--- /dev/null
+++ b/vendor/go.opencensus.io/trace/trace_nongo11.go
@@ -0,0 +1,25 @@
+// Copyright 2018, OpenCensus Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// +build !go1.11
+
+package trace
+
+import (
+ "context"
+)
+
+func startExecutionTracerTask(ctx context.Context, name string) (context.Context, func()) {
+ return ctx, func() {}
+}
diff --git a/vendor/go.opencensus.io/trace/tracestate/tracestate.go b/vendor/go.opencensus.io/trace/tracestate/tracestate.go
new file mode 100644
index 000000000..2d6c713eb
--- /dev/null
+++ b/vendor/go.opencensus.io/trace/tracestate/tracestate.go
@@ -0,0 +1,147 @@
+// Copyright 2018, OpenCensus Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package tracestate implements support for the Tracestate header of the
+// W3C TraceContext propagation format.
+package tracestate
+
+import (
+ "fmt"
+ "regexp"
+)
+
+const (
+ keyMaxSize = 256
+ valueMaxSize = 256
+ maxKeyValuePairs = 32
+)
+
+const (
+ keyWithoutVendorFormat = `[a-z][_0-9a-z\-\*\/]{0,255}`
+ keyWithVendorFormat = `[a-z][_0-9a-z\-\*\/]{0,240}@[a-z][_0-9a-z\-\*\/]{0,13}`
+ keyFormat = `(` + keyWithoutVendorFormat + `)|(` + keyWithVendorFormat + `)`
+ valueFormat = `[\x20-\x2b\x2d-\x3c\x3e-\x7e]{0,255}[\x21-\x2b\x2d-\x3c\x3e-\x7e]`
+)
+
+var keyValidationRegExp = regexp.MustCompile(`^(` + keyFormat + `)$`)
+var valueValidationRegExp = regexp.MustCompile(`^(` + valueFormat + `)$`)
+
+// Tracestate represents tracing-system specific context in a list of key-value pairs. Tracestate allows different
+// vendors propagate additional information and inter-operate with their legacy Id formats.
+type Tracestate struct {
+ entries []Entry
+}
+
+// Entry represents one key-value pair in a list of key-value pair of Tracestate.
+type Entry struct {
+ // Key is an opaque string up to 256 characters printable. It MUST begin with a lowercase letter,
+ // and can only contain lowercase letters a-z, digits 0-9, underscores _, dashes -, asterisks *, and
+ // forward slashes /.
+ Key string
+
+ // Value is an opaque string up to 256 characters printable ASCII RFC0020 characters (i.e., the
+ // range 0x20 to 0x7E) except comma , and =.
+ Value string
+}
+
+// Entries returns a slice of Entry.
+func (ts *Tracestate) Entries() []Entry {
+ if ts == nil {
+ return nil
+ }
+ return ts.entries
+}
+
+func (ts *Tracestate) remove(key string) *Entry {
+ for index, entry := range ts.entries {
+ if entry.Key == key {
+ ts.entries = append(ts.entries[:index], ts.entries[index+1:]...)
+ return &entry
+ }
+ }
+ return nil
+}
+
+func (ts *Tracestate) add(entries []Entry) error {
+ for _, entry := range entries {
+ ts.remove(entry.Key)
+ }
+ if len(ts.entries)+len(entries) > maxKeyValuePairs {
+ return fmt.Errorf("adding %d key-value pairs to current %d pairs exceeds the limit of %d",
+ len(entries), len(ts.entries), maxKeyValuePairs)
+ }
+ ts.entries = append(entries, ts.entries...)
+ return nil
+}
+
+func isValid(entry Entry) bool {
+ return keyValidationRegExp.MatchString(entry.Key) &&
+ valueValidationRegExp.MatchString(entry.Value)
+}
+
+func containsDuplicateKey(entries ...Entry) (string, bool) {
+ keyMap := make(map[string]int)
+ for _, entry := range entries {
+ if _, ok := keyMap[entry.Key]; ok {
+ return entry.Key, true
+ }
+ keyMap[entry.Key] = 1
+ }
+ return "", false
+}
+
+func areEntriesValid(entries ...Entry) (*Entry, bool) {
+ for _, entry := range entries {
+ if !isValid(entry) {
+ return &entry, false
+ }
+ }
+ return nil, true
+}
+
+// New creates a Tracestate object from a parent and/or entries (key-value pair).
+// Entries from the parent are copied if present. The entries passed to this function
+// are inserted in front of those copied from the parent. If an entry copied from the
+// parent contains the same key as one of the entry in entries then the entry copied
+// from the parent is removed. See add func.
+//
+// An error is returned with nil Tracestate if
+// 1. one or more entry in entries is invalid.
+// 2. two or more entries in the input entries have the same key.
+// 3. the number of entries combined from the parent and the input entries exceeds maxKeyValuePairs.
+// (duplicate entry is counted only once).
+func New(parent *Tracestate, entries ...Entry) (*Tracestate, error) {
+ if parent == nil && len(entries) == 0 {
+ return nil, nil
+ }
+ if entry, ok := areEntriesValid(entries...); !ok {
+ return nil, fmt.Errorf("key-value pair {%s, %s} is invalid", entry.Key, entry.Value)
+ }
+
+ if key, duplicate := containsDuplicateKey(entries...); duplicate {
+ return nil, fmt.Errorf("contains duplicate keys (%s)", key)
+ }
+
+ tracestate := Tracestate{}
+
+ if parent != nil && len(parent.entries) > 0 {
+ tracestate.entries = append([]Entry{}, parent.entries...)
+ }
+
+ err := tracestate.add(entries)
+ if err != nil {
+ return nil, err
+ }
+ return &tracestate, nil
+}
diff --git a/vendor/golang.org/x/net/context/ctxhttp/ctxhttp.go b/vendor/golang.org/x/net/context/ctxhttp/ctxhttp.go
new file mode 100644
index 000000000..606cf1f97
--- /dev/null
+++ b/vendor/golang.org/x/net/context/ctxhttp/ctxhttp.go
@@ -0,0 +1,74 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build go1.7
+
+// Package ctxhttp provides helper functions for performing context-aware HTTP requests.
+package ctxhttp // import "golang.org/x/net/context/ctxhttp"
+
+import (
+ "io"
+ "net/http"
+ "net/url"
+ "strings"
+
+ "golang.org/x/net/context"
+)
+
+// Do sends an HTTP request with the provided http.Client and returns
+// an HTTP response.
+//
+// If the client is nil, http.DefaultClient is used.
+//
+// The provided ctx must be non-nil. If it is canceled or times out,
+// ctx.Err() will be returned.
+func Do(ctx context.Context, client *http.Client, req *http.Request) (*http.Response, error) {
+ if client == nil {
+ client = http.DefaultClient
+ }
+ resp, err := client.Do(req.WithContext(ctx))
+ // If we got an error, and the context has been canceled,
+ // the context's error is probably more useful.
+ if err != nil {
+ select {
+ case <-ctx.Done():
+ err = ctx.Err()
+ default:
+ }
+ }
+ return resp, err
+}
+
+// Get issues a GET request via the Do function.
+func Get(ctx context.Context, client *http.Client, url string) (*http.Response, error) {
+ req, err := http.NewRequest("GET", url, nil)
+ if err != nil {
+ return nil, err
+ }
+ return Do(ctx, client, req)
+}
+
+// Head issues a HEAD request via the Do function.
+func Head(ctx context.Context, client *http.Client, url string) (*http.Response, error) {
+ req, err := http.NewRequest("HEAD", url, nil)
+ if err != nil {
+ return nil, err
+ }
+ return Do(ctx, client, req)
+}
+
+// Post issues a POST request via the Do function.
+func Post(ctx context.Context, client *http.Client, url string, bodyType string, body io.Reader) (*http.Response, error) {
+ req, err := http.NewRequest("POST", url, body)
+ if err != nil {
+ return nil, err
+ }
+ req.Header.Set("Content-Type", bodyType)
+ return Do(ctx, client, req)
+}
+
+// PostForm issues a POST request via the Do function.
+func PostForm(ctx context.Context, client *http.Client, url string, data url.Values) (*http.Response, error) {
+ return Post(ctx, client, url, "application/x-www-form-urlencoded", strings.NewReader(data.Encode()))
+}
diff --git a/vendor/golang.org/x/net/context/ctxhttp/ctxhttp_pre17.go b/vendor/golang.org/x/net/context/ctxhttp/ctxhttp_pre17.go
new file mode 100644
index 000000000..926870cc2
--- /dev/null
+++ b/vendor/golang.org/x/net/context/ctxhttp/ctxhttp_pre17.go
@@ -0,0 +1,147 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !go1.7
+
+package ctxhttp // import "golang.org/x/net/context/ctxhttp"
+
+import (
+ "io"
+ "net/http"
+ "net/url"
+ "strings"
+
+ "golang.org/x/net/context"
+)
+
+func nop() {}
+
+var (
+ testHookContextDoneBeforeHeaders = nop
+ testHookDoReturned = nop
+ testHookDidBodyClose = nop
+)
+
+// Do sends an HTTP request with the provided http.Client and returns an HTTP response.
+// If the client is nil, http.DefaultClient is used.
+// If the context is canceled or times out, ctx.Err() will be returned.
+func Do(ctx context.Context, client *http.Client, req *http.Request) (*http.Response, error) {
+ if client == nil {
+ client = http.DefaultClient
+ }
+
+ // TODO(djd): Respect any existing value of req.Cancel.
+ cancel := make(chan struct{})
+ req.Cancel = cancel
+
+ type responseAndError struct {
+ resp *http.Response
+ err error
+ }
+ result := make(chan responseAndError, 1)
+
+ // Make local copies of test hooks closed over by goroutines below.
+ // Prevents data races in tests.
+ testHookDoReturned := testHookDoReturned
+ testHookDidBodyClose := testHookDidBodyClose
+
+ go func() {
+ resp, err := client.Do(req)
+ testHookDoReturned()
+ result <- responseAndError{resp, err}
+ }()
+
+ var resp *http.Response
+
+ select {
+ case <-ctx.Done():
+ testHookContextDoneBeforeHeaders()
+ close(cancel)
+ // Clean up after the goroutine calling client.Do:
+ go func() {
+ if r := <-result; r.resp != nil {
+ testHookDidBodyClose()
+ r.resp.Body.Close()
+ }
+ }()
+ return nil, ctx.Err()
+ case r := <-result:
+ var err error
+ resp, err = r.resp, r.err
+ if err != nil {
+ return resp, err
+ }
+ }
+
+ c := make(chan struct{})
+ go func() {
+ select {
+ case <-ctx.Done():
+ close(cancel)
+ case <-c:
+ // The response's Body is closed.
+ }
+ }()
+ resp.Body = &notifyingReader{resp.Body, c}
+
+ return resp, nil
+}
+
+// Get issues a GET request via the Do function.
+func Get(ctx context.Context, client *http.Client, url string) (*http.Response, error) {
+ req, err := http.NewRequest("GET", url, nil)
+ if err != nil {
+ return nil, err
+ }
+ return Do(ctx, client, req)
+}
+
+// Head issues a HEAD request via the Do function.
+func Head(ctx context.Context, client *http.Client, url string) (*http.Response, error) {
+ req, err := http.NewRequest("HEAD", url, nil)
+ if err != nil {
+ return nil, err
+ }
+ return Do(ctx, client, req)
+}
+
+// Post issues a POST request via the Do function.
+func Post(ctx context.Context, client *http.Client, url string, bodyType string, body io.Reader) (*http.Response, error) {
+ req, err := http.NewRequest("POST", url, body)
+ if err != nil {
+ return nil, err
+ }
+ req.Header.Set("Content-Type", bodyType)
+ return Do(ctx, client, req)
+}
+
+// PostForm issues a POST request via the Do function.
+func PostForm(ctx context.Context, client *http.Client, url string, data url.Values) (*http.Response, error) {
+ return Post(ctx, client, url, "application/x-www-form-urlencoded", strings.NewReader(data.Encode()))
+}
+
+// notifyingReader is an io.ReadCloser that closes the notify channel after
+// Close is called or a Read fails on the underlying ReadCloser.
+type notifyingReader struct {
+ io.ReadCloser
+ notify chan<- struct{}
+}
+
+func (r *notifyingReader) Read(p []byte) (int, error) {
+ n, err := r.ReadCloser.Read(p)
+ if err != nil && r.notify != nil {
+ close(r.notify)
+ r.notify = nil
+ }
+ return n, err
+}
+
+func (r *notifyingReader) Close() error {
+ err := r.ReadCloser.Close()
+ if r.notify != nil {
+ close(r.notify)
+ r.notify = nil
+ }
+ return err
+}
diff --git a/vendor/golang.org/x/net/http/httpguts/guts.go b/vendor/golang.org/x/net/http/httpguts/guts.go
new file mode 100644
index 000000000..e6cd0ced3
--- /dev/null
+++ b/vendor/golang.org/x/net/http/httpguts/guts.go
@@ -0,0 +1,50 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package httpguts provides functions implementing various details
+// of the HTTP specification.
+//
+// This package is shared by the standard library (which vendors it)
+// and x/net/http2. It comes with no API stability promise.
+package httpguts
+
+import (
+ "net/textproto"
+ "strings"
+)
+
+// ValidTrailerHeader reports whether name is a valid header field name to appear
+// in trailers.
+// See RFC 7230, Section 4.1.2
+func ValidTrailerHeader(name string) bool {
+ name = textproto.CanonicalMIMEHeaderKey(name)
+ if strings.HasPrefix(name, "If-") || badTrailer[name] {
+ return false
+ }
+ return true
+}
+
+var badTrailer = map[string]bool{
+ "Authorization": true,
+ "Cache-Control": true,
+ "Connection": true,
+ "Content-Encoding": true,
+ "Content-Length": true,
+ "Content-Range": true,
+ "Content-Type": true,
+ "Expect": true,
+ "Host": true,
+ "Keep-Alive": true,
+ "Max-Forwards": true,
+ "Pragma": true,
+ "Proxy-Authenticate": true,
+ "Proxy-Authorization": true,
+ "Proxy-Connection": true,
+ "Range": true,
+ "Realm": true,
+ "Te": true,
+ "Trailer": true,
+ "Transfer-Encoding": true,
+ "Www-Authenticate": true,
+}
diff --git a/vendor/golang.org/x/net/http/httpguts/httplex.go b/vendor/golang.org/x/net/http/httpguts/httplex.go
new file mode 100644
index 000000000..e7de24ee6
--- /dev/null
+++ b/vendor/golang.org/x/net/http/httpguts/httplex.go
@@ -0,0 +1,346 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package httpguts
+
+import (
+ "net"
+ "strings"
+ "unicode/utf8"
+
+ "golang.org/x/net/idna"
+)
+
+var isTokenTable = [127]bool{
+ '!': true,
+ '#': true,
+ '$': true,
+ '%': true,
+ '&': true,
+ '\'': true,
+ '*': true,
+ '+': true,
+ '-': true,
+ '.': true,
+ '0': true,
+ '1': true,
+ '2': true,
+ '3': true,
+ '4': true,
+ '5': true,
+ '6': true,
+ '7': true,
+ '8': true,
+ '9': true,
+ 'A': true,
+ 'B': true,
+ 'C': true,
+ 'D': true,
+ 'E': true,
+ 'F': true,
+ 'G': true,
+ 'H': true,
+ 'I': true,
+ 'J': true,
+ 'K': true,
+ 'L': true,
+ 'M': true,
+ 'N': true,
+ 'O': true,
+ 'P': true,
+ 'Q': true,
+ 'R': true,
+ 'S': true,
+ 'T': true,
+ 'U': true,
+ 'W': true,
+ 'V': true,
+ 'X': true,
+ 'Y': true,
+ 'Z': true,
+ '^': true,
+ '_': true,
+ '`': true,
+ 'a': true,
+ 'b': true,
+ 'c': true,
+ 'd': true,
+ 'e': true,
+ 'f': true,
+ 'g': true,
+ 'h': true,
+ 'i': true,
+ 'j': true,
+ 'k': true,
+ 'l': true,
+ 'm': true,
+ 'n': true,
+ 'o': true,
+ 'p': true,
+ 'q': true,
+ 'r': true,
+ 's': true,
+ 't': true,
+ 'u': true,
+ 'v': true,
+ 'w': true,
+ 'x': true,
+ 'y': true,
+ 'z': true,
+ '|': true,
+ '~': true,
+}
+
+func IsTokenRune(r rune) bool {
+ i := int(r)
+ return i < len(isTokenTable) && isTokenTable[i]
+}
+
+func isNotToken(r rune) bool {
+ return !IsTokenRune(r)
+}
+
+// HeaderValuesContainsToken reports whether any string in values
+// contains the provided token, ASCII case-insensitively.
+func HeaderValuesContainsToken(values []string, token string) bool {
+ for _, v := range values {
+ if headerValueContainsToken(v, token) {
+ return true
+ }
+ }
+ return false
+}
+
+// isOWS reports whether b is an optional whitespace byte, as defined
+// by RFC 7230 section 3.2.3.
+func isOWS(b byte) bool { return b == ' ' || b == '\t' }
+
+// trimOWS returns x with all optional whitespace removes from the
+// beginning and end.
+func trimOWS(x string) string {
+ // TODO: consider using strings.Trim(x, " \t") instead,
+ // if and when it's fast enough. See issue 10292.
+ // But this ASCII-only code will probably always beat UTF-8
+ // aware code.
+ for len(x) > 0 && isOWS(x[0]) {
+ x = x[1:]
+ }
+ for len(x) > 0 && isOWS(x[len(x)-1]) {
+ x = x[:len(x)-1]
+ }
+ return x
+}
+
+// headerValueContainsToken reports whether v (assumed to be a
+// 0#element, in the ABNF extension described in RFC 7230 section 7)
+// contains token amongst its comma-separated tokens, ASCII
+// case-insensitively.
+func headerValueContainsToken(v string, token string) bool {
+ v = trimOWS(v)
+ if comma := strings.IndexByte(v, ','); comma != -1 {
+ return tokenEqual(trimOWS(v[:comma]), token) || headerValueContainsToken(v[comma+1:], token)
+ }
+ return tokenEqual(v, token)
+}
+
+// lowerASCII returns the ASCII lowercase version of b.
+func lowerASCII(b byte) byte {
+ if 'A' <= b && b <= 'Z' {
+ return b + ('a' - 'A')
+ }
+ return b
+}
+
+// tokenEqual reports whether t1 and t2 are equal, ASCII case-insensitively.
+func tokenEqual(t1, t2 string) bool {
+ if len(t1) != len(t2) {
+ return false
+ }
+ for i, b := range t1 {
+ if b >= utf8.RuneSelf {
+ // No UTF-8 or non-ASCII allowed in tokens.
+ return false
+ }
+ if lowerASCII(byte(b)) != lowerASCII(t2[i]) {
+ return false
+ }
+ }
+ return true
+}
+
+// isLWS reports whether b is linear white space, according
+// to http://www.w3.org/Protocols/rfc2616/rfc2616-sec2.html#sec2.2
+// LWS = [CRLF] 1*( SP | HT )
+func isLWS(b byte) bool { return b == ' ' || b == '\t' }
+
+// isCTL reports whether b is a control byte, according
+// to http://www.w3.org/Protocols/rfc2616/rfc2616-sec2.html#sec2.2
+// CTL = <any US-ASCII control character
+// (octets 0 - 31) and DEL (127)>
+func isCTL(b byte) bool {
+ const del = 0x7f // a CTL
+ return b < ' ' || b == del
+}
+
+// ValidHeaderFieldName reports whether v is a valid HTTP/1.x header name.
+// HTTP/2 imposes the additional restriction that uppercase ASCII
+// letters are not allowed.
+//
+// RFC 7230 says:
+// header-field = field-name ":" OWS field-value OWS
+// field-name = token
+// token = 1*tchar
+// tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+" / "-" / "." /
+// "^" / "_" / "`" / "|" / "~" / DIGIT / ALPHA
+func ValidHeaderFieldName(v string) bool {
+ if len(v) == 0 {
+ return false
+ }
+ for _, r := range v {
+ if !IsTokenRune(r) {
+ return false
+ }
+ }
+ return true
+}
+
+// ValidHostHeader reports whether h is a valid host header.
+func ValidHostHeader(h string) bool {
+ // The latest spec is actually this:
+ //
+ // http://tools.ietf.org/html/rfc7230#section-5.4
+ // Host = uri-host [ ":" port ]
+ //
+ // Where uri-host is:
+ // http://tools.ietf.org/html/rfc3986#section-3.2.2
+ //
+ // But we're going to be much more lenient for now and just
+ // search for any byte that's not a valid byte in any of those
+ // expressions.
+ for i := 0; i < len(h); i++ {
+ if !validHostByte[h[i]] {
+ return false
+ }
+ }
+ return true
+}
+
+// See the validHostHeader comment.
+var validHostByte = [256]bool{
+ '0': true, '1': true, '2': true, '3': true, '4': true, '5': true, '6': true, '7': true,
+ '8': true, '9': true,
+
+ 'a': true, 'b': true, 'c': true, 'd': true, 'e': true, 'f': true, 'g': true, 'h': true,
+ 'i': true, 'j': true, 'k': true, 'l': true, 'm': true, 'n': true, 'o': true, 'p': true,
+ 'q': true, 'r': true, 's': true, 't': true, 'u': true, 'v': true, 'w': true, 'x': true,
+ 'y': true, 'z': true,
+
+ 'A': true, 'B': true, 'C': true, 'D': true, 'E': true, 'F': true, 'G': true, 'H': true,
+ 'I': true, 'J': true, 'K': true, 'L': true, 'M': true, 'N': true, 'O': true, 'P': true,
+ 'Q': true, 'R': true, 'S': true, 'T': true, 'U': true, 'V': true, 'W': true, 'X': true,
+ 'Y': true, 'Z': true,
+
+ '!': true, // sub-delims
+ '$': true, // sub-delims
+ '%': true, // pct-encoded (and used in IPv6 zones)
+ '&': true, // sub-delims
+ '(': true, // sub-delims
+ ')': true, // sub-delims
+ '*': true, // sub-delims
+ '+': true, // sub-delims
+ ',': true, // sub-delims
+ '-': true, // unreserved
+ '.': true, // unreserved
+ ':': true, // IPv6address + Host expression's optional port
+ ';': true, // sub-delims
+ '=': true, // sub-delims
+ '[': true,
+ '\'': true, // sub-delims
+ ']': true,
+ '_': true, // unreserved
+ '~': true, // unreserved
+}
+
+// ValidHeaderFieldValue reports whether v is a valid "field-value" according to
+// http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2 :
+//
+// message-header = field-name ":" [ field-value ]
+// field-value = *( field-content | LWS )
+// field-content = <the OCTETs making up the field-value
+// and consisting of either *TEXT or combinations
+// of token, separators, and quoted-string>
+//
+// http://www.w3.org/Protocols/rfc2616/rfc2616-sec2.html#sec2.2 :
+//
+// TEXT = <any OCTET except CTLs,
+// but including LWS>
+// LWS = [CRLF] 1*( SP | HT )
+// CTL = <any US-ASCII control character
+// (octets 0 - 31) and DEL (127)>
+//
+// RFC 7230 says:
+// field-value = *( field-content / obs-fold )
+// obj-fold = N/A to http2, and deprecated
+// field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ]
+// field-vchar = VCHAR / obs-text
+// obs-text = %x80-FF
+// VCHAR = "any visible [USASCII] character"
+//
+// http2 further says: "Similarly, HTTP/2 allows header field values
+// that are not valid. While most of the values that can be encoded
+// will not alter header field parsing, carriage return (CR, ASCII
+// 0xd), line feed (LF, ASCII 0xa), and the zero character (NUL, ASCII
+// 0x0) might be exploited by an attacker if they are translated
+// verbatim. Any request or response that contains a character not
+// permitted in a header field value MUST be treated as malformed
+// (Section 8.1.2.6). Valid characters are defined by the
+// field-content ABNF rule in Section 3.2 of [RFC7230]."
+//
+// This function does not (yet?) properly handle the rejection of
+// strings that begin or end with SP or HTAB.
+func ValidHeaderFieldValue(v string) bool {
+ for i := 0; i < len(v); i++ {
+ b := v[i]
+ if isCTL(b) && !isLWS(b) {
+ return false
+ }
+ }
+ return true
+}
+
+func isASCII(s string) bool {
+ for i := 0; i < len(s); i++ {
+ if s[i] >= utf8.RuneSelf {
+ return false
+ }
+ }
+ return true
+}
+
+// PunycodeHostPort returns the IDNA Punycode version
+// of the provided "host" or "host:port" string.
+func PunycodeHostPort(v string) (string, error) {
+ if isASCII(v) {
+ return v, nil
+ }
+
+ host, port, err := net.SplitHostPort(v)
+ if err != nil {
+ // The input 'v' argument was just a "host" argument,
+ // without a port. This error should not be returned
+ // to the caller.
+ host = v
+ port = ""
+ }
+ host, err = idna.ToASCII(host)
+ if err != nil {
+ // Non-UTF-8? Not representable in Punycode, in any
+ // case.
+ return "", err
+ }
+ if port == "" {
+ return host, nil
+ }
+ return net.JoinHostPort(host, port), nil
+}
diff --git a/vendor/golang.org/x/net/http2/Dockerfile b/vendor/golang.org/x/net/http2/Dockerfile
new file mode 100644
index 000000000..53fc52579
--- /dev/null
+++ b/vendor/golang.org/x/net/http2/Dockerfile
@@ -0,0 +1,51 @@
+#
+# This Dockerfile builds a recent curl with HTTP/2 client support, using
+# a recent nghttp2 build.
+#
+# See the Makefile for how to tag it. If Docker and that image is found, the
+# Go tests use this curl binary for integration tests.
+#
+
+FROM ubuntu:trusty
+
+RUN apt-get update && \
+ apt-get upgrade -y && \
+ apt-get install -y git-core build-essential wget
+
+RUN apt-get install -y --no-install-recommends \
+ autotools-dev libtool pkg-config zlib1g-dev \
+ libcunit1-dev libssl-dev libxml2-dev libevent-dev \
+ automake autoconf
+
+# The list of packages nghttp2 recommends for h2load:
+RUN apt-get install -y --no-install-recommends make binutils \
+ autoconf automake autotools-dev \
+ libtool pkg-config zlib1g-dev libcunit1-dev libssl-dev libxml2-dev \
+ libev-dev libevent-dev libjansson-dev libjemalloc-dev \
+ cython python3.4-dev python-setuptools
+
+# Note: setting NGHTTP2_VER before the git clone, so an old git clone isn't cached:
+ENV NGHTTP2_VER 895da9a
+RUN cd /root && git clone https://github.com/tatsuhiro-t/nghttp2.git
+
+WORKDIR /root/nghttp2
+RUN git reset --hard $NGHTTP2_VER
+RUN autoreconf -i
+RUN automake
+RUN autoconf
+RUN ./configure
+RUN make
+RUN make install
+
+WORKDIR /root
+RUN wget http://curl.haxx.se/download/curl-7.45.0.tar.gz
+RUN tar -zxvf curl-7.45.0.tar.gz
+WORKDIR /root/curl-7.45.0
+RUN ./configure --with-ssl --with-nghttp2=/usr/local
+RUN make
+RUN make install
+RUN ldconfig
+
+CMD ["-h"]
+ENTRYPOINT ["/usr/local/bin/curl"]
+
diff --git a/vendor/golang.org/x/net/http2/Makefile b/vendor/golang.org/x/net/http2/Makefile
new file mode 100644
index 000000000..55fd826f7
--- /dev/null
+++ b/vendor/golang.org/x/net/http2/Makefile
@@ -0,0 +1,3 @@
+curlimage:
+ docker build -t gohttp2/curl .
+
diff --git a/vendor/golang.org/x/net/http2/README b/vendor/golang.org/x/net/http2/README
new file mode 100644
index 000000000..360d5aa37
--- /dev/null
+++ b/vendor/golang.org/x/net/http2/README
@@ -0,0 +1,20 @@
+This is a work-in-progress HTTP/2 implementation for Go.
+
+It will eventually live in the Go standard library and won't require
+any changes to your code to use. It will just be automatic.
+
+Status:
+
+* The server support is pretty good. A few things are missing
+ but are being worked on.
+* The client work has just started but shares a lot of code
+ is coming along much quicker.
+
+Docs are at https://godoc.org/golang.org/x/net/http2
+
+Demo test server at https://http2.golang.org/
+
+Help & bug reports welcome!
+
+Contributing: https://golang.org/doc/contribute.html
+Bugs: https://golang.org/issue/new?title=x/net/http2:+
diff --git a/vendor/golang.org/x/net/http2/ciphers.go b/vendor/golang.org/x/net/http2/ciphers.go
new file mode 100644
index 000000000..c9a0cf3b4
--- /dev/null
+++ b/vendor/golang.org/x/net/http2/ciphers.go
@@ -0,0 +1,641 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package http2
+
+// A list of the possible cipher suite ids. Taken from
+// https://www.iana.org/assignments/tls-parameters/tls-parameters.txt
+
+const (
+ cipher_TLS_NULL_WITH_NULL_NULL uint16 = 0x0000
+ cipher_TLS_RSA_WITH_NULL_MD5 uint16 = 0x0001
+ cipher_TLS_RSA_WITH_NULL_SHA uint16 = 0x0002
+ cipher_TLS_RSA_EXPORT_WITH_RC4_40_MD5 uint16 = 0x0003
+ cipher_TLS_RSA_WITH_RC4_128_MD5 uint16 = 0x0004
+ cipher_TLS_RSA_WITH_RC4_128_SHA uint16 = 0x0005
+ cipher_TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 uint16 = 0x0006
+ cipher_TLS_RSA_WITH_IDEA_CBC_SHA uint16 = 0x0007
+ cipher_TLS_RSA_EXPORT_WITH_DES40_CBC_SHA uint16 = 0x0008
+ cipher_TLS_RSA_WITH_DES_CBC_SHA uint16 = 0x0009
+ cipher_TLS_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0x000A
+ cipher_TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA uint16 = 0x000B
+ cipher_TLS_DH_DSS_WITH_DES_CBC_SHA uint16 = 0x000C
+ cipher_TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA uint16 = 0x000D
+ cipher_TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA uint16 = 0x000E
+ cipher_TLS_DH_RSA_WITH_DES_CBC_SHA uint16 = 0x000F
+ cipher_TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0x0010
+ cipher_TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA uint16 = 0x0011
+ cipher_TLS_DHE_DSS_WITH_DES_CBC_SHA uint16 = 0x0012
+ cipher_TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA uint16 = 0x0013
+ cipher_TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA uint16 = 0x0014
+ cipher_TLS_DHE_RSA_WITH_DES_CBC_SHA uint16 = 0x0015
+ cipher_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0x0016
+ cipher_TLS_DH_anon_EXPORT_WITH_RC4_40_MD5 uint16 = 0x0017
+ cipher_TLS_DH_anon_WITH_RC4_128_MD5 uint16 = 0x0018
+ cipher_TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA uint16 = 0x0019
+ cipher_TLS_DH_anon_WITH_DES_CBC_SHA uint16 = 0x001A
+ cipher_TLS_DH_anon_WITH_3DES_EDE_CBC_SHA uint16 = 0x001B
+ // Reserved uint16 = 0x001C-1D
+ cipher_TLS_KRB5_WITH_DES_CBC_SHA uint16 = 0x001E
+ cipher_TLS_KRB5_WITH_3DES_EDE_CBC_SHA uint16 = 0x001F
+ cipher_TLS_KRB5_WITH_RC4_128_SHA uint16 = 0x0020
+ cipher_TLS_KRB5_WITH_IDEA_CBC_SHA uint16 = 0x0021
+ cipher_TLS_KRB5_WITH_DES_CBC_MD5 uint16 = 0x0022
+ cipher_TLS_KRB5_WITH_3DES_EDE_CBC_MD5 uint16 = 0x0023
+ cipher_TLS_KRB5_WITH_RC4_128_MD5 uint16 = 0x0024
+ cipher_TLS_KRB5_WITH_IDEA_CBC_MD5 uint16 = 0x0025
+ cipher_TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA uint16 = 0x0026
+ cipher_TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA uint16 = 0x0027
+ cipher_TLS_KRB5_EXPORT_WITH_RC4_40_SHA uint16 = 0x0028
+ cipher_TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5 uint16 = 0x0029
+ cipher_TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5 uint16 = 0x002A
+ cipher_TLS_KRB5_EXPORT_WITH_RC4_40_MD5 uint16 = 0x002B
+ cipher_TLS_PSK_WITH_NULL_SHA uint16 = 0x002C
+ cipher_TLS_DHE_PSK_WITH_NULL_SHA uint16 = 0x002D
+ cipher_TLS_RSA_PSK_WITH_NULL_SHA uint16 = 0x002E
+ cipher_TLS_RSA_WITH_AES_128_CBC_SHA uint16 = 0x002F
+ cipher_TLS_DH_DSS_WITH_AES_128_CBC_SHA uint16 = 0x0030
+ cipher_TLS_DH_RSA_WITH_AES_128_CBC_SHA uint16 = 0x0031
+ cipher_TLS_DHE_DSS_WITH_AES_128_CBC_SHA uint16 = 0x0032
+ cipher_TLS_DHE_RSA_WITH_AES_128_CBC_SHA uint16 = 0x0033
+ cipher_TLS_DH_anon_WITH_AES_128_CBC_SHA uint16 = 0x0034
+ cipher_TLS_RSA_WITH_AES_256_CBC_SHA uint16 = 0x0035
+ cipher_TLS_DH_DSS_WITH_AES_256_CBC_SHA uint16 = 0x0036
+ cipher_TLS_DH_RSA_WITH_AES_256_CBC_SHA uint16 = 0x0037
+ cipher_TLS_DHE_DSS_WITH_AES_256_CBC_SHA uint16 = 0x0038
+ cipher_TLS_DHE_RSA_WITH_AES_256_CBC_SHA uint16 = 0x0039
+ cipher_TLS_DH_anon_WITH_AES_256_CBC_SHA uint16 = 0x003A
+ cipher_TLS_RSA_WITH_NULL_SHA256 uint16 = 0x003B
+ cipher_TLS_RSA_WITH_AES_128_CBC_SHA256 uint16 = 0x003C
+ cipher_TLS_RSA_WITH_AES_256_CBC_SHA256 uint16 = 0x003D
+ cipher_TLS_DH_DSS_WITH_AES_128_CBC_SHA256 uint16 = 0x003E
+ cipher_TLS_DH_RSA_WITH_AES_128_CBC_SHA256 uint16 = 0x003F
+ cipher_TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 uint16 = 0x0040
+ cipher_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA uint16 = 0x0041
+ cipher_TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA uint16 = 0x0042
+ cipher_TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA uint16 = 0x0043
+ cipher_TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA uint16 = 0x0044
+ cipher_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA uint16 = 0x0045
+ cipher_TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA uint16 = 0x0046
+ // Reserved uint16 = 0x0047-4F
+ // Reserved uint16 = 0x0050-58
+ // Reserved uint16 = 0x0059-5C
+ // Unassigned uint16 = 0x005D-5F
+ // Reserved uint16 = 0x0060-66
+ cipher_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 uint16 = 0x0067
+ cipher_TLS_DH_DSS_WITH_AES_256_CBC_SHA256 uint16 = 0x0068
+ cipher_TLS_DH_RSA_WITH_AES_256_CBC_SHA256 uint16 = 0x0069
+ cipher_TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 uint16 = 0x006A
+ cipher_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 uint16 = 0x006B
+ cipher_TLS_DH_anon_WITH_AES_128_CBC_SHA256 uint16 = 0x006C
+ cipher_TLS_DH_anon_WITH_AES_256_CBC_SHA256 uint16 = 0x006D
+ // Unassigned uint16 = 0x006E-83
+ cipher_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA uint16 = 0x0084
+ cipher_TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA uint16 = 0x0085
+ cipher_TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA uint16 = 0x0086
+ cipher_TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA uint16 = 0x0087
+ cipher_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA uint16 = 0x0088
+ cipher_TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA uint16 = 0x0089
+ cipher_TLS_PSK_WITH_RC4_128_SHA uint16 = 0x008A
+ cipher_TLS_PSK_WITH_3DES_EDE_CBC_SHA uint16 = 0x008B
+ cipher_TLS_PSK_WITH_AES_128_CBC_SHA uint16 = 0x008C
+ cipher_TLS_PSK_WITH_AES_256_CBC_SHA uint16 = 0x008D
+ cipher_TLS_DHE_PSK_WITH_RC4_128_SHA uint16 = 0x008E
+ cipher_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA uint16 = 0x008F
+ cipher_TLS_DHE_PSK_WITH_AES_128_CBC_SHA uint16 = 0x0090
+ cipher_TLS_DHE_PSK_WITH_AES_256_CBC_SHA uint16 = 0x0091
+ cipher_TLS_RSA_PSK_WITH_RC4_128_SHA uint16 = 0x0092
+ cipher_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA uint16 = 0x0093
+ cipher_TLS_RSA_PSK_WITH_AES_128_CBC_SHA uint16 = 0x0094
+ cipher_TLS_RSA_PSK_WITH_AES_256_CBC_SHA uint16 = 0x0095
+ cipher_TLS_RSA_WITH_SEED_CBC_SHA uint16 = 0x0096
+ cipher_TLS_DH_DSS_WITH_SEED_CBC_SHA uint16 = 0x0097
+ cipher_TLS_DH_RSA_WITH_SEED_CBC_SHA uint16 = 0x0098
+ cipher_TLS_DHE_DSS_WITH_SEED_CBC_SHA uint16 = 0x0099
+ cipher_TLS_DHE_RSA_WITH_SEED_CBC_SHA uint16 = 0x009A
+ cipher_TLS_DH_anon_WITH_SEED_CBC_SHA uint16 = 0x009B
+ cipher_TLS_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0x009C
+ cipher_TLS_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0x009D
+ cipher_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0x009E
+ cipher_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0x009F
+ cipher_TLS_DH_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0x00A0
+ cipher_TLS_DH_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0x00A1
+ cipher_TLS_DHE_DSS_WITH_AES_128_GCM_SHA256 uint16 = 0x00A2
+ cipher_TLS_DHE_DSS_WITH_AES_256_GCM_SHA384 uint16 = 0x00A3
+ cipher_TLS_DH_DSS_WITH_AES_128_GCM_SHA256 uint16 = 0x00A4
+ cipher_TLS_DH_DSS_WITH_AES_256_GCM_SHA384 uint16 = 0x00A5
+ cipher_TLS_DH_anon_WITH_AES_128_GCM_SHA256 uint16 = 0x00A6
+ cipher_TLS_DH_anon_WITH_AES_256_GCM_SHA384 uint16 = 0x00A7
+ cipher_TLS_PSK_WITH_AES_128_GCM_SHA256 uint16 = 0x00A8
+ cipher_TLS_PSK_WITH_AES_256_GCM_SHA384 uint16 = 0x00A9
+ cipher_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 uint16 = 0x00AA
+ cipher_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 uint16 = 0x00AB
+ cipher_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 uint16 = 0x00AC
+ cipher_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 uint16 = 0x00AD
+ cipher_TLS_PSK_WITH_AES_128_CBC_SHA256 uint16 = 0x00AE
+ cipher_TLS_PSK_WITH_AES_256_CBC_SHA384 uint16 = 0x00AF
+ cipher_TLS_PSK_WITH_NULL_SHA256 uint16 = 0x00B0
+ cipher_TLS_PSK_WITH_NULL_SHA384 uint16 = 0x00B1
+ cipher_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 uint16 = 0x00B2
+ cipher_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 uint16 = 0x00B3
+ cipher_TLS_DHE_PSK_WITH_NULL_SHA256 uint16 = 0x00B4
+ cipher_TLS_DHE_PSK_WITH_NULL_SHA384 uint16 = 0x00B5
+ cipher_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 uint16 = 0x00B6
+ cipher_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 uint16 = 0x00B7
+ cipher_TLS_RSA_PSK_WITH_NULL_SHA256 uint16 = 0x00B8
+ cipher_TLS_RSA_PSK_WITH_NULL_SHA384 uint16 = 0x00B9
+ cipher_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0x00BA
+ cipher_TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0x00BB
+ cipher_TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0x00BC
+ cipher_TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0x00BD
+ cipher_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0x00BE
+ cipher_TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0x00BF
+ cipher_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 uint16 = 0x00C0
+ cipher_TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256 uint16 = 0x00C1
+ cipher_TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256 uint16 = 0x00C2
+ cipher_TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256 uint16 = 0x00C3
+ cipher_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 uint16 = 0x00C4
+ cipher_TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256 uint16 = 0x00C5
+ // Unassigned uint16 = 0x00C6-FE
+ cipher_TLS_EMPTY_RENEGOTIATION_INFO_SCSV uint16 = 0x00FF
+ // Unassigned uint16 = 0x01-55,*
+ cipher_TLS_FALLBACK_SCSV uint16 = 0x5600
+ // Unassigned uint16 = 0x5601 - 0xC000
+ cipher_TLS_ECDH_ECDSA_WITH_NULL_SHA uint16 = 0xC001
+ cipher_TLS_ECDH_ECDSA_WITH_RC4_128_SHA uint16 = 0xC002
+ cipher_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA uint16 = 0xC003
+ cipher_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA uint16 = 0xC004
+ cipher_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA uint16 = 0xC005
+ cipher_TLS_ECDHE_ECDSA_WITH_NULL_SHA uint16 = 0xC006
+ cipher_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA uint16 = 0xC007
+ cipher_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA uint16 = 0xC008
+ cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA uint16 = 0xC009
+ cipher_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA uint16 = 0xC00A
+ cipher_TLS_ECDH_RSA_WITH_NULL_SHA uint16 = 0xC00B
+ cipher_TLS_ECDH_RSA_WITH_RC4_128_SHA uint16 = 0xC00C
+ cipher_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0xC00D
+ cipher_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA uint16 = 0xC00E
+ cipher_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA uint16 = 0xC00F
+ cipher_TLS_ECDHE_RSA_WITH_NULL_SHA uint16 = 0xC010
+ cipher_TLS_ECDHE_RSA_WITH_RC4_128_SHA uint16 = 0xC011
+ cipher_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0xC012
+ cipher_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA uint16 = 0xC013
+ cipher_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA uint16 = 0xC014
+ cipher_TLS_ECDH_anon_WITH_NULL_SHA uint16 = 0xC015
+ cipher_TLS_ECDH_anon_WITH_RC4_128_SHA uint16 = 0xC016
+ cipher_TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA uint16 = 0xC017
+ cipher_TLS_ECDH_anon_WITH_AES_128_CBC_SHA uint16 = 0xC018
+ cipher_TLS_ECDH_anon_WITH_AES_256_CBC_SHA uint16 = 0xC019
+ cipher_TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA uint16 = 0xC01A
+ cipher_TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA uint16 = 0xC01B
+ cipher_TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA uint16 = 0xC01C
+ cipher_TLS_SRP_SHA_WITH_AES_128_CBC_SHA uint16 = 0xC01D
+ cipher_TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA uint16 = 0xC01E
+ cipher_TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA uint16 = 0xC01F
+ cipher_TLS_SRP_SHA_WITH_AES_256_CBC_SHA uint16 = 0xC020
+ cipher_TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA uint16 = 0xC021
+ cipher_TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA uint16 = 0xC022
+ cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 uint16 = 0xC023
+ cipher_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 uint16 = 0xC024
+ cipher_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 uint16 = 0xC025
+ cipher_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 uint16 = 0xC026
+ cipher_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 uint16 = 0xC027
+ cipher_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 uint16 = 0xC028
+ cipher_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 uint16 = 0xC029
+ cipher_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 uint16 = 0xC02A
+ cipher_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 uint16 = 0xC02B
+ cipher_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 uint16 = 0xC02C
+ cipher_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 uint16 = 0xC02D
+ cipher_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 uint16 = 0xC02E
+ cipher_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0xC02F
+ cipher_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0xC030
+ cipher_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 uint16 = 0xC031
+ cipher_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0xC032
+ cipher_TLS_ECDHE_PSK_WITH_RC4_128_SHA uint16 = 0xC033
+ cipher_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA uint16 = 0xC034
+ cipher_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA uint16 = 0xC035
+ cipher_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA uint16 = 0xC036
+ cipher_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 uint16 = 0xC037
+ cipher_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 uint16 = 0xC038
+ cipher_TLS_ECDHE_PSK_WITH_NULL_SHA uint16 = 0xC039
+ cipher_TLS_ECDHE_PSK_WITH_NULL_SHA256 uint16 = 0xC03A
+ cipher_TLS_ECDHE_PSK_WITH_NULL_SHA384 uint16 = 0xC03B
+ cipher_TLS_RSA_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC03C
+ cipher_TLS_RSA_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC03D
+ cipher_TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC03E
+ cipher_TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC03F
+ cipher_TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC040
+ cipher_TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC041
+ cipher_TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC042
+ cipher_TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC043
+ cipher_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC044
+ cipher_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC045
+ cipher_TLS_DH_anon_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC046
+ cipher_TLS_DH_anon_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC047
+ cipher_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC048
+ cipher_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC049
+ cipher_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC04A
+ cipher_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC04B
+ cipher_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC04C
+ cipher_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC04D
+ cipher_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC04E
+ cipher_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC04F
+ cipher_TLS_RSA_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC050
+ cipher_TLS_RSA_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC051
+ cipher_TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC052
+ cipher_TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC053
+ cipher_TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC054
+ cipher_TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC055
+ cipher_TLS_DHE_DSS_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC056
+ cipher_TLS_DHE_DSS_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC057
+ cipher_TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC058
+ cipher_TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC059
+ cipher_TLS_DH_anon_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC05A
+ cipher_TLS_DH_anon_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC05B
+ cipher_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC05C
+ cipher_TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC05D
+ cipher_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC05E
+ cipher_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC05F
+ cipher_TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC060
+ cipher_TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC061
+ cipher_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC062
+ cipher_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC063
+ cipher_TLS_PSK_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC064
+ cipher_TLS_PSK_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC065
+ cipher_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC066
+ cipher_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC067
+ cipher_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC068
+ cipher_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC069
+ cipher_TLS_PSK_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC06A
+ cipher_TLS_PSK_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC06B
+ cipher_TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC06C
+ cipher_TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC06D
+ cipher_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256 uint16 = 0xC06E
+ cipher_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384 uint16 = 0xC06F
+ cipher_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256 uint16 = 0xC070
+ cipher_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 uint16 = 0xC071
+ cipher_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0xC072
+ cipher_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 uint16 = 0xC073
+ cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0xC074
+ cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 uint16 = 0xC075
+ cipher_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0xC076
+ cipher_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 uint16 = 0xC077
+ cipher_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0xC078
+ cipher_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 uint16 = 0xC079
+ cipher_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC07A
+ cipher_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC07B
+ cipher_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC07C
+ cipher_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC07D
+ cipher_TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC07E
+ cipher_TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC07F
+ cipher_TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC080
+ cipher_TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC081
+ cipher_TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC082
+ cipher_TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC083
+ cipher_TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC084
+ cipher_TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC085
+ cipher_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC086
+ cipher_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC087
+ cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC088
+ cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC089
+ cipher_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC08A
+ cipher_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC08B
+ cipher_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC08C
+ cipher_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC08D
+ cipher_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC08E
+ cipher_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC08F
+ cipher_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC090
+ cipher_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC091
+ cipher_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 uint16 = 0xC092
+ cipher_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 uint16 = 0xC093
+ cipher_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0xC094
+ cipher_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 uint16 = 0xC095
+ cipher_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0xC096
+ cipher_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 uint16 = 0xC097
+ cipher_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0xC098
+ cipher_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 uint16 = 0xC099
+ cipher_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 uint16 = 0xC09A
+ cipher_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 uint16 = 0xC09B
+ cipher_TLS_RSA_WITH_AES_128_CCM uint16 = 0xC09C
+ cipher_TLS_RSA_WITH_AES_256_CCM uint16 = 0xC09D
+ cipher_TLS_DHE_RSA_WITH_AES_128_CCM uint16 = 0xC09E
+ cipher_TLS_DHE_RSA_WITH_AES_256_CCM uint16 = 0xC09F
+ cipher_TLS_RSA_WITH_AES_128_CCM_8 uint16 = 0xC0A0
+ cipher_TLS_RSA_WITH_AES_256_CCM_8 uint16 = 0xC0A1
+ cipher_TLS_DHE_RSA_WITH_AES_128_CCM_8 uint16 = 0xC0A2
+ cipher_TLS_DHE_RSA_WITH_AES_256_CCM_8 uint16 = 0xC0A3
+ cipher_TLS_PSK_WITH_AES_128_CCM uint16 = 0xC0A4
+ cipher_TLS_PSK_WITH_AES_256_CCM uint16 = 0xC0A5
+ cipher_TLS_DHE_PSK_WITH_AES_128_CCM uint16 = 0xC0A6
+ cipher_TLS_DHE_PSK_WITH_AES_256_CCM uint16 = 0xC0A7
+ cipher_TLS_PSK_WITH_AES_128_CCM_8 uint16 = 0xC0A8
+ cipher_TLS_PSK_WITH_AES_256_CCM_8 uint16 = 0xC0A9
+ cipher_TLS_PSK_DHE_WITH_AES_128_CCM_8 uint16 = 0xC0AA
+ cipher_TLS_PSK_DHE_WITH_AES_256_CCM_8 uint16 = 0xC0AB
+ cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CCM uint16 = 0xC0AC
+ cipher_TLS_ECDHE_ECDSA_WITH_AES_256_CCM uint16 = 0xC0AD
+ cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 uint16 = 0xC0AE
+ cipher_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 uint16 = 0xC0AF
+ // Unassigned uint16 = 0xC0B0-FF
+ // Unassigned uint16 = 0xC1-CB,*
+ // Unassigned uint16 = 0xCC00-A7
+ cipher_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xCCA8
+ cipher_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xCCA9
+ cipher_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xCCAA
+ cipher_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xCCAB
+ cipher_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xCCAC
+ cipher_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xCCAD
+ cipher_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0xCCAE
+)
+
+// isBadCipher reports whether the cipher is blacklisted by the HTTP/2 spec.
+// References:
+// https://tools.ietf.org/html/rfc7540#appendix-A
+// Reject cipher suites from Appendix A.
+// "This list includes those cipher suites that do not
+// offer an ephemeral key exchange and those that are
+// based on the TLS null, stream or block cipher type"
+func isBadCipher(cipher uint16) bool {
+ switch cipher {
+ case cipher_TLS_NULL_WITH_NULL_NULL,
+ cipher_TLS_RSA_WITH_NULL_MD5,
+ cipher_TLS_RSA_WITH_NULL_SHA,
+ cipher_TLS_RSA_EXPORT_WITH_RC4_40_MD5,
+ cipher_TLS_RSA_WITH_RC4_128_MD5,
+ cipher_TLS_RSA_WITH_RC4_128_SHA,
+ cipher_TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5,
+ cipher_TLS_RSA_WITH_IDEA_CBC_SHA,
+ cipher_TLS_RSA_EXPORT_WITH_DES40_CBC_SHA,
+ cipher_TLS_RSA_WITH_DES_CBC_SHA,
+ cipher_TLS_RSA_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA,
+ cipher_TLS_DH_DSS_WITH_DES_CBC_SHA,
+ cipher_TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA,
+ cipher_TLS_DH_RSA_WITH_DES_CBC_SHA,
+ cipher_TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA,
+ cipher_TLS_DHE_DSS_WITH_DES_CBC_SHA,
+ cipher_TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA,
+ cipher_TLS_DHE_RSA_WITH_DES_CBC_SHA,
+ cipher_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_DH_anon_EXPORT_WITH_RC4_40_MD5,
+ cipher_TLS_DH_anon_WITH_RC4_128_MD5,
+ cipher_TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA,
+ cipher_TLS_DH_anon_WITH_DES_CBC_SHA,
+ cipher_TLS_DH_anon_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_KRB5_WITH_DES_CBC_SHA,
+ cipher_TLS_KRB5_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_KRB5_WITH_RC4_128_SHA,
+ cipher_TLS_KRB5_WITH_IDEA_CBC_SHA,
+ cipher_TLS_KRB5_WITH_DES_CBC_MD5,
+ cipher_TLS_KRB5_WITH_3DES_EDE_CBC_MD5,
+ cipher_TLS_KRB5_WITH_RC4_128_MD5,
+ cipher_TLS_KRB5_WITH_IDEA_CBC_MD5,
+ cipher_TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA,
+ cipher_TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA,
+ cipher_TLS_KRB5_EXPORT_WITH_RC4_40_SHA,
+ cipher_TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5,
+ cipher_TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5,
+ cipher_TLS_KRB5_EXPORT_WITH_RC4_40_MD5,
+ cipher_TLS_PSK_WITH_NULL_SHA,
+ cipher_TLS_DHE_PSK_WITH_NULL_SHA,
+ cipher_TLS_RSA_PSK_WITH_NULL_SHA,
+ cipher_TLS_RSA_WITH_AES_128_CBC_SHA,
+ cipher_TLS_DH_DSS_WITH_AES_128_CBC_SHA,
+ cipher_TLS_DH_RSA_WITH_AES_128_CBC_SHA,
+ cipher_TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
+ cipher_TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
+ cipher_TLS_DH_anon_WITH_AES_128_CBC_SHA,
+ cipher_TLS_RSA_WITH_AES_256_CBC_SHA,
+ cipher_TLS_DH_DSS_WITH_AES_256_CBC_SHA,
+ cipher_TLS_DH_RSA_WITH_AES_256_CBC_SHA,
+ cipher_TLS_DHE_DSS_WITH_AES_256_CBC_SHA,
+ cipher_TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
+ cipher_TLS_DH_anon_WITH_AES_256_CBC_SHA,
+ cipher_TLS_RSA_WITH_NULL_SHA256,
+ cipher_TLS_RSA_WITH_AES_128_CBC_SHA256,
+ cipher_TLS_RSA_WITH_AES_256_CBC_SHA256,
+ cipher_TLS_DH_DSS_WITH_AES_128_CBC_SHA256,
+ cipher_TLS_DH_RSA_WITH_AES_128_CBC_SHA256,
+ cipher_TLS_DHE_DSS_WITH_AES_128_CBC_SHA256,
+ cipher_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA,
+ cipher_TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA,
+ cipher_TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA,
+ cipher_TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA,
+ cipher_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA,
+ cipher_TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA,
+ cipher_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,
+ cipher_TLS_DH_DSS_WITH_AES_256_CBC_SHA256,
+ cipher_TLS_DH_RSA_WITH_AES_256_CBC_SHA256,
+ cipher_TLS_DHE_DSS_WITH_AES_256_CBC_SHA256,
+ cipher_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,
+ cipher_TLS_DH_anon_WITH_AES_128_CBC_SHA256,
+ cipher_TLS_DH_anon_WITH_AES_256_CBC_SHA256,
+ cipher_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA,
+ cipher_TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA,
+ cipher_TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA,
+ cipher_TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA,
+ cipher_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA,
+ cipher_TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA,
+ cipher_TLS_PSK_WITH_RC4_128_SHA,
+ cipher_TLS_PSK_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_PSK_WITH_AES_128_CBC_SHA,
+ cipher_TLS_PSK_WITH_AES_256_CBC_SHA,
+ cipher_TLS_DHE_PSK_WITH_RC4_128_SHA,
+ cipher_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_DHE_PSK_WITH_AES_128_CBC_SHA,
+ cipher_TLS_DHE_PSK_WITH_AES_256_CBC_SHA,
+ cipher_TLS_RSA_PSK_WITH_RC4_128_SHA,
+ cipher_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_RSA_PSK_WITH_AES_128_CBC_SHA,
+ cipher_TLS_RSA_PSK_WITH_AES_256_CBC_SHA,
+ cipher_TLS_RSA_WITH_SEED_CBC_SHA,
+ cipher_TLS_DH_DSS_WITH_SEED_CBC_SHA,
+ cipher_TLS_DH_RSA_WITH_SEED_CBC_SHA,
+ cipher_TLS_DHE_DSS_WITH_SEED_CBC_SHA,
+ cipher_TLS_DHE_RSA_WITH_SEED_CBC_SHA,
+ cipher_TLS_DH_anon_WITH_SEED_CBC_SHA,
+ cipher_TLS_RSA_WITH_AES_128_GCM_SHA256,
+ cipher_TLS_RSA_WITH_AES_256_GCM_SHA384,
+ cipher_TLS_DH_RSA_WITH_AES_128_GCM_SHA256,
+ cipher_TLS_DH_RSA_WITH_AES_256_GCM_SHA384,
+ cipher_TLS_DH_DSS_WITH_AES_128_GCM_SHA256,
+ cipher_TLS_DH_DSS_WITH_AES_256_GCM_SHA384,
+ cipher_TLS_DH_anon_WITH_AES_128_GCM_SHA256,
+ cipher_TLS_DH_anon_WITH_AES_256_GCM_SHA384,
+ cipher_TLS_PSK_WITH_AES_128_GCM_SHA256,
+ cipher_TLS_PSK_WITH_AES_256_GCM_SHA384,
+ cipher_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256,
+ cipher_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384,
+ cipher_TLS_PSK_WITH_AES_128_CBC_SHA256,
+ cipher_TLS_PSK_WITH_AES_256_CBC_SHA384,
+ cipher_TLS_PSK_WITH_NULL_SHA256,
+ cipher_TLS_PSK_WITH_NULL_SHA384,
+ cipher_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256,
+ cipher_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384,
+ cipher_TLS_DHE_PSK_WITH_NULL_SHA256,
+ cipher_TLS_DHE_PSK_WITH_NULL_SHA384,
+ cipher_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256,
+ cipher_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384,
+ cipher_TLS_RSA_PSK_WITH_NULL_SHA256,
+ cipher_TLS_RSA_PSK_WITH_NULL_SHA384,
+ cipher_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256,
+ cipher_TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256,
+ cipher_TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256,
+ cipher_TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256,
+ cipher_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,
+ cipher_TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256,
+ cipher_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256,
+ cipher_TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256,
+ cipher_TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256,
+ cipher_TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256,
+ cipher_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256,
+ cipher_TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256,
+ cipher_TLS_EMPTY_RENEGOTIATION_INFO_SCSV,
+ cipher_TLS_ECDH_ECDSA_WITH_NULL_SHA,
+ cipher_TLS_ECDH_ECDSA_WITH_RC4_128_SHA,
+ cipher_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,
+ cipher_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,
+ cipher_TLS_ECDHE_ECDSA_WITH_NULL_SHA,
+ cipher_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
+ cipher_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
+ cipher_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
+ cipher_TLS_ECDH_RSA_WITH_NULL_SHA,
+ cipher_TLS_ECDH_RSA_WITH_RC4_128_SHA,
+ cipher_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,
+ cipher_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,
+ cipher_TLS_ECDHE_RSA_WITH_NULL_SHA,
+ cipher_TLS_ECDHE_RSA_WITH_RC4_128_SHA,
+ cipher_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
+ cipher_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
+ cipher_TLS_ECDH_anon_WITH_NULL_SHA,
+ cipher_TLS_ECDH_anon_WITH_RC4_128_SHA,
+ cipher_TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_ECDH_anon_WITH_AES_128_CBC_SHA,
+ cipher_TLS_ECDH_anon_WITH_AES_256_CBC_SHA,
+ cipher_TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_SRP_SHA_WITH_AES_128_CBC_SHA,
+ cipher_TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA,
+ cipher_TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA,
+ cipher_TLS_SRP_SHA_WITH_AES_256_CBC_SHA,
+ cipher_TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA,
+ cipher_TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA,
+ cipher_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
+ cipher_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
+ cipher_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256,
+ cipher_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384,
+ cipher_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
+ cipher_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
+ cipher_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256,
+ cipher_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384,
+ cipher_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256,
+ cipher_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384,
+ cipher_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256,
+ cipher_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384,
+ cipher_TLS_ECDHE_PSK_WITH_RC4_128_SHA,
+ cipher_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA,
+ cipher_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA,
+ cipher_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA,
+ cipher_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256,
+ cipher_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384,
+ cipher_TLS_ECDHE_PSK_WITH_NULL_SHA,
+ cipher_TLS_ECDHE_PSK_WITH_NULL_SHA256,
+ cipher_TLS_ECDHE_PSK_WITH_NULL_SHA384,
+ cipher_TLS_RSA_WITH_ARIA_128_CBC_SHA256,
+ cipher_TLS_RSA_WITH_ARIA_256_CBC_SHA384,
+ cipher_TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256,
+ cipher_TLS_DH_DSS_WITH_ARIA_256_CBC_SHA384,
+ cipher_TLS_DH_RSA_WITH_ARIA_128_CBC_SHA256,
+ cipher_TLS_DH_RSA_WITH_ARIA_256_CBC_SHA384,
+ cipher_TLS_DHE_DSS_WITH_ARIA_128_CBC_SHA256,
+ cipher_TLS_DHE_DSS_WITH_ARIA_256_CBC_SHA384,
+ cipher_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256,
+ cipher_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384,
+ cipher_TLS_DH_anon_WITH_ARIA_128_CBC_SHA256,
+ cipher_TLS_DH_anon_WITH_ARIA_256_CBC_SHA384,
+ cipher_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256,
+ cipher_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384,
+ cipher_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256,
+ cipher_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384,
+ cipher_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256,
+ cipher_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384,
+ cipher_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256,
+ cipher_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384,
+ cipher_TLS_RSA_WITH_ARIA_128_GCM_SHA256,
+ cipher_TLS_RSA_WITH_ARIA_256_GCM_SHA384,
+ cipher_TLS_DH_RSA_WITH_ARIA_128_GCM_SHA256,
+ cipher_TLS_DH_RSA_WITH_ARIA_256_GCM_SHA384,
+ cipher_TLS_DH_DSS_WITH_ARIA_128_GCM_SHA256,
+ cipher_TLS_DH_DSS_WITH_ARIA_256_GCM_SHA384,
+ cipher_TLS_DH_anon_WITH_ARIA_128_GCM_SHA256,
+ cipher_TLS_DH_anon_WITH_ARIA_256_GCM_SHA384,
+ cipher_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256,
+ cipher_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384,
+ cipher_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256,
+ cipher_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384,
+ cipher_TLS_PSK_WITH_ARIA_128_CBC_SHA256,
+ cipher_TLS_PSK_WITH_ARIA_256_CBC_SHA384,
+ cipher_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256,
+ cipher_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384,
+ cipher_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256,
+ cipher_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384,
+ cipher_TLS_PSK_WITH_ARIA_128_GCM_SHA256,
+ cipher_TLS_PSK_WITH_ARIA_256_GCM_SHA384,
+ cipher_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256,
+ cipher_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384,
+ cipher_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256,
+ cipher_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384,
+ cipher_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256,
+ cipher_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384,
+ cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256,
+ cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384,
+ cipher_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,
+ cipher_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384,
+ cipher_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256,
+ cipher_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384,
+ cipher_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256,
+ cipher_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384,
+ cipher_TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256,
+ cipher_TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384,
+ cipher_TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256,
+ cipher_TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384,
+ cipher_TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256,
+ cipher_TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384,
+ cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256,
+ cipher_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384,
+ cipher_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256,
+ cipher_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384,
+ cipher_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256,
+ cipher_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384,
+ cipher_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256,
+ cipher_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384,
+ cipher_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256,
+ cipher_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384,
+ cipher_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256,
+ cipher_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384,
+ cipher_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256,
+ cipher_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384,
+ cipher_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256,
+ cipher_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384,
+ cipher_TLS_RSA_WITH_AES_128_CCM,
+ cipher_TLS_RSA_WITH_AES_256_CCM,
+ cipher_TLS_RSA_WITH_AES_128_CCM_8,
+ cipher_TLS_RSA_WITH_AES_256_CCM_8,
+ cipher_TLS_PSK_WITH_AES_128_CCM,
+ cipher_TLS_PSK_WITH_AES_256_CCM,
+ cipher_TLS_PSK_WITH_AES_128_CCM_8,
+ cipher_TLS_PSK_WITH_AES_256_CCM_8:
+ return true
+ default:
+ return false
+ }
+}
diff --git a/vendor/golang.org/x/net/http2/client_conn_pool.go b/vendor/golang.org/x/net/http2/client_conn_pool.go
new file mode 100644
index 000000000..f4d9b5ece
--- /dev/null
+++ b/vendor/golang.org/x/net/http2/client_conn_pool.go
@@ -0,0 +1,282 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Transport code's client connection pooling.
+
+package http2
+
+import (
+ "crypto/tls"
+ "net/http"
+ "sync"
+)
+
+// ClientConnPool manages a pool of HTTP/2 client connections.
+type ClientConnPool interface {
+ GetClientConn(req *http.Request, addr string) (*ClientConn, error)
+ MarkDead(*ClientConn)
+}
+
+// clientConnPoolIdleCloser is the interface implemented by ClientConnPool
+// implementations which can close their idle connections.
+type clientConnPoolIdleCloser interface {
+ ClientConnPool
+ closeIdleConnections()
+}
+
+var (
+ _ clientConnPoolIdleCloser = (*clientConnPool)(nil)
+ _ clientConnPoolIdleCloser = noDialClientConnPool{}
+)
+
+// TODO: use singleflight for dialing and addConnCalls?
+type clientConnPool struct {
+ t *Transport
+
+ mu sync.Mutex // TODO: maybe switch to RWMutex
+ // TODO: add support for sharing conns based on cert names
+ // (e.g. share conn for googleapis.com and appspot.com)
+ conns map[string][]*ClientConn // key is host:port
+ dialing map[string]*dialCall // currently in-flight dials
+ keys map[*ClientConn][]string
+ addConnCalls map[string]*addConnCall // in-flight addConnIfNeede calls
+}
+
+func (p *clientConnPool) GetClientConn(req *http.Request, addr string) (*ClientConn, error) {
+ return p.getClientConn(req, addr, dialOnMiss)
+}
+
+const (
+ dialOnMiss = true
+ noDialOnMiss = false
+)
+
+// shouldTraceGetConn reports whether getClientConn should call any
+// ClientTrace.GetConn hook associated with the http.Request.
+//
+// This complexity is needed to avoid double calls of the GetConn hook
+// during the back-and-forth between net/http and x/net/http2 (when the
+// net/http.Transport is upgraded to also speak http2), as well as support
+// the case where x/net/http2 is being used directly.
+func (p *clientConnPool) shouldTraceGetConn(st clientConnIdleState) bool {
+ // If our Transport wasn't made via ConfigureTransport, always
+ // trace the GetConn hook if provided, because that means the
+ // http2 package is being used directly and it's the one
+ // dialing, as opposed to net/http.
+ if _, ok := p.t.ConnPool.(noDialClientConnPool); !ok {
+ return true
+ }
+ // Otherwise, only use the GetConn hook if this connection has
+ // been used previously for other requests. For fresh
+ // connections, the net/http package does the dialing.
+ return !st.freshConn
+}
+
+func (p *clientConnPool) getClientConn(req *http.Request, addr string, dialOnMiss bool) (*ClientConn, error) {
+ if isConnectionCloseRequest(req) && dialOnMiss {
+ // It gets its own connection.
+ traceGetConn(req, addr)
+ const singleUse = true
+ cc, err := p.t.dialClientConn(addr, singleUse)
+ if err != nil {
+ return nil, err
+ }
+ return cc, nil
+ }
+ p.mu.Lock()
+ for _, cc := range p.conns[addr] {
+ if st := cc.idleState(); st.canTakeNewRequest {
+ if p.shouldTraceGetConn(st) {
+ traceGetConn(req, addr)
+ }
+ p.mu.Unlock()
+ return cc, nil
+ }
+ }
+ if !dialOnMiss {
+ p.mu.Unlock()
+ return nil, ErrNoCachedConn
+ }
+ traceGetConn(req, addr)
+ call := p.getStartDialLocked(addr)
+ p.mu.Unlock()
+ <-call.done
+ return call.res, call.err
+}
+
+// dialCall is an in-flight Transport dial call to a host.
+type dialCall struct {
+ p *clientConnPool
+ done chan struct{} // closed when done
+ res *ClientConn // valid after done is closed
+ err error // valid after done is closed
+}
+
+// requires p.mu is held.
+func (p *clientConnPool) getStartDialLocked(addr string) *dialCall {
+ if call, ok := p.dialing[addr]; ok {
+ // A dial is already in-flight. Don't start another.
+ return call
+ }
+ call := &dialCall{p: p, done: make(chan struct{})}
+ if p.dialing == nil {
+ p.dialing = make(map[string]*dialCall)
+ }
+ p.dialing[addr] = call
+ go call.dial(addr)
+ return call
+}
+
+// run in its own goroutine.
+func (c *dialCall) dial(addr string) {
+ const singleUse = false // shared conn
+ c.res, c.err = c.p.t.dialClientConn(addr, singleUse)
+ close(c.done)
+
+ c.p.mu.Lock()
+ delete(c.p.dialing, addr)
+ if c.err == nil {
+ c.p.addConnLocked(addr, c.res)
+ }
+ c.p.mu.Unlock()
+}
+
+// addConnIfNeeded makes a NewClientConn out of c if a connection for key doesn't
+// already exist. It coalesces concurrent calls with the same key.
+// This is used by the http1 Transport code when it creates a new connection. Because
+// the http1 Transport doesn't de-dup TCP dials to outbound hosts (because it doesn't know
+// the protocol), it can get into a situation where it has multiple TLS connections.
+// This code decides which ones live or die.
+// The return value used is whether c was used.
+// c is never closed.
+func (p *clientConnPool) addConnIfNeeded(key string, t *Transport, c *tls.Conn) (used bool, err error) {
+ p.mu.Lock()
+ for _, cc := range p.conns[key] {
+ if cc.CanTakeNewRequest() {
+ p.mu.Unlock()
+ return false, nil
+ }
+ }
+ call, dup := p.addConnCalls[key]
+ if !dup {
+ if p.addConnCalls == nil {
+ p.addConnCalls = make(map[string]*addConnCall)
+ }
+ call = &addConnCall{
+ p: p,
+ done: make(chan struct{}),
+ }
+ p.addConnCalls[key] = call
+ go call.run(t, key, c)
+ }
+ p.mu.Unlock()
+
+ <-call.done
+ if call.err != nil {
+ return false, call.err
+ }
+ return !dup, nil
+}
+
+type addConnCall struct {
+ p *clientConnPool
+ done chan struct{} // closed when done
+ err error
+}
+
+func (c *addConnCall) run(t *Transport, key string, tc *tls.Conn) {
+ cc, err := t.NewClientConn(tc)
+
+ p := c.p
+ p.mu.Lock()
+ if err != nil {
+ c.err = err
+ } else {
+ p.addConnLocked(key, cc)
+ }
+ delete(p.addConnCalls, key)
+ p.mu.Unlock()
+ close(c.done)
+}
+
+func (p *clientConnPool) addConn(key string, cc *ClientConn) {
+ p.mu.Lock()
+ p.addConnLocked(key, cc)
+ p.mu.Unlock()
+}
+
+// p.mu must be held
+func (p *clientConnPool) addConnLocked(key string, cc *ClientConn) {
+ for _, v := range p.conns[key] {
+ if v == cc {
+ return
+ }
+ }
+ if p.conns == nil {
+ p.conns = make(map[string][]*ClientConn)
+ }
+ if p.keys == nil {
+ p.keys = make(map[*ClientConn][]string)
+ }
+ p.conns[key] = append(p.conns[key], cc)
+ p.keys[cc] = append(p.keys[cc], key)
+}
+
+func (p *clientConnPool) MarkDead(cc *ClientConn) {
+ p.mu.Lock()
+ defer p.mu.Unlock()
+ for _, key := range p.keys[cc] {
+ vv, ok := p.conns[key]
+ if !ok {
+ continue
+ }
+ newList := filterOutClientConn(vv, cc)
+ if len(newList) > 0 {
+ p.conns[key] = newList
+ } else {
+ delete(p.conns, key)
+ }
+ }
+ delete(p.keys, cc)
+}
+
+func (p *clientConnPool) closeIdleConnections() {
+ p.mu.Lock()
+ defer p.mu.Unlock()
+ // TODO: don't close a cc if it was just added to the pool
+ // milliseconds ago and has never been used. There's currently
+ // a small race window with the HTTP/1 Transport's integration
+ // where it can add an idle conn just before using it, and
+ // somebody else can concurrently call CloseIdleConns and
+ // break some caller's RoundTrip.
+ for _, vv := range p.conns {
+ for _, cc := range vv {
+ cc.closeIfIdle()
+ }
+ }
+}
+
+func filterOutClientConn(in []*ClientConn, exclude *ClientConn) []*ClientConn {
+ out := in[:0]
+ for _, v := range in {
+ if v != exclude {
+ out = append(out, v)
+ }
+ }
+ // If we filtered it out, zero out the last item to prevent
+ // the GC from seeing it.
+ if len(in) != len(out) {
+ in[len(in)-1] = nil
+ }
+ return out
+}
+
+// noDialClientConnPool is an implementation of http2.ClientConnPool
+// which never dials. We let the HTTP/1.1 client dial and use its TLS
+// connection instead.
+type noDialClientConnPool struct{ *clientConnPool }
+
+func (p noDialClientConnPool) GetClientConn(req *http.Request, addr string) (*ClientConn, error) {
+ return p.getClientConn(req, addr, noDialOnMiss)
+}
diff --git a/vendor/golang.org/x/net/http2/databuffer.go b/vendor/golang.org/x/net/http2/databuffer.go
new file mode 100644
index 000000000..a3067f8de
--- /dev/null
+++ b/vendor/golang.org/x/net/http2/databuffer.go
@@ -0,0 +1,146 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package http2
+
+import (
+ "errors"
+ "fmt"
+ "sync"
+)
+
+// Buffer chunks are allocated from a pool to reduce pressure on GC.
+// The maximum wasted space per dataBuffer is 2x the largest size class,
+// which happens when the dataBuffer has multiple chunks and there is
+// one unread byte in both the first and last chunks. We use a few size
+// classes to minimize overheads for servers that typically receive very
+// small request bodies.
+//
+// TODO: Benchmark to determine if the pools are necessary. The GC may have
+// improved enough that we can instead allocate chunks like this:
+// make([]byte, max(16<<10, expectedBytesRemaining))
+var (
+ dataChunkSizeClasses = []int{
+ 1 << 10,
+ 2 << 10,
+ 4 << 10,
+ 8 << 10,
+ 16 << 10,
+ }
+ dataChunkPools = [...]sync.Pool{
+ {New: func() interface{} { return make([]byte, 1<<10) }},
+ {New: func() interface{} { return make([]byte, 2<<10) }},
+ {New: func() interface{} { return make([]byte, 4<<10) }},
+ {New: func() interface{} { return make([]byte, 8<<10) }},
+ {New: func() interface{} { return make([]byte, 16<<10) }},
+ }
+)
+
+func getDataBufferChunk(size int64) []byte {
+ i := 0
+ for ; i < len(dataChunkSizeClasses)-1; i++ {
+ if size <= int64(dataChunkSizeClasses[i]) {
+ break
+ }
+ }
+ return dataChunkPools[i].Get().([]byte)
+}
+
+func putDataBufferChunk(p []byte) {
+ for i, n := range dataChunkSizeClasses {
+ if len(p) == n {
+ dataChunkPools[i].Put(p)
+ return
+ }
+ }
+ panic(fmt.Sprintf("unexpected buffer len=%v", len(p)))
+}
+
+// dataBuffer is an io.ReadWriter backed by a list of data chunks.
+// Each dataBuffer is used to read DATA frames on a single stream.
+// The buffer is divided into chunks so the server can limit the
+// total memory used by a single connection without limiting the
+// request body size on any single stream.
+type dataBuffer struct {
+ chunks [][]byte
+ r int // next byte to read is chunks[0][r]
+ w int // next byte to write is chunks[len(chunks)-1][w]
+ size int // total buffered bytes
+ expected int64 // we expect at least this many bytes in future Write calls (ignored if <= 0)
+}
+
+var errReadEmpty = errors.New("read from empty dataBuffer")
+
+// Read copies bytes from the buffer into p.
+// It is an error to read when no data is available.
+func (b *dataBuffer) Read(p []byte) (int, error) {
+ if b.size == 0 {
+ return 0, errReadEmpty
+ }
+ var ntotal int
+ for len(p) > 0 && b.size > 0 {
+ readFrom := b.bytesFromFirstChunk()
+ n := copy(p, readFrom)
+ p = p[n:]
+ ntotal += n
+ b.r += n
+ b.size -= n
+ // If the first chunk has been consumed, advance to the next chunk.
+ if b.r == len(b.chunks[0]) {
+ putDataBufferChunk(b.chunks[0])
+ end := len(b.chunks) - 1
+ copy(b.chunks[:end], b.chunks[1:])
+ b.chunks[end] = nil
+ b.chunks = b.chunks[:end]
+ b.r = 0
+ }
+ }
+ return ntotal, nil
+}
+
+func (b *dataBuffer) bytesFromFirstChunk() []byte {
+ if len(b.chunks) == 1 {
+ return b.chunks[0][b.r:b.w]
+ }
+ return b.chunks[0][b.r:]
+}
+
+// Len returns the number of bytes of the unread portion of the buffer.
+func (b *dataBuffer) Len() int {
+ return b.size
+}
+
+// Write appends p to the buffer.
+func (b *dataBuffer) Write(p []byte) (int, error) {
+ ntotal := len(p)
+ for len(p) > 0 {
+ // If the last chunk is empty, allocate a new chunk. Try to allocate
+ // enough to fully copy p plus any additional bytes we expect to
+ // receive. However, this may allocate less than len(p).
+ want := int64(len(p))
+ if b.expected > want {
+ want = b.expected
+ }
+ chunk := b.lastChunkOrAlloc(want)
+ n := copy(chunk[b.w:], p)
+ p = p[n:]
+ b.w += n
+ b.size += n
+ b.expected -= int64(n)
+ }
+ return ntotal, nil
+}
+
+func (b *dataBuffer) lastChunkOrAlloc(want int64) []byte {
+ if len(b.chunks) != 0 {
+ last := b.chunks[len(b.chunks)-1]
+ if b.w < len(last) {
+ return last
+ }
+ }
+ chunk := getDataBufferChunk(want)
+ b.chunks = append(b.chunks, chunk)
+ b.w = 0
+ return chunk
+}
diff --git a/vendor/golang.org/x/net/http2/errors.go b/vendor/golang.org/x/net/http2/errors.go
new file mode 100644
index 000000000..71f2c4631
--- /dev/null
+++ b/vendor/golang.org/x/net/http2/errors.go
@@ -0,0 +1,133 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package http2
+
+import (
+ "errors"
+ "fmt"
+)
+
+// An ErrCode is an unsigned 32-bit error code as defined in the HTTP/2 spec.
+type ErrCode uint32
+
+const (
+ ErrCodeNo ErrCode = 0x0
+ ErrCodeProtocol ErrCode = 0x1
+ ErrCodeInternal ErrCode = 0x2
+ ErrCodeFlowControl ErrCode = 0x3
+ ErrCodeSettingsTimeout ErrCode = 0x4
+ ErrCodeStreamClosed ErrCode = 0x5
+ ErrCodeFrameSize ErrCode = 0x6
+ ErrCodeRefusedStream ErrCode = 0x7
+ ErrCodeCancel ErrCode = 0x8
+ ErrCodeCompression ErrCode = 0x9
+ ErrCodeConnect ErrCode = 0xa
+ ErrCodeEnhanceYourCalm ErrCode = 0xb
+ ErrCodeInadequateSecurity ErrCode = 0xc
+ ErrCodeHTTP11Required ErrCode = 0xd
+)
+
+var errCodeName = map[ErrCode]string{
+ ErrCodeNo: "NO_ERROR",
+ ErrCodeProtocol: "PROTOCOL_ERROR",
+ ErrCodeInternal: "INTERNAL_ERROR",
+ ErrCodeFlowControl: "FLOW_CONTROL_ERROR",
+ ErrCodeSettingsTimeout: "SETTINGS_TIMEOUT",
+ ErrCodeStreamClosed: "STREAM_CLOSED",
+ ErrCodeFrameSize: "FRAME_SIZE_ERROR",
+ ErrCodeRefusedStream: "REFUSED_STREAM",
+ ErrCodeCancel: "CANCEL",
+ ErrCodeCompression: "COMPRESSION_ERROR",
+ ErrCodeConnect: "CONNECT_ERROR",
+ ErrCodeEnhanceYourCalm: "ENHANCE_YOUR_CALM",
+ ErrCodeInadequateSecurity: "INADEQUATE_SECURITY",
+ ErrCodeHTTP11Required: "HTTP_1_1_REQUIRED",
+}
+
+func (e ErrCode) String() string {
+ if s, ok := errCodeName[e]; ok {
+ return s
+ }
+ return fmt.Sprintf("unknown error code 0x%x", uint32(e))
+}
+
+// ConnectionError is an error that results in the termination of the
+// entire connection.
+type ConnectionError ErrCode
+
+func (e ConnectionError) Error() string { return fmt.Sprintf("connection error: %s", ErrCode(e)) }
+
+// StreamError is an error that only affects one stream within an
+// HTTP/2 connection.
+type StreamError struct {
+ StreamID uint32
+ Code ErrCode
+ Cause error // optional additional detail
+}
+
+func streamError(id uint32, code ErrCode) StreamError {
+ return StreamError{StreamID: id, Code: code}
+}
+
+func (e StreamError) Error() string {
+ if e.Cause != nil {
+ return fmt.Sprintf("stream error: stream ID %d; %v; %v", e.StreamID, e.Code, e.Cause)
+ }
+ return fmt.Sprintf("stream error: stream ID %d; %v", e.StreamID, e.Code)
+}
+
+// 6.9.1 The Flow Control Window
+// "If a sender receives a WINDOW_UPDATE that causes a flow control
+// window to exceed this maximum it MUST terminate either the stream
+// or the connection, as appropriate. For streams, [...]; for the
+// connection, a GOAWAY frame with a FLOW_CONTROL_ERROR code."
+type goAwayFlowError struct{}
+
+func (goAwayFlowError) Error() string { return "connection exceeded flow control window size" }
+
+// connError represents an HTTP/2 ConnectionError error code, along
+// with a string (for debugging) explaining why.
+//
+// Errors of this type are only returned by the frame parser functions
+// and converted into ConnectionError(Code), after stashing away
+// the Reason into the Framer's errDetail field, accessible via
+// the (*Framer).ErrorDetail method.
+type connError struct {
+ Code ErrCode // the ConnectionError error code
+ Reason string // additional reason
+}
+
+func (e connError) Error() string {
+ return fmt.Sprintf("http2: connection error: %v: %v", e.Code, e.Reason)
+}
+
+type pseudoHeaderError string
+
+func (e pseudoHeaderError) Error() string {
+ return fmt.Sprintf("invalid pseudo-header %q", string(e))
+}
+
+type duplicatePseudoHeaderError string
+
+func (e duplicatePseudoHeaderError) Error() string {
+ return fmt.Sprintf("duplicate pseudo-header %q", string(e))
+}
+
+type headerFieldNameError string
+
+func (e headerFieldNameError) Error() string {
+ return fmt.Sprintf("invalid header field name %q", string(e))
+}
+
+type headerFieldValueError string
+
+func (e headerFieldValueError) Error() string {
+ return fmt.Sprintf("invalid header field value %q", string(e))
+}
+
+var (
+ errMixPseudoHeaderTypes = errors.New("mix of request and response pseudo headers")
+ errPseudoAfterRegular = errors.New("pseudo header field after regular")
+)
diff --git a/vendor/golang.org/x/net/http2/flow.go b/vendor/golang.org/x/net/http2/flow.go
new file mode 100644
index 000000000..cea601fcd
--- /dev/null
+++ b/vendor/golang.org/x/net/http2/flow.go
@@ -0,0 +1,50 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Flow control
+
+package http2
+
+// flow is the flow control window's size.
+type flow struct {
+ // n is the number of DATA bytes we're allowed to send.
+ // A flow is kept both on a conn and a per-stream.
+ n int32
+
+ // conn points to the shared connection-level flow that is
+ // shared by all streams on that conn. It is nil for the flow
+ // that's on the conn directly.
+ conn *flow
+}
+
+func (f *flow) setConnFlow(cf *flow) { f.conn = cf }
+
+func (f *flow) available() int32 {
+ n := f.n
+ if f.conn != nil && f.conn.n < n {
+ n = f.conn.n
+ }
+ return n
+}
+
+func (f *flow) take(n int32) {
+ if n > f.available() {
+ panic("internal error: took too much")
+ }
+ f.n -= n
+ if f.conn != nil {
+ f.conn.n -= n
+ }
+}
+
+// add adds n bytes (positive or negative) to the flow control window.
+// It returns false if the sum would exceed 2^31-1.
+func (f *flow) add(n int32) bool {
+ sum := f.n + n
+ if (sum > n) == (f.n > 0) {
+ f.n = sum
+ return true
+ }
+ return false
+}
diff --git a/vendor/golang.org/x/net/http2/frame.go b/vendor/golang.org/x/net/http2/frame.go
new file mode 100644
index 000000000..514c126c5
--- /dev/null
+++ b/vendor/golang.org/x/net/http2/frame.go
@@ -0,0 +1,1614 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package http2
+
+import (
+ "bytes"
+ "encoding/binary"
+ "errors"
+ "fmt"
+ "io"
+ "log"
+ "strings"
+ "sync"
+
+ "golang.org/x/net/http/httpguts"
+ "golang.org/x/net/http2/hpack"
+)
+
+const frameHeaderLen = 9
+
+var padZeros = make([]byte, 255) // zeros for padding
+
+// A FrameType is a registered frame type as defined in
+// http://http2.github.io/http2-spec/#rfc.section.11.2
+type FrameType uint8
+
+const (
+ FrameData FrameType = 0x0
+ FrameHeaders FrameType = 0x1
+ FramePriority FrameType = 0x2
+ FrameRSTStream FrameType = 0x3
+ FrameSettings FrameType = 0x4
+ FramePushPromise FrameType = 0x5
+ FramePing FrameType = 0x6
+ FrameGoAway FrameType = 0x7
+ FrameWindowUpdate FrameType = 0x8
+ FrameContinuation FrameType = 0x9
+)
+
+var frameName = map[FrameType]string{
+ FrameData: "DATA",
+ FrameHeaders: "HEADERS",
+ FramePriority: "PRIORITY",
+ FrameRSTStream: "RST_STREAM",
+ FrameSettings: "SETTINGS",
+ FramePushPromise: "PUSH_PROMISE",
+ FramePing: "PING",
+ FrameGoAway: "GOAWAY",
+ FrameWindowUpdate: "WINDOW_UPDATE",
+ FrameContinuation: "CONTINUATION",
+}
+
+func (t FrameType) String() string {
+ if s, ok := frameName[t]; ok {
+ return s
+ }
+ return fmt.Sprintf("UNKNOWN_FRAME_TYPE_%d", uint8(t))
+}
+
+// Flags is a bitmask of HTTP/2 flags.
+// The meaning of flags varies depending on the frame type.
+type Flags uint8
+
+// Has reports whether f contains all (0 or more) flags in v.
+func (f Flags) Has(v Flags) bool {
+ return (f & v) == v
+}
+
+// Frame-specific FrameHeader flag bits.
+const (
+ // Data Frame
+ FlagDataEndStream Flags = 0x1
+ FlagDataPadded Flags = 0x8
+
+ // Headers Frame
+ FlagHeadersEndStream Flags = 0x1
+ FlagHeadersEndHeaders Flags = 0x4
+ FlagHeadersPadded Flags = 0x8
+ FlagHeadersPriority Flags = 0x20
+
+ // Settings Frame
+ FlagSettingsAck Flags = 0x1
+
+ // Ping Frame
+ FlagPingAck Flags = 0x1
+
+ // Continuation Frame
+ FlagContinuationEndHeaders Flags = 0x4
+
+ FlagPushPromiseEndHeaders Flags = 0x4
+ FlagPushPromisePadded Flags = 0x8
+)
+
+var flagName = map[FrameType]map[Flags]string{
+ FrameData: {
+ FlagDataEndStream: "END_STREAM",
+ FlagDataPadded: "PADDED",
+ },
+ FrameHeaders: {
+ FlagHeadersEndStream: "END_STREAM",
+ FlagHeadersEndHeaders: "END_HEADERS",
+ FlagHeadersPadded: "PADDED",
+ FlagHeadersPriority: "PRIORITY",
+ },
+ FrameSettings: {
+ FlagSettingsAck: "ACK",
+ },
+ FramePing: {
+ FlagPingAck: "ACK",
+ },
+ FrameContinuation: {
+ FlagContinuationEndHeaders: "END_HEADERS",
+ },
+ FramePushPromise: {
+ FlagPushPromiseEndHeaders: "END_HEADERS",
+ FlagPushPromisePadded: "PADDED",
+ },
+}
+
+// a frameParser parses a frame given its FrameHeader and payload
+// bytes. The length of payload will always equal fh.Length (which
+// might be 0).
+type frameParser func(fc *frameCache, fh FrameHeader, payload []byte) (Frame, error)
+
+var frameParsers = map[FrameType]frameParser{
+ FrameData: parseDataFrame,
+ FrameHeaders: parseHeadersFrame,
+ FramePriority: parsePriorityFrame,
+ FrameRSTStream: parseRSTStreamFrame,
+ FrameSettings: parseSettingsFrame,
+ FramePushPromise: parsePushPromise,
+ FramePing: parsePingFrame,
+ FrameGoAway: parseGoAwayFrame,
+ FrameWindowUpdate: parseWindowUpdateFrame,
+ FrameContinuation: parseContinuationFrame,
+}
+
+func typeFrameParser(t FrameType) frameParser {
+ if f := frameParsers[t]; f != nil {
+ return f
+ }
+ return parseUnknownFrame
+}
+
+// A FrameHeader is the 9 byte header of all HTTP/2 frames.
+//
+// See http://http2.github.io/http2-spec/#FrameHeader
+type FrameHeader struct {
+ valid bool // caller can access []byte fields in the Frame
+
+ // Type is the 1 byte frame type. There are ten standard frame
+ // types, but extension frame types may be written by WriteRawFrame
+ // and will be returned by ReadFrame (as UnknownFrame).
+ Type FrameType
+
+ // Flags are the 1 byte of 8 potential bit flags per frame.
+ // They are specific to the frame type.
+ Flags Flags
+
+ // Length is the length of the frame, not including the 9 byte header.
+ // The maximum size is one byte less than 16MB (uint24), but only
+ // frames up to 16KB are allowed without peer agreement.
+ Length uint32
+
+ // StreamID is which stream this frame is for. Certain frames
+ // are not stream-specific, in which case this field is 0.
+ StreamID uint32
+}
+
+// Header returns h. It exists so FrameHeaders can be embedded in other
+// specific frame types and implement the Frame interface.
+func (h FrameHeader) Header() FrameHeader { return h }
+
+func (h FrameHeader) String() string {
+ var buf bytes.Buffer
+ buf.WriteString("[FrameHeader ")
+ h.writeDebug(&buf)
+ buf.WriteByte(']')
+ return buf.String()
+}
+
+func (h FrameHeader) writeDebug(buf *bytes.Buffer) {
+ buf.WriteString(h.Type.String())
+ if h.Flags != 0 {
+ buf.WriteString(" flags=")
+ set := 0
+ for i := uint8(0); i < 8; i++ {
+ if h.Flags&(1<<i) == 0 {
+ continue
+ }
+ set++
+ if set > 1 {
+ buf.WriteByte('|')
+ }
+ name := flagName[h.Type][Flags(1<<i)]
+ if name != "" {
+ buf.WriteString(name)
+ } else {
+ fmt.Fprintf(buf, "0x%x", 1<<i)
+ }
+ }
+ }
+ if h.StreamID != 0 {
+ fmt.Fprintf(buf, " stream=%d", h.StreamID)
+ }
+ fmt.Fprintf(buf, " len=%d", h.Length)
+}
+
+func (h *FrameHeader) checkValid() {
+ if !h.valid {
+ panic("Frame accessor called on non-owned Frame")
+ }
+}
+
+func (h *FrameHeader) invalidate() { h.valid = false }
+
+// frame header bytes.
+// Used only by ReadFrameHeader.
+var fhBytes = sync.Pool{
+ New: func() interface{} {
+ buf := make([]byte, frameHeaderLen)
+ return &buf
+ },
+}
+
+// ReadFrameHeader reads 9 bytes from r and returns a FrameHeader.
+// Most users should use Framer.ReadFrame instead.
+func ReadFrameHeader(r io.Reader) (FrameHeader, error) {
+ bufp := fhBytes.Get().(*[]byte)
+ defer fhBytes.Put(bufp)
+ return readFrameHeader(*bufp, r)
+}
+
+func readFrameHeader(buf []byte, r io.Reader) (FrameHeader, error) {
+ _, err := io.ReadFull(r, buf[:frameHeaderLen])
+ if err != nil {
+ return FrameHeader{}, err
+ }
+ return FrameHeader{
+ Length: (uint32(buf[0])<<16 | uint32(buf[1])<<8 | uint32(buf[2])),
+ Type: FrameType(buf[3]),
+ Flags: Flags(buf[4]),
+ StreamID: binary.BigEndian.Uint32(buf[5:]) & (1<<31 - 1),
+ valid: true,
+ }, nil
+}
+
+// A Frame is the base interface implemented by all frame types.
+// Callers will generally type-assert the specific frame type:
+// *HeadersFrame, *SettingsFrame, *WindowUpdateFrame, etc.
+//
+// Frames are only valid until the next call to Framer.ReadFrame.
+type Frame interface {
+ Header() FrameHeader
+
+ // invalidate is called by Framer.ReadFrame to make this
+ // frame's buffers as being invalid, since the subsequent
+ // frame will reuse them.
+ invalidate()
+}
+
+// A Framer reads and writes Frames.
+type Framer struct {
+ r io.Reader
+ lastFrame Frame
+ errDetail error
+
+ // lastHeaderStream is non-zero if the last frame was an
+ // unfinished HEADERS/CONTINUATION.
+ lastHeaderStream uint32
+
+ maxReadSize uint32
+ headerBuf [frameHeaderLen]byte
+
+ // TODO: let getReadBuf be configurable, and use a less memory-pinning
+ // allocator in server.go to minimize memory pinned for many idle conns.
+ // Will probably also need to make frame invalidation have a hook too.
+ getReadBuf func(size uint32) []byte
+ readBuf []byte // cache for default getReadBuf
+
+ maxWriteSize uint32 // zero means unlimited; TODO: implement
+
+ w io.Writer
+ wbuf []byte
+
+ // AllowIllegalWrites permits the Framer's Write methods to
+ // write frames that do not conform to the HTTP/2 spec. This
+ // permits using the Framer to test other HTTP/2
+ // implementations' conformance to the spec.
+ // If false, the Write methods will prefer to return an error
+ // rather than comply.
+ AllowIllegalWrites bool
+
+ // AllowIllegalReads permits the Framer's ReadFrame method
+ // to return non-compliant frames or frame orders.
+ // This is for testing and permits using the Framer to test
+ // other HTTP/2 implementations' conformance to the spec.
+ // It is not compatible with ReadMetaHeaders.
+ AllowIllegalReads bool
+
+ // ReadMetaHeaders if non-nil causes ReadFrame to merge
+ // HEADERS and CONTINUATION frames together and return
+ // MetaHeadersFrame instead.
+ ReadMetaHeaders *hpack.Decoder
+
+ // MaxHeaderListSize is the http2 MAX_HEADER_LIST_SIZE.
+ // It's used only if ReadMetaHeaders is set; 0 means a sane default
+ // (currently 16MB)
+ // If the limit is hit, MetaHeadersFrame.Truncated is set true.
+ MaxHeaderListSize uint32
+
+ // TODO: track which type of frame & with which flags was sent
+ // last. Then return an error (unless AllowIllegalWrites) if
+ // we're in the middle of a header block and a
+ // non-Continuation or Continuation on a different stream is
+ // attempted to be written.
+
+ logReads, logWrites bool
+
+ debugFramer *Framer // only use for logging written writes
+ debugFramerBuf *bytes.Buffer
+ debugReadLoggerf func(string, ...interface{})
+ debugWriteLoggerf func(string, ...interface{})
+
+ frameCache *frameCache // nil if frames aren't reused (default)
+}
+
+func (fr *Framer) maxHeaderListSize() uint32 {
+ if fr.MaxHeaderListSize == 0 {
+ return 16 << 20 // sane default, per docs
+ }
+ return fr.MaxHeaderListSize
+}
+
+func (f *Framer) startWrite(ftype FrameType, flags Flags, streamID uint32) {
+ // Write the FrameHeader.
+ f.wbuf = append(f.wbuf[:0],
+ 0, // 3 bytes of length, filled in in endWrite
+ 0,
+ 0,
+ byte(ftype),
+ byte(flags),
+ byte(streamID>>24),
+ byte(streamID>>16),
+ byte(streamID>>8),
+ byte(streamID))
+}
+
+func (f *Framer) endWrite() error {
+ // Now that we know the final size, fill in the FrameHeader in
+ // the space previously reserved for it. Abuse append.
+ length := len(f.wbuf) - frameHeaderLen
+ if length >= (1 << 24) {
+ return ErrFrameTooLarge
+ }
+ _ = append(f.wbuf[:0],
+ byte(length>>16),
+ byte(length>>8),
+ byte(length))
+ if f.logWrites {
+ f.logWrite()
+ }
+
+ n, err := f.w.Write(f.wbuf)
+ if err == nil && n != len(f.wbuf) {
+ err = io.ErrShortWrite
+ }
+ return err
+}
+
+func (f *Framer) logWrite() {
+ if f.debugFramer == nil {
+ f.debugFramerBuf = new(bytes.Buffer)
+ f.debugFramer = NewFramer(nil, f.debugFramerBuf)
+ f.debugFramer.logReads = false // we log it ourselves, saying "wrote" below
+ // Let us read anything, even if we accidentally wrote it
+ // in the wrong order:
+ f.debugFramer.AllowIllegalReads = true
+ }
+ f.debugFramerBuf.Write(f.wbuf)
+ fr, err := f.debugFramer.ReadFrame()
+ if err != nil {
+ f.debugWriteLoggerf("http2: Framer %p: failed to decode just-written frame", f)
+ return
+ }
+ f.debugWriteLoggerf("http2: Framer %p: wrote %v", f, summarizeFrame(fr))
+}
+
+func (f *Framer) writeByte(v byte) { f.wbuf = append(f.wbuf, v) }
+func (f *Framer) writeBytes(v []byte) { f.wbuf = append(f.wbuf, v...) }
+func (f *Framer) writeUint16(v uint16) { f.wbuf = append(f.wbuf, byte(v>>8), byte(v)) }
+func (f *Framer) writeUint32(v uint32) {
+ f.wbuf = append(f.wbuf, byte(v>>24), byte(v>>16), byte(v>>8), byte(v))
+}
+
+const (
+ minMaxFrameSize = 1 << 14
+ maxFrameSize = 1<<24 - 1
+)
+
+// SetReuseFrames allows the Framer to reuse Frames.
+// If called on a Framer, Frames returned by calls to ReadFrame are only
+// valid until the next call to ReadFrame.
+func (fr *Framer) SetReuseFrames() {
+ if fr.frameCache != nil {
+ return
+ }
+ fr.frameCache = &frameCache{}
+}
+
+type frameCache struct {
+ dataFrame DataFrame
+}
+
+func (fc *frameCache) getDataFrame() *DataFrame {
+ if fc == nil {
+ return &DataFrame{}
+ }
+ return &fc.dataFrame
+}
+
+// NewFramer returns a Framer that writes frames to w and reads them from r.
+func NewFramer(w io.Writer, r io.Reader) *Framer {
+ fr := &Framer{
+ w: w,
+ r: r,
+ logReads: logFrameReads,
+ logWrites: logFrameWrites,
+ debugReadLoggerf: log.Printf,
+ debugWriteLoggerf: log.Printf,
+ }
+ fr.getReadBuf = func(size uint32) []byte {
+ if cap(fr.readBuf) >= int(size) {
+ return fr.readBuf[:size]
+ }
+ fr.readBuf = make([]byte, size)
+ return fr.readBuf
+ }
+ fr.SetMaxReadFrameSize(maxFrameSize)
+ return fr
+}
+
+// SetMaxReadFrameSize sets the maximum size of a frame
+// that will be read by a subsequent call to ReadFrame.
+// It is the caller's responsibility to advertise this
+// limit with a SETTINGS frame.
+func (fr *Framer) SetMaxReadFrameSize(v uint32) {
+ if v > maxFrameSize {
+ v = maxFrameSize
+ }
+ fr.maxReadSize = v
+}
+
+// ErrorDetail returns a more detailed error of the last error
+// returned by Framer.ReadFrame. For instance, if ReadFrame
+// returns a StreamError with code PROTOCOL_ERROR, ErrorDetail
+// will say exactly what was invalid. ErrorDetail is not guaranteed
+// to return a non-nil value and like the rest of the http2 package,
+// its return value is not protected by an API compatibility promise.
+// ErrorDetail is reset after the next call to ReadFrame.
+func (fr *Framer) ErrorDetail() error {
+ return fr.errDetail
+}
+
+// ErrFrameTooLarge is returned from Framer.ReadFrame when the peer
+// sends a frame that is larger than declared with SetMaxReadFrameSize.
+var ErrFrameTooLarge = errors.New("http2: frame too large")
+
+// terminalReadFrameError reports whether err is an unrecoverable
+// error from ReadFrame and no other frames should be read.
+func terminalReadFrameError(err error) bool {
+ if _, ok := err.(StreamError); ok {
+ return false
+ }
+ return err != nil
+}
+
+// ReadFrame reads a single frame. The returned Frame is only valid
+// until the next call to ReadFrame.
+//
+// If the frame is larger than previously set with SetMaxReadFrameSize, the
+// returned error is ErrFrameTooLarge. Other errors may be of type
+// ConnectionError, StreamError, or anything else from the underlying
+// reader.
+func (fr *Framer) ReadFrame() (Frame, error) {
+ fr.errDetail = nil
+ if fr.lastFrame != nil {
+ fr.lastFrame.invalidate()
+ }
+ fh, err := readFrameHeader(fr.headerBuf[:], fr.r)
+ if err != nil {
+ return nil, err
+ }
+ if fh.Length > fr.maxReadSize {
+ return nil, ErrFrameTooLarge
+ }
+ payload := fr.getReadBuf(fh.Length)
+ if _, err := io.ReadFull(fr.r, payload); err != nil {
+ return nil, err
+ }
+ f, err := typeFrameParser(fh.Type)(fr.frameCache, fh, payload)
+ if err != nil {
+ if ce, ok := err.(connError); ok {
+ return nil, fr.connError(ce.Code, ce.Reason)
+ }
+ return nil, err
+ }
+ if err := fr.checkFrameOrder(f); err != nil {
+ return nil, err
+ }
+ if fr.logReads {
+ fr.debugReadLoggerf("http2: Framer %p: read %v", fr, summarizeFrame(f))
+ }
+ if fh.Type == FrameHeaders && fr.ReadMetaHeaders != nil {
+ return fr.readMetaFrame(f.(*HeadersFrame))
+ }
+ return f, nil
+}
+
+// connError returns ConnectionError(code) but first
+// stashes away a public reason to the caller can optionally relay it
+// to the peer before hanging up on them. This might help others debug
+// their implementations.
+func (fr *Framer) connError(code ErrCode, reason string) error {
+ fr.errDetail = errors.New(reason)
+ return ConnectionError(code)
+}
+
+// checkFrameOrder reports an error if f is an invalid frame to return
+// next from ReadFrame. Mostly it checks whether HEADERS and
+// CONTINUATION frames are contiguous.
+func (fr *Framer) checkFrameOrder(f Frame) error {
+ last := fr.lastFrame
+ fr.lastFrame = f
+ if fr.AllowIllegalReads {
+ return nil
+ }
+
+ fh := f.Header()
+ if fr.lastHeaderStream != 0 {
+ if fh.Type != FrameContinuation {
+ return fr.connError(ErrCodeProtocol,
+ fmt.Sprintf("got %s for stream %d; expected CONTINUATION following %s for stream %d",
+ fh.Type, fh.StreamID,
+ last.Header().Type, fr.lastHeaderStream))
+ }
+ if fh.StreamID != fr.lastHeaderStream {
+ return fr.connError(ErrCodeProtocol,
+ fmt.Sprintf("got CONTINUATION for stream %d; expected stream %d",
+ fh.StreamID, fr.lastHeaderStream))
+ }
+ } else if fh.Type == FrameContinuation {
+ return fr.connError(ErrCodeProtocol, fmt.Sprintf("unexpected CONTINUATION for stream %d", fh.StreamID))
+ }
+
+ switch fh.Type {
+ case FrameHeaders, FrameContinuation:
+ if fh.Flags.Has(FlagHeadersEndHeaders) {
+ fr.lastHeaderStream = 0
+ } else {
+ fr.lastHeaderStream = fh.StreamID
+ }
+ }
+
+ return nil
+}
+
+// A DataFrame conveys arbitrary, variable-length sequences of octets
+// associated with a stream.
+// See http://http2.github.io/http2-spec/#rfc.section.6.1
+type DataFrame struct {
+ FrameHeader
+ data []byte
+}
+
+func (f *DataFrame) StreamEnded() bool {
+ return f.FrameHeader.Flags.Has(FlagDataEndStream)
+}
+
+// Data returns the frame's data octets, not including any padding
+// size byte or padding suffix bytes.
+// The caller must not retain the returned memory past the next
+// call to ReadFrame.
+func (f *DataFrame) Data() []byte {
+ f.checkValid()
+ return f.data
+}
+
+func parseDataFrame(fc *frameCache, fh FrameHeader, payload []byte) (Frame, error) {
+ if fh.StreamID == 0 {
+ // DATA frames MUST be associated with a stream. If a
+ // DATA frame is received whose stream identifier
+ // field is 0x0, the recipient MUST respond with a
+ // connection error (Section 5.4.1) of type
+ // PROTOCOL_ERROR.
+ return nil, connError{ErrCodeProtocol, "DATA frame with stream ID 0"}
+ }
+ f := fc.getDataFrame()
+ f.FrameHeader = fh
+
+ var padSize byte
+ if fh.Flags.Has(FlagDataPadded) {
+ var err error
+ payload, padSize, err = readByte(payload)
+ if err != nil {
+ return nil, err
+ }
+ }
+ if int(padSize) > len(payload) {
+ // If the length of the padding is greater than the
+ // length of the frame payload, the recipient MUST
+ // treat this as a connection error.
+ // Filed: https://github.com/http2/http2-spec/issues/610
+ return nil, connError{ErrCodeProtocol, "pad size larger than data payload"}
+ }
+ f.data = payload[:len(payload)-int(padSize)]
+ return f, nil
+}
+
+var (
+ errStreamID = errors.New("invalid stream ID")
+ errDepStreamID = errors.New("invalid dependent stream ID")
+ errPadLength = errors.New("pad length too large")
+ errPadBytes = errors.New("padding bytes must all be zeros unless AllowIllegalWrites is enabled")
+)
+
+func validStreamIDOrZero(streamID uint32) bool {
+ return streamID&(1<<31) == 0
+}
+
+func validStreamID(streamID uint32) bool {
+ return streamID != 0 && streamID&(1<<31) == 0
+}
+
+// WriteData writes a DATA frame.
+//
+// It will perform exactly one Write to the underlying Writer.
+// It is the caller's responsibility not to violate the maximum frame size
+// and to not call other Write methods concurrently.
+func (f *Framer) WriteData(streamID uint32, endStream bool, data []byte) error {
+ return f.WriteDataPadded(streamID, endStream, data, nil)
+}
+
+// WriteDataPadded writes a DATA frame with optional padding.
+//
+// If pad is nil, the padding bit is not sent.
+// The length of pad must not exceed 255 bytes.
+// The bytes of pad must all be zero, unless f.AllowIllegalWrites is set.
+//
+// It will perform exactly one Write to the underlying Writer.
+// It is the caller's responsibility not to violate the maximum frame size
+// and to not call other Write methods concurrently.
+func (f *Framer) WriteDataPadded(streamID uint32, endStream bool, data, pad []byte) error {
+ if !validStreamID(streamID) && !f.AllowIllegalWrites {
+ return errStreamID
+ }
+ if len(pad) > 0 {
+ if len(pad) > 255 {
+ return errPadLength
+ }
+ if !f.AllowIllegalWrites {
+ for _, b := range pad {
+ if b != 0 {
+ // "Padding octets MUST be set to zero when sending."
+ return errPadBytes
+ }
+ }
+ }
+ }
+ var flags Flags
+ if endStream {
+ flags |= FlagDataEndStream
+ }
+ if pad != nil {
+ flags |= FlagDataPadded
+ }
+ f.startWrite(FrameData, flags, streamID)
+ if pad != nil {
+ f.wbuf = append(f.wbuf, byte(len(pad)))
+ }
+ f.wbuf = append(f.wbuf, data...)
+ f.wbuf = append(f.wbuf, pad...)
+ return f.endWrite()
+}
+
+// A SettingsFrame conveys configuration parameters that affect how
+// endpoints communicate, such as preferences and constraints on peer
+// behavior.
+//
+// See http://http2.github.io/http2-spec/#SETTINGS
+type SettingsFrame struct {
+ FrameHeader
+ p []byte
+}
+
+func parseSettingsFrame(_ *frameCache, fh FrameHeader, p []byte) (Frame, error) {
+ if fh.Flags.Has(FlagSettingsAck) && fh.Length > 0 {
+ // When this (ACK 0x1) bit is set, the payload of the
+ // SETTINGS frame MUST be empty. Receipt of a
+ // SETTINGS frame with the ACK flag set and a length
+ // field value other than 0 MUST be treated as a
+ // connection error (Section 5.4.1) of type
+ // FRAME_SIZE_ERROR.
+ return nil, ConnectionError(ErrCodeFrameSize)
+ }
+ if fh.StreamID != 0 {
+ // SETTINGS frames always apply to a connection,
+ // never a single stream. The stream identifier for a
+ // SETTINGS frame MUST be zero (0x0). If an endpoint
+ // receives a SETTINGS frame whose stream identifier
+ // field is anything other than 0x0, the endpoint MUST
+ // respond with a connection error (Section 5.4.1) of
+ // type PROTOCOL_ERROR.
+ return nil, ConnectionError(ErrCodeProtocol)
+ }
+ if len(p)%6 != 0 {
+ // Expecting even number of 6 byte settings.
+ return nil, ConnectionError(ErrCodeFrameSize)
+ }
+ f := &SettingsFrame{FrameHeader: fh, p: p}
+ if v, ok := f.Value(SettingInitialWindowSize); ok && v > (1<<31)-1 {
+ // Values above the maximum flow control window size of 2^31 - 1 MUST
+ // be treated as a connection error (Section 5.4.1) of type
+ // FLOW_CONTROL_ERROR.
+ return nil, ConnectionError(ErrCodeFlowControl)
+ }
+ return f, nil
+}
+
+func (f *SettingsFrame) IsAck() bool {
+ return f.FrameHeader.Flags.Has(FlagSettingsAck)
+}
+
+func (f *SettingsFrame) Value(id SettingID) (v uint32, ok bool) {
+ f.checkValid()
+ for i := 0; i < f.NumSettings(); i++ {
+ if s := f.Setting(i); s.ID == id {
+ return s.Val, true
+ }
+ }
+ return 0, false
+}
+
+// Setting returns the setting from the frame at the given 0-based index.
+// The index must be >= 0 and less than f.NumSettings().
+func (f *SettingsFrame) Setting(i int) Setting {
+ buf := f.p
+ return Setting{
+ ID: SettingID(binary.BigEndian.Uint16(buf[i*6 : i*6+2])),
+ Val: binary.BigEndian.Uint32(buf[i*6+2 : i*6+6]),
+ }
+}
+
+func (f *SettingsFrame) NumSettings() int { return len(f.p) / 6 }
+
+// HasDuplicates reports whether f contains any duplicate setting IDs.
+func (f *SettingsFrame) HasDuplicates() bool {
+ num := f.NumSettings()
+ if num == 0 {
+ return false
+ }
+ // If it's small enough (the common case), just do the n^2
+ // thing and avoid a map allocation.
+ if num < 10 {
+ for i := 0; i < num; i++ {
+ idi := f.Setting(i).ID
+ for j := i + 1; j < num; j++ {
+ idj := f.Setting(j).ID
+ if idi == idj {
+ return true
+ }
+ }
+ }
+ return false
+ }
+ seen := map[SettingID]bool{}
+ for i := 0; i < num; i++ {
+ id := f.Setting(i).ID
+ if seen[id] {
+ return true
+ }
+ seen[id] = true
+ }
+ return false
+}
+
+// ForeachSetting runs fn for each setting.
+// It stops and returns the first error.
+func (f *SettingsFrame) ForeachSetting(fn func(Setting) error) error {
+ f.checkValid()
+ for i := 0; i < f.NumSettings(); i++ {
+ if err := fn(f.Setting(i)); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+// WriteSettings writes a SETTINGS frame with zero or more settings
+// specified and the ACK bit not set.
+//
+// It will perform exactly one Write to the underlying Writer.
+// It is the caller's responsibility to not call other Write methods concurrently.
+func (f *Framer) WriteSettings(settings ...Setting) error {
+ f.startWrite(FrameSettings, 0, 0)
+ for _, s := range settings {
+ f.writeUint16(uint16(s.ID))
+ f.writeUint32(s.Val)
+ }
+ return f.endWrite()
+}
+
+// WriteSettingsAck writes an empty SETTINGS frame with the ACK bit set.
+//
+// It will perform exactly one Write to the underlying Writer.
+// It is the caller's responsibility to not call other Write methods concurrently.
+func (f *Framer) WriteSettingsAck() error {
+ f.startWrite(FrameSettings, FlagSettingsAck, 0)
+ return f.endWrite()
+}
+
+// A PingFrame is a mechanism for measuring a minimal round trip time
+// from the sender, as well as determining whether an idle connection
+// is still functional.
+// See http://http2.github.io/http2-spec/#rfc.section.6.7
+type PingFrame struct {
+ FrameHeader
+ Data [8]byte
+}
+
+func (f *PingFrame) IsAck() bool { return f.Flags.Has(FlagPingAck) }
+
+func parsePingFrame(_ *frameCache, fh FrameHeader, payload []byte) (Frame, error) {
+ if len(payload) != 8 {
+ return nil, ConnectionError(ErrCodeFrameSize)
+ }
+ if fh.StreamID != 0 {
+ return nil, ConnectionError(ErrCodeProtocol)
+ }
+ f := &PingFrame{FrameHeader: fh}
+ copy(f.Data[:], payload)
+ return f, nil
+}
+
+func (f *Framer) WritePing(ack bool, data [8]byte) error {
+ var flags Flags
+ if ack {
+ flags = FlagPingAck
+ }
+ f.startWrite(FramePing, flags, 0)
+ f.writeBytes(data[:])
+ return f.endWrite()
+}
+
+// A GoAwayFrame informs the remote peer to stop creating streams on this connection.
+// See http://http2.github.io/http2-spec/#rfc.section.6.8
+type GoAwayFrame struct {
+ FrameHeader
+ LastStreamID uint32
+ ErrCode ErrCode
+ debugData []byte
+}
+
+// DebugData returns any debug data in the GOAWAY frame. Its contents
+// are not defined.
+// The caller must not retain the returned memory past the next
+// call to ReadFrame.
+func (f *GoAwayFrame) DebugData() []byte {
+ f.checkValid()
+ return f.debugData
+}
+
+func parseGoAwayFrame(_ *frameCache, fh FrameHeader, p []byte) (Frame, error) {
+ if fh.StreamID != 0 {
+ return nil, ConnectionError(ErrCodeProtocol)
+ }
+ if len(p) < 8 {
+ return nil, ConnectionError(ErrCodeFrameSize)
+ }
+ return &GoAwayFrame{
+ FrameHeader: fh,
+ LastStreamID: binary.BigEndian.Uint32(p[:4]) & (1<<31 - 1),
+ ErrCode: ErrCode(binary.BigEndian.Uint32(p[4:8])),
+ debugData: p[8:],
+ }, nil
+}
+
+func (f *Framer) WriteGoAway(maxStreamID uint32, code ErrCode, debugData []byte) error {
+ f.startWrite(FrameGoAway, 0, 0)
+ f.writeUint32(maxStreamID & (1<<31 - 1))
+ f.writeUint32(uint32(code))
+ f.writeBytes(debugData)
+ return f.endWrite()
+}
+
+// An UnknownFrame is the frame type returned when the frame type is unknown
+// or no specific frame type parser exists.
+type UnknownFrame struct {
+ FrameHeader
+ p []byte
+}
+
+// Payload returns the frame's payload (after the header). It is not
+// valid to call this method after a subsequent call to
+// Framer.ReadFrame, nor is it valid to retain the returned slice.
+// The memory is owned by the Framer and is invalidated when the next
+// frame is read.
+func (f *UnknownFrame) Payload() []byte {
+ f.checkValid()
+ return f.p
+}
+
+func parseUnknownFrame(_ *frameCache, fh FrameHeader, p []byte) (Frame, error) {
+ return &UnknownFrame{fh, p}, nil
+}
+
+// A WindowUpdateFrame is used to implement flow control.
+// See http://http2.github.io/http2-spec/#rfc.section.6.9
+type WindowUpdateFrame struct {
+ FrameHeader
+ Increment uint32 // never read with high bit set
+}
+
+func parseWindowUpdateFrame(_ *frameCache, fh FrameHeader, p []byte) (Frame, error) {
+ if len(p) != 4 {
+ return nil, ConnectionError(ErrCodeFrameSize)
+ }
+ inc := binary.BigEndian.Uint32(p[:4]) & 0x7fffffff // mask off high reserved bit
+ if inc == 0 {
+ // A receiver MUST treat the receipt of a
+ // WINDOW_UPDATE frame with an flow control window
+ // increment of 0 as a stream error (Section 5.4.2) of
+ // type PROTOCOL_ERROR; errors on the connection flow
+ // control window MUST be treated as a connection
+ // error (Section 5.4.1).
+ if fh.StreamID == 0 {
+ return nil, ConnectionError(ErrCodeProtocol)
+ }
+ return nil, streamError(fh.StreamID, ErrCodeProtocol)
+ }
+ return &WindowUpdateFrame{
+ FrameHeader: fh,
+ Increment: inc,
+ }, nil
+}
+
+// WriteWindowUpdate writes a WINDOW_UPDATE frame.
+// The increment value must be between 1 and 2,147,483,647, inclusive.
+// If the Stream ID is zero, the window update applies to the
+// connection as a whole.
+func (f *Framer) WriteWindowUpdate(streamID, incr uint32) error {
+ // "The legal range for the increment to the flow control window is 1 to 2^31-1 (2,147,483,647) octets."
+ if (incr < 1 || incr > 2147483647) && !f.AllowIllegalWrites {
+ return errors.New("illegal window increment value")
+ }
+ f.startWrite(FrameWindowUpdate, 0, streamID)
+ f.writeUint32(incr)
+ return f.endWrite()
+}
+
+// A HeadersFrame is used to open a stream and additionally carries a
+// header block fragment.
+type HeadersFrame struct {
+ FrameHeader
+
+ // Priority is set if FlagHeadersPriority is set in the FrameHeader.
+ Priority PriorityParam
+
+ headerFragBuf []byte // not owned
+}
+
+func (f *HeadersFrame) HeaderBlockFragment() []byte {
+ f.checkValid()
+ return f.headerFragBuf
+}
+
+func (f *HeadersFrame) HeadersEnded() bool {
+ return f.FrameHeader.Flags.Has(FlagHeadersEndHeaders)
+}
+
+func (f *HeadersFrame) StreamEnded() bool {
+ return f.FrameHeader.Flags.Has(FlagHeadersEndStream)
+}
+
+func (f *HeadersFrame) HasPriority() bool {
+ return f.FrameHeader.Flags.Has(FlagHeadersPriority)
+}
+
+func parseHeadersFrame(_ *frameCache, fh FrameHeader, p []byte) (_ Frame, err error) {
+ hf := &HeadersFrame{
+ FrameHeader: fh,
+ }
+ if fh.StreamID == 0 {
+ // HEADERS frames MUST be associated with a stream. If a HEADERS frame
+ // is received whose stream identifier field is 0x0, the recipient MUST
+ // respond with a connection error (Section 5.4.1) of type
+ // PROTOCOL_ERROR.
+ return nil, connError{ErrCodeProtocol, "HEADERS frame with stream ID 0"}
+ }
+ var padLength uint8
+ if fh.Flags.Has(FlagHeadersPadded) {
+ if p, padLength, err = readByte(p); err != nil {
+ return
+ }
+ }
+ if fh.Flags.Has(FlagHeadersPriority) {
+ var v uint32
+ p, v, err = readUint32(p)
+ if err != nil {
+ return nil, err
+ }
+ hf.Priority.StreamDep = v & 0x7fffffff
+ hf.Priority.Exclusive = (v != hf.Priority.StreamDep) // high bit was set
+ p, hf.Priority.Weight, err = readByte(p)
+ if err != nil {
+ return nil, err
+ }
+ }
+ if len(p)-int(padLength) <= 0 {
+ return nil, streamError(fh.StreamID, ErrCodeProtocol)
+ }
+ hf.headerFragBuf = p[:len(p)-int(padLength)]
+ return hf, nil
+}
+
+// HeadersFrameParam are the parameters for writing a HEADERS frame.
+type HeadersFrameParam struct {
+ // StreamID is the required Stream ID to initiate.
+ StreamID uint32
+ // BlockFragment is part (or all) of a Header Block.
+ BlockFragment []byte
+
+ // EndStream indicates that the header block is the last that
+ // the endpoint will send for the identified stream. Setting
+ // this flag causes the stream to enter one of "half closed"
+ // states.
+ EndStream bool
+
+ // EndHeaders indicates that this frame contains an entire
+ // header block and is not followed by any
+ // CONTINUATION frames.
+ EndHeaders bool
+
+ // PadLength is the optional number of bytes of zeros to add
+ // to this frame.
+ PadLength uint8
+
+ // Priority, if non-zero, includes stream priority information
+ // in the HEADER frame.
+ Priority PriorityParam
+}
+
+// WriteHeaders writes a single HEADERS frame.
+//
+// This is a low-level header writing method. Encoding headers and
+// splitting them into any necessary CONTINUATION frames is handled
+// elsewhere.
+//
+// It will perform exactly one Write to the underlying Writer.
+// It is the caller's responsibility to not call other Write methods concurrently.
+func (f *Framer) WriteHeaders(p HeadersFrameParam) error {
+ if !validStreamID(p.StreamID) && !f.AllowIllegalWrites {
+ return errStreamID
+ }
+ var flags Flags
+ if p.PadLength != 0 {
+ flags |= FlagHeadersPadded
+ }
+ if p.EndStream {
+ flags |= FlagHeadersEndStream
+ }
+ if p.EndHeaders {
+ flags |= FlagHeadersEndHeaders
+ }
+ if !p.Priority.IsZero() {
+ flags |= FlagHeadersPriority
+ }
+ f.startWrite(FrameHeaders, flags, p.StreamID)
+ if p.PadLength != 0 {
+ f.writeByte(p.PadLength)
+ }
+ if !p.Priority.IsZero() {
+ v := p.Priority.StreamDep
+ if !validStreamIDOrZero(v) && !f.AllowIllegalWrites {
+ return errDepStreamID
+ }
+ if p.Priority.Exclusive {
+ v |= 1 << 31
+ }
+ f.writeUint32(v)
+ f.writeByte(p.Priority.Weight)
+ }
+ f.wbuf = append(f.wbuf, p.BlockFragment...)
+ f.wbuf = append(f.wbuf, padZeros[:p.PadLength]...)
+ return f.endWrite()
+}
+
+// A PriorityFrame specifies the sender-advised priority of a stream.
+// See http://http2.github.io/http2-spec/#rfc.section.6.3
+type PriorityFrame struct {
+ FrameHeader
+ PriorityParam
+}
+
+// PriorityParam are the stream prioritzation parameters.
+type PriorityParam struct {
+ // StreamDep is a 31-bit stream identifier for the
+ // stream that this stream depends on. Zero means no
+ // dependency.
+ StreamDep uint32
+
+ // Exclusive is whether the dependency is exclusive.
+ Exclusive bool
+
+ // Weight is the stream's zero-indexed weight. It should be
+ // set together with StreamDep, or neither should be set. Per
+ // the spec, "Add one to the value to obtain a weight between
+ // 1 and 256."
+ Weight uint8
+}
+
+func (p PriorityParam) IsZero() bool {
+ return p == PriorityParam{}
+}
+
+func parsePriorityFrame(_ *frameCache, fh FrameHeader, payload []byte) (Frame, error) {
+ if fh.StreamID == 0 {
+ return nil, connError{ErrCodeProtocol, "PRIORITY frame with stream ID 0"}
+ }
+ if len(payload) != 5 {
+ return nil, connError{ErrCodeFrameSize, fmt.Sprintf("PRIORITY frame payload size was %d; want 5", len(payload))}
+ }
+ v := binary.BigEndian.Uint32(payload[:4])
+ streamID := v & 0x7fffffff // mask off high bit
+ return &PriorityFrame{
+ FrameHeader: fh,
+ PriorityParam: PriorityParam{
+ Weight: payload[4],
+ StreamDep: streamID,
+ Exclusive: streamID != v, // was high bit set?
+ },
+ }, nil
+}
+
+// WritePriority writes a PRIORITY frame.
+//
+// It will perform exactly one Write to the underlying Writer.
+// It is the caller's responsibility to not call other Write methods concurrently.
+func (f *Framer) WritePriority(streamID uint32, p PriorityParam) error {
+ if !validStreamID(streamID) && !f.AllowIllegalWrites {
+ return errStreamID
+ }
+ if !validStreamIDOrZero(p.StreamDep) {
+ return errDepStreamID
+ }
+ f.startWrite(FramePriority, 0, streamID)
+ v := p.StreamDep
+ if p.Exclusive {
+ v |= 1 << 31
+ }
+ f.writeUint32(v)
+ f.writeByte(p.Weight)
+ return f.endWrite()
+}
+
+// A RSTStreamFrame allows for abnormal termination of a stream.
+// See http://http2.github.io/http2-spec/#rfc.section.6.4
+type RSTStreamFrame struct {
+ FrameHeader
+ ErrCode ErrCode
+}
+
+func parseRSTStreamFrame(_ *frameCache, fh FrameHeader, p []byte) (Frame, error) {
+ if len(p) != 4 {
+ return nil, ConnectionError(ErrCodeFrameSize)
+ }
+ if fh.StreamID == 0 {
+ return nil, ConnectionError(ErrCodeProtocol)
+ }
+ return &RSTStreamFrame{fh, ErrCode(binary.BigEndian.Uint32(p[:4]))}, nil
+}
+
+// WriteRSTStream writes a RST_STREAM frame.
+//
+// It will perform exactly one Write to the underlying Writer.
+// It is the caller's responsibility to not call other Write methods concurrently.
+func (f *Framer) WriteRSTStream(streamID uint32, code ErrCode) error {
+ if !validStreamID(streamID) && !f.AllowIllegalWrites {
+ return errStreamID
+ }
+ f.startWrite(FrameRSTStream, 0, streamID)
+ f.writeUint32(uint32(code))
+ return f.endWrite()
+}
+
+// A ContinuationFrame is used to continue a sequence of header block fragments.
+// See http://http2.github.io/http2-spec/#rfc.section.6.10
+type ContinuationFrame struct {
+ FrameHeader
+ headerFragBuf []byte
+}
+
+func parseContinuationFrame(_ *frameCache, fh FrameHeader, p []byte) (Frame, error) {
+ if fh.StreamID == 0 {
+ return nil, connError{ErrCodeProtocol, "CONTINUATION frame with stream ID 0"}
+ }
+ return &ContinuationFrame{fh, p}, nil
+}
+
+func (f *ContinuationFrame) HeaderBlockFragment() []byte {
+ f.checkValid()
+ return f.headerFragBuf
+}
+
+func (f *ContinuationFrame) HeadersEnded() bool {
+ return f.FrameHeader.Flags.Has(FlagContinuationEndHeaders)
+}
+
+// WriteContinuation writes a CONTINUATION frame.
+//
+// It will perform exactly one Write to the underlying Writer.
+// It is the caller's responsibility to not call other Write methods concurrently.
+func (f *Framer) WriteContinuation(streamID uint32, endHeaders bool, headerBlockFragment []byte) error {
+ if !validStreamID(streamID) && !f.AllowIllegalWrites {
+ return errStreamID
+ }
+ var flags Flags
+ if endHeaders {
+ flags |= FlagContinuationEndHeaders
+ }
+ f.startWrite(FrameContinuation, flags, streamID)
+ f.wbuf = append(f.wbuf, headerBlockFragment...)
+ return f.endWrite()
+}
+
+// A PushPromiseFrame is used to initiate a server stream.
+// See http://http2.github.io/http2-spec/#rfc.section.6.6
+type PushPromiseFrame struct {
+ FrameHeader
+ PromiseID uint32
+ headerFragBuf []byte // not owned
+}
+
+func (f *PushPromiseFrame) HeaderBlockFragment() []byte {
+ f.checkValid()
+ return f.headerFragBuf
+}
+
+func (f *PushPromiseFrame) HeadersEnded() bool {
+ return f.FrameHeader.Flags.Has(FlagPushPromiseEndHeaders)
+}
+
+func parsePushPromise(_ *frameCache, fh FrameHeader, p []byte) (_ Frame, err error) {
+ pp := &PushPromiseFrame{
+ FrameHeader: fh,
+ }
+ if pp.StreamID == 0 {
+ // PUSH_PROMISE frames MUST be associated with an existing,
+ // peer-initiated stream. The stream identifier of a
+ // PUSH_PROMISE frame indicates the stream it is associated
+ // with. If the stream identifier field specifies the value
+ // 0x0, a recipient MUST respond with a connection error
+ // (Section 5.4.1) of type PROTOCOL_ERROR.
+ return nil, ConnectionError(ErrCodeProtocol)
+ }
+ // The PUSH_PROMISE frame includes optional padding.
+ // Padding fields and flags are identical to those defined for DATA frames
+ var padLength uint8
+ if fh.Flags.Has(FlagPushPromisePadded) {
+ if p, padLength, err = readByte(p); err != nil {
+ return
+ }
+ }
+
+ p, pp.PromiseID, err = readUint32(p)
+ if err != nil {
+ return
+ }
+ pp.PromiseID = pp.PromiseID & (1<<31 - 1)
+
+ if int(padLength) > len(p) {
+ // like the DATA frame, error out if padding is longer than the body.
+ return nil, ConnectionError(ErrCodeProtocol)
+ }
+ pp.headerFragBuf = p[:len(p)-int(padLength)]
+ return pp, nil
+}
+
+// PushPromiseParam are the parameters for writing a PUSH_PROMISE frame.
+type PushPromiseParam struct {
+ // StreamID is the required Stream ID to initiate.
+ StreamID uint32
+
+ // PromiseID is the required Stream ID which this
+ // Push Promises
+ PromiseID uint32
+
+ // BlockFragment is part (or all) of a Header Block.
+ BlockFragment []byte
+
+ // EndHeaders indicates that this frame contains an entire
+ // header block and is not followed by any
+ // CONTINUATION frames.
+ EndHeaders bool
+
+ // PadLength is the optional number of bytes of zeros to add
+ // to this frame.
+ PadLength uint8
+}
+
+// WritePushPromise writes a single PushPromise Frame.
+//
+// As with Header Frames, This is the low level call for writing
+// individual frames. Continuation frames are handled elsewhere.
+//
+// It will perform exactly one Write to the underlying Writer.
+// It is the caller's responsibility to not call other Write methods concurrently.
+func (f *Framer) WritePushPromise(p PushPromiseParam) error {
+ if !validStreamID(p.StreamID) && !f.AllowIllegalWrites {
+ return errStreamID
+ }
+ var flags Flags
+ if p.PadLength != 0 {
+ flags |= FlagPushPromisePadded
+ }
+ if p.EndHeaders {
+ flags |= FlagPushPromiseEndHeaders
+ }
+ f.startWrite(FramePushPromise, flags, p.StreamID)
+ if p.PadLength != 0 {
+ f.writeByte(p.PadLength)
+ }
+ if !validStreamID(p.PromiseID) && !f.AllowIllegalWrites {
+ return errStreamID
+ }
+ f.writeUint32(p.PromiseID)
+ f.wbuf = append(f.wbuf, p.BlockFragment...)
+ f.wbuf = append(f.wbuf, padZeros[:p.PadLength]...)
+ return f.endWrite()
+}
+
+// WriteRawFrame writes a raw frame. This can be used to write
+// extension frames unknown to this package.
+func (f *Framer) WriteRawFrame(t FrameType, flags Flags, streamID uint32, payload []byte) error {
+ f.startWrite(t, flags, streamID)
+ f.writeBytes(payload)
+ return f.endWrite()
+}
+
+func readByte(p []byte) (remain []byte, b byte, err error) {
+ if len(p) == 0 {
+ return nil, 0, io.ErrUnexpectedEOF
+ }
+ return p[1:], p[0], nil
+}
+
+func readUint32(p []byte) (remain []byte, v uint32, err error) {
+ if len(p) < 4 {
+ return nil, 0, io.ErrUnexpectedEOF
+ }
+ return p[4:], binary.BigEndian.Uint32(p[:4]), nil
+}
+
+type streamEnder interface {
+ StreamEnded() bool
+}
+
+type headersEnder interface {
+ HeadersEnded() bool
+}
+
+type headersOrContinuation interface {
+ headersEnder
+ HeaderBlockFragment() []byte
+}
+
+// A MetaHeadersFrame is the representation of one HEADERS frame and
+// zero or more contiguous CONTINUATION frames and the decoding of
+// their HPACK-encoded contents.
+//
+// This type of frame does not appear on the wire and is only returned
+// by the Framer when Framer.ReadMetaHeaders is set.
+type MetaHeadersFrame struct {
+ *HeadersFrame
+
+ // Fields are the fields contained in the HEADERS and
+ // CONTINUATION frames. The underlying slice is owned by the
+ // Framer and must not be retained after the next call to
+ // ReadFrame.
+ //
+ // Fields are guaranteed to be in the correct http2 order and
+ // not have unknown pseudo header fields or invalid header
+ // field names or values. Required pseudo header fields may be
+ // missing, however. Use the MetaHeadersFrame.Pseudo accessor
+ // method access pseudo headers.
+ Fields []hpack.HeaderField
+
+ // Truncated is whether the max header list size limit was hit
+ // and Fields is incomplete. The hpack decoder state is still
+ // valid, however.
+ Truncated bool
+}
+
+// PseudoValue returns the given pseudo header field's value.
+// The provided pseudo field should not contain the leading colon.
+func (mh *MetaHeadersFrame) PseudoValue(pseudo string) string {
+ for _, hf := range mh.Fields {
+ if !hf.IsPseudo() {
+ return ""
+ }
+ if hf.Name[1:] == pseudo {
+ return hf.Value
+ }
+ }
+ return ""
+}
+
+// RegularFields returns the regular (non-pseudo) header fields of mh.
+// The caller does not own the returned slice.
+func (mh *MetaHeadersFrame) RegularFields() []hpack.HeaderField {
+ for i, hf := range mh.Fields {
+ if !hf.IsPseudo() {
+ return mh.Fields[i:]
+ }
+ }
+ return nil
+}
+
+// PseudoFields returns the pseudo header fields of mh.
+// The caller does not own the returned slice.
+func (mh *MetaHeadersFrame) PseudoFields() []hpack.HeaderField {
+ for i, hf := range mh.Fields {
+ if !hf.IsPseudo() {
+ return mh.Fields[:i]
+ }
+ }
+ return mh.Fields
+}
+
+func (mh *MetaHeadersFrame) checkPseudos() error {
+ var isRequest, isResponse bool
+ pf := mh.PseudoFields()
+ for i, hf := range pf {
+ switch hf.Name {
+ case ":method", ":path", ":scheme", ":authority":
+ isRequest = true
+ case ":status":
+ isResponse = true
+ default:
+ return pseudoHeaderError(hf.Name)
+ }
+ // Check for duplicates.
+ // This would be a bad algorithm, but N is 4.
+ // And this doesn't allocate.
+ for _, hf2 := range pf[:i] {
+ if hf.Name == hf2.Name {
+ return duplicatePseudoHeaderError(hf.Name)
+ }
+ }
+ }
+ if isRequest && isResponse {
+ return errMixPseudoHeaderTypes
+ }
+ return nil
+}
+
+func (fr *Framer) maxHeaderStringLen() int {
+ v := fr.maxHeaderListSize()
+ if uint32(int(v)) == v {
+ return int(v)
+ }
+ // They had a crazy big number for MaxHeaderBytes anyway,
+ // so give them unlimited header lengths:
+ return 0
+}
+
+// readMetaFrame returns 0 or more CONTINUATION frames from fr and
+// merge them into the provided hf and returns a MetaHeadersFrame
+// with the decoded hpack values.
+func (fr *Framer) readMetaFrame(hf *HeadersFrame) (*MetaHeadersFrame, error) {
+ if fr.AllowIllegalReads {
+ return nil, errors.New("illegal use of AllowIllegalReads with ReadMetaHeaders")
+ }
+ mh := &MetaHeadersFrame{
+ HeadersFrame: hf,
+ }
+ var remainSize = fr.maxHeaderListSize()
+ var sawRegular bool
+
+ var invalid error // pseudo header field errors
+ hdec := fr.ReadMetaHeaders
+ hdec.SetEmitEnabled(true)
+ hdec.SetMaxStringLength(fr.maxHeaderStringLen())
+ hdec.SetEmitFunc(func(hf hpack.HeaderField) {
+ if VerboseLogs && fr.logReads {
+ fr.debugReadLoggerf("http2: decoded hpack field %+v", hf)
+ }
+ if !httpguts.ValidHeaderFieldValue(hf.Value) {
+ invalid = headerFieldValueError(hf.Value)
+ }
+ isPseudo := strings.HasPrefix(hf.Name, ":")
+ if isPseudo {
+ if sawRegular {
+ invalid = errPseudoAfterRegular
+ }
+ } else {
+ sawRegular = true
+ if !validWireHeaderFieldName(hf.Name) {
+ invalid = headerFieldNameError(hf.Name)
+ }
+ }
+
+ if invalid != nil {
+ hdec.SetEmitEnabled(false)
+ return
+ }
+
+ size := hf.Size()
+ if size > remainSize {
+ hdec.SetEmitEnabled(false)
+ mh.Truncated = true
+ return
+ }
+ remainSize -= size
+
+ mh.Fields = append(mh.Fields, hf)
+ })
+ // Lose reference to MetaHeadersFrame:
+ defer hdec.SetEmitFunc(func(hf hpack.HeaderField) {})
+
+ var hc headersOrContinuation = hf
+ for {
+ frag := hc.HeaderBlockFragment()
+ if _, err := hdec.Write(frag); err != nil {
+ return nil, ConnectionError(ErrCodeCompression)
+ }
+
+ if hc.HeadersEnded() {
+ break
+ }
+ if f, err := fr.ReadFrame(); err != nil {
+ return nil, err
+ } else {
+ hc = f.(*ContinuationFrame) // guaranteed by checkFrameOrder
+ }
+ }
+
+ mh.HeadersFrame.headerFragBuf = nil
+ mh.HeadersFrame.invalidate()
+
+ if err := hdec.Close(); err != nil {
+ return nil, ConnectionError(ErrCodeCompression)
+ }
+ if invalid != nil {
+ fr.errDetail = invalid
+ if VerboseLogs {
+ log.Printf("http2: invalid header: %v", invalid)
+ }
+ return nil, StreamError{mh.StreamID, ErrCodeProtocol, invalid}
+ }
+ if err := mh.checkPseudos(); err != nil {
+ fr.errDetail = err
+ if VerboseLogs {
+ log.Printf("http2: invalid pseudo headers: %v", err)
+ }
+ return nil, StreamError{mh.StreamID, ErrCodeProtocol, err}
+ }
+ return mh, nil
+}
+
+func summarizeFrame(f Frame) string {
+ var buf bytes.Buffer
+ f.Header().writeDebug(&buf)
+ switch f := f.(type) {
+ case *SettingsFrame:
+ n := 0
+ f.ForeachSetting(func(s Setting) error {
+ n++
+ if n == 1 {
+ buf.WriteString(", settings:")
+ }
+ fmt.Fprintf(&buf, " %v=%v,", s.ID, s.Val)
+ return nil
+ })
+ if n > 0 {
+ buf.Truncate(buf.Len() - 1) // remove trailing comma
+ }
+ case *DataFrame:
+ data := f.Data()
+ const max = 256
+ if len(data) > max {
+ data = data[:max]
+ }
+ fmt.Fprintf(&buf, " data=%q", data)
+ if len(f.Data()) > max {
+ fmt.Fprintf(&buf, " (%d bytes omitted)", len(f.Data())-max)
+ }
+ case *WindowUpdateFrame:
+ if f.StreamID == 0 {
+ buf.WriteString(" (conn)")
+ }
+ fmt.Fprintf(&buf, " incr=%v", f.Increment)
+ case *PingFrame:
+ fmt.Fprintf(&buf, " ping=%q", f.Data[:])
+ case *GoAwayFrame:
+ fmt.Fprintf(&buf, " LastStreamID=%v ErrCode=%v Debug=%q",
+ f.LastStreamID, f.ErrCode, f.debugData)
+ case *RSTStreamFrame:
+ fmt.Fprintf(&buf, " ErrCode=%v", f.ErrCode)
+ }
+ return buf.String()
+}
diff --git a/vendor/golang.org/x/net/http2/go111.go b/vendor/golang.org/x/net/http2/go111.go
new file mode 100644
index 000000000..3a131016b
--- /dev/null
+++ b/vendor/golang.org/x/net/http2/go111.go
@@ -0,0 +1,29 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build go1.11
+
+package http2
+
+import (
+ "net/http/httptrace"
+ "net/textproto"
+)
+
+func traceHasWroteHeaderField(trace *httptrace.ClientTrace) bool {
+ return trace != nil && trace.WroteHeaderField != nil
+}
+
+func traceWroteHeaderField(trace *httptrace.ClientTrace, k, v string) {
+ if trace != nil && trace.WroteHeaderField != nil {
+ trace.WroteHeaderField(k, []string{v})
+ }
+}
+
+func traceGot1xxResponseFunc(trace *httptrace.ClientTrace) func(int, textproto.MIMEHeader) error {
+ if trace != nil {
+ return trace.Got1xxResponse
+ }
+ return nil
+}
diff --git a/vendor/golang.org/x/net/http2/gotrack.go b/vendor/golang.org/x/net/http2/gotrack.go
new file mode 100644
index 000000000..9933c9f8c
--- /dev/null
+++ b/vendor/golang.org/x/net/http2/gotrack.go
@@ -0,0 +1,170 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Defensive debug-only utility to track that functions run on the
+// goroutine that they're supposed to.
+
+package http2
+
+import (
+ "bytes"
+ "errors"
+ "fmt"
+ "os"
+ "runtime"
+ "strconv"
+ "sync"
+)
+
+var DebugGoroutines = os.Getenv("DEBUG_HTTP2_GOROUTINES") == "1"
+
+type goroutineLock uint64
+
+func newGoroutineLock() goroutineLock {
+ if !DebugGoroutines {
+ return 0
+ }
+ return goroutineLock(curGoroutineID())
+}
+
+func (g goroutineLock) check() {
+ if !DebugGoroutines {
+ return
+ }
+ if curGoroutineID() != uint64(g) {
+ panic("running on the wrong goroutine")
+ }
+}
+
+func (g goroutineLock) checkNotOn() {
+ if !DebugGoroutines {
+ return
+ }
+ if curGoroutineID() == uint64(g) {
+ panic("running on the wrong goroutine")
+ }
+}
+
+var goroutineSpace = []byte("goroutine ")
+
+func curGoroutineID() uint64 {
+ bp := littleBuf.Get().(*[]byte)
+ defer littleBuf.Put(bp)
+ b := *bp
+ b = b[:runtime.Stack(b, false)]
+ // Parse the 4707 out of "goroutine 4707 ["
+ b = bytes.TrimPrefix(b, goroutineSpace)
+ i := bytes.IndexByte(b, ' ')
+ if i < 0 {
+ panic(fmt.Sprintf("No space found in %q", b))
+ }
+ b = b[:i]
+ n, err := parseUintBytes(b, 10, 64)
+ if err != nil {
+ panic(fmt.Sprintf("Failed to parse goroutine ID out of %q: %v", b, err))
+ }
+ return n
+}
+
+var littleBuf = sync.Pool{
+ New: func() interface{} {
+ buf := make([]byte, 64)
+ return &buf
+ },
+}
+
+// parseUintBytes is like strconv.ParseUint, but using a []byte.
+func parseUintBytes(s []byte, base int, bitSize int) (n uint64, err error) {
+ var cutoff, maxVal uint64
+
+ if bitSize == 0 {
+ bitSize = int(strconv.IntSize)
+ }
+
+ s0 := s
+ switch {
+ case len(s) < 1:
+ err = strconv.ErrSyntax
+ goto Error
+
+ case 2 <= base && base <= 36:
+ // valid base; nothing to do
+
+ case base == 0:
+ // Look for octal, hex prefix.
+ switch {
+ case s[0] == '0' && len(s) > 1 && (s[1] == 'x' || s[1] == 'X'):
+ base = 16
+ s = s[2:]
+ if len(s) < 1 {
+ err = strconv.ErrSyntax
+ goto Error
+ }
+ case s[0] == '0':
+ base = 8
+ default:
+ base = 10
+ }
+
+ default:
+ err = errors.New("invalid base " + strconv.Itoa(base))
+ goto Error
+ }
+
+ n = 0
+ cutoff = cutoff64(base)
+ maxVal = 1<<uint(bitSize) - 1
+
+ for i := 0; i < len(s); i++ {
+ var v byte
+ d := s[i]
+ switch {
+ case '0' <= d && d <= '9':
+ v = d - '0'
+ case 'a' <= d && d <= 'z':
+ v = d - 'a' + 10
+ case 'A' <= d && d <= 'Z':
+ v = d - 'A' + 10
+ default:
+ n = 0
+ err = strconv.ErrSyntax
+ goto Error
+ }
+ if int(v) >= base {
+ n = 0
+ err = strconv.ErrSyntax
+ goto Error
+ }
+
+ if n >= cutoff {
+ // n*base overflows
+ n = 1<<64 - 1
+ err = strconv.ErrRange
+ goto Error
+ }
+ n *= uint64(base)
+
+ n1 := n + uint64(v)
+ if n1 < n || n1 > maxVal {
+ // n+v overflows
+ n = 1<<64 - 1
+ err = strconv.ErrRange
+ goto Error
+ }
+ n = n1
+ }
+
+ return n, nil
+
+Error:
+ return n, &strconv.NumError{Func: "ParseUint", Num: string(s0), Err: err}
+}
+
+// Return the first number n such that n*base >= 1<<64.
+func cutoff64(base int) uint64 {
+ if base < 2 {
+ return 0
+ }
+ return (1<<64-1)/uint64(base) + 1
+}
diff --git a/vendor/golang.org/x/net/http2/headermap.go b/vendor/golang.org/x/net/http2/headermap.go
new file mode 100644
index 000000000..c3ff3fa1c
--- /dev/null
+++ b/vendor/golang.org/x/net/http2/headermap.go
@@ -0,0 +1,88 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package http2
+
+import (
+ "net/http"
+ "strings"
+ "sync"
+)
+
+var (
+ commonBuildOnce sync.Once
+ commonLowerHeader map[string]string // Go-Canonical-Case -> lower-case
+ commonCanonHeader map[string]string // lower-case -> Go-Canonical-Case
+)
+
+func buildCommonHeaderMapsOnce() {
+ commonBuildOnce.Do(buildCommonHeaderMaps)
+}
+
+func buildCommonHeaderMaps() {
+ common := []string{
+ "accept",
+ "accept-charset",
+ "accept-encoding",
+ "accept-language",
+ "accept-ranges",
+ "age",
+ "access-control-allow-origin",
+ "allow",
+ "authorization",
+ "cache-control",
+ "content-disposition",
+ "content-encoding",
+ "content-language",
+ "content-length",
+ "content-location",
+ "content-range",
+ "content-type",
+ "cookie",
+ "date",
+ "etag",
+ "expect",
+ "expires",
+ "from",
+ "host",
+ "if-match",
+ "if-modified-since",
+ "if-none-match",
+ "if-unmodified-since",
+ "last-modified",
+ "link",
+ "location",
+ "max-forwards",
+ "proxy-authenticate",
+ "proxy-authorization",
+ "range",
+ "referer",
+ "refresh",
+ "retry-after",
+ "server",
+ "set-cookie",
+ "strict-transport-security",
+ "trailer",
+ "transfer-encoding",
+ "user-agent",
+ "vary",
+ "via",
+ "www-authenticate",
+ }
+ commonLowerHeader = make(map[string]string, len(common))
+ commonCanonHeader = make(map[string]string, len(common))
+ for _, v := range common {
+ chk := http.CanonicalHeaderKey(v)
+ commonLowerHeader[chk] = v
+ commonCanonHeader[v] = chk
+ }
+}
+
+func lowerHeader(v string) string {
+ buildCommonHeaderMapsOnce()
+ if s, ok := commonLowerHeader[v]; ok {
+ return s
+ }
+ return strings.ToLower(v)
+}
diff --git a/vendor/golang.org/x/net/http2/hpack/encode.go b/vendor/golang.org/x/net/http2/hpack/encode.go
new file mode 100644
index 000000000..1565cf270
--- /dev/null
+++ b/vendor/golang.org/x/net/http2/hpack/encode.go
@@ -0,0 +1,240 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package hpack
+
+import (
+ "io"
+)
+
+const (
+ uint32Max = ^uint32(0)
+ initialHeaderTableSize = 4096
+)
+
+type Encoder struct {
+ dynTab dynamicTable
+ // minSize is the minimum table size set by
+ // SetMaxDynamicTableSize after the previous Header Table Size
+ // Update.
+ minSize uint32
+ // maxSizeLimit is the maximum table size this encoder
+ // supports. This will protect the encoder from too large
+ // size.
+ maxSizeLimit uint32
+ // tableSizeUpdate indicates whether "Header Table Size
+ // Update" is required.
+ tableSizeUpdate bool
+ w io.Writer
+ buf []byte
+}
+
+// NewEncoder returns a new Encoder which performs HPACK encoding. An
+// encoded data is written to w.
+func NewEncoder(w io.Writer) *Encoder {
+ e := &Encoder{
+ minSize: uint32Max,
+ maxSizeLimit: initialHeaderTableSize,
+ tableSizeUpdate: false,
+ w: w,
+ }
+ e.dynTab.table.init()
+ e.dynTab.setMaxSize(initialHeaderTableSize)
+ return e
+}
+
+// WriteField encodes f into a single Write to e's underlying Writer.
+// This function may also produce bytes for "Header Table Size Update"
+// if necessary. If produced, it is done before encoding f.
+func (e *Encoder) WriteField(f HeaderField) error {
+ e.buf = e.buf[:0]
+
+ if e.tableSizeUpdate {
+ e.tableSizeUpdate = false
+ if e.minSize < e.dynTab.maxSize {
+ e.buf = appendTableSize(e.buf, e.minSize)
+ }
+ e.minSize = uint32Max
+ e.buf = appendTableSize(e.buf, e.dynTab.maxSize)
+ }
+
+ idx, nameValueMatch := e.searchTable(f)
+ if nameValueMatch {
+ e.buf = appendIndexed(e.buf, idx)
+ } else {
+ indexing := e.shouldIndex(f)
+ if indexing {
+ e.dynTab.add(f)
+ }
+
+ if idx == 0 {
+ e.buf = appendNewName(e.buf, f, indexing)
+ } else {
+ e.buf = appendIndexedName(e.buf, f, idx, indexing)
+ }
+ }
+ n, err := e.w.Write(e.buf)
+ if err == nil && n != len(e.buf) {
+ err = io.ErrShortWrite
+ }
+ return err
+}
+
+// searchTable searches f in both stable and dynamic header tables.
+// The static header table is searched first. Only when there is no
+// exact match for both name and value, the dynamic header table is
+// then searched. If there is no match, i is 0. If both name and value
+// match, i is the matched index and nameValueMatch becomes true. If
+// only name matches, i points to that index and nameValueMatch
+// becomes false.
+func (e *Encoder) searchTable(f HeaderField) (i uint64, nameValueMatch bool) {
+ i, nameValueMatch = staticTable.search(f)
+ if nameValueMatch {
+ return i, true
+ }
+
+ j, nameValueMatch := e.dynTab.table.search(f)
+ if nameValueMatch || (i == 0 && j != 0) {
+ return j + uint64(staticTable.len()), nameValueMatch
+ }
+
+ return i, false
+}
+
+// SetMaxDynamicTableSize changes the dynamic header table size to v.
+// The actual size is bounded by the value passed to
+// SetMaxDynamicTableSizeLimit.
+func (e *Encoder) SetMaxDynamicTableSize(v uint32) {
+ if v > e.maxSizeLimit {
+ v = e.maxSizeLimit
+ }
+ if v < e.minSize {
+ e.minSize = v
+ }
+ e.tableSizeUpdate = true
+ e.dynTab.setMaxSize(v)
+}
+
+// SetMaxDynamicTableSizeLimit changes the maximum value that can be
+// specified in SetMaxDynamicTableSize to v. By default, it is set to
+// 4096, which is the same size of the default dynamic header table
+// size described in HPACK specification. If the current maximum
+// dynamic header table size is strictly greater than v, "Header Table
+// Size Update" will be done in the next WriteField call and the
+// maximum dynamic header table size is truncated to v.
+func (e *Encoder) SetMaxDynamicTableSizeLimit(v uint32) {
+ e.maxSizeLimit = v
+ if e.dynTab.maxSize > v {
+ e.tableSizeUpdate = true
+ e.dynTab.setMaxSize(v)
+ }
+}
+
+// shouldIndex reports whether f should be indexed.
+func (e *Encoder) shouldIndex(f HeaderField) bool {
+ return !f.Sensitive && f.Size() <= e.dynTab.maxSize
+}
+
+// appendIndexed appends index i, as encoded in "Indexed Header Field"
+// representation, to dst and returns the extended buffer.
+func appendIndexed(dst []byte, i uint64) []byte {
+ first := len(dst)
+ dst = appendVarInt(dst, 7, i)
+ dst[first] |= 0x80
+ return dst
+}
+
+// appendNewName appends f, as encoded in one of "Literal Header field
+// - New Name" representation variants, to dst and returns the
+// extended buffer.
+//
+// If f.Sensitive is true, "Never Indexed" representation is used. If
+// f.Sensitive is false and indexing is true, "Inremental Indexing"
+// representation is used.
+func appendNewName(dst []byte, f HeaderField, indexing bool) []byte {
+ dst = append(dst, encodeTypeByte(indexing, f.Sensitive))
+ dst = appendHpackString(dst, f.Name)
+ return appendHpackString(dst, f.Value)
+}
+
+// appendIndexedName appends f and index i referring indexed name
+// entry, as encoded in one of "Literal Header field - Indexed Name"
+// representation variants, to dst and returns the extended buffer.
+//
+// If f.Sensitive is true, "Never Indexed" representation is used. If
+// f.Sensitive is false and indexing is true, "Incremental Indexing"
+// representation is used.
+func appendIndexedName(dst []byte, f HeaderField, i uint64, indexing bool) []byte {
+ first := len(dst)
+ var n byte
+ if indexing {
+ n = 6
+ } else {
+ n = 4
+ }
+ dst = appendVarInt(dst, n, i)
+ dst[first] |= encodeTypeByte(indexing, f.Sensitive)
+ return appendHpackString(dst, f.Value)
+}
+
+// appendTableSize appends v, as encoded in "Header Table Size Update"
+// representation, to dst and returns the extended buffer.
+func appendTableSize(dst []byte, v uint32) []byte {
+ first := len(dst)
+ dst = appendVarInt(dst, 5, uint64(v))
+ dst[first] |= 0x20
+ return dst
+}
+
+// appendVarInt appends i, as encoded in variable integer form using n
+// bit prefix, to dst and returns the extended buffer.
+//
+// See
+// http://http2.github.io/http2-spec/compression.html#integer.representation
+func appendVarInt(dst []byte, n byte, i uint64) []byte {
+ k := uint64((1 << n) - 1)
+ if i < k {
+ return append(dst, byte(i))
+ }
+ dst = append(dst, byte(k))
+ i -= k
+ for ; i >= 128; i >>= 7 {
+ dst = append(dst, byte(0x80|(i&0x7f)))
+ }
+ return append(dst, byte(i))
+}
+
+// appendHpackString appends s, as encoded in "String Literal"
+// representation, to dst and returns the extended buffer.
+//
+// s will be encoded in Huffman codes only when it produces strictly
+// shorter byte string.
+func appendHpackString(dst []byte, s string) []byte {
+ huffmanLength := HuffmanEncodeLength(s)
+ if huffmanLength < uint64(len(s)) {
+ first := len(dst)
+ dst = appendVarInt(dst, 7, huffmanLength)
+ dst = AppendHuffmanString(dst, s)
+ dst[first] |= 0x80
+ } else {
+ dst = appendVarInt(dst, 7, uint64(len(s)))
+ dst = append(dst, s...)
+ }
+ return dst
+}
+
+// encodeTypeByte returns type byte. If sensitive is true, type byte
+// for "Never Indexed" representation is returned. If sensitive is
+// false and indexing is true, type byte for "Incremental Indexing"
+// representation is returned. Otherwise, type byte for "Without
+// Indexing" is returned.
+func encodeTypeByte(indexing, sensitive bool) byte {
+ if sensitive {
+ return 0x10
+ }
+ if indexing {
+ return 0x40
+ }
+ return 0
+}
diff --git a/vendor/golang.org/x/net/http2/hpack/hpack.go b/vendor/golang.org/x/net/http2/hpack/hpack.go
new file mode 100644
index 000000000..166788cee
--- /dev/null
+++ b/vendor/golang.org/x/net/http2/hpack/hpack.go
@@ -0,0 +1,496 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package hpack implements HPACK, a compression format for
+// efficiently representing HTTP header fields in the context of HTTP/2.
+//
+// See http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-09
+package hpack
+
+import (
+ "bytes"
+ "errors"
+ "fmt"
+)
+
+// A DecodingError is something the spec defines as a decoding error.
+type DecodingError struct {
+ Err error
+}
+
+func (de DecodingError) Error() string {
+ return fmt.Sprintf("decoding error: %v", de.Err)
+}
+
+// An InvalidIndexError is returned when an encoder references a table
+// entry before the static table or after the end of the dynamic table.
+type InvalidIndexError int
+
+func (e InvalidIndexError) Error() string {
+ return fmt.Sprintf("invalid indexed representation index %d", int(e))
+}
+
+// A HeaderField is a name-value pair. Both the name and value are
+// treated as opaque sequences of octets.
+type HeaderField struct {
+ Name, Value string
+
+ // Sensitive means that this header field should never be
+ // indexed.
+ Sensitive bool
+}
+
+// IsPseudo reports whether the header field is an http2 pseudo header.
+// That is, it reports whether it starts with a colon.
+// It is not otherwise guaranteed to be a valid pseudo header field,
+// though.
+func (hf HeaderField) IsPseudo() bool {
+ return len(hf.Name) != 0 && hf.Name[0] == ':'
+}
+
+func (hf HeaderField) String() string {
+ var suffix string
+ if hf.Sensitive {
+ suffix = " (sensitive)"
+ }
+ return fmt.Sprintf("header field %q = %q%s", hf.Name, hf.Value, suffix)
+}
+
+// Size returns the size of an entry per RFC 7541 section 4.1.
+func (hf HeaderField) Size() uint32 {
+ // http://http2.github.io/http2-spec/compression.html#rfc.section.4.1
+ // "The size of the dynamic table is the sum of the size of
+ // its entries. The size of an entry is the sum of its name's
+ // length in octets (as defined in Section 5.2), its value's
+ // length in octets (see Section 5.2), plus 32. The size of
+ // an entry is calculated using the length of the name and
+ // value without any Huffman encoding applied."
+
+ // This can overflow if somebody makes a large HeaderField
+ // Name and/or Value by hand, but we don't care, because that
+ // won't happen on the wire because the encoding doesn't allow
+ // it.
+ return uint32(len(hf.Name) + len(hf.Value) + 32)
+}
+
+// A Decoder is the decoding context for incremental processing of
+// header blocks.
+type Decoder struct {
+ dynTab dynamicTable
+ emit func(f HeaderField)
+
+ emitEnabled bool // whether calls to emit are enabled
+ maxStrLen int // 0 means unlimited
+
+ // buf is the unparsed buffer. It's only written to
+ // saveBuf if it was truncated in the middle of a header
+ // block. Because it's usually not owned, we can only
+ // process it under Write.
+ buf []byte // not owned; only valid during Write
+
+ // saveBuf is previous data passed to Write which we weren't able
+ // to fully parse before. Unlike buf, we own this data.
+ saveBuf bytes.Buffer
+}
+
+// NewDecoder returns a new decoder with the provided maximum dynamic
+// table size. The emitFunc will be called for each valid field
+// parsed, in the same goroutine as calls to Write, before Write returns.
+func NewDecoder(maxDynamicTableSize uint32, emitFunc func(f HeaderField)) *Decoder {
+ d := &Decoder{
+ emit: emitFunc,
+ emitEnabled: true,
+ }
+ d.dynTab.table.init()
+ d.dynTab.allowedMaxSize = maxDynamicTableSize
+ d.dynTab.setMaxSize(maxDynamicTableSize)
+ return d
+}
+
+// ErrStringLength is returned by Decoder.Write when the max string length
+// (as configured by Decoder.SetMaxStringLength) would be violated.
+var ErrStringLength = errors.New("hpack: string too long")
+
+// SetMaxStringLength sets the maximum size of a HeaderField name or
+// value string. If a string exceeds this length (even after any
+// decompression), Write will return ErrStringLength.
+// A value of 0 means unlimited and is the default from NewDecoder.
+func (d *Decoder) SetMaxStringLength(n int) {
+ d.maxStrLen = n
+}
+
+// SetEmitFunc changes the callback used when new header fields
+// are decoded.
+// It must be non-nil. It does not affect EmitEnabled.
+func (d *Decoder) SetEmitFunc(emitFunc func(f HeaderField)) {
+ d.emit = emitFunc
+}
+
+// SetEmitEnabled controls whether the emitFunc provided to NewDecoder
+// should be called. The default is true.
+//
+// This facility exists to let servers enforce MAX_HEADER_LIST_SIZE
+// while still decoding and keeping in-sync with decoder state, but
+// without doing unnecessary decompression or generating unnecessary
+// garbage for header fields past the limit.
+func (d *Decoder) SetEmitEnabled(v bool) { d.emitEnabled = v }
+
+// EmitEnabled reports whether calls to the emitFunc provided to NewDecoder
+// are currently enabled. The default is true.
+func (d *Decoder) EmitEnabled() bool { return d.emitEnabled }
+
+// TODO: add method *Decoder.Reset(maxSize, emitFunc) to let callers re-use Decoders and their
+// underlying buffers for garbage reasons.
+
+func (d *Decoder) SetMaxDynamicTableSize(v uint32) {
+ d.dynTab.setMaxSize(v)
+}
+
+// SetAllowedMaxDynamicTableSize sets the upper bound that the encoded
+// stream (via dynamic table size updates) may set the maximum size
+// to.
+func (d *Decoder) SetAllowedMaxDynamicTableSize(v uint32) {
+ d.dynTab.allowedMaxSize = v
+}
+
+type dynamicTable struct {
+ // http://http2.github.io/http2-spec/compression.html#rfc.section.2.3.2
+ table headerFieldTable
+ size uint32 // in bytes
+ maxSize uint32 // current maxSize
+ allowedMaxSize uint32 // maxSize may go up to this, inclusive
+}
+
+func (dt *dynamicTable) setMaxSize(v uint32) {
+ dt.maxSize = v
+ dt.evict()
+}
+
+func (dt *dynamicTable) add(f HeaderField) {
+ dt.table.addEntry(f)
+ dt.size += f.Size()
+ dt.evict()
+}
+
+// If we're too big, evict old stuff.
+func (dt *dynamicTable) evict() {
+ var n int
+ for dt.size > dt.maxSize && n < dt.table.len() {
+ dt.size -= dt.table.ents[n].Size()
+ n++
+ }
+ dt.table.evictOldest(n)
+}
+
+func (d *Decoder) maxTableIndex() int {
+ // This should never overflow. RFC 7540 Section 6.5.2 limits the size of
+ // the dynamic table to 2^32 bytes, where each entry will occupy more than
+ // one byte. Further, the staticTable has a fixed, small length.
+ return d.dynTab.table.len() + staticTable.len()
+}
+
+func (d *Decoder) at(i uint64) (hf HeaderField, ok bool) {
+ // See Section 2.3.3.
+ if i == 0 {
+ return
+ }
+ if i <= uint64(staticTable.len()) {
+ return staticTable.ents[i-1], true
+ }
+ if i > uint64(d.maxTableIndex()) {
+ return
+ }
+ // In the dynamic table, newer entries have lower indices.
+ // However, dt.ents[0] is the oldest entry. Hence, dt.ents is
+ // the reversed dynamic table.
+ dt := d.dynTab.table
+ return dt.ents[dt.len()-(int(i)-staticTable.len())], true
+}
+
+// Decode decodes an entire block.
+//
+// TODO: remove this method and make it incremental later? This is
+// easier for debugging now.
+func (d *Decoder) DecodeFull(p []byte) ([]HeaderField, error) {
+ var hf []HeaderField
+ saveFunc := d.emit
+ defer func() { d.emit = saveFunc }()
+ d.emit = func(f HeaderField) { hf = append(hf, f) }
+ if _, err := d.Write(p); err != nil {
+ return nil, err
+ }
+ if err := d.Close(); err != nil {
+ return nil, err
+ }
+ return hf, nil
+}
+
+func (d *Decoder) Close() error {
+ if d.saveBuf.Len() > 0 {
+ d.saveBuf.Reset()
+ return DecodingError{errors.New("truncated headers")}
+ }
+ return nil
+}
+
+func (d *Decoder) Write(p []byte) (n int, err error) {
+ if len(p) == 0 {
+ // Prevent state machine CPU attacks (making us redo
+ // work up to the point of finding out we don't have
+ // enough data)
+ return
+ }
+ // Only copy the data if we have to. Optimistically assume
+ // that p will contain a complete header block.
+ if d.saveBuf.Len() == 0 {
+ d.buf = p
+ } else {
+ d.saveBuf.Write(p)
+ d.buf = d.saveBuf.Bytes()
+ d.saveBuf.Reset()
+ }
+
+ for len(d.buf) > 0 {
+ err = d.parseHeaderFieldRepr()
+ if err == errNeedMore {
+ // Extra paranoia, making sure saveBuf won't
+ // get too large. All the varint and string
+ // reading code earlier should already catch
+ // overlong things and return ErrStringLength,
+ // but keep this as a last resort.
+ const varIntOverhead = 8 // conservative
+ if d.maxStrLen != 0 && int64(len(d.buf)) > 2*(int64(d.maxStrLen)+varIntOverhead) {
+ return 0, ErrStringLength
+ }
+ d.saveBuf.Write(d.buf)
+ return len(p), nil
+ }
+ if err != nil {
+ break
+ }
+ }
+ return len(p), err
+}
+
+// errNeedMore is an internal sentinel error value that means the
+// buffer is truncated and we need to read more data before we can
+// continue parsing.
+var errNeedMore = errors.New("need more data")
+
+type indexType int
+
+const (
+ indexedTrue indexType = iota
+ indexedFalse
+ indexedNever
+)
+
+func (v indexType) indexed() bool { return v == indexedTrue }
+func (v indexType) sensitive() bool { return v == indexedNever }
+
+// returns errNeedMore if there isn't enough data available.
+// any other error is fatal.
+// consumes d.buf iff it returns nil.
+// precondition: must be called with len(d.buf) > 0
+func (d *Decoder) parseHeaderFieldRepr() error {
+ b := d.buf[0]
+ switch {
+ case b&128 != 0:
+ // Indexed representation.
+ // High bit set?
+ // http://http2.github.io/http2-spec/compression.html#rfc.section.6.1
+ return d.parseFieldIndexed()
+ case b&192 == 64:
+ // 6.2.1 Literal Header Field with Incremental Indexing
+ // 0b10xxxxxx: top two bits are 10
+ // http://http2.github.io/http2-spec/compression.html#rfc.section.6.2.1
+ return d.parseFieldLiteral(6, indexedTrue)
+ case b&240 == 0:
+ // 6.2.2 Literal Header Field without Indexing
+ // 0b0000xxxx: top four bits are 0000
+ // http://http2.github.io/http2-spec/compression.html#rfc.section.6.2.2
+ return d.parseFieldLiteral(4, indexedFalse)
+ case b&240 == 16:
+ // 6.2.3 Literal Header Field never Indexed
+ // 0b0001xxxx: top four bits are 0001
+ // http://http2.github.io/http2-spec/compression.html#rfc.section.6.2.3
+ return d.parseFieldLiteral(4, indexedNever)
+ case b&224 == 32:
+ // 6.3 Dynamic Table Size Update
+ // Top three bits are '001'.
+ // http://http2.github.io/http2-spec/compression.html#rfc.section.6.3
+ return d.parseDynamicTableSizeUpdate()
+ }
+
+ return DecodingError{errors.New("invalid encoding")}
+}
+
+// (same invariants and behavior as parseHeaderFieldRepr)
+func (d *Decoder) parseFieldIndexed() error {
+ buf := d.buf
+ idx, buf, err := readVarInt(7, buf)
+ if err != nil {
+ return err
+ }
+ hf, ok := d.at(idx)
+ if !ok {
+ return DecodingError{InvalidIndexError(idx)}
+ }
+ d.buf = buf
+ return d.callEmit(HeaderField{Name: hf.Name, Value: hf.Value})
+}
+
+// (same invariants and behavior as parseHeaderFieldRepr)
+func (d *Decoder) parseFieldLiteral(n uint8, it indexType) error {
+ buf := d.buf
+ nameIdx, buf, err := readVarInt(n, buf)
+ if err != nil {
+ return err
+ }
+
+ var hf HeaderField
+ wantStr := d.emitEnabled || it.indexed()
+ if nameIdx > 0 {
+ ihf, ok := d.at(nameIdx)
+ if !ok {
+ return DecodingError{InvalidIndexError(nameIdx)}
+ }
+ hf.Name = ihf.Name
+ } else {
+ hf.Name, buf, err = d.readString(buf, wantStr)
+ if err != nil {
+ return err
+ }
+ }
+ hf.Value, buf, err = d.readString(buf, wantStr)
+ if err != nil {
+ return err
+ }
+ d.buf = buf
+ if it.indexed() {
+ d.dynTab.add(hf)
+ }
+ hf.Sensitive = it.sensitive()
+ return d.callEmit(hf)
+}
+
+func (d *Decoder) callEmit(hf HeaderField) error {
+ if d.maxStrLen != 0 {
+ if len(hf.Name) > d.maxStrLen || len(hf.Value) > d.maxStrLen {
+ return ErrStringLength
+ }
+ }
+ if d.emitEnabled {
+ d.emit(hf)
+ }
+ return nil
+}
+
+// (same invariants and behavior as parseHeaderFieldRepr)
+func (d *Decoder) parseDynamicTableSizeUpdate() error {
+ // RFC 7541, sec 4.2: This dynamic table size update MUST occur at the
+ // beginning of the first header block following the change to the dynamic table size.
+ if d.dynTab.size > 0 {
+ return DecodingError{errors.New("dynamic table size update MUST occur at the beginning of a header block")}
+ }
+
+ buf := d.buf
+ size, buf, err := readVarInt(5, buf)
+ if err != nil {
+ return err
+ }
+ if size > uint64(d.dynTab.allowedMaxSize) {
+ return DecodingError{errors.New("dynamic table size update too large")}
+ }
+ d.dynTab.setMaxSize(uint32(size))
+ d.buf = buf
+ return nil
+}
+
+var errVarintOverflow = DecodingError{errors.New("varint integer overflow")}
+
+// readVarInt reads an unsigned variable length integer off the
+// beginning of p. n is the parameter as described in
+// http://http2.github.io/http2-spec/compression.html#rfc.section.5.1.
+//
+// n must always be between 1 and 8.
+//
+// The returned remain buffer is either a smaller suffix of p, or err != nil.
+// The error is errNeedMore if p doesn't contain a complete integer.
+func readVarInt(n byte, p []byte) (i uint64, remain []byte, err error) {
+ if n < 1 || n > 8 {
+ panic("bad n")
+ }
+ if len(p) == 0 {
+ return 0, p, errNeedMore
+ }
+ i = uint64(p[0])
+ if n < 8 {
+ i &= (1 << uint64(n)) - 1
+ }
+ if i < (1<<uint64(n))-1 {
+ return i, p[1:], nil
+ }
+
+ origP := p
+ p = p[1:]
+ var m uint64
+ for len(p) > 0 {
+ b := p[0]
+ p = p[1:]
+ i += uint64(b&127) << m
+ if b&128 == 0 {
+ return i, p, nil
+ }
+ m += 7
+ if m >= 63 { // TODO: proper overflow check. making this up.
+ return 0, origP, errVarintOverflow
+ }
+ }
+ return 0, origP, errNeedMore
+}
+
+// readString decodes an hpack string from p.
+//
+// wantStr is whether s will be used. If false, decompression and
+// []byte->string garbage are skipped if s will be ignored
+// anyway. This does mean that huffman decoding errors for non-indexed
+// strings past the MAX_HEADER_LIST_SIZE are ignored, but the server
+// is returning an error anyway, and because they're not indexed, the error
+// won't affect the decoding state.
+func (d *Decoder) readString(p []byte, wantStr bool) (s string, remain []byte, err error) {
+ if len(p) == 0 {
+ return "", p, errNeedMore
+ }
+ isHuff := p[0]&128 != 0
+ strLen, p, err := readVarInt(7, p)
+ if err != nil {
+ return "", p, err
+ }
+ if d.maxStrLen != 0 && strLen > uint64(d.maxStrLen) {
+ return "", nil, ErrStringLength
+ }
+ if uint64(len(p)) < strLen {
+ return "", p, errNeedMore
+ }
+ if !isHuff {
+ if wantStr {
+ s = string(p[:strLen])
+ }
+ return s, p[strLen:], nil
+ }
+
+ if wantStr {
+ buf := bufPool.Get().(*bytes.Buffer)
+ buf.Reset() // don't trust others
+ defer bufPool.Put(buf)
+ if err := huffmanDecode(buf, d.maxStrLen, p[:strLen]); err != nil {
+ buf.Reset()
+ return "", nil, err
+ }
+ s = buf.String()
+ buf.Reset() // be nice to GC
+ }
+ return s, p[strLen:], nil
+}
diff --git a/vendor/golang.org/x/net/http2/hpack/huffman.go b/vendor/golang.org/x/net/http2/hpack/huffman.go
new file mode 100644
index 000000000..b412a96c5
--- /dev/null
+++ b/vendor/golang.org/x/net/http2/hpack/huffman.go
@@ -0,0 +1,222 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package hpack
+
+import (
+ "bytes"
+ "errors"
+ "io"
+ "sync"
+)
+
+var bufPool = sync.Pool{
+ New: func() interface{} { return new(bytes.Buffer) },
+}
+
+// HuffmanDecode decodes the string in v and writes the expanded
+// result to w, returning the number of bytes written to w and the
+// Write call's return value. At most one Write call is made.
+func HuffmanDecode(w io.Writer, v []byte) (int, error) {
+ buf := bufPool.Get().(*bytes.Buffer)
+ buf.Reset()
+ defer bufPool.Put(buf)
+ if err := huffmanDecode(buf, 0, v); err != nil {
+ return 0, err
+ }
+ return w.Write(buf.Bytes())
+}
+
+// HuffmanDecodeToString decodes the string in v.
+func HuffmanDecodeToString(v []byte) (string, error) {
+ buf := bufPool.Get().(*bytes.Buffer)
+ buf.Reset()
+ defer bufPool.Put(buf)
+ if err := huffmanDecode(buf, 0, v); err != nil {
+ return "", err
+ }
+ return buf.String(), nil
+}
+
+// ErrInvalidHuffman is returned for errors found decoding
+// Huffman-encoded strings.
+var ErrInvalidHuffman = errors.New("hpack: invalid Huffman-encoded data")
+
+// huffmanDecode decodes v to buf.
+// If maxLen is greater than 0, attempts to write more to buf than
+// maxLen bytes will return ErrStringLength.
+func huffmanDecode(buf *bytes.Buffer, maxLen int, v []byte) error {
+ rootHuffmanNode := getRootHuffmanNode()
+ n := rootHuffmanNode
+ // cur is the bit buffer that has not been fed into n.
+ // cbits is the number of low order bits in cur that are valid.
+ // sbits is the number of bits of the symbol prefix being decoded.
+ cur, cbits, sbits := uint(0), uint8(0), uint8(0)
+ for _, b := range v {
+ cur = cur<<8 | uint(b)
+ cbits += 8
+ sbits += 8
+ for cbits >= 8 {
+ idx := byte(cur >> (cbits - 8))
+ n = n.children[idx]
+ if n == nil {
+ return ErrInvalidHuffman
+ }
+ if n.children == nil {
+ if maxLen != 0 && buf.Len() == maxLen {
+ return ErrStringLength
+ }
+ buf.WriteByte(n.sym)
+ cbits -= n.codeLen
+ n = rootHuffmanNode
+ sbits = cbits
+ } else {
+ cbits -= 8
+ }
+ }
+ }
+ for cbits > 0 {
+ n = n.children[byte(cur<<(8-cbits))]
+ if n == nil {
+ return ErrInvalidHuffman
+ }
+ if n.children != nil || n.codeLen > cbits {
+ break
+ }
+ if maxLen != 0 && buf.Len() == maxLen {
+ return ErrStringLength
+ }
+ buf.WriteByte(n.sym)
+ cbits -= n.codeLen
+ n = rootHuffmanNode
+ sbits = cbits
+ }
+ if sbits > 7 {
+ // Either there was an incomplete symbol, or overlong padding.
+ // Both are decoding errors per RFC 7541 section 5.2.
+ return ErrInvalidHuffman
+ }
+ if mask := uint(1<<cbits - 1); cur&mask != mask {
+ // Trailing bits must be a prefix of EOS per RFC 7541 section 5.2.
+ return ErrInvalidHuffman
+ }
+
+ return nil
+}
+
+type node struct {
+ // children is non-nil for internal nodes
+ children *[256]*node
+
+ // The following are only valid if children is nil:
+ codeLen uint8 // number of bits that led to the output of sym
+ sym byte // output symbol
+}
+
+func newInternalNode() *node {
+ return &node{children: new([256]*node)}
+}
+
+var (
+ buildRootOnce sync.Once
+ lazyRootHuffmanNode *node
+)
+
+func getRootHuffmanNode() *node {
+ buildRootOnce.Do(buildRootHuffmanNode)
+ return lazyRootHuffmanNode
+}
+
+func buildRootHuffmanNode() {
+ if len(huffmanCodes) != 256 {
+ panic("unexpected size")
+ }
+ lazyRootHuffmanNode = newInternalNode()
+ for i, code := range huffmanCodes {
+ addDecoderNode(byte(i), code, huffmanCodeLen[i])
+ }
+}
+
+func addDecoderNode(sym byte, code uint32, codeLen uint8) {
+ cur := lazyRootHuffmanNode
+ for codeLen > 8 {
+ codeLen -= 8
+ i := uint8(code >> codeLen)
+ if cur.children[i] == nil {
+ cur.children[i] = newInternalNode()
+ }
+ cur = cur.children[i]
+ }
+ shift := 8 - codeLen
+ start, end := int(uint8(code<<shift)), int(1<<shift)
+ for i := start; i < start+end; i++ {
+ cur.children[i] = &node{sym: sym, codeLen: codeLen}
+ }
+}
+
+// AppendHuffmanString appends s, as encoded in Huffman codes, to dst
+// and returns the extended buffer.
+func AppendHuffmanString(dst []byte, s string) []byte {
+ rembits := uint8(8)
+
+ for i := 0; i < len(s); i++ {
+ if rembits == 8 {
+ dst = append(dst, 0)
+ }
+ dst, rembits = appendByteToHuffmanCode(dst, rembits, s[i])
+ }
+
+ if rembits < 8 {
+ // special EOS symbol
+ code := uint32(0x3fffffff)
+ nbits := uint8(30)
+
+ t := uint8(code >> (nbits - rembits))
+ dst[len(dst)-1] |= t
+ }
+
+ return dst
+}
+
+// HuffmanEncodeLength returns the number of bytes required to encode
+// s in Huffman codes. The result is round up to byte boundary.
+func HuffmanEncodeLength(s string) uint64 {
+ n := uint64(0)
+ for i := 0; i < len(s); i++ {
+ n += uint64(huffmanCodeLen[s[i]])
+ }
+ return (n + 7) / 8
+}
+
+// appendByteToHuffmanCode appends Huffman code for c to dst and
+// returns the extended buffer and the remaining bits in the last
+// element. The appending is not byte aligned and the remaining bits
+// in the last element of dst is given in rembits.
+func appendByteToHuffmanCode(dst []byte, rembits uint8, c byte) ([]byte, uint8) {
+ code := huffmanCodes[c]
+ nbits := huffmanCodeLen[c]
+
+ for {
+ if rembits > nbits {
+ t := uint8(code << (rembits - nbits))
+ dst[len(dst)-1] |= t
+ rembits -= nbits
+ break
+ }
+
+ t := uint8(code >> (nbits - rembits))
+ dst[len(dst)-1] |= t
+
+ nbits -= rembits
+ rembits = 8
+
+ if nbits == 0 {
+ break
+ }
+
+ dst = append(dst, 0)
+ }
+
+ return dst, rembits
+}
diff --git a/vendor/golang.org/x/net/http2/hpack/tables.go b/vendor/golang.org/x/net/http2/hpack/tables.go
new file mode 100644
index 000000000..a66cfbea6
--- /dev/null
+++ b/vendor/golang.org/x/net/http2/hpack/tables.go
@@ -0,0 +1,479 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package hpack
+
+import (
+ "fmt"
+)
+
+// headerFieldTable implements a list of HeaderFields.
+// This is used to implement the static and dynamic tables.
+type headerFieldTable struct {
+ // For static tables, entries are never evicted.
+ //
+ // For dynamic tables, entries are evicted from ents[0] and added to the end.
+ // Each entry has a unique id that starts at one and increments for each
+ // entry that is added. This unique id is stable across evictions, meaning
+ // it can be used as a pointer to a specific entry. As in hpack, unique ids
+ // are 1-based. The unique id for ents[k] is k + evictCount + 1.
+ //
+ // Zero is not a valid unique id.
+ //
+ // evictCount should not overflow in any remotely practical situation. In
+ // practice, we will have one dynamic table per HTTP/2 connection. If we
+ // assume a very powerful server that handles 1M QPS per connection and each
+ // request adds (then evicts) 100 entries from the table, it would still take
+ // 2M years for evictCount to overflow.
+ ents []HeaderField
+ evictCount uint64
+
+ // byName maps a HeaderField name to the unique id of the newest entry with
+ // the same name. See above for a definition of "unique id".
+ byName map[string]uint64
+
+ // byNameValue maps a HeaderField name/value pair to the unique id of the newest
+ // entry with the same name and value. See above for a definition of "unique id".
+ byNameValue map[pairNameValue]uint64
+}
+
+type pairNameValue struct {
+ name, value string
+}
+
+func (t *headerFieldTable) init() {
+ t.byName = make(map[string]uint64)
+ t.byNameValue = make(map[pairNameValue]uint64)
+}
+
+// len reports the number of entries in the table.
+func (t *headerFieldTable) len() int {
+ return len(t.ents)
+}
+
+// addEntry adds a new entry.
+func (t *headerFieldTable) addEntry(f HeaderField) {
+ id := uint64(t.len()) + t.evictCount + 1
+ t.byName[f.Name] = id
+ t.byNameValue[pairNameValue{f.Name, f.Value}] = id
+ t.ents = append(t.ents, f)
+}
+
+// evictOldest evicts the n oldest entries in the table.
+func (t *headerFieldTable) evictOldest(n int) {
+ if n > t.len() {
+ panic(fmt.Sprintf("evictOldest(%v) on table with %v entries", n, t.len()))
+ }
+ for k := 0; k < n; k++ {
+ f := t.ents[k]
+ id := t.evictCount + uint64(k) + 1
+ if t.byName[f.Name] == id {
+ delete(t.byName, f.Name)
+ }
+ if p := (pairNameValue{f.Name, f.Value}); t.byNameValue[p] == id {
+ delete(t.byNameValue, p)
+ }
+ }
+ copy(t.ents, t.ents[n:])
+ for k := t.len() - n; k < t.len(); k++ {
+ t.ents[k] = HeaderField{} // so strings can be garbage collected
+ }
+ t.ents = t.ents[:t.len()-n]
+ if t.evictCount+uint64(n) < t.evictCount {
+ panic("evictCount overflow")
+ }
+ t.evictCount += uint64(n)
+}
+
+// search finds f in the table. If there is no match, i is 0.
+// If both name and value match, i is the matched index and nameValueMatch
+// becomes true. If only name matches, i points to that index and
+// nameValueMatch becomes false.
+//
+// The returned index is a 1-based HPACK index. For dynamic tables, HPACK says
+// that index 1 should be the newest entry, but t.ents[0] is the oldest entry,
+// meaning t.ents is reversed for dynamic tables. Hence, when t is a dynamic
+// table, the return value i actually refers to the entry t.ents[t.len()-i].
+//
+// All tables are assumed to be a dynamic tables except for the global
+// staticTable pointer.
+//
+// See Section 2.3.3.
+func (t *headerFieldTable) search(f HeaderField) (i uint64, nameValueMatch bool) {
+ if !f.Sensitive {
+ if id := t.byNameValue[pairNameValue{f.Name, f.Value}]; id != 0 {
+ return t.idToIndex(id), true
+ }
+ }
+ if id := t.byName[f.Name]; id != 0 {
+ return t.idToIndex(id), false
+ }
+ return 0, false
+}
+
+// idToIndex converts a unique id to an HPACK index.
+// See Section 2.3.3.
+func (t *headerFieldTable) idToIndex(id uint64) uint64 {
+ if id <= t.evictCount {
+ panic(fmt.Sprintf("id (%v) <= evictCount (%v)", id, t.evictCount))
+ }
+ k := id - t.evictCount - 1 // convert id to an index t.ents[k]
+ if t != staticTable {
+ return uint64(t.len()) - k // dynamic table
+ }
+ return k + 1
+}
+
+// http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-07#appendix-B
+var staticTable = newStaticTable()
+var staticTableEntries = [...]HeaderField{
+ {Name: ":authority"},
+ {Name: ":method", Value: "GET"},
+ {Name: ":method", Value: "POST"},
+ {Name: ":path", Value: "/"},
+ {Name: ":path", Value: "/index.html"},
+ {Name: ":scheme", Value: "http"},
+ {Name: ":scheme", Value: "https"},
+ {Name: ":status", Value: "200"},
+ {Name: ":status", Value: "204"},
+ {Name: ":status", Value: "206"},
+ {Name: ":status", Value: "304"},
+ {Name: ":status", Value: "400"},
+ {Name: ":status", Value: "404"},
+ {Name: ":status", Value: "500"},
+ {Name: "accept-charset"},
+ {Name: "accept-encoding", Value: "gzip, deflate"},
+ {Name: "accept-language"},
+ {Name: "accept-ranges"},
+ {Name: "accept"},
+ {Name: "access-control-allow-origin"},
+ {Name: "age"},
+ {Name: "allow"},
+ {Name: "authorization"},
+ {Name: "cache-control"},
+ {Name: "content-disposition"},
+ {Name: "content-encoding"},
+ {Name: "content-language"},
+ {Name: "content-length"},
+ {Name: "content-location"},
+ {Name: "content-range"},
+ {Name: "content-type"},
+ {Name: "cookie"},
+ {Name: "date"},
+ {Name: "etag"},
+ {Name: "expect"},
+ {Name: "expires"},
+ {Name: "from"},
+ {Name: "host"},
+ {Name: "if-match"},
+ {Name: "if-modified-since"},
+ {Name: "if-none-match"},
+ {Name: "if-range"},
+ {Name: "if-unmodified-since"},
+ {Name: "last-modified"},
+ {Name: "link"},
+ {Name: "location"},
+ {Name: "max-forwards"},
+ {Name: "proxy-authenticate"},
+ {Name: "proxy-authorization"},
+ {Name: "range"},
+ {Name: "referer"},
+ {Name: "refresh"},
+ {Name: "retry-after"},
+ {Name: "server"},
+ {Name: "set-cookie"},
+ {Name: "strict-transport-security"},
+ {Name: "transfer-encoding"},
+ {Name: "user-agent"},
+ {Name: "vary"},
+ {Name: "via"},
+ {Name: "www-authenticate"},
+}
+
+func newStaticTable() *headerFieldTable {
+ t := &headerFieldTable{}
+ t.init()
+ for _, e := range staticTableEntries[:] {
+ t.addEntry(e)
+ }
+ return t
+}
+
+var huffmanCodes = [256]uint32{
+ 0x1ff8,
+ 0x7fffd8,
+ 0xfffffe2,
+ 0xfffffe3,
+ 0xfffffe4,
+ 0xfffffe5,
+ 0xfffffe6,
+ 0xfffffe7,
+ 0xfffffe8,
+ 0xffffea,
+ 0x3ffffffc,
+ 0xfffffe9,
+ 0xfffffea,
+ 0x3ffffffd,
+ 0xfffffeb,
+ 0xfffffec,
+ 0xfffffed,
+ 0xfffffee,
+ 0xfffffef,
+ 0xffffff0,
+ 0xffffff1,
+ 0xffffff2,
+ 0x3ffffffe,
+ 0xffffff3,
+ 0xffffff4,
+ 0xffffff5,
+ 0xffffff6,
+ 0xffffff7,
+ 0xffffff8,
+ 0xffffff9,
+ 0xffffffa,
+ 0xffffffb,
+ 0x14,
+ 0x3f8,
+ 0x3f9,
+ 0xffa,
+ 0x1ff9,
+ 0x15,
+ 0xf8,
+ 0x7fa,
+ 0x3fa,
+ 0x3fb,
+ 0xf9,
+ 0x7fb,
+ 0xfa,
+ 0x16,
+ 0x17,
+ 0x18,
+ 0x0,
+ 0x1,
+ 0x2,
+ 0x19,
+ 0x1a,
+ 0x1b,
+ 0x1c,
+ 0x1d,
+ 0x1e,
+ 0x1f,
+ 0x5c,
+ 0xfb,
+ 0x7ffc,
+ 0x20,
+ 0xffb,
+ 0x3fc,
+ 0x1ffa,
+ 0x21,
+ 0x5d,
+ 0x5e,
+ 0x5f,
+ 0x60,
+ 0x61,
+ 0x62,
+ 0x63,
+ 0x64,
+ 0x65,
+ 0x66,
+ 0x67,
+ 0x68,
+ 0x69,
+ 0x6a,
+ 0x6b,
+ 0x6c,
+ 0x6d,
+ 0x6e,
+ 0x6f,
+ 0x70,
+ 0x71,
+ 0x72,
+ 0xfc,
+ 0x73,
+ 0xfd,
+ 0x1ffb,
+ 0x7fff0,
+ 0x1ffc,
+ 0x3ffc,
+ 0x22,
+ 0x7ffd,
+ 0x3,
+ 0x23,
+ 0x4,
+ 0x24,
+ 0x5,
+ 0x25,
+ 0x26,
+ 0x27,
+ 0x6,
+ 0x74,
+ 0x75,
+ 0x28,
+ 0x29,
+ 0x2a,
+ 0x7,
+ 0x2b,
+ 0x76,
+ 0x2c,
+ 0x8,
+ 0x9,
+ 0x2d,
+ 0x77,
+ 0x78,
+ 0x79,
+ 0x7a,
+ 0x7b,
+ 0x7ffe,
+ 0x7fc,
+ 0x3ffd,
+ 0x1ffd,
+ 0xffffffc,
+ 0xfffe6,
+ 0x3fffd2,
+ 0xfffe7,
+ 0xfffe8,
+ 0x3fffd3,
+ 0x3fffd4,
+ 0x3fffd5,
+ 0x7fffd9,
+ 0x3fffd6,
+ 0x7fffda,
+ 0x7fffdb,
+ 0x7fffdc,
+ 0x7fffdd,
+ 0x7fffde,
+ 0xffffeb,
+ 0x7fffdf,
+ 0xffffec,
+ 0xffffed,
+ 0x3fffd7,
+ 0x7fffe0,
+ 0xffffee,
+ 0x7fffe1,
+ 0x7fffe2,
+ 0x7fffe3,
+ 0x7fffe4,
+ 0x1fffdc,
+ 0x3fffd8,
+ 0x7fffe5,
+ 0x3fffd9,
+ 0x7fffe6,
+ 0x7fffe7,
+ 0xffffef,
+ 0x3fffda,
+ 0x1fffdd,
+ 0xfffe9,
+ 0x3fffdb,
+ 0x3fffdc,
+ 0x7fffe8,
+ 0x7fffe9,
+ 0x1fffde,
+ 0x7fffea,
+ 0x3fffdd,
+ 0x3fffde,
+ 0xfffff0,
+ 0x1fffdf,
+ 0x3fffdf,
+ 0x7fffeb,
+ 0x7fffec,
+ 0x1fffe0,
+ 0x1fffe1,
+ 0x3fffe0,
+ 0x1fffe2,
+ 0x7fffed,
+ 0x3fffe1,
+ 0x7fffee,
+ 0x7fffef,
+ 0xfffea,
+ 0x3fffe2,
+ 0x3fffe3,
+ 0x3fffe4,
+ 0x7ffff0,
+ 0x3fffe5,
+ 0x3fffe6,
+ 0x7ffff1,
+ 0x3ffffe0,
+ 0x3ffffe1,
+ 0xfffeb,
+ 0x7fff1,
+ 0x3fffe7,
+ 0x7ffff2,
+ 0x3fffe8,
+ 0x1ffffec,
+ 0x3ffffe2,
+ 0x3ffffe3,
+ 0x3ffffe4,
+ 0x7ffffde,
+ 0x7ffffdf,
+ 0x3ffffe5,
+ 0xfffff1,
+ 0x1ffffed,
+ 0x7fff2,
+ 0x1fffe3,
+ 0x3ffffe6,
+ 0x7ffffe0,
+ 0x7ffffe1,
+ 0x3ffffe7,
+ 0x7ffffe2,
+ 0xfffff2,
+ 0x1fffe4,
+ 0x1fffe5,
+ 0x3ffffe8,
+ 0x3ffffe9,
+ 0xffffffd,
+ 0x7ffffe3,
+ 0x7ffffe4,
+ 0x7ffffe5,
+ 0xfffec,
+ 0xfffff3,
+ 0xfffed,
+ 0x1fffe6,
+ 0x3fffe9,
+ 0x1fffe7,
+ 0x1fffe8,
+ 0x7ffff3,
+ 0x3fffea,
+ 0x3fffeb,
+ 0x1ffffee,
+ 0x1ffffef,
+ 0xfffff4,
+ 0xfffff5,
+ 0x3ffffea,
+ 0x7ffff4,
+ 0x3ffffeb,
+ 0x7ffffe6,
+ 0x3ffffec,
+ 0x3ffffed,
+ 0x7ffffe7,
+ 0x7ffffe8,
+ 0x7ffffe9,
+ 0x7ffffea,
+ 0x7ffffeb,
+ 0xffffffe,
+ 0x7ffffec,
+ 0x7ffffed,
+ 0x7ffffee,
+ 0x7ffffef,
+ 0x7fffff0,
+ 0x3ffffee,
+}
+
+var huffmanCodeLen = [256]uint8{
+ 13, 23, 28, 28, 28, 28, 28, 28, 28, 24, 30, 28, 28, 30, 28, 28,
+ 28, 28, 28, 28, 28, 28, 30, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+ 6, 10, 10, 12, 13, 6, 8, 11, 10, 10, 8, 11, 8, 6, 6, 6,
+ 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 8, 15, 6, 12, 10,
+ 13, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 8, 7, 8, 13, 19, 13, 14, 6,
+ 15, 5, 6, 5, 6, 5, 6, 6, 6, 5, 7, 7, 6, 6, 6, 5,
+ 6, 7, 6, 5, 5, 6, 7, 7, 7, 7, 7, 15, 11, 14, 13, 28,
+ 20, 22, 20, 20, 22, 22, 22, 23, 22, 23, 23, 23, 23, 23, 24, 23,
+ 24, 24, 22, 23, 24, 23, 23, 23, 23, 21, 22, 23, 22, 23, 23, 24,
+ 22, 21, 20, 22, 22, 23, 23, 21, 23, 22, 22, 24, 21, 22, 23, 23,
+ 21, 21, 22, 21, 23, 22, 23, 23, 20, 22, 22, 22, 23, 22, 22, 23,
+ 26, 26, 20, 19, 22, 23, 22, 25, 26, 26, 26, 27, 27, 26, 24, 25,
+ 19, 21, 26, 27, 27, 26, 27, 24, 21, 21, 26, 26, 28, 27, 27, 27,
+ 20, 24, 20, 21, 22, 21, 21, 23, 22, 22, 25, 25, 24, 24, 26, 23,
+ 26, 27, 26, 26, 27, 27, 27, 27, 27, 28, 27, 27, 27, 27, 27, 26,
+}
diff --git a/vendor/golang.org/x/net/http2/http2.go b/vendor/golang.org/x/net/http2/http2.go
new file mode 100644
index 000000000..bdaba1d46
--- /dev/null
+++ b/vendor/golang.org/x/net/http2/http2.go
@@ -0,0 +1,384 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package http2 implements the HTTP/2 protocol.
+//
+// This package is low-level and intended to be used directly by very
+// few people. Most users will use it indirectly through the automatic
+// use by the net/http package (from Go 1.6 and later).
+// For use in earlier Go versions see ConfigureServer. (Transport support
+// requires Go 1.6 or later)
+//
+// See https://http2.github.io/ for more information on HTTP/2.
+//
+// See https://http2.golang.org/ for a test server running this code.
+//
+package http2 // import "golang.org/x/net/http2"
+
+import (
+ "bufio"
+ "crypto/tls"
+ "errors"
+ "fmt"
+ "io"
+ "net/http"
+ "os"
+ "sort"
+ "strconv"
+ "strings"
+ "sync"
+
+ "golang.org/x/net/http/httpguts"
+)
+
+var (
+ VerboseLogs bool
+ logFrameWrites bool
+ logFrameReads bool
+ inTests bool
+)
+
+func init() {
+ e := os.Getenv("GODEBUG")
+ if strings.Contains(e, "http2debug=1") {
+ VerboseLogs = true
+ }
+ if strings.Contains(e, "http2debug=2") {
+ VerboseLogs = true
+ logFrameWrites = true
+ logFrameReads = true
+ }
+}
+
+const (
+ // ClientPreface is the string that must be sent by new
+ // connections from clients.
+ ClientPreface = "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"
+
+ // SETTINGS_MAX_FRAME_SIZE default
+ // http://http2.github.io/http2-spec/#rfc.section.6.5.2
+ initialMaxFrameSize = 16384
+
+ // NextProtoTLS is the NPN/ALPN protocol negotiated during
+ // HTTP/2's TLS setup.
+ NextProtoTLS = "h2"
+
+ // http://http2.github.io/http2-spec/#SettingValues
+ initialHeaderTableSize = 4096
+
+ initialWindowSize = 65535 // 6.9.2 Initial Flow Control Window Size
+
+ defaultMaxReadFrameSize = 1 << 20
+)
+
+var (
+ clientPreface = []byte(ClientPreface)
+)
+
+type streamState int
+
+// HTTP/2 stream states.
+//
+// See http://tools.ietf.org/html/rfc7540#section-5.1.
+//
+// For simplicity, the server code merges "reserved (local)" into
+// "half-closed (remote)". This is one less state transition to track.
+// The only downside is that we send PUSH_PROMISEs slightly less
+// liberally than allowable. More discussion here:
+// https://lists.w3.org/Archives/Public/ietf-http-wg/2016JulSep/0599.html
+//
+// "reserved (remote)" is omitted since the client code does not
+// support server push.
+const (
+ stateIdle streamState = iota
+ stateOpen
+ stateHalfClosedLocal
+ stateHalfClosedRemote
+ stateClosed
+)
+
+var stateName = [...]string{
+ stateIdle: "Idle",
+ stateOpen: "Open",
+ stateHalfClosedLocal: "HalfClosedLocal",
+ stateHalfClosedRemote: "HalfClosedRemote",
+ stateClosed: "Closed",
+}
+
+func (st streamState) String() string {
+ return stateName[st]
+}
+
+// Setting is a setting parameter: which setting it is, and its value.
+type Setting struct {
+ // ID is which setting is being set.
+ // See http://http2.github.io/http2-spec/#SettingValues
+ ID SettingID
+
+ // Val is the value.
+ Val uint32
+}
+
+func (s Setting) String() string {
+ return fmt.Sprintf("[%v = %d]", s.ID, s.Val)
+}
+
+// Valid reports whether the setting is valid.
+func (s Setting) Valid() error {
+ // Limits and error codes from 6.5.2 Defined SETTINGS Parameters
+ switch s.ID {
+ case SettingEnablePush:
+ if s.Val != 1 && s.Val != 0 {
+ return ConnectionError(ErrCodeProtocol)
+ }
+ case SettingInitialWindowSize:
+ if s.Val > 1<<31-1 {
+ return ConnectionError(ErrCodeFlowControl)
+ }
+ case SettingMaxFrameSize:
+ if s.Val < 16384 || s.Val > 1<<24-1 {
+ return ConnectionError(ErrCodeProtocol)
+ }
+ }
+ return nil
+}
+
+// A SettingID is an HTTP/2 setting as defined in
+// http://http2.github.io/http2-spec/#iana-settings
+type SettingID uint16
+
+const (
+ SettingHeaderTableSize SettingID = 0x1
+ SettingEnablePush SettingID = 0x2
+ SettingMaxConcurrentStreams SettingID = 0x3
+ SettingInitialWindowSize SettingID = 0x4
+ SettingMaxFrameSize SettingID = 0x5
+ SettingMaxHeaderListSize SettingID = 0x6
+)
+
+var settingName = map[SettingID]string{
+ SettingHeaderTableSize: "HEADER_TABLE_SIZE",
+ SettingEnablePush: "ENABLE_PUSH",
+ SettingMaxConcurrentStreams: "MAX_CONCURRENT_STREAMS",
+ SettingInitialWindowSize: "INITIAL_WINDOW_SIZE",
+ SettingMaxFrameSize: "MAX_FRAME_SIZE",
+ SettingMaxHeaderListSize: "MAX_HEADER_LIST_SIZE",
+}
+
+func (s SettingID) String() string {
+ if v, ok := settingName[s]; ok {
+ return v
+ }
+ return fmt.Sprintf("UNKNOWN_SETTING_%d", uint16(s))
+}
+
+var (
+ errInvalidHeaderFieldName = errors.New("http2: invalid header field name")
+ errInvalidHeaderFieldValue = errors.New("http2: invalid header field value")
+)
+
+// validWireHeaderFieldName reports whether v is a valid header field
+// name (key). See httpguts.ValidHeaderName for the base rules.
+//
+// Further, http2 says:
+// "Just as in HTTP/1.x, header field names are strings of ASCII
+// characters that are compared in a case-insensitive
+// fashion. However, header field names MUST be converted to
+// lowercase prior to their encoding in HTTP/2. "
+func validWireHeaderFieldName(v string) bool {
+ if len(v) == 0 {
+ return false
+ }
+ for _, r := range v {
+ if !httpguts.IsTokenRune(r) {
+ return false
+ }
+ if 'A' <= r && r <= 'Z' {
+ return false
+ }
+ }
+ return true
+}
+
+func httpCodeString(code int) string {
+ switch code {
+ case 200:
+ return "200"
+ case 404:
+ return "404"
+ }
+ return strconv.Itoa(code)
+}
+
+// from pkg io
+type stringWriter interface {
+ WriteString(s string) (n int, err error)
+}
+
+// A gate lets two goroutines coordinate their activities.
+type gate chan struct{}
+
+func (g gate) Done() { g <- struct{}{} }
+func (g gate) Wait() { <-g }
+
+// A closeWaiter is like a sync.WaitGroup but only goes 1 to 0 (open to closed).
+type closeWaiter chan struct{}
+
+// Init makes a closeWaiter usable.
+// It exists because so a closeWaiter value can be placed inside a
+// larger struct and have the Mutex and Cond's memory in the same
+// allocation.
+func (cw *closeWaiter) Init() {
+ *cw = make(chan struct{})
+}
+
+// Close marks the closeWaiter as closed and unblocks any waiters.
+func (cw closeWaiter) Close() {
+ close(cw)
+}
+
+// Wait waits for the closeWaiter to become closed.
+func (cw closeWaiter) Wait() {
+ <-cw
+}
+
+// bufferedWriter is a buffered writer that writes to w.
+// Its buffered writer is lazily allocated as needed, to minimize
+// idle memory usage with many connections.
+type bufferedWriter struct {
+ w io.Writer // immutable
+ bw *bufio.Writer // non-nil when data is buffered
+}
+
+func newBufferedWriter(w io.Writer) *bufferedWriter {
+ return &bufferedWriter{w: w}
+}
+
+// bufWriterPoolBufferSize is the size of bufio.Writer's
+// buffers created using bufWriterPool.
+//
+// TODO: pick a less arbitrary value? this is a bit under
+// (3 x typical 1500 byte MTU) at least. Other than that,
+// not much thought went into it.
+const bufWriterPoolBufferSize = 4 << 10
+
+var bufWriterPool = sync.Pool{
+ New: func() interface{} {
+ return bufio.NewWriterSize(nil, bufWriterPoolBufferSize)
+ },
+}
+
+func (w *bufferedWriter) Available() int {
+ if w.bw == nil {
+ return bufWriterPoolBufferSize
+ }
+ return w.bw.Available()
+}
+
+func (w *bufferedWriter) Write(p []byte) (n int, err error) {
+ if w.bw == nil {
+ bw := bufWriterPool.Get().(*bufio.Writer)
+ bw.Reset(w.w)
+ w.bw = bw
+ }
+ return w.bw.Write(p)
+}
+
+func (w *bufferedWriter) Flush() error {
+ bw := w.bw
+ if bw == nil {
+ return nil
+ }
+ err := bw.Flush()
+ bw.Reset(nil)
+ bufWriterPool.Put(bw)
+ w.bw = nil
+ return err
+}
+
+func mustUint31(v int32) uint32 {
+ if v < 0 || v > 2147483647 {
+ panic("out of range")
+ }
+ return uint32(v)
+}
+
+// bodyAllowedForStatus reports whether a given response status code
+// permits a body. See RFC 7230, section 3.3.
+func bodyAllowedForStatus(status int) bool {
+ switch {
+ case status >= 100 && status <= 199:
+ return false
+ case status == 204:
+ return false
+ case status == 304:
+ return false
+ }
+ return true
+}
+
+type httpError struct {
+ msg string
+ timeout bool
+}
+
+func (e *httpError) Error() string { return e.msg }
+func (e *httpError) Timeout() bool { return e.timeout }
+func (e *httpError) Temporary() bool { return true }
+
+var errTimeout error = &httpError{msg: "http2: timeout awaiting response headers", timeout: true}
+
+type connectionStater interface {
+ ConnectionState() tls.ConnectionState
+}
+
+var sorterPool = sync.Pool{New: func() interface{} { return new(sorter) }}
+
+type sorter struct {
+ v []string // owned by sorter
+}
+
+func (s *sorter) Len() int { return len(s.v) }
+func (s *sorter) Swap(i, j int) { s.v[i], s.v[j] = s.v[j], s.v[i] }
+func (s *sorter) Less(i, j int) bool { return s.v[i] < s.v[j] }
+
+// Keys returns the sorted keys of h.
+//
+// The returned slice is only valid until s used again or returned to
+// its pool.
+func (s *sorter) Keys(h http.Header) []string {
+ keys := s.v[:0]
+ for k := range h {
+ keys = append(keys, k)
+ }
+ s.v = keys
+ sort.Sort(s)
+ return keys
+}
+
+func (s *sorter) SortStrings(ss []string) {
+ // Our sorter works on s.v, which sorter owns, so
+ // stash it away while we sort the user's buffer.
+ save := s.v
+ s.v = ss
+ sort.Sort(s)
+ s.v = save
+}
+
+// validPseudoPath reports whether v is a valid :path pseudo-header
+// value. It must be either:
+//
+// *) a non-empty string starting with '/'
+// *) the string '*', for OPTIONS requests.
+//
+// For now this is only used a quick check for deciding when to clean
+// up Opaque URLs before sending requests from the Transport.
+// See golang.org/issue/16847
+//
+// We used to enforce that the path also didn't start with "//", but
+// Google's GFE accepts such paths and Chrome sends them, so ignore
+// that part of the spec. See golang.org/issue/19103.
+func validPseudoPath(v string) bool {
+ return (len(v) > 0 && v[0] == '/') || v == "*"
+}
diff --git a/vendor/golang.org/x/net/http2/not_go111.go b/vendor/golang.org/x/net/http2/not_go111.go
new file mode 100644
index 000000000..161bca7ce
--- /dev/null
+++ b/vendor/golang.org/x/net/http2/not_go111.go
@@ -0,0 +1,20 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !go1.11
+
+package http2
+
+import (
+ "net/http/httptrace"
+ "net/textproto"
+)
+
+func traceHasWroteHeaderField(trace *httptrace.ClientTrace) bool { return false }
+
+func traceWroteHeaderField(trace *httptrace.ClientTrace, k, v string) {}
+
+func traceGot1xxResponseFunc(trace *httptrace.ClientTrace) func(int, textproto.MIMEHeader) error {
+ return nil
+}
diff --git a/vendor/golang.org/x/net/http2/pipe.go b/vendor/golang.org/x/net/http2/pipe.go
new file mode 100644
index 000000000..a6140099c
--- /dev/null
+++ b/vendor/golang.org/x/net/http2/pipe.go
@@ -0,0 +1,163 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package http2
+
+import (
+ "errors"
+ "io"
+ "sync"
+)
+
+// pipe is a goroutine-safe io.Reader/io.Writer pair. It's like
+// io.Pipe except there are no PipeReader/PipeWriter halves, and the
+// underlying buffer is an interface. (io.Pipe is always unbuffered)
+type pipe struct {
+ mu sync.Mutex
+ c sync.Cond // c.L lazily initialized to &p.mu
+ b pipeBuffer // nil when done reading
+ err error // read error once empty. non-nil means closed.
+ breakErr error // immediate read error (caller doesn't see rest of b)
+ donec chan struct{} // closed on error
+ readFn func() // optional code to run in Read before error
+}
+
+type pipeBuffer interface {
+ Len() int
+ io.Writer
+ io.Reader
+}
+
+func (p *pipe) Len() int {
+ p.mu.Lock()
+ defer p.mu.Unlock()
+ if p.b == nil {
+ return 0
+ }
+ return p.b.Len()
+}
+
+// Read waits until data is available and copies bytes
+// from the buffer into p.
+func (p *pipe) Read(d []byte) (n int, err error) {
+ p.mu.Lock()
+ defer p.mu.Unlock()
+ if p.c.L == nil {
+ p.c.L = &p.mu
+ }
+ for {
+ if p.breakErr != nil {
+ return 0, p.breakErr
+ }
+ if p.b != nil && p.b.Len() > 0 {
+ return p.b.Read(d)
+ }
+ if p.err != nil {
+ if p.readFn != nil {
+ p.readFn() // e.g. copy trailers
+ p.readFn = nil // not sticky like p.err
+ }
+ p.b = nil
+ return 0, p.err
+ }
+ p.c.Wait()
+ }
+}
+
+var errClosedPipeWrite = errors.New("write on closed buffer")
+
+// Write copies bytes from p into the buffer and wakes a reader.
+// It is an error to write more data than the buffer can hold.
+func (p *pipe) Write(d []byte) (n int, err error) {
+ p.mu.Lock()
+ defer p.mu.Unlock()
+ if p.c.L == nil {
+ p.c.L = &p.mu
+ }
+ defer p.c.Signal()
+ if p.err != nil {
+ return 0, errClosedPipeWrite
+ }
+ if p.breakErr != nil {
+ return len(d), nil // discard when there is no reader
+ }
+ return p.b.Write(d)
+}
+
+// CloseWithError causes the next Read (waking up a current blocked
+// Read if needed) to return the provided err after all data has been
+// read.
+//
+// The error must be non-nil.
+func (p *pipe) CloseWithError(err error) { p.closeWithError(&p.err, err, nil) }
+
+// BreakWithError causes the next Read (waking up a current blocked
+// Read if needed) to return the provided err immediately, without
+// waiting for unread data.
+func (p *pipe) BreakWithError(err error) { p.closeWithError(&p.breakErr, err, nil) }
+
+// closeWithErrorAndCode is like CloseWithError but also sets some code to run
+// in the caller's goroutine before returning the error.
+func (p *pipe) closeWithErrorAndCode(err error, fn func()) { p.closeWithError(&p.err, err, fn) }
+
+func (p *pipe) closeWithError(dst *error, err error, fn func()) {
+ if err == nil {
+ panic("err must be non-nil")
+ }
+ p.mu.Lock()
+ defer p.mu.Unlock()
+ if p.c.L == nil {
+ p.c.L = &p.mu
+ }
+ defer p.c.Signal()
+ if *dst != nil {
+ // Already been done.
+ return
+ }
+ p.readFn = fn
+ if dst == &p.breakErr {
+ p.b = nil
+ }
+ *dst = err
+ p.closeDoneLocked()
+}
+
+// requires p.mu be held.
+func (p *pipe) closeDoneLocked() {
+ if p.donec == nil {
+ return
+ }
+ // Close if unclosed. This isn't racy since we always
+ // hold p.mu while closing.
+ select {
+ case <-p.donec:
+ default:
+ close(p.donec)
+ }
+}
+
+// Err returns the error (if any) first set by BreakWithError or CloseWithError.
+func (p *pipe) Err() error {
+ p.mu.Lock()
+ defer p.mu.Unlock()
+ if p.breakErr != nil {
+ return p.breakErr
+ }
+ return p.err
+}
+
+// Done returns a channel which is closed if and when this pipe is closed
+// with CloseWithError.
+func (p *pipe) Done() <-chan struct{} {
+ p.mu.Lock()
+ defer p.mu.Unlock()
+ if p.donec == nil {
+ p.donec = make(chan struct{})
+ if p.err != nil || p.breakErr != nil {
+ // Already hit an error.
+ p.closeDoneLocked()
+ }
+ }
+ return p.donec
+}
diff --git a/vendor/golang.org/x/net/http2/server.go b/vendor/golang.org/x/net/http2/server.go
new file mode 100644
index 000000000..8f1701914
--- /dev/null
+++ b/vendor/golang.org/x/net/http2/server.go
@@ -0,0 +1,2895 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// TODO: turn off the serve goroutine when idle, so
+// an idle conn only has the readFrames goroutine active. (which could
+// also be optimized probably to pin less memory in crypto/tls). This
+// would involve tracking when the serve goroutine is active (atomic
+// int32 read/CAS probably?) and starting it up when frames arrive,
+// and shutting it down when all handlers exit. the occasional PING
+// packets could use time.AfterFunc to call sc.wakeStartServeLoop()
+// (which is a no-op if already running) and then queue the PING write
+// as normal. The serve loop would then exit in most cases (if no
+// Handlers running) and not be woken up again until the PING packet
+// returns.
+
+// TODO (maybe): add a mechanism for Handlers to going into
+// half-closed-local mode (rw.(io.Closer) test?) but not exit their
+// handler, and continue to be able to read from the
+// Request.Body. This would be a somewhat semantic change from HTTP/1
+// (or at least what we expose in net/http), so I'd probably want to
+// add it there too. For now, this package says that returning from
+// the Handler ServeHTTP function means you're both done reading and
+// done writing, without a way to stop just one or the other.
+
+package http2
+
+import (
+ "bufio"
+ "bytes"
+ "context"
+ "crypto/tls"
+ "errors"
+ "fmt"
+ "io"
+ "log"
+ "math"
+ "net"
+ "net/http"
+ "net/textproto"
+ "net/url"
+ "os"
+ "reflect"
+ "runtime"
+ "strconv"
+ "strings"
+ "sync"
+ "time"
+
+ "golang.org/x/net/http/httpguts"
+ "golang.org/x/net/http2/hpack"
+)
+
+const (
+ prefaceTimeout = 10 * time.Second
+ firstSettingsTimeout = 2 * time.Second // should be in-flight with preface anyway
+ handlerChunkWriteSize = 4 << 10
+ defaultMaxStreams = 250 // TODO: make this 100 as the GFE seems to?
+)
+
+var (
+ errClientDisconnected = errors.New("client disconnected")
+ errClosedBody = errors.New("body closed by handler")
+ errHandlerComplete = errors.New("http2: request body closed due to handler exiting")
+ errStreamClosed = errors.New("http2: stream closed")
+)
+
+var responseWriterStatePool = sync.Pool{
+ New: func() interface{} {
+ rws := &responseWriterState{}
+ rws.bw = bufio.NewWriterSize(chunkWriter{rws}, handlerChunkWriteSize)
+ return rws
+ },
+}
+
+// Test hooks.
+var (
+ testHookOnConn func()
+ testHookGetServerConn func(*serverConn)
+ testHookOnPanicMu *sync.Mutex // nil except in tests
+ testHookOnPanic func(sc *serverConn, panicVal interface{}) (rePanic bool)
+)
+
+// Server is an HTTP/2 server.
+type Server struct {
+ // MaxHandlers limits the number of http.Handler ServeHTTP goroutines
+ // which may run at a time over all connections.
+ // Negative or zero no limit.
+ // TODO: implement
+ MaxHandlers int
+
+ // MaxConcurrentStreams optionally specifies the number of
+ // concurrent streams that each client may have open at a
+ // time. This is unrelated to the number of http.Handler goroutines
+ // which may be active globally, which is MaxHandlers.
+ // If zero, MaxConcurrentStreams defaults to at least 100, per
+ // the HTTP/2 spec's recommendations.
+ MaxConcurrentStreams uint32
+
+ // MaxReadFrameSize optionally specifies the largest frame
+ // this server is willing to read. A valid value is between
+ // 16k and 16M, inclusive. If zero or otherwise invalid, a
+ // default value is used.
+ MaxReadFrameSize uint32
+
+ // PermitProhibitedCipherSuites, if true, permits the use of
+ // cipher suites prohibited by the HTTP/2 spec.
+ PermitProhibitedCipherSuites bool
+
+ // IdleTimeout specifies how long until idle clients should be
+ // closed with a GOAWAY frame. PING frames are not considered
+ // activity for the purposes of IdleTimeout.
+ IdleTimeout time.Duration
+
+ // MaxUploadBufferPerConnection is the size of the initial flow
+ // control window for each connections. The HTTP/2 spec does not
+ // allow this to be smaller than 65535 or larger than 2^32-1.
+ // If the value is outside this range, a default value will be
+ // used instead.
+ MaxUploadBufferPerConnection int32
+
+ // MaxUploadBufferPerStream is the size of the initial flow control
+ // window for each stream. The HTTP/2 spec does not allow this to
+ // be larger than 2^32-1. If the value is zero or larger than the
+ // maximum, a default value will be used instead.
+ MaxUploadBufferPerStream int32
+
+ // NewWriteScheduler constructs a write scheduler for a connection.
+ // If nil, a default scheduler is chosen.
+ NewWriteScheduler func() WriteScheduler
+
+ // Internal state. This is a pointer (rather than embedded directly)
+ // so that we don't embed a Mutex in this struct, which will make the
+ // struct non-copyable, which might break some callers.
+ state *serverInternalState
+}
+
+func (s *Server) initialConnRecvWindowSize() int32 {
+ if s.MaxUploadBufferPerConnection > initialWindowSize {
+ return s.MaxUploadBufferPerConnection
+ }
+ return 1 << 20
+}
+
+func (s *Server) initialStreamRecvWindowSize() int32 {
+ if s.MaxUploadBufferPerStream > 0 {
+ return s.MaxUploadBufferPerStream
+ }
+ return 1 << 20
+}
+
+func (s *Server) maxReadFrameSize() uint32 {
+ if v := s.MaxReadFrameSize; v >= minMaxFrameSize && v <= maxFrameSize {
+ return v
+ }
+ return defaultMaxReadFrameSize
+}
+
+func (s *Server) maxConcurrentStreams() uint32 {
+ if v := s.MaxConcurrentStreams; v > 0 {
+ return v
+ }
+ return defaultMaxStreams
+}
+
+type serverInternalState struct {
+ mu sync.Mutex
+ activeConns map[*serverConn]struct{}
+}
+
+func (s *serverInternalState) registerConn(sc *serverConn) {
+ if s == nil {
+ return // if the Server was used without calling ConfigureServer
+ }
+ s.mu.Lock()
+ s.activeConns[sc] = struct{}{}
+ s.mu.Unlock()
+}
+
+func (s *serverInternalState) unregisterConn(sc *serverConn) {
+ if s == nil {
+ return // if the Server was used without calling ConfigureServer
+ }
+ s.mu.Lock()
+ delete(s.activeConns, sc)
+ s.mu.Unlock()
+}
+
+func (s *serverInternalState) startGracefulShutdown() {
+ if s == nil {
+ return // if the Server was used without calling ConfigureServer
+ }
+ s.mu.Lock()
+ for sc := range s.activeConns {
+ sc.startGracefulShutdown()
+ }
+ s.mu.Unlock()
+}
+
+// ConfigureServer adds HTTP/2 support to a net/http Server.
+//
+// The configuration conf may be nil.
+//
+// ConfigureServer must be called before s begins serving.
+func ConfigureServer(s *http.Server, conf *Server) error {
+ if s == nil {
+ panic("nil *http.Server")
+ }
+ if conf == nil {
+ conf = new(Server)
+ }
+ conf.state = &serverInternalState{activeConns: make(map[*serverConn]struct{})}
+ if h1, h2 := s, conf; h2.IdleTimeout == 0 {
+ if h1.IdleTimeout != 0 {
+ h2.IdleTimeout = h1.IdleTimeout
+ } else {
+ h2.IdleTimeout = h1.ReadTimeout
+ }
+ }
+ s.RegisterOnShutdown(conf.state.startGracefulShutdown)
+
+ if s.TLSConfig == nil {
+ s.TLSConfig = new(tls.Config)
+ } else if s.TLSConfig.CipherSuites != nil {
+ // If they already provided a CipherSuite list, return
+ // an error if it has a bad order or is missing
+ // ECDHE_RSA_WITH_AES_128_GCM_SHA256 or ECDHE_ECDSA_WITH_AES_128_GCM_SHA256.
+ haveRequired := false
+ sawBad := false
+ for i, cs := range s.TLSConfig.CipherSuites {
+ switch cs {
+ case tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+ // Alternative MTI cipher to not discourage ECDSA-only servers.
+ // See http://golang.org/cl/30721 for further information.
+ tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
+ haveRequired = true
+ }
+ if isBadCipher(cs) {
+ sawBad = true
+ } else if sawBad {
+ return fmt.Errorf("http2: TLSConfig.CipherSuites index %d contains an HTTP/2-approved cipher suite (%#04x), but it comes after unapproved cipher suites. With this configuration, clients that don't support previous, approved cipher suites may be given an unapproved one and reject the connection.", i, cs)
+ }
+ }
+ if !haveRequired {
+ return fmt.Errorf("http2: TLSConfig.CipherSuites is missing an HTTP/2-required AES_128_GCM_SHA256 cipher.")
+ }
+ }
+
+ // Note: not setting MinVersion to tls.VersionTLS12,
+ // as we don't want to interfere with HTTP/1.1 traffic
+ // on the user's server. We enforce TLS 1.2 later once
+ // we accept a connection. Ideally this should be done
+ // during next-proto selection, but using TLS <1.2 with
+ // HTTP/2 is still the client's bug.
+
+ s.TLSConfig.PreferServerCipherSuites = true
+
+ haveNPN := false
+ for _, p := range s.TLSConfig.NextProtos {
+ if p == NextProtoTLS {
+ haveNPN = true
+ break
+ }
+ }
+ if !haveNPN {
+ s.TLSConfig.NextProtos = append(s.TLSConfig.NextProtos, NextProtoTLS)
+ }
+
+ if s.TLSNextProto == nil {
+ s.TLSNextProto = map[string]func(*http.Server, *tls.Conn, http.Handler){}
+ }
+ protoHandler := func(hs *http.Server, c *tls.Conn, h http.Handler) {
+ if testHookOnConn != nil {
+ testHookOnConn()
+ }
+ conf.ServeConn(c, &ServeConnOpts{
+ Handler: h,
+ BaseConfig: hs,
+ })
+ }
+ s.TLSNextProto[NextProtoTLS] = protoHandler
+ return nil
+}
+
+// ServeConnOpts are options for the Server.ServeConn method.
+type ServeConnOpts struct {
+ // BaseConfig optionally sets the base configuration
+ // for values. If nil, defaults are used.
+ BaseConfig *http.Server
+
+ // Handler specifies which handler to use for processing
+ // requests. If nil, BaseConfig.Handler is used. If BaseConfig
+ // or BaseConfig.Handler is nil, http.DefaultServeMux is used.
+ Handler http.Handler
+}
+
+func (o *ServeConnOpts) baseConfig() *http.Server {
+ if o != nil && o.BaseConfig != nil {
+ return o.BaseConfig
+ }
+ return new(http.Server)
+}
+
+func (o *ServeConnOpts) handler() http.Handler {
+ if o != nil {
+ if o.Handler != nil {
+ return o.Handler
+ }
+ if o.BaseConfig != nil && o.BaseConfig.Handler != nil {
+ return o.BaseConfig.Handler
+ }
+ }
+ return http.DefaultServeMux
+}
+
+// ServeConn serves HTTP/2 requests on the provided connection and
+// blocks until the connection is no longer readable.
+//
+// ServeConn starts speaking HTTP/2 assuming that c has not had any
+// reads or writes. It writes its initial settings frame and expects
+// to be able to read the preface and settings frame from the
+// client. If c has a ConnectionState method like a *tls.Conn, the
+// ConnectionState is used to verify the TLS ciphersuite and to set
+// the Request.TLS field in Handlers.
+//
+// ServeConn does not support h2c by itself. Any h2c support must be
+// implemented in terms of providing a suitably-behaving net.Conn.
+//
+// The opts parameter is optional. If nil, default values are used.
+func (s *Server) ServeConn(c net.Conn, opts *ServeConnOpts) {
+ baseCtx, cancel := serverConnBaseContext(c, opts)
+ defer cancel()
+
+ sc := &serverConn{
+ srv: s,
+ hs: opts.baseConfig(),
+ conn: c,
+ baseCtx: baseCtx,
+ remoteAddrStr: c.RemoteAddr().String(),
+ bw: newBufferedWriter(c),
+ handler: opts.handler(),
+ streams: make(map[uint32]*stream),
+ readFrameCh: make(chan readFrameResult),
+ wantWriteFrameCh: make(chan FrameWriteRequest, 8),
+ serveMsgCh: make(chan interface{}, 8),
+ wroteFrameCh: make(chan frameWriteResult, 1), // buffered; one send in writeFrameAsync
+ bodyReadCh: make(chan bodyReadMsg), // buffering doesn't matter either way
+ doneServing: make(chan struct{}),
+ clientMaxStreams: math.MaxUint32, // Section 6.5.2: "Initially, there is no limit to this value"
+ advMaxStreams: s.maxConcurrentStreams(),
+ initialStreamSendWindowSize: initialWindowSize,
+ maxFrameSize: initialMaxFrameSize,
+ headerTableSize: initialHeaderTableSize,
+ serveG: newGoroutineLock(),
+ pushEnabled: true,
+ }
+
+ s.state.registerConn(sc)
+ defer s.state.unregisterConn(sc)
+
+ // The net/http package sets the write deadline from the
+ // http.Server.WriteTimeout during the TLS handshake, but then
+ // passes the connection off to us with the deadline already set.
+ // Write deadlines are set per stream in serverConn.newStream.
+ // Disarm the net.Conn write deadline here.
+ if sc.hs.WriteTimeout != 0 {
+ sc.conn.SetWriteDeadline(time.Time{})
+ }
+
+ if s.NewWriteScheduler != nil {
+ sc.writeSched = s.NewWriteScheduler()
+ } else {
+ sc.writeSched = NewRandomWriteScheduler()
+ }
+
+ // These start at the RFC-specified defaults. If there is a higher
+ // configured value for inflow, that will be updated when we send a
+ // WINDOW_UPDATE shortly after sending SETTINGS.
+ sc.flow.add(initialWindowSize)
+ sc.inflow.add(initialWindowSize)
+ sc.hpackEncoder = hpack.NewEncoder(&sc.headerWriteBuf)
+
+ fr := NewFramer(sc.bw, c)
+ fr.ReadMetaHeaders = hpack.NewDecoder(initialHeaderTableSize, nil)
+ fr.MaxHeaderListSize = sc.maxHeaderListSize()
+ fr.SetMaxReadFrameSize(s.maxReadFrameSize())
+ sc.framer = fr
+
+ if tc, ok := c.(connectionStater); ok {
+ sc.tlsState = new(tls.ConnectionState)
+ *sc.tlsState = tc.ConnectionState()
+ // 9.2 Use of TLS Features
+ // An implementation of HTTP/2 over TLS MUST use TLS
+ // 1.2 or higher with the restrictions on feature set
+ // and cipher suite described in this section. Due to
+ // implementation limitations, it might not be
+ // possible to fail TLS negotiation. An endpoint MUST
+ // immediately terminate an HTTP/2 connection that
+ // does not meet the TLS requirements described in
+ // this section with a connection error (Section
+ // 5.4.1) of type INADEQUATE_SECURITY.
+ if sc.tlsState.Version < tls.VersionTLS12 {
+ sc.rejectConn(ErrCodeInadequateSecurity, "TLS version too low")
+ return
+ }
+
+ if sc.tlsState.ServerName == "" {
+ // Client must use SNI, but we don't enforce that anymore,
+ // since it was causing problems when connecting to bare IP
+ // addresses during development.
+ //
+ // TODO: optionally enforce? Or enforce at the time we receive
+ // a new request, and verify the ServerName matches the :authority?
+ // But that precludes proxy situations, perhaps.
+ //
+ // So for now, do nothing here again.
+ }
+
+ if !s.PermitProhibitedCipherSuites && isBadCipher(sc.tlsState.CipherSuite) {
+ // "Endpoints MAY choose to generate a connection error
+ // (Section 5.4.1) of type INADEQUATE_SECURITY if one of
+ // the prohibited cipher suites are negotiated."
+ //
+ // We choose that. In my opinion, the spec is weak
+ // here. It also says both parties must support at least
+ // TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 so there's no
+ // excuses here. If we really must, we could allow an
+ // "AllowInsecureWeakCiphers" option on the server later.
+ // Let's see how it plays out first.
+ sc.rejectConn(ErrCodeInadequateSecurity, fmt.Sprintf("Prohibited TLS 1.2 Cipher Suite: %x", sc.tlsState.CipherSuite))
+ return
+ }
+ }
+
+ if hook := testHookGetServerConn; hook != nil {
+ hook(sc)
+ }
+ sc.serve()
+}
+
+func serverConnBaseContext(c net.Conn, opts *ServeConnOpts) (ctx context.Context, cancel func()) {
+ ctx, cancel = context.WithCancel(context.Background())
+ ctx = context.WithValue(ctx, http.LocalAddrContextKey, c.LocalAddr())
+ if hs := opts.baseConfig(); hs != nil {
+ ctx = context.WithValue(ctx, http.ServerContextKey, hs)
+ }
+ return
+}
+
+func (sc *serverConn) rejectConn(err ErrCode, debug string) {
+ sc.vlogf("http2: server rejecting conn: %v, %s", err, debug)
+ // ignoring errors. hanging up anyway.
+ sc.framer.WriteGoAway(0, err, []byte(debug))
+ sc.bw.Flush()
+ sc.conn.Close()
+}
+
+type serverConn struct {
+ // Immutable:
+ srv *Server
+ hs *http.Server
+ conn net.Conn
+ bw *bufferedWriter // writing to conn
+ handler http.Handler
+ baseCtx context.Context
+ framer *Framer
+ doneServing chan struct{} // closed when serverConn.serve ends
+ readFrameCh chan readFrameResult // written by serverConn.readFrames
+ wantWriteFrameCh chan FrameWriteRequest // from handlers -> serve
+ wroteFrameCh chan frameWriteResult // from writeFrameAsync -> serve, tickles more frame writes
+ bodyReadCh chan bodyReadMsg // from handlers -> serve
+ serveMsgCh chan interface{} // misc messages & code to send to / run on the serve loop
+ flow flow // conn-wide (not stream-specific) outbound flow control
+ inflow flow // conn-wide inbound flow control
+ tlsState *tls.ConnectionState // shared by all handlers, like net/http
+ remoteAddrStr string
+ writeSched WriteScheduler
+
+ // Everything following is owned by the serve loop; use serveG.check():
+ serveG goroutineLock // used to verify funcs are on serve()
+ pushEnabled bool
+ sawFirstSettings bool // got the initial SETTINGS frame after the preface
+ needToSendSettingsAck bool
+ unackedSettings int // how many SETTINGS have we sent without ACKs?
+ clientMaxStreams uint32 // SETTINGS_MAX_CONCURRENT_STREAMS from client (our PUSH_PROMISE limit)
+ advMaxStreams uint32 // our SETTINGS_MAX_CONCURRENT_STREAMS advertised the client
+ curClientStreams uint32 // number of open streams initiated by the client
+ curPushedStreams uint32 // number of open streams initiated by server push
+ maxClientStreamID uint32 // max ever seen from client (odd), or 0 if there have been no client requests
+ maxPushPromiseID uint32 // ID of the last push promise (even), or 0 if there have been no pushes
+ streams map[uint32]*stream
+ initialStreamSendWindowSize int32
+ maxFrameSize int32
+ headerTableSize uint32
+ peerMaxHeaderListSize uint32 // zero means unknown (default)
+ canonHeader map[string]string // http2-lower-case -> Go-Canonical-Case
+ writingFrame bool // started writing a frame (on serve goroutine or separate)
+ writingFrameAsync bool // started a frame on its own goroutine but haven't heard back on wroteFrameCh
+ needsFrameFlush bool // last frame write wasn't a flush
+ inGoAway bool // we've started to or sent GOAWAY
+ inFrameScheduleLoop bool // whether we're in the scheduleFrameWrite loop
+ needToSendGoAway bool // we need to schedule a GOAWAY frame write
+ goAwayCode ErrCode
+ shutdownTimer *time.Timer // nil until used
+ idleTimer *time.Timer // nil if unused
+
+ // Owned by the writeFrameAsync goroutine:
+ headerWriteBuf bytes.Buffer
+ hpackEncoder *hpack.Encoder
+
+ // Used by startGracefulShutdown.
+ shutdownOnce sync.Once
+}
+
+func (sc *serverConn) maxHeaderListSize() uint32 {
+ n := sc.hs.MaxHeaderBytes
+ if n <= 0 {
+ n = http.DefaultMaxHeaderBytes
+ }
+ // http2's count is in a slightly different unit and includes 32 bytes per pair.
+ // So, take the net/http.Server value and pad it up a bit, assuming 10 headers.
+ const perFieldOverhead = 32 // per http2 spec
+ const typicalHeaders = 10 // conservative
+ return uint32(n + typicalHeaders*perFieldOverhead)
+}
+
+func (sc *serverConn) curOpenStreams() uint32 {
+ sc.serveG.check()
+ return sc.curClientStreams + sc.curPushedStreams
+}
+
+// stream represents a stream. This is the minimal metadata needed by
+// the serve goroutine. Most of the actual stream state is owned by
+// the http.Handler's goroutine in the responseWriter. Because the
+// responseWriter's responseWriterState is recycled at the end of a
+// handler, this struct intentionally has no pointer to the
+// *responseWriter{,State} itself, as the Handler ending nils out the
+// responseWriter's state field.
+type stream struct {
+ // immutable:
+ sc *serverConn
+ id uint32
+ body *pipe // non-nil if expecting DATA frames
+ cw closeWaiter // closed wait stream transitions to closed state
+ ctx context.Context
+ cancelCtx func()
+
+ // owned by serverConn's serve loop:
+ bodyBytes int64 // body bytes seen so far
+ declBodyBytes int64 // or -1 if undeclared
+ flow flow // limits writing from Handler to client
+ inflow flow // what the client is allowed to POST/etc to us
+ parent *stream // or nil
+ numTrailerValues int64
+ weight uint8
+ state streamState
+ resetQueued bool // RST_STREAM queued for write; set by sc.resetStream
+ gotTrailerHeader bool // HEADER frame for trailers was seen
+ wroteHeaders bool // whether we wrote headers (not status 100)
+ writeDeadline *time.Timer // nil if unused
+
+ trailer http.Header // accumulated trailers
+ reqTrailer http.Header // handler's Request.Trailer
+}
+
+func (sc *serverConn) Framer() *Framer { return sc.framer }
+func (sc *serverConn) CloseConn() error { return sc.conn.Close() }
+func (sc *serverConn) Flush() error { return sc.bw.Flush() }
+func (sc *serverConn) HeaderEncoder() (*hpack.Encoder, *bytes.Buffer) {
+ return sc.hpackEncoder, &sc.headerWriteBuf
+}
+
+func (sc *serverConn) state(streamID uint32) (streamState, *stream) {
+ sc.serveG.check()
+ // http://tools.ietf.org/html/rfc7540#section-5.1
+ if st, ok := sc.streams[streamID]; ok {
+ return st.state, st
+ }
+ // "The first use of a new stream identifier implicitly closes all
+ // streams in the "idle" state that might have been initiated by
+ // that peer with a lower-valued stream identifier. For example, if
+ // a client sends a HEADERS frame on stream 7 without ever sending a
+ // frame on stream 5, then stream 5 transitions to the "closed"
+ // state when the first frame for stream 7 is sent or received."
+ if streamID%2 == 1 {
+ if streamID <= sc.maxClientStreamID {
+ return stateClosed, nil
+ }
+ } else {
+ if streamID <= sc.maxPushPromiseID {
+ return stateClosed, nil
+ }
+ }
+ return stateIdle, nil
+}
+
+// setConnState calls the net/http ConnState hook for this connection, if configured.
+// Note that the net/http package does StateNew and StateClosed for us.
+// There is currently no plan for StateHijacked or hijacking HTTP/2 connections.
+func (sc *serverConn) setConnState(state http.ConnState) {
+ if sc.hs.ConnState != nil {
+ sc.hs.ConnState(sc.conn, state)
+ }
+}
+
+func (sc *serverConn) vlogf(format string, args ...interface{}) {
+ if VerboseLogs {
+ sc.logf(format, args...)
+ }
+}
+
+func (sc *serverConn) logf(format string, args ...interface{}) {
+ if lg := sc.hs.ErrorLog; lg != nil {
+ lg.Printf(format, args...)
+ } else {
+ log.Printf(format, args...)
+ }
+}
+
+// errno returns v's underlying uintptr, else 0.
+//
+// TODO: remove this helper function once http2 can use build
+// tags. See comment in isClosedConnError.
+func errno(v error) uintptr {
+ if rv := reflect.ValueOf(v); rv.Kind() == reflect.Uintptr {
+ return uintptr(rv.Uint())
+ }
+ return 0
+}
+
+// isClosedConnError reports whether err is an error from use of a closed
+// network connection.
+func isClosedConnError(err error) bool {
+ if err == nil {
+ return false
+ }
+
+ // TODO: remove this string search and be more like the Windows
+ // case below. That might involve modifying the standard library
+ // to return better error types.
+ str := err.Error()
+ if strings.Contains(str, "use of closed network connection") {
+ return true
+ }
+
+ // TODO(bradfitz): x/tools/cmd/bundle doesn't really support
+ // build tags, so I can't make an http2_windows.go file with
+ // Windows-specific stuff. Fix that and move this, once we
+ // have a way to bundle this into std's net/http somehow.
+ if runtime.GOOS == "windows" {
+ if oe, ok := err.(*net.OpError); ok && oe.Op == "read" {
+ if se, ok := oe.Err.(*os.SyscallError); ok && se.Syscall == "wsarecv" {
+ const WSAECONNABORTED = 10053
+ const WSAECONNRESET = 10054
+ if n := errno(se.Err); n == WSAECONNRESET || n == WSAECONNABORTED {
+ return true
+ }
+ }
+ }
+ }
+ return false
+}
+
+func (sc *serverConn) condlogf(err error, format string, args ...interface{}) {
+ if err == nil {
+ return
+ }
+ if err == io.EOF || err == io.ErrUnexpectedEOF || isClosedConnError(err) || err == errPrefaceTimeout {
+ // Boring, expected errors.
+ sc.vlogf(format, args...)
+ } else {
+ sc.logf(format, args...)
+ }
+}
+
+func (sc *serverConn) canonicalHeader(v string) string {
+ sc.serveG.check()
+ buildCommonHeaderMapsOnce()
+ cv, ok := commonCanonHeader[v]
+ if ok {
+ return cv
+ }
+ cv, ok = sc.canonHeader[v]
+ if ok {
+ return cv
+ }
+ if sc.canonHeader == nil {
+ sc.canonHeader = make(map[string]string)
+ }
+ cv = http.CanonicalHeaderKey(v)
+ sc.canonHeader[v] = cv
+ return cv
+}
+
+type readFrameResult struct {
+ f Frame // valid until readMore is called
+ err error
+
+ // readMore should be called once the consumer no longer needs or
+ // retains f. After readMore, f is invalid and more frames can be
+ // read.
+ readMore func()
+}
+
+// readFrames is the loop that reads incoming frames.
+// It takes care to only read one frame at a time, blocking until the
+// consumer is done with the frame.
+// It's run on its own goroutine.
+func (sc *serverConn) readFrames() {
+ gate := make(gate)
+ gateDone := gate.Done
+ for {
+ f, err := sc.framer.ReadFrame()
+ select {
+ case sc.readFrameCh <- readFrameResult{f, err, gateDone}:
+ case <-sc.doneServing:
+ return
+ }
+ select {
+ case <-gate:
+ case <-sc.doneServing:
+ return
+ }
+ if terminalReadFrameError(err) {
+ return
+ }
+ }
+}
+
+// frameWriteResult is the message passed from writeFrameAsync to the serve goroutine.
+type frameWriteResult struct {
+ wr FrameWriteRequest // what was written (or attempted)
+ err error // result of the writeFrame call
+}
+
+// writeFrameAsync runs in its own goroutine and writes a single frame
+// and then reports when it's done.
+// At most one goroutine can be running writeFrameAsync at a time per
+// serverConn.
+func (sc *serverConn) writeFrameAsync(wr FrameWriteRequest) {
+ err := wr.write.writeFrame(sc)
+ sc.wroteFrameCh <- frameWriteResult{wr, err}
+}
+
+func (sc *serverConn) closeAllStreamsOnConnClose() {
+ sc.serveG.check()
+ for _, st := range sc.streams {
+ sc.closeStream(st, errClientDisconnected)
+ }
+}
+
+func (sc *serverConn) stopShutdownTimer() {
+ sc.serveG.check()
+ if t := sc.shutdownTimer; t != nil {
+ t.Stop()
+ }
+}
+
+func (sc *serverConn) notePanic() {
+ // Note: this is for serverConn.serve panicking, not http.Handler code.
+ if testHookOnPanicMu != nil {
+ testHookOnPanicMu.Lock()
+ defer testHookOnPanicMu.Unlock()
+ }
+ if testHookOnPanic != nil {
+ if e := recover(); e != nil {
+ if testHookOnPanic(sc, e) {
+ panic(e)
+ }
+ }
+ }
+}
+
+func (sc *serverConn) serve() {
+ sc.serveG.check()
+ defer sc.notePanic()
+ defer sc.conn.Close()
+ defer sc.closeAllStreamsOnConnClose()
+ defer sc.stopShutdownTimer()
+ defer close(sc.doneServing) // unblocks handlers trying to send
+
+ if VerboseLogs {
+ sc.vlogf("http2: server connection from %v on %p", sc.conn.RemoteAddr(), sc.hs)
+ }
+
+ sc.writeFrame(FrameWriteRequest{
+ write: writeSettings{
+ {SettingMaxFrameSize, sc.srv.maxReadFrameSize()},
+ {SettingMaxConcurrentStreams, sc.advMaxStreams},
+ {SettingMaxHeaderListSize, sc.maxHeaderListSize()},
+ {SettingInitialWindowSize, uint32(sc.srv.initialStreamRecvWindowSize())},
+ },
+ })
+ sc.unackedSettings++
+
+ // Each connection starts with intialWindowSize inflow tokens.
+ // If a higher value is configured, we add more tokens.
+ if diff := sc.srv.initialConnRecvWindowSize() - initialWindowSize; diff > 0 {
+ sc.sendWindowUpdate(nil, int(diff))
+ }
+
+ if err := sc.readPreface(); err != nil {
+ sc.condlogf(err, "http2: server: error reading preface from client %v: %v", sc.conn.RemoteAddr(), err)
+ return
+ }
+ // Now that we've got the preface, get us out of the
+ // "StateNew" state. We can't go directly to idle, though.
+ // Active means we read some data and anticipate a request. We'll
+ // do another Active when we get a HEADERS frame.
+ sc.setConnState(http.StateActive)
+ sc.setConnState(http.StateIdle)
+
+ if sc.srv.IdleTimeout != 0 {
+ sc.idleTimer = time.AfterFunc(sc.srv.IdleTimeout, sc.onIdleTimer)
+ defer sc.idleTimer.Stop()
+ }
+
+ go sc.readFrames() // closed by defer sc.conn.Close above
+
+ settingsTimer := time.AfterFunc(firstSettingsTimeout, sc.onSettingsTimer)
+ defer settingsTimer.Stop()
+
+ loopNum := 0
+ for {
+ loopNum++
+ select {
+ case wr := <-sc.wantWriteFrameCh:
+ if se, ok := wr.write.(StreamError); ok {
+ sc.resetStream(se)
+ break
+ }
+ sc.writeFrame(wr)
+ case res := <-sc.wroteFrameCh:
+ sc.wroteFrame(res)
+ case res := <-sc.readFrameCh:
+ if !sc.processFrameFromReader(res) {
+ return
+ }
+ res.readMore()
+ if settingsTimer != nil {
+ settingsTimer.Stop()
+ settingsTimer = nil
+ }
+ case m := <-sc.bodyReadCh:
+ sc.noteBodyRead(m.st, m.n)
+ case msg := <-sc.serveMsgCh:
+ switch v := msg.(type) {
+ case func(int):
+ v(loopNum) // for testing
+ case *serverMessage:
+ switch v {
+ case settingsTimerMsg:
+ sc.logf("timeout waiting for SETTINGS frames from %v", sc.conn.RemoteAddr())
+ return
+ case idleTimerMsg:
+ sc.vlogf("connection is idle")
+ sc.goAway(ErrCodeNo)
+ case shutdownTimerMsg:
+ sc.vlogf("GOAWAY close timer fired; closing conn from %v", sc.conn.RemoteAddr())
+ return
+ case gracefulShutdownMsg:
+ sc.startGracefulShutdownInternal()
+ default:
+ panic("unknown timer")
+ }
+ case *startPushRequest:
+ sc.startPush(v)
+ default:
+ panic(fmt.Sprintf("unexpected type %T", v))
+ }
+ }
+
+ // Start the shutdown timer after sending a GOAWAY. When sending GOAWAY
+ // with no error code (graceful shutdown), don't start the timer until
+ // all open streams have been completed.
+ sentGoAway := sc.inGoAway && !sc.needToSendGoAway && !sc.writingFrame
+ gracefulShutdownComplete := sc.goAwayCode == ErrCodeNo && sc.curOpenStreams() == 0
+ if sentGoAway && sc.shutdownTimer == nil && (sc.goAwayCode != ErrCodeNo || gracefulShutdownComplete) {
+ sc.shutDownIn(goAwayTimeout)
+ }
+ }
+}
+
+func (sc *serverConn) awaitGracefulShutdown(sharedCh <-chan struct{}, privateCh chan struct{}) {
+ select {
+ case <-sc.doneServing:
+ case <-sharedCh:
+ close(privateCh)
+ }
+}
+
+type serverMessage int
+
+// Message values sent to serveMsgCh.
+var (
+ settingsTimerMsg = new(serverMessage)
+ idleTimerMsg = new(serverMessage)
+ shutdownTimerMsg = new(serverMessage)
+ gracefulShutdownMsg = new(serverMessage)
+)
+
+func (sc *serverConn) onSettingsTimer() { sc.sendServeMsg(settingsTimerMsg) }
+func (sc *serverConn) onIdleTimer() { sc.sendServeMsg(idleTimerMsg) }
+func (sc *serverConn) onShutdownTimer() { sc.sendServeMsg(shutdownTimerMsg) }
+
+func (sc *serverConn) sendServeMsg(msg interface{}) {
+ sc.serveG.checkNotOn() // NOT
+ select {
+ case sc.serveMsgCh <- msg:
+ case <-sc.doneServing:
+ }
+}
+
+var errPrefaceTimeout = errors.New("timeout waiting for client preface")
+
+// readPreface reads the ClientPreface greeting from the peer or
+// returns errPrefaceTimeout on timeout, or an error if the greeting
+// is invalid.
+func (sc *serverConn) readPreface() error {
+ errc := make(chan error, 1)
+ go func() {
+ // Read the client preface
+ buf := make([]byte, len(ClientPreface))
+ if _, err := io.ReadFull(sc.conn, buf); err != nil {
+ errc <- err
+ } else if !bytes.Equal(buf, clientPreface) {
+ errc <- fmt.Errorf("bogus greeting %q", buf)
+ } else {
+ errc <- nil
+ }
+ }()
+ timer := time.NewTimer(prefaceTimeout) // TODO: configurable on *Server?
+ defer timer.Stop()
+ select {
+ case <-timer.C:
+ return errPrefaceTimeout
+ case err := <-errc:
+ if err == nil {
+ if VerboseLogs {
+ sc.vlogf("http2: server: client %v said hello", sc.conn.RemoteAddr())
+ }
+ }
+ return err
+ }
+}
+
+var errChanPool = sync.Pool{
+ New: func() interface{} { return make(chan error, 1) },
+}
+
+var writeDataPool = sync.Pool{
+ New: func() interface{} { return new(writeData) },
+}
+
+// writeDataFromHandler writes DATA response frames from a handler on
+// the given stream.
+func (sc *serverConn) writeDataFromHandler(stream *stream, data []byte, endStream bool) error {
+ ch := errChanPool.Get().(chan error)
+ writeArg := writeDataPool.Get().(*writeData)
+ *writeArg = writeData{stream.id, data, endStream}
+ err := sc.writeFrameFromHandler(FrameWriteRequest{
+ write: writeArg,
+ stream: stream,
+ done: ch,
+ })
+ if err != nil {
+ return err
+ }
+ var frameWriteDone bool // the frame write is done (successfully or not)
+ select {
+ case err = <-ch:
+ frameWriteDone = true
+ case <-sc.doneServing:
+ return errClientDisconnected
+ case <-stream.cw:
+ // If both ch and stream.cw were ready (as might
+ // happen on the final Write after an http.Handler
+ // ends), prefer the write result. Otherwise this
+ // might just be us successfully closing the stream.
+ // The writeFrameAsync and serve goroutines guarantee
+ // that the ch send will happen before the stream.cw
+ // close.
+ select {
+ case err = <-ch:
+ frameWriteDone = true
+ default:
+ return errStreamClosed
+ }
+ }
+ errChanPool.Put(ch)
+ if frameWriteDone {
+ writeDataPool.Put(writeArg)
+ }
+ return err
+}
+
+// writeFrameFromHandler sends wr to sc.wantWriteFrameCh, but aborts
+// if the connection has gone away.
+//
+// This must not be run from the serve goroutine itself, else it might
+// deadlock writing to sc.wantWriteFrameCh (which is only mildly
+// buffered and is read by serve itself). If you're on the serve
+// goroutine, call writeFrame instead.
+func (sc *serverConn) writeFrameFromHandler(wr FrameWriteRequest) error {
+ sc.serveG.checkNotOn() // NOT
+ select {
+ case sc.wantWriteFrameCh <- wr:
+ return nil
+ case <-sc.doneServing:
+ // Serve loop is gone.
+ // Client has closed their connection to the server.
+ return errClientDisconnected
+ }
+}
+
+// writeFrame schedules a frame to write and sends it if there's nothing
+// already being written.
+//
+// There is no pushback here (the serve goroutine never blocks). It's
+// the http.Handlers that block, waiting for their previous frames to
+// make it onto the wire
+//
+// If you're not on the serve goroutine, use writeFrameFromHandler instead.
+func (sc *serverConn) writeFrame(wr FrameWriteRequest) {
+ sc.serveG.check()
+
+ // If true, wr will not be written and wr.done will not be signaled.
+ var ignoreWrite bool
+
+ // We are not allowed to write frames on closed streams. RFC 7540 Section
+ // 5.1.1 says: "An endpoint MUST NOT send frames other than PRIORITY on
+ // a closed stream." Our server never sends PRIORITY, so that exception
+ // does not apply.
+ //
+ // The serverConn might close an open stream while the stream's handler
+ // is still running. For example, the server might close a stream when it
+ // receives bad data from the client. If this happens, the handler might
+ // attempt to write a frame after the stream has been closed (since the
+ // handler hasn't yet been notified of the close). In this case, we simply
+ // ignore the frame. The handler will notice that the stream is closed when
+ // it waits for the frame to be written.
+ //
+ // As an exception to this rule, we allow sending RST_STREAM after close.
+ // This allows us to immediately reject new streams without tracking any
+ // state for those streams (except for the queued RST_STREAM frame). This
+ // may result in duplicate RST_STREAMs in some cases, but the client should
+ // ignore those.
+ if wr.StreamID() != 0 {
+ _, isReset := wr.write.(StreamError)
+ if state, _ := sc.state(wr.StreamID()); state == stateClosed && !isReset {
+ ignoreWrite = true
+ }
+ }
+
+ // Don't send a 100-continue response if we've already sent headers.
+ // See golang.org/issue/14030.
+ switch wr.write.(type) {
+ case *writeResHeaders:
+ wr.stream.wroteHeaders = true
+ case write100ContinueHeadersFrame:
+ if wr.stream.wroteHeaders {
+ // We do not need to notify wr.done because this frame is
+ // never written with wr.done != nil.
+ if wr.done != nil {
+ panic("wr.done != nil for write100ContinueHeadersFrame")
+ }
+ ignoreWrite = true
+ }
+ }
+
+ if !ignoreWrite {
+ sc.writeSched.Push(wr)
+ }
+ sc.scheduleFrameWrite()
+}
+
+// startFrameWrite starts a goroutine to write wr (in a separate
+// goroutine since that might block on the network), and updates the
+// serve goroutine's state about the world, updated from info in wr.
+func (sc *serverConn) startFrameWrite(wr FrameWriteRequest) {
+ sc.serveG.check()
+ if sc.writingFrame {
+ panic("internal error: can only be writing one frame at a time")
+ }
+
+ st := wr.stream
+ if st != nil {
+ switch st.state {
+ case stateHalfClosedLocal:
+ switch wr.write.(type) {
+ case StreamError, handlerPanicRST, writeWindowUpdate:
+ // RFC 7540 Section 5.1 allows sending RST_STREAM, PRIORITY, and WINDOW_UPDATE
+ // in this state. (We never send PRIORITY from the server, so that is not checked.)
+ default:
+ panic(fmt.Sprintf("internal error: attempt to send frame on a half-closed-local stream: %v", wr))
+ }
+ case stateClosed:
+ panic(fmt.Sprintf("internal error: attempt to send frame on a closed stream: %v", wr))
+ }
+ }
+ if wpp, ok := wr.write.(*writePushPromise); ok {
+ var err error
+ wpp.promisedID, err = wpp.allocatePromisedID()
+ if err != nil {
+ sc.writingFrameAsync = false
+ wr.replyToWriter(err)
+ return
+ }
+ }
+
+ sc.writingFrame = true
+ sc.needsFrameFlush = true
+ if wr.write.staysWithinBuffer(sc.bw.Available()) {
+ sc.writingFrameAsync = false
+ err := wr.write.writeFrame(sc)
+ sc.wroteFrame(frameWriteResult{wr, err})
+ } else {
+ sc.writingFrameAsync = true
+ go sc.writeFrameAsync(wr)
+ }
+}
+
+// errHandlerPanicked is the error given to any callers blocked in a read from
+// Request.Body when the main goroutine panics. Since most handlers read in the
+// main ServeHTTP goroutine, this will show up rarely.
+var errHandlerPanicked = errors.New("http2: handler panicked")
+
+// wroteFrame is called on the serve goroutine with the result of
+// whatever happened on writeFrameAsync.
+func (sc *serverConn) wroteFrame(res frameWriteResult) {
+ sc.serveG.check()
+ if !sc.writingFrame {
+ panic("internal error: expected to be already writing a frame")
+ }
+ sc.writingFrame = false
+ sc.writingFrameAsync = false
+
+ wr := res.wr
+
+ if writeEndsStream(wr.write) {
+ st := wr.stream
+ if st == nil {
+ panic("internal error: expecting non-nil stream")
+ }
+ switch st.state {
+ case stateOpen:
+ // Here we would go to stateHalfClosedLocal in
+ // theory, but since our handler is done and
+ // the net/http package provides no mechanism
+ // for closing a ResponseWriter while still
+ // reading data (see possible TODO at top of
+ // this file), we go into closed state here
+ // anyway, after telling the peer we're
+ // hanging up on them. We'll transition to
+ // stateClosed after the RST_STREAM frame is
+ // written.
+ st.state = stateHalfClosedLocal
+ // Section 8.1: a server MAY request that the client abort
+ // transmission of a request without error by sending a
+ // RST_STREAM with an error code of NO_ERROR after sending
+ // a complete response.
+ sc.resetStream(streamError(st.id, ErrCodeNo))
+ case stateHalfClosedRemote:
+ sc.closeStream(st, errHandlerComplete)
+ }
+ } else {
+ switch v := wr.write.(type) {
+ case StreamError:
+ // st may be unknown if the RST_STREAM was generated to reject bad input.
+ if st, ok := sc.streams[v.StreamID]; ok {
+ sc.closeStream(st, v)
+ }
+ case handlerPanicRST:
+ sc.closeStream(wr.stream, errHandlerPanicked)
+ }
+ }
+
+ // Reply (if requested) to unblock the ServeHTTP goroutine.
+ wr.replyToWriter(res.err)
+
+ sc.scheduleFrameWrite()
+}
+
+// scheduleFrameWrite tickles the frame writing scheduler.
+//
+// If a frame is already being written, nothing happens. This will be called again
+// when the frame is done being written.
+//
+// If a frame isn't being written we need to send one, the best frame
+// to send is selected, preferring first things that aren't
+// stream-specific (e.g. ACKing settings), and then finding the
+// highest priority stream.
+//
+// If a frame isn't being written and there's nothing else to send, we
+// flush the write buffer.
+func (sc *serverConn) scheduleFrameWrite() {
+ sc.serveG.check()
+ if sc.writingFrame || sc.inFrameScheduleLoop {
+ return
+ }
+ sc.inFrameScheduleLoop = true
+ for !sc.writingFrameAsync {
+ if sc.needToSendGoAway {
+ sc.needToSendGoAway = false
+ sc.startFrameWrite(FrameWriteRequest{
+ write: &writeGoAway{
+ maxStreamID: sc.maxClientStreamID,
+ code: sc.goAwayCode,
+ },
+ })
+ continue
+ }
+ if sc.needToSendSettingsAck {
+ sc.needToSendSettingsAck = false
+ sc.startFrameWrite(FrameWriteRequest{write: writeSettingsAck{}})
+ continue
+ }
+ if !sc.inGoAway || sc.goAwayCode == ErrCodeNo {
+ if wr, ok := sc.writeSched.Pop(); ok {
+ sc.startFrameWrite(wr)
+ continue
+ }
+ }
+ if sc.needsFrameFlush {
+ sc.startFrameWrite(FrameWriteRequest{write: flushFrameWriter{}})
+ sc.needsFrameFlush = false // after startFrameWrite, since it sets this true
+ continue
+ }
+ break
+ }
+ sc.inFrameScheduleLoop = false
+}
+
+// startGracefulShutdown gracefully shuts down a connection. This
+// sends GOAWAY with ErrCodeNo to tell the client we're gracefully
+// shutting down. The connection isn't closed until all current
+// streams are done.
+//
+// startGracefulShutdown returns immediately; it does not wait until
+// the connection has shut down.
+func (sc *serverConn) startGracefulShutdown() {
+ sc.serveG.checkNotOn() // NOT
+ sc.shutdownOnce.Do(func() { sc.sendServeMsg(gracefulShutdownMsg) })
+}
+
+// After sending GOAWAY, the connection will close after goAwayTimeout.
+// If we close the connection immediately after sending GOAWAY, there may
+// be unsent data in our kernel receive buffer, which will cause the kernel
+// to send a TCP RST on close() instead of a FIN. This RST will abort the
+// connection immediately, whether or not the client had received the GOAWAY.
+//
+// Ideally we should delay for at least 1 RTT + epsilon so the client has
+// a chance to read the GOAWAY and stop sending messages. Measuring RTT
+// is hard, so we approximate with 1 second. See golang.org/issue/18701.
+//
+// This is a var so it can be shorter in tests, where all requests uses the
+// loopback interface making the expected RTT very small.
+//
+// TODO: configurable?
+var goAwayTimeout = 1 * time.Second
+
+func (sc *serverConn) startGracefulShutdownInternal() {
+ sc.goAway(ErrCodeNo)
+}
+
+func (sc *serverConn) goAway(code ErrCode) {
+ sc.serveG.check()
+ if sc.inGoAway {
+ return
+ }
+ sc.inGoAway = true
+ sc.needToSendGoAway = true
+ sc.goAwayCode = code
+ sc.scheduleFrameWrite()
+}
+
+func (sc *serverConn) shutDownIn(d time.Duration) {
+ sc.serveG.check()
+ sc.shutdownTimer = time.AfterFunc(d, sc.onShutdownTimer)
+}
+
+func (sc *serverConn) resetStream(se StreamError) {
+ sc.serveG.check()
+ sc.writeFrame(FrameWriteRequest{write: se})
+ if st, ok := sc.streams[se.StreamID]; ok {
+ st.resetQueued = true
+ }
+}
+
+// processFrameFromReader processes the serve loop's read from readFrameCh from the
+// frame-reading goroutine.
+// processFrameFromReader returns whether the connection should be kept open.
+func (sc *serverConn) processFrameFromReader(res readFrameResult) bool {
+ sc.serveG.check()
+ err := res.err
+ if err != nil {
+ if err == ErrFrameTooLarge {
+ sc.goAway(ErrCodeFrameSize)
+ return true // goAway will close the loop
+ }
+ clientGone := err == io.EOF || err == io.ErrUnexpectedEOF || isClosedConnError(err)
+ if clientGone {
+ // TODO: could we also get into this state if
+ // the peer does a half close
+ // (e.g. CloseWrite) because they're done
+ // sending frames but they're still wanting
+ // our open replies? Investigate.
+ // TODO: add CloseWrite to crypto/tls.Conn first
+ // so we have a way to test this? I suppose
+ // just for testing we could have a non-TLS mode.
+ return false
+ }
+ } else {
+ f := res.f
+ if VerboseLogs {
+ sc.vlogf("http2: server read frame %v", summarizeFrame(f))
+ }
+ err = sc.processFrame(f)
+ if err == nil {
+ return true
+ }
+ }
+
+ switch ev := err.(type) {
+ case StreamError:
+ sc.resetStream(ev)
+ return true
+ case goAwayFlowError:
+ sc.goAway(ErrCodeFlowControl)
+ return true
+ case ConnectionError:
+ sc.logf("http2: server connection error from %v: %v", sc.conn.RemoteAddr(), ev)
+ sc.goAway(ErrCode(ev))
+ return true // goAway will handle shutdown
+ default:
+ if res.err != nil {
+ sc.vlogf("http2: server closing client connection; error reading frame from client %s: %v", sc.conn.RemoteAddr(), err)
+ } else {
+ sc.logf("http2: server closing client connection: %v", err)
+ }
+ return false
+ }
+}
+
+func (sc *serverConn) processFrame(f Frame) error {
+ sc.serveG.check()
+
+ // First frame received must be SETTINGS.
+ if !sc.sawFirstSettings {
+ if _, ok := f.(*SettingsFrame); !ok {
+ return ConnectionError(ErrCodeProtocol)
+ }
+ sc.sawFirstSettings = true
+ }
+
+ switch f := f.(type) {
+ case *SettingsFrame:
+ return sc.processSettings(f)
+ case *MetaHeadersFrame:
+ return sc.processHeaders(f)
+ case *WindowUpdateFrame:
+ return sc.processWindowUpdate(f)
+ case *PingFrame:
+ return sc.processPing(f)
+ case *DataFrame:
+ return sc.processData(f)
+ case *RSTStreamFrame:
+ return sc.processResetStream(f)
+ case *PriorityFrame:
+ return sc.processPriority(f)
+ case *GoAwayFrame:
+ return sc.processGoAway(f)
+ case *PushPromiseFrame:
+ // A client cannot push. Thus, servers MUST treat the receipt of a PUSH_PROMISE
+ // frame as a connection error (Section 5.4.1) of type PROTOCOL_ERROR.
+ return ConnectionError(ErrCodeProtocol)
+ default:
+ sc.vlogf("http2: server ignoring frame: %v", f.Header())
+ return nil
+ }
+}
+
+func (sc *serverConn) processPing(f *PingFrame) error {
+ sc.serveG.check()
+ if f.IsAck() {
+ // 6.7 PING: " An endpoint MUST NOT respond to PING frames
+ // containing this flag."
+ return nil
+ }
+ if f.StreamID != 0 {
+ // "PING frames are not associated with any individual
+ // stream. If a PING frame is received with a stream
+ // identifier field value other than 0x0, the recipient MUST
+ // respond with a connection error (Section 5.4.1) of type
+ // PROTOCOL_ERROR."
+ return ConnectionError(ErrCodeProtocol)
+ }
+ if sc.inGoAway && sc.goAwayCode != ErrCodeNo {
+ return nil
+ }
+ sc.writeFrame(FrameWriteRequest{write: writePingAck{f}})
+ return nil
+}
+
+func (sc *serverConn) processWindowUpdate(f *WindowUpdateFrame) error {
+ sc.serveG.check()
+ switch {
+ case f.StreamID != 0: // stream-level flow control
+ state, st := sc.state(f.StreamID)
+ if state == stateIdle {
+ // Section 5.1: "Receiving any frame other than HEADERS
+ // or PRIORITY on a stream in this state MUST be
+ // treated as a connection error (Section 5.4.1) of
+ // type PROTOCOL_ERROR."
+ return ConnectionError(ErrCodeProtocol)
+ }
+ if st == nil {
+ // "WINDOW_UPDATE can be sent by a peer that has sent a
+ // frame bearing the END_STREAM flag. This means that a
+ // receiver could receive a WINDOW_UPDATE frame on a "half
+ // closed (remote)" or "closed" stream. A receiver MUST
+ // NOT treat this as an error, see Section 5.1."
+ return nil
+ }
+ if !st.flow.add(int32(f.Increment)) {
+ return streamError(f.StreamID, ErrCodeFlowControl)
+ }
+ default: // connection-level flow control
+ if !sc.flow.add(int32(f.Increment)) {
+ return goAwayFlowError{}
+ }
+ }
+ sc.scheduleFrameWrite()
+ return nil
+}
+
+func (sc *serverConn) processResetStream(f *RSTStreamFrame) error {
+ sc.serveG.check()
+
+ state, st := sc.state(f.StreamID)
+ if state == stateIdle {
+ // 6.4 "RST_STREAM frames MUST NOT be sent for a
+ // stream in the "idle" state. If a RST_STREAM frame
+ // identifying an idle stream is received, the
+ // recipient MUST treat this as a connection error
+ // (Section 5.4.1) of type PROTOCOL_ERROR.
+ return ConnectionError(ErrCodeProtocol)
+ }
+ if st != nil {
+ st.cancelCtx()
+ sc.closeStream(st, streamError(f.StreamID, f.ErrCode))
+ }
+ return nil
+}
+
+func (sc *serverConn) closeStream(st *stream, err error) {
+ sc.serveG.check()
+ if st.state == stateIdle || st.state == stateClosed {
+ panic(fmt.Sprintf("invariant; can't close stream in state %v", st.state))
+ }
+ st.state = stateClosed
+ if st.writeDeadline != nil {
+ st.writeDeadline.Stop()
+ }
+ if st.isPushed() {
+ sc.curPushedStreams--
+ } else {
+ sc.curClientStreams--
+ }
+ delete(sc.streams, st.id)
+ if len(sc.streams) == 0 {
+ sc.setConnState(http.StateIdle)
+ if sc.srv.IdleTimeout != 0 {
+ sc.idleTimer.Reset(sc.srv.IdleTimeout)
+ }
+ if h1ServerKeepAlivesDisabled(sc.hs) {
+ sc.startGracefulShutdownInternal()
+ }
+ }
+ if p := st.body; p != nil {
+ // Return any buffered unread bytes worth of conn-level flow control.
+ // See golang.org/issue/16481
+ sc.sendWindowUpdate(nil, p.Len())
+
+ p.CloseWithError(err)
+ }
+ st.cw.Close() // signals Handler's CloseNotifier, unblocks writes, etc
+ sc.writeSched.CloseStream(st.id)
+}
+
+func (sc *serverConn) processSettings(f *SettingsFrame) error {
+ sc.serveG.check()
+ if f.IsAck() {
+ sc.unackedSettings--
+ if sc.unackedSettings < 0 {
+ // Why is the peer ACKing settings we never sent?
+ // The spec doesn't mention this case, but
+ // hang up on them anyway.
+ return ConnectionError(ErrCodeProtocol)
+ }
+ return nil
+ }
+ if f.NumSettings() > 100 || f.HasDuplicates() {
+ // This isn't actually in the spec, but hang up on
+ // suspiciously large settings frames or those with
+ // duplicate entries.
+ return ConnectionError(ErrCodeProtocol)
+ }
+ if err := f.ForeachSetting(sc.processSetting); err != nil {
+ return err
+ }
+ sc.needToSendSettingsAck = true
+ sc.scheduleFrameWrite()
+ return nil
+}
+
+func (sc *serverConn) processSetting(s Setting) error {
+ sc.serveG.check()
+ if err := s.Valid(); err != nil {
+ return err
+ }
+ if VerboseLogs {
+ sc.vlogf("http2: server processing setting %v", s)
+ }
+ switch s.ID {
+ case SettingHeaderTableSize:
+ sc.headerTableSize = s.Val
+ sc.hpackEncoder.SetMaxDynamicTableSize(s.Val)
+ case SettingEnablePush:
+ sc.pushEnabled = s.Val != 0
+ case SettingMaxConcurrentStreams:
+ sc.clientMaxStreams = s.Val
+ case SettingInitialWindowSize:
+ return sc.processSettingInitialWindowSize(s.Val)
+ case SettingMaxFrameSize:
+ sc.maxFrameSize = int32(s.Val) // the maximum valid s.Val is < 2^31
+ case SettingMaxHeaderListSize:
+ sc.peerMaxHeaderListSize = s.Val
+ default:
+ // Unknown setting: "An endpoint that receives a SETTINGS
+ // frame with any unknown or unsupported identifier MUST
+ // ignore that setting."
+ if VerboseLogs {
+ sc.vlogf("http2: server ignoring unknown setting %v", s)
+ }
+ }
+ return nil
+}
+
+func (sc *serverConn) processSettingInitialWindowSize(val uint32) error {
+ sc.serveG.check()
+ // Note: val already validated to be within range by
+ // processSetting's Valid call.
+
+ // "A SETTINGS frame can alter the initial flow control window
+ // size for all current streams. When the value of
+ // SETTINGS_INITIAL_WINDOW_SIZE changes, a receiver MUST
+ // adjust the size of all stream flow control windows that it
+ // maintains by the difference between the new value and the
+ // old value."
+ old := sc.initialStreamSendWindowSize
+ sc.initialStreamSendWindowSize = int32(val)
+ growth := int32(val) - old // may be negative
+ for _, st := range sc.streams {
+ if !st.flow.add(growth) {
+ // 6.9.2 Initial Flow Control Window Size
+ // "An endpoint MUST treat a change to
+ // SETTINGS_INITIAL_WINDOW_SIZE that causes any flow
+ // control window to exceed the maximum size as a
+ // connection error (Section 5.4.1) of type
+ // FLOW_CONTROL_ERROR."
+ return ConnectionError(ErrCodeFlowControl)
+ }
+ }
+ return nil
+}
+
+func (sc *serverConn) processData(f *DataFrame) error {
+ sc.serveG.check()
+ if sc.inGoAway && sc.goAwayCode != ErrCodeNo {
+ return nil
+ }
+ data := f.Data()
+
+ // "If a DATA frame is received whose stream is not in "open"
+ // or "half closed (local)" state, the recipient MUST respond
+ // with a stream error (Section 5.4.2) of type STREAM_CLOSED."
+ id := f.Header().StreamID
+ state, st := sc.state(id)
+ if id == 0 || state == stateIdle {
+ // Section 5.1: "Receiving any frame other than HEADERS
+ // or PRIORITY on a stream in this state MUST be
+ // treated as a connection error (Section 5.4.1) of
+ // type PROTOCOL_ERROR."
+ return ConnectionError(ErrCodeProtocol)
+ }
+ if st == nil || state != stateOpen || st.gotTrailerHeader || st.resetQueued {
+ // This includes sending a RST_STREAM if the stream is
+ // in stateHalfClosedLocal (which currently means that
+ // the http.Handler returned, so it's done reading &
+ // done writing). Try to stop the client from sending
+ // more DATA.
+
+ // But still enforce their connection-level flow control,
+ // and return any flow control bytes since we're not going
+ // to consume them.
+ if sc.inflow.available() < int32(f.Length) {
+ return streamError(id, ErrCodeFlowControl)
+ }
+ // Deduct the flow control from inflow, since we're
+ // going to immediately add it back in
+ // sendWindowUpdate, which also schedules sending the
+ // frames.
+ sc.inflow.take(int32(f.Length))
+ sc.sendWindowUpdate(nil, int(f.Length)) // conn-level
+
+ if st != nil && st.resetQueued {
+ // Already have a stream error in flight. Don't send another.
+ return nil
+ }
+ return streamError(id, ErrCodeStreamClosed)
+ }
+ if st.body == nil {
+ panic("internal error: should have a body in this state")
+ }
+
+ // Sender sending more than they'd declared?
+ if st.declBodyBytes != -1 && st.bodyBytes+int64(len(data)) > st.declBodyBytes {
+ st.body.CloseWithError(fmt.Errorf("sender tried to send more than declared Content-Length of %d bytes", st.declBodyBytes))
+ // RFC 7540, sec 8.1.2.6: A request or response is also malformed if the
+ // value of a content-length header field does not equal the sum of the
+ // DATA frame payload lengths that form the body.
+ return streamError(id, ErrCodeProtocol)
+ }
+ if f.Length > 0 {
+ // Check whether the client has flow control quota.
+ if st.inflow.available() < int32(f.Length) {
+ return streamError(id, ErrCodeFlowControl)
+ }
+ st.inflow.take(int32(f.Length))
+
+ if len(data) > 0 {
+ wrote, err := st.body.Write(data)
+ if err != nil {
+ return streamError(id, ErrCodeStreamClosed)
+ }
+ if wrote != len(data) {
+ panic("internal error: bad Writer")
+ }
+ st.bodyBytes += int64(len(data))
+ }
+
+ // Return any padded flow control now, since we won't
+ // refund it later on body reads.
+ if pad := int32(f.Length) - int32(len(data)); pad > 0 {
+ sc.sendWindowUpdate32(nil, pad)
+ sc.sendWindowUpdate32(st, pad)
+ }
+ }
+ if f.StreamEnded() {
+ st.endStream()
+ }
+ return nil
+}
+
+func (sc *serverConn) processGoAway(f *GoAwayFrame) error {
+ sc.serveG.check()
+ if f.ErrCode != ErrCodeNo {
+ sc.logf("http2: received GOAWAY %+v, starting graceful shutdown", f)
+ } else {
+ sc.vlogf("http2: received GOAWAY %+v, starting graceful shutdown", f)
+ }
+ sc.startGracefulShutdownInternal()
+ // http://tools.ietf.org/html/rfc7540#section-6.8
+ // We should not create any new streams, which means we should disable push.
+ sc.pushEnabled = false
+ return nil
+}
+
+// isPushed reports whether the stream is server-initiated.
+func (st *stream) isPushed() bool {
+ return st.id%2 == 0
+}
+
+// endStream closes a Request.Body's pipe. It is called when a DATA
+// frame says a request body is over (or after trailers).
+func (st *stream) endStream() {
+ sc := st.sc
+ sc.serveG.check()
+
+ if st.declBodyBytes != -1 && st.declBodyBytes != st.bodyBytes {
+ st.body.CloseWithError(fmt.Errorf("request declared a Content-Length of %d but only wrote %d bytes",
+ st.declBodyBytes, st.bodyBytes))
+ } else {
+ st.body.closeWithErrorAndCode(io.EOF, st.copyTrailersToHandlerRequest)
+ st.body.CloseWithError(io.EOF)
+ }
+ st.state = stateHalfClosedRemote
+}
+
+// copyTrailersToHandlerRequest is run in the Handler's goroutine in
+// its Request.Body.Read just before it gets io.EOF.
+func (st *stream) copyTrailersToHandlerRequest() {
+ for k, vv := range st.trailer {
+ if _, ok := st.reqTrailer[k]; ok {
+ // Only copy it over it was pre-declared.
+ st.reqTrailer[k] = vv
+ }
+ }
+}
+
+// onWriteTimeout is run on its own goroutine (from time.AfterFunc)
+// when the stream's WriteTimeout has fired.
+func (st *stream) onWriteTimeout() {
+ st.sc.writeFrameFromHandler(FrameWriteRequest{write: streamError(st.id, ErrCodeInternal)})
+}
+
+func (sc *serverConn) processHeaders(f *MetaHeadersFrame) error {
+ sc.serveG.check()
+ id := f.StreamID
+ if sc.inGoAway {
+ // Ignore.
+ return nil
+ }
+ // http://tools.ietf.org/html/rfc7540#section-5.1.1
+ // Streams initiated by a client MUST use odd-numbered stream
+ // identifiers. [...] An endpoint that receives an unexpected
+ // stream identifier MUST respond with a connection error
+ // (Section 5.4.1) of type PROTOCOL_ERROR.
+ if id%2 != 1 {
+ return ConnectionError(ErrCodeProtocol)
+ }
+ // A HEADERS frame can be used to create a new stream or
+ // send a trailer for an open one. If we already have a stream
+ // open, let it process its own HEADERS frame (trailers at this
+ // point, if it's valid).
+ if st := sc.streams[f.StreamID]; st != nil {
+ if st.resetQueued {
+ // We're sending RST_STREAM to close the stream, so don't bother
+ // processing this frame.
+ return nil
+ }
+ // RFC 7540, sec 5.1: If an endpoint receives additional frames, other than
+ // WINDOW_UPDATE, PRIORITY, or RST_STREAM, for a stream that is in
+ // this state, it MUST respond with a stream error (Section 5.4.2) of
+ // type STREAM_CLOSED.
+ if st.state == stateHalfClosedRemote {
+ return streamError(id, ErrCodeStreamClosed)
+ }
+ return st.processTrailerHeaders(f)
+ }
+
+ // [...] The identifier of a newly established stream MUST be
+ // numerically greater than all streams that the initiating
+ // endpoint has opened or reserved. [...] An endpoint that
+ // receives an unexpected stream identifier MUST respond with
+ // a connection error (Section 5.4.1) of type PROTOCOL_ERROR.
+ if id <= sc.maxClientStreamID {
+ return ConnectionError(ErrCodeProtocol)
+ }
+ sc.maxClientStreamID = id
+
+ if sc.idleTimer != nil {
+ sc.idleTimer.Stop()
+ }
+
+ // http://tools.ietf.org/html/rfc7540#section-5.1.2
+ // [...] Endpoints MUST NOT exceed the limit set by their peer. An
+ // endpoint that receives a HEADERS frame that causes their
+ // advertised concurrent stream limit to be exceeded MUST treat
+ // this as a stream error (Section 5.4.2) of type PROTOCOL_ERROR
+ // or REFUSED_STREAM.
+ if sc.curClientStreams+1 > sc.advMaxStreams {
+ if sc.unackedSettings == 0 {
+ // They should know better.
+ return streamError(id, ErrCodeProtocol)
+ }
+ // Assume it's a network race, where they just haven't
+ // received our last SETTINGS update. But actually
+ // this can't happen yet, because we don't yet provide
+ // a way for users to adjust server parameters at
+ // runtime.
+ return streamError(id, ErrCodeRefusedStream)
+ }
+
+ initialState := stateOpen
+ if f.StreamEnded() {
+ initialState = stateHalfClosedRemote
+ }
+ st := sc.newStream(id, 0, initialState)
+
+ if f.HasPriority() {
+ if err := checkPriority(f.StreamID, f.Priority); err != nil {
+ return err
+ }
+ sc.writeSched.AdjustStream(st.id, f.Priority)
+ }
+
+ rw, req, err := sc.newWriterAndRequest(st, f)
+ if err != nil {
+ return err
+ }
+ st.reqTrailer = req.Trailer
+ if st.reqTrailer != nil {
+ st.trailer = make(http.Header)
+ }
+ st.body = req.Body.(*requestBody).pipe // may be nil
+ st.declBodyBytes = req.ContentLength
+
+ handler := sc.handler.ServeHTTP
+ if f.Truncated {
+ // Their header list was too long. Send a 431 error.
+ handler = handleHeaderListTooLong
+ } else if err := checkValidHTTP2RequestHeaders(req.Header); err != nil {
+ handler = new400Handler(err)
+ }
+
+ // The net/http package sets the read deadline from the
+ // http.Server.ReadTimeout during the TLS handshake, but then
+ // passes the connection off to us with the deadline already
+ // set. Disarm it here after the request headers are read,
+ // similar to how the http1 server works. Here it's
+ // technically more like the http1 Server's ReadHeaderTimeout
+ // (in Go 1.8), though. That's a more sane option anyway.
+ if sc.hs.ReadTimeout != 0 {
+ sc.conn.SetReadDeadline(time.Time{})
+ }
+
+ go sc.runHandler(rw, req, handler)
+ return nil
+}
+
+func (st *stream) processTrailerHeaders(f *MetaHeadersFrame) error {
+ sc := st.sc
+ sc.serveG.check()
+ if st.gotTrailerHeader {
+ return ConnectionError(ErrCodeProtocol)
+ }
+ st.gotTrailerHeader = true
+ if !f.StreamEnded() {
+ return streamError(st.id, ErrCodeProtocol)
+ }
+
+ if len(f.PseudoFields()) > 0 {
+ return streamError(st.id, ErrCodeProtocol)
+ }
+ if st.trailer != nil {
+ for _, hf := range f.RegularFields() {
+ key := sc.canonicalHeader(hf.Name)
+ if !httpguts.ValidTrailerHeader(key) {
+ // TODO: send more details to the peer somehow. But http2 has
+ // no way to send debug data at a stream level. Discuss with
+ // HTTP folk.
+ return streamError(st.id, ErrCodeProtocol)
+ }
+ st.trailer[key] = append(st.trailer[key], hf.Value)
+ }
+ }
+ st.endStream()
+ return nil
+}
+
+func checkPriority(streamID uint32, p PriorityParam) error {
+ if streamID == p.StreamDep {
+ // Section 5.3.1: "A stream cannot depend on itself. An endpoint MUST treat
+ // this as a stream error (Section 5.4.2) of type PROTOCOL_ERROR."
+ // Section 5.3.3 says that a stream can depend on one of its dependencies,
+ // so it's only self-dependencies that are forbidden.
+ return streamError(streamID, ErrCodeProtocol)
+ }
+ return nil
+}
+
+func (sc *serverConn) processPriority(f *PriorityFrame) error {
+ if sc.inGoAway {
+ return nil
+ }
+ if err := checkPriority(f.StreamID, f.PriorityParam); err != nil {
+ return err
+ }
+ sc.writeSched.AdjustStream(f.StreamID, f.PriorityParam)
+ return nil
+}
+
+func (sc *serverConn) newStream(id, pusherID uint32, state streamState) *stream {
+ sc.serveG.check()
+ if id == 0 {
+ panic("internal error: cannot create stream with id 0")
+ }
+
+ ctx, cancelCtx := context.WithCancel(sc.baseCtx)
+ st := &stream{
+ sc: sc,
+ id: id,
+ state: state,
+ ctx: ctx,
+ cancelCtx: cancelCtx,
+ }
+ st.cw.Init()
+ st.flow.conn = &sc.flow // link to conn-level counter
+ st.flow.add(sc.initialStreamSendWindowSize)
+ st.inflow.conn = &sc.inflow // link to conn-level counter
+ st.inflow.add(sc.srv.initialStreamRecvWindowSize())
+ if sc.hs.WriteTimeout != 0 {
+ st.writeDeadline = time.AfterFunc(sc.hs.WriteTimeout, st.onWriteTimeout)
+ }
+
+ sc.streams[id] = st
+ sc.writeSched.OpenStream(st.id, OpenStreamOptions{PusherID: pusherID})
+ if st.isPushed() {
+ sc.curPushedStreams++
+ } else {
+ sc.curClientStreams++
+ }
+ if sc.curOpenStreams() == 1 {
+ sc.setConnState(http.StateActive)
+ }
+
+ return st
+}
+
+func (sc *serverConn) newWriterAndRequest(st *stream, f *MetaHeadersFrame) (*responseWriter, *http.Request, error) {
+ sc.serveG.check()
+
+ rp := requestParam{
+ method: f.PseudoValue("method"),
+ scheme: f.PseudoValue("scheme"),
+ authority: f.PseudoValue("authority"),
+ path: f.PseudoValue("path"),
+ }
+
+ isConnect := rp.method == "CONNECT"
+ if isConnect {
+ if rp.path != "" || rp.scheme != "" || rp.authority == "" {
+ return nil, nil, streamError(f.StreamID, ErrCodeProtocol)
+ }
+ } else if rp.method == "" || rp.path == "" || (rp.scheme != "https" && rp.scheme != "http") {
+ // See 8.1.2.6 Malformed Requests and Responses:
+ //
+ // Malformed requests or responses that are detected
+ // MUST be treated as a stream error (Section 5.4.2)
+ // of type PROTOCOL_ERROR."
+ //
+ // 8.1.2.3 Request Pseudo-Header Fields
+ // "All HTTP/2 requests MUST include exactly one valid
+ // value for the :method, :scheme, and :path
+ // pseudo-header fields"
+ return nil, nil, streamError(f.StreamID, ErrCodeProtocol)
+ }
+
+ bodyOpen := !f.StreamEnded()
+ if rp.method == "HEAD" && bodyOpen {
+ // HEAD requests can't have bodies
+ return nil, nil, streamError(f.StreamID, ErrCodeProtocol)
+ }
+
+ rp.header = make(http.Header)
+ for _, hf := range f.RegularFields() {
+ rp.header.Add(sc.canonicalHeader(hf.Name), hf.Value)
+ }
+ if rp.authority == "" {
+ rp.authority = rp.header.Get("Host")
+ }
+
+ rw, req, err := sc.newWriterAndRequestNoBody(st, rp)
+ if err != nil {
+ return nil, nil, err
+ }
+ if bodyOpen {
+ if vv, ok := rp.header["Content-Length"]; ok {
+ req.ContentLength, _ = strconv.ParseInt(vv[0], 10, 64)
+ } else {
+ req.ContentLength = -1
+ }
+ req.Body.(*requestBody).pipe = &pipe{
+ b: &dataBuffer{expected: req.ContentLength},
+ }
+ }
+ return rw, req, nil
+}
+
+type requestParam struct {
+ method string
+ scheme, authority, path string
+ header http.Header
+}
+
+func (sc *serverConn) newWriterAndRequestNoBody(st *stream, rp requestParam) (*responseWriter, *http.Request, error) {
+ sc.serveG.check()
+
+ var tlsState *tls.ConnectionState // nil if not scheme https
+ if rp.scheme == "https" {
+ tlsState = sc.tlsState
+ }
+
+ needsContinue := rp.header.Get("Expect") == "100-continue"
+ if needsContinue {
+ rp.header.Del("Expect")
+ }
+ // Merge Cookie headers into one "; "-delimited value.
+ if cookies := rp.header["Cookie"]; len(cookies) > 1 {
+ rp.header.Set("Cookie", strings.Join(cookies, "; "))
+ }
+
+ // Setup Trailers
+ var trailer http.Header
+ for _, v := range rp.header["Trailer"] {
+ for _, key := range strings.Split(v, ",") {
+ key = http.CanonicalHeaderKey(strings.TrimSpace(key))
+ switch key {
+ case "Transfer-Encoding", "Trailer", "Content-Length":
+ // Bogus. (copy of http1 rules)
+ // Ignore.
+ default:
+ if trailer == nil {
+ trailer = make(http.Header)
+ }
+ trailer[key] = nil
+ }
+ }
+ }
+ delete(rp.header, "Trailer")
+
+ var url_ *url.URL
+ var requestURI string
+ if rp.method == "CONNECT" {
+ url_ = &url.URL{Host: rp.authority}
+ requestURI = rp.authority // mimic HTTP/1 server behavior
+ } else {
+ var err error
+ url_, err = url.ParseRequestURI(rp.path)
+ if err != nil {
+ return nil, nil, streamError(st.id, ErrCodeProtocol)
+ }
+ requestURI = rp.path
+ }
+
+ body := &requestBody{
+ conn: sc,
+ stream: st,
+ needsContinue: needsContinue,
+ }
+ req := &http.Request{
+ Method: rp.method,
+ URL: url_,
+ RemoteAddr: sc.remoteAddrStr,
+ Header: rp.header,
+ RequestURI: requestURI,
+ Proto: "HTTP/2.0",
+ ProtoMajor: 2,
+ ProtoMinor: 0,
+ TLS: tlsState,
+ Host: rp.authority,
+ Body: body,
+ Trailer: trailer,
+ }
+ req = req.WithContext(st.ctx)
+
+ rws := responseWriterStatePool.Get().(*responseWriterState)
+ bwSave := rws.bw
+ *rws = responseWriterState{} // zero all the fields
+ rws.conn = sc
+ rws.bw = bwSave
+ rws.bw.Reset(chunkWriter{rws})
+ rws.stream = st
+ rws.req = req
+ rws.body = body
+
+ rw := &responseWriter{rws: rws}
+ return rw, req, nil
+}
+
+// Run on its own goroutine.
+func (sc *serverConn) runHandler(rw *responseWriter, req *http.Request, handler func(http.ResponseWriter, *http.Request)) {
+ didPanic := true
+ defer func() {
+ rw.rws.stream.cancelCtx()
+ if didPanic {
+ e := recover()
+ sc.writeFrameFromHandler(FrameWriteRequest{
+ write: handlerPanicRST{rw.rws.stream.id},
+ stream: rw.rws.stream,
+ })
+ // Same as net/http:
+ if e != nil && e != http.ErrAbortHandler {
+ const size = 64 << 10
+ buf := make([]byte, size)
+ buf = buf[:runtime.Stack(buf, false)]
+ sc.logf("http2: panic serving %v: %v\n%s", sc.conn.RemoteAddr(), e, buf)
+ }
+ return
+ }
+ rw.handlerDone()
+ }()
+ handler(rw, req)
+ didPanic = false
+}
+
+func handleHeaderListTooLong(w http.ResponseWriter, r *http.Request) {
+ // 10.5.1 Limits on Header Block Size:
+ // .. "A server that receives a larger header block than it is
+ // willing to handle can send an HTTP 431 (Request Header Fields Too
+ // Large) status code"
+ const statusRequestHeaderFieldsTooLarge = 431 // only in Go 1.6+
+ w.WriteHeader(statusRequestHeaderFieldsTooLarge)
+ io.WriteString(w, "<h1>HTTP Error 431</h1><p>Request Header Field(s) Too Large</p>")
+}
+
+// called from handler goroutines.
+// h may be nil.
+func (sc *serverConn) writeHeaders(st *stream, headerData *writeResHeaders) error {
+ sc.serveG.checkNotOn() // NOT on
+ var errc chan error
+ if headerData.h != nil {
+ // If there's a header map (which we don't own), so we have to block on
+ // waiting for this frame to be written, so an http.Flush mid-handler
+ // writes out the correct value of keys, before a handler later potentially
+ // mutates it.
+ errc = errChanPool.Get().(chan error)
+ }
+ if err := sc.writeFrameFromHandler(FrameWriteRequest{
+ write: headerData,
+ stream: st,
+ done: errc,
+ }); err != nil {
+ return err
+ }
+ if errc != nil {
+ select {
+ case err := <-errc:
+ errChanPool.Put(errc)
+ return err
+ case <-sc.doneServing:
+ return errClientDisconnected
+ case <-st.cw:
+ return errStreamClosed
+ }
+ }
+ return nil
+}
+
+// called from handler goroutines.
+func (sc *serverConn) write100ContinueHeaders(st *stream) {
+ sc.writeFrameFromHandler(FrameWriteRequest{
+ write: write100ContinueHeadersFrame{st.id},
+ stream: st,
+ })
+}
+
+// A bodyReadMsg tells the server loop that the http.Handler read n
+// bytes of the DATA from the client on the given stream.
+type bodyReadMsg struct {
+ st *stream
+ n int
+}
+
+// called from handler goroutines.
+// Notes that the handler for the given stream ID read n bytes of its body
+// and schedules flow control tokens to be sent.
+func (sc *serverConn) noteBodyReadFromHandler(st *stream, n int, err error) {
+ sc.serveG.checkNotOn() // NOT on
+ if n > 0 {
+ select {
+ case sc.bodyReadCh <- bodyReadMsg{st, n}:
+ case <-sc.doneServing:
+ }
+ }
+}
+
+func (sc *serverConn) noteBodyRead(st *stream, n int) {
+ sc.serveG.check()
+ sc.sendWindowUpdate(nil, n) // conn-level
+ if st.state != stateHalfClosedRemote && st.state != stateClosed {
+ // Don't send this WINDOW_UPDATE if the stream is closed
+ // remotely.
+ sc.sendWindowUpdate(st, n)
+ }
+}
+
+// st may be nil for conn-level
+func (sc *serverConn) sendWindowUpdate(st *stream, n int) {
+ sc.serveG.check()
+ // "The legal range for the increment to the flow control
+ // window is 1 to 2^31-1 (2,147,483,647) octets."
+ // A Go Read call on 64-bit machines could in theory read
+ // a larger Read than this. Very unlikely, but we handle it here
+ // rather than elsewhere for now.
+ const maxUint31 = 1<<31 - 1
+ for n >= maxUint31 {
+ sc.sendWindowUpdate32(st, maxUint31)
+ n -= maxUint31
+ }
+ sc.sendWindowUpdate32(st, int32(n))
+}
+
+// st may be nil for conn-level
+func (sc *serverConn) sendWindowUpdate32(st *stream, n int32) {
+ sc.serveG.check()
+ if n == 0 {
+ return
+ }
+ if n < 0 {
+ panic("negative update")
+ }
+ var streamID uint32
+ if st != nil {
+ streamID = st.id
+ }
+ sc.writeFrame(FrameWriteRequest{
+ write: writeWindowUpdate{streamID: streamID, n: uint32(n)},
+ stream: st,
+ })
+ var ok bool
+ if st == nil {
+ ok = sc.inflow.add(n)
+ } else {
+ ok = st.inflow.add(n)
+ }
+ if !ok {
+ panic("internal error; sent too many window updates without decrements?")
+ }
+}
+
+// requestBody is the Handler's Request.Body type.
+// Read and Close may be called concurrently.
+type requestBody struct {
+ stream *stream
+ conn *serverConn
+ closed bool // for use by Close only
+ sawEOF bool // for use by Read only
+ pipe *pipe // non-nil if we have a HTTP entity message body
+ needsContinue bool // need to send a 100-continue
+}
+
+func (b *requestBody) Close() error {
+ if b.pipe != nil && !b.closed {
+ b.pipe.BreakWithError(errClosedBody)
+ }
+ b.closed = true
+ return nil
+}
+
+func (b *requestBody) Read(p []byte) (n int, err error) {
+ if b.needsContinue {
+ b.needsContinue = false
+ b.conn.write100ContinueHeaders(b.stream)
+ }
+ if b.pipe == nil || b.sawEOF {
+ return 0, io.EOF
+ }
+ n, err = b.pipe.Read(p)
+ if err == io.EOF {
+ b.sawEOF = true
+ }
+ if b.conn == nil && inTests {
+ return
+ }
+ b.conn.noteBodyReadFromHandler(b.stream, n, err)
+ return
+}
+
+// responseWriter is the http.ResponseWriter implementation. It's
+// intentionally small (1 pointer wide) to minimize garbage. The
+// responseWriterState pointer inside is zeroed at the end of a
+// request (in handlerDone) and calls on the responseWriter thereafter
+// simply crash (caller's mistake), but the much larger responseWriterState
+// and buffers are reused between multiple requests.
+type responseWriter struct {
+ rws *responseWriterState
+}
+
+// Optional http.ResponseWriter interfaces implemented.
+var (
+ _ http.CloseNotifier = (*responseWriter)(nil)
+ _ http.Flusher = (*responseWriter)(nil)
+ _ stringWriter = (*responseWriter)(nil)
+)
+
+type responseWriterState struct {
+ // immutable within a request:
+ stream *stream
+ req *http.Request
+ body *requestBody // to close at end of request, if DATA frames didn't
+ conn *serverConn
+
+ // TODO: adjust buffer writing sizes based on server config, frame size updates from peer, etc
+ bw *bufio.Writer // writing to a chunkWriter{this *responseWriterState}
+
+ // mutated by http.Handler goroutine:
+ handlerHeader http.Header // nil until called
+ snapHeader http.Header // snapshot of handlerHeader at WriteHeader time
+ trailers []string // set in writeChunk
+ status int // status code passed to WriteHeader
+ wroteHeader bool // WriteHeader called (explicitly or implicitly). Not necessarily sent to user yet.
+ sentHeader bool // have we sent the header frame?
+ handlerDone bool // handler has finished
+ dirty bool // a Write failed; don't reuse this responseWriterState
+
+ sentContentLen int64 // non-zero if handler set a Content-Length header
+ wroteBytes int64
+
+ closeNotifierMu sync.Mutex // guards closeNotifierCh
+ closeNotifierCh chan bool // nil until first used
+}
+
+type chunkWriter struct{ rws *responseWriterState }
+
+func (cw chunkWriter) Write(p []byte) (n int, err error) { return cw.rws.writeChunk(p) }
+
+func (rws *responseWriterState) hasTrailers() bool { return len(rws.trailers) != 0 }
+
+// declareTrailer is called for each Trailer header when the
+// response header is written. It notes that a header will need to be
+// written in the trailers at the end of the response.
+func (rws *responseWriterState) declareTrailer(k string) {
+ k = http.CanonicalHeaderKey(k)
+ if !httpguts.ValidTrailerHeader(k) {
+ // Forbidden by RFC 7230, section 4.1.2.
+ rws.conn.logf("ignoring invalid trailer %q", k)
+ return
+ }
+ if !strSliceContains(rws.trailers, k) {
+ rws.trailers = append(rws.trailers, k)
+ }
+}
+
+// writeChunk writes chunks from the bufio.Writer. But because
+// bufio.Writer may bypass its chunking, sometimes p may be
+// arbitrarily large.
+//
+// writeChunk is also responsible (on the first chunk) for sending the
+// HEADER response.
+func (rws *responseWriterState) writeChunk(p []byte) (n int, err error) {
+ if !rws.wroteHeader {
+ rws.writeHeader(200)
+ }
+
+ isHeadResp := rws.req.Method == "HEAD"
+ if !rws.sentHeader {
+ rws.sentHeader = true
+ var ctype, clen string
+ if clen = rws.snapHeader.Get("Content-Length"); clen != "" {
+ rws.snapHeader.Del("Content-Length")
+ clen64, err := strconv.ParseInt(clen, 10, 64)
+ if err == nil && clen64 >= 0 {
+ rws.sentContentLen = clen64
+ } else {
+ clen = ""
+ }
+ }
+ if clen == "" && rws.handlerDone && bodyAllowedForStatus(rws.status) && (len(p) > 0 || !isHeadResp) {
+ clen = strconv.Itoa(len(p))
+ }
+ _, hasContentType := rws.snapHeader["Content-Type"]
+ if !hasContentType && bodyAllowedForStatus(rws.status) && len(p) > 0 {
+ ctype = http.DetectContentType(p)
+ }
+ var date string
+ if _, ok := rws.snapHeader["Date"]; !ok {
+ // TODO(bradfitz): be faster here, like net/http? measure.
+ date = time.Now().UTC().Format(http.TimeFormat)
+ }
+
+ for _, v := range rws.snapHeader["Trailer"] {
+ foreachHeaderElement(v, rws.declareTrailer)
+ }
+
+ // "Connection" headers aren't allowed in HTTP/2 (RFC 7540, 8.1.2.2),
+ // but respect "Connection" == "close" to mean sending a GOAWAY and tearing
+ // down the TCP connection when idle, like we do for HTTP/1.
+ // TODO: remove more Connection-specific header fields here, in addition
+ // to "Connection".
+ if _, ok := rws.snapHeader["Connection"]; ok {
+ v := rws.snapHeader.Get("Connection")
+ delete(rws.snapHeader, "Connection")
+ if v == "close" {
+ rws.conn.startGracefulShutdown()
+ }
+ }
+
+ endStream := (rws.handlerDone && !rws.hasTrailers() && len(p) == 0) || isHeadResp
+ err = rws.conn.writeHeaders(rws.stream, &writeResHeaders{
+ streamID: rws.stream.id,
+ httpResCode: rws.status,
+ h: rws.snapHeader,
+ endStream: endStream,
+ contentType: ctype,
+ contentLength: clen,
+ date: date,
+ })
+ if err != nil {
+ rws.dirty = true
+ return 0, err
+ }
+ if endStream {
+ return 0, nil
+ }
+ }
+ if isHeadResp {
+ return len(p), nil
+ }
+ if len(p) == 0 && !rws.handlerDone {
+ return 0, nil
+ }
+
+ if rws.handlerDone {
+ rws.promoteUndeclaredTrailers()
+ }
+
+ endStream := rws.handlerDone && !rws.hasTrailers()
+ if len(p) > 0 || endStream {
+ // only send a 0 byte DATA frame if we're ending the stream.
+ if err := rws.conn.writeDataFromHandler(rws.stream, p, endStream); err != nil {
+ rws.dirty = true
+ return 0, err
+ }
+ }
+
+ if rws.handlerDone && rws.hasTrailers() {
+ err = rws.conn.writeHeaders(rws.stream, &writeResHeaders{
+ streamID: rws.stream.id,
+ h: rws.handlerHeader,
+ trailers: rws.trailers,
+ endStream: true,
+ })
+ if err != nil {
+ rws.dirty = true
+ }
+ return len(p), err
+ }
+ return len(p), nil
+}
+
+// TrailerPrefix is a magic prefix for ResponseWriter.Header map keys
+// that, if present, signals that the map entry is actually for
+// the response trailers, and not the response headers. The prefix
+// is stripped after the ServeHTTP call finishes and the values are
+// sent in the trailers.
+//
+// This mechanism is intended only for trailers that are not known
+// prior to the headers being written. If the set of trailers is fixed
+// or known before the header is written, the normal Go trailers mechanism
+// is preferred:
+// https://golang.org/pkg/net/http/#ResponseWriter
+// https://golang.org/pkg/net/http/#example_ResponseWriter_trailers
+const TrailerPrefix = "Trailer:"
+
+// promoteUndeclaredTrailers permits http.Handlers to set trailers
+// after the header has already been flushed. Because the Go
+// ResponseWriter interface has no way to set Trailers (only the
+// Header), and because we didn't want to expand the ResponseWriter
+// interface, and because nobody used trailers, and because RFC 7230
+// says you SHOULD (but not must) predeclare any trailers in the
+// header, the official ResponseWriter rules said trailers in Go must
+// be predeclared, and then we reuse the same ResponseWriter.Header()
+// map to mean both Headers and Trailers. When it's time to write the
+// Trailers, we pick out the fields of Headers that were declared as
+// trailers. That worked for a while, until we found the first major
+// user of Trailers in the wild: gRPC (using them only over http2),
+// and gRPC libraries permit setting trailers mid-stream without
+// predeclarnig them. So: change of plans. We still permit the old
+// way, but we also permit this hack: if a Header() key begins with
+// "Trailer:", the suffix of that key is a Trailer. Because ':' is an
+// invalid token byte anyway, there is no ambiguity. (And it's already
+// filtered out) It's mildly hacky, but not terrible.
+//
+// This method runs after the Handler is done and promotes any Header
+// fields to be trailers.
+func (rws *responseWriterState) promoteUndeclaredTrailers() {
+ for k, vv := range rws.handlerHeader {
+ if !strings.HasPrefix(k, TrailerPrefix) {
+ continue
+ }
+ trailerKey := strings.TrimPrefix(k, TrailerPrefix)
+ rws.declareTrailer(trailerKey)
+ rws.handlerHeader[http.CanonicalHeaderKey(trailerKey)] = vv
+ }
+
+ if len(rws.trailers) > 1 {
+ sorter := sorterPool.Get().(*sorter)
+ sorter.SortStrings(rws.trailers)
+ sorterPool.Put(sorter)
+ }
+}
+
+func (w *responseWriter) Flush() {
+ rws := w.rws
+ if rws == nil {
+ panic("Header called after Handler finished")
+ }
+ if rws.bw.Buffered() > 0 {
+ if err := rws.bw.Flush(); err != nil {
+ // Ignore the error. The frame writer already knows.
+ return
+ }
+ } else {
+ // The bufio.Writer won't call chunkWriter.Write
+ // (writeChunk with zero bytes, so we have to do it
+ // ourselves to force the HTTP response header and/or
+ // final DATA frame (with END_STREAM) to be sent.
+ rws.writeChunk(nil)
+ }
+}
+
+func (w *responseWriter) CloseNotify() <-chan bool {
+ rws := w.rws
+ if rws == nil {
+ panic("CloseNotify called after Handler finished")
+ }
+ rws.closeNotifierMu.Lock()
+ ch := rws.closeNotifierCh
+ if ch == nil {
+ ch = make(chan bool, 1)
+ rws.closeNotifierCh = ch
+ cw := rws.stream.cw
+ go func() {
+ cw.Wait() // wait for close
+ ch <- true
+ }()
+ }
+ rws.closeNotifierMu.Unlock()
+ return ch
+}
+
+func (w *responseWriter) Header() http.Header {
+ rws := w.rws
+ if rws == nil {
+ panic("Header called after Handler finished")
+ }
+ if rws.handlerHeader == nil {
+ rws.handlerHeader = make(http.Header)
+ }
+ return rws.handlerHeader
+}
+
+// checkWriteHeaderCode is a copy of net/http's checkWriteHeaderCode.
+func checkWriteHeaderCode(code int) {
+ // Issue 22880: require valid WriteHeader status codes.
+ // For now we only enforce that it's three digits.
+ // In the future we might block things over 599 (600 and above aren't defined
+ // at http://httpwg.org/specs/rfc7231.html#status.codes)
+ // and we might block under 200 (once we have more mature 1xx support).
+ // But for now any three digits.
+ //
+ // We used to send "HTTP/1.1 000 0" on the wire in responses but there's
+ // no equivalent bogus thing we can realistically send in HTTP/2,
+ // so we'll consistently panic instead and help people find their bugs
+ // early. (We can't return an error from WriteHeader even if we wanted to.)
+ if code < 100 || code > 999 {
+ panic(fmt.Sprintf("invalid WriteHeader code %v", code))
+ }
+}
+
+func (w *responseWriter) WriteHeader(code int) {
+ rws := w.rws
+ if rws == nil {
+ panic("WriteHeader called after Handler finished")
+ }
+ rws.writeHeader(code)
+}
+
+func (rws *responseWriterState) writeHeader(code int) {
+ if !rws.wroteHeader {
+ checkWriteHeaderCode(code)
+ rws.wroteHeader = true
+ rws.status = code
+ if len(rws.handlerHeader) > 0 {
+ rws.snapHeader = cloneHeader(rws.handlerHeader)
+ }
+ }
+}
+
+func cloneHeader(h http.Header) http.Header {
+ h2 := make(http.Header, len(h))
+ for k, vv := range h {
+ vv2 := make([]string, len(vv))
+ copy(vv2, vv)
+ h2[k] = vv2
+ }
+ return h2
+}
+
+// The Life Of A Write is like this:
+//
+// * Handler calls w.Write or w.WriteString ->
+// * -> rws.bw (*bufio.Writer) ->
+// * (Handler might call Flush)
+// * -> chunkWriter{rws}
+// * -> responseWriterState.writeChunk(p []byte)
+// * -> responseWriterState.writeChunk (most of the magic; see comment there)
+func (w *responseWriter) Write(p []byte) (n int, err error) {
+ return w.write(len(p), p, "")
+}
+
+func (w *responseWriter) WriteString(s string) (n int, err error) {
+ return w.write(len(s), nil, s)
+}
+
+// either dataB or dataS is non-zero.
+func (w *responseWriter) write(lenData int, dataB []byte, dataS string) (n int, err error) {
+ rws := w.rws
+ if rws == nil {
+ panic("Write called after Handler finished")
+ }
+ if !rws.wroteHeader {
+ w.WriteHeader(200)
+ }
+ if !bodyAllowedForStatus(rws.status) {
+ return 0, http.ErrBodyNotAllowed
+ }
+ rws.wroteBytes += int64(len(dataB)) + int64(len(dataS)) // only one can be set
+ if rws.sentContentLen != 0 && rws.wroteBytes > rws.sentContentLen {
+ // TODO: send a RST_STREAM
+ return 0, errors.New("http2: handler wrote more than declared Content-Length")
+ }
+
+ if dataB != nil {
+ return rws.bw.Write(dataB)
+ } else {
+ return rws.bw.WriteString(dataS)
+ }
+}
+
+func (w *responseWriter) handlerDone() {
+ rws := w.rws
+ dirty := rws.dirty
+ rws.handlerDone = true
+ w.Flush()
+ w.rws = nil
+ if !dirty {
+ // Only recycle the pool if all prior Write calls to
+ // the serverConn goroutine completed successfully. If
+ // they returned earlier due to resets from the peer
+ // there might still be write goroutines outstanding
+ // from the serverConn referencing the rws memory. See
+ // issue 20704.
+ responseWriterStatePool.Put(rws)
+ }
+}
+
+// Push errors.
+var (
+ ErrRecursivePush = errors.New("http2: recursive push not allowed")
+ ErrPushLimitReached = errors.New("http2: push would exceed peer's SETTINGS_MAX_CONCURRENT_STREAMS")
+)
+
+var _ http.Pusher = (*responseWriter)(nil)
+
+func (w *responseWriter) Push(target string, opts *http.PushOptions) error {
+ st := w.rws.stream
+ sc := st.sc
+ sc.serveG.checkNotOn()
+
+ // No recursive pushes: "PUSH_PROMISE frames MUST only be sent on a peer-initiated stream."
+ // http://tools.ietf.org/html/rfc7540#section-6.6
+ if st.isPushed() {
+ return ErrRecursivePush
+ }
+
+ if opts == nil {
+ opts = new(http.PushOptions)
+ }
+
+ // Default options.
+ if opts.Method == "" {
+ opts.Method = "GET"
+ }
+ if opts.Header == nil {
+ opts.Header = http.Header{}
+ }
+ wantScheme := "http"
+ if w.rws.req.TLS != nil {
+ wantScheme = "https"
+ }
+
+ // Validate the request.
+ u, err := url.Parse(target)
+ if err != nil {
+ return err
+ }
+ if u.Scheme == "" {
+ if !strings.HasPrefix(target, "/") {
+ return fmt.Errorf("target must be an absolute URL or an absolute path: %q", target)
+ }
+ u.Scheme = wantScheme
+ u.Host = w.rws.req.Host
+ } else {
+ if u.Scheme != wantScheme {
+ return fmt.Errorf("cannot push URL with scheme %q from request with scheme %q", u.Scheme, wantScheme)
+ }
+ if u.Host == "" {
+ return errors.New("URL must have a host")
+ }
+ }
+ for k := range opts.Header {
+ if strings.HasPrefix(k, ":") {
+ return fmt.Errorf("promised request headers cannot include pseudo header %q", k)
+ }
+ // These headers are meaningful only if the request has a body,
+ // but PUSH_PROMISE requests cannot have a body.
+ // http://tools.ietf.org/html/rfc7540#section-8.2
+ // Also disallow Host, since the promised URL must be absolute.
+ switch strings.ToLower(k) {
+ case "content-length", "content-encoding", "trailer", "te", "expect", "host":
+ return fmt.Errorf("promised request headers cannot include %q", k)
+ }
+ }
+ if err := checkValidHTTP2RequestHeaders(opts.Header); err != nil {
+ return err
+ }
+
+ // The RFC effectively limits promised requests to GET and HEAD:
+ // "Promised requests MUST be cacheable [GET, HEAD, or POST], and MUST be safe [GET or HEAD]"
+ // http://tools.ietf.org/html/rfc7540#section-8.2
+ if opts.Method != "GET" && opts.Method != "HEAD" {
+ return fmt.Errorf("method %q must be GET or HEAD", opts.Method)
+ }
+
+ msg := &startPushRequest{
+ parent: st,
+ method: opts.Method,
+ url: u,
+ header: cloneHeader(opts.Header),
+ done: errChanPool.Get().(chan error),
+ }
+
+ select {
+ case <-sc.doneServing:
+ return errClientDisconnected
+ case <-st.cw:
+ return errStreamClosed
+ case sc.serveMsgCh <- msg:
+ }
+
+ select {
+ case <-sc.doneServing:
+ return errClientDisconnected
+ case <-st.cw:
+ return errStreamClosed
+ case err := <-msg.done:
+ errChanPool.Put(msg.done)
+ return err
+ }
+}
+
+type startPushRequest struct {
+ parent *stream
+ method string
+ url *url.URL
+ header http.Header
+ done chan error
+}
+
+func (sc *serverConn) startPush(msg *startPushRequest) {
+ sc.serveG.check()
+
+ // http://tools.ietf.org/html/rfc7540#section-6.6.
+ // PUSH_PROMISE frames MUST only be sent on a peer-initiated stream that
+ // is in either the "open" or "half-closed (remote)" state.
+ if msg.parent.state != stateOpen && msg.parent.state != stateHalfClosedRemote {
+ // responseWriter.Push checks that the stream is peer-initiaed.
+ msg.done <- errStreamClosed
+ return
+ }
+
+ // http://tools.ietf.org/html/rfc7540#section-6.6.
+ if !sc.pushEnabled {
+ msg.done <- http.ErrNotSupported
+ return
+ }
+
+ // PUSH_PROMISE frames must be sent in increasing order by stream ID, so
+ // we allocate an ID for the promised stream lazily, when the PUSH_PROMISE
+ // is written. Once the ID is allocated, we start the request handler.
+ allocatePromisedID := func() (uint32, error) {
+ sc.serveG.check()
+
+ // Check this again, just in case. Technically, we might have received
+ // an updated SETTINGS by the time we got around to writing this frame.
+ if !sc.pushEnabled {
+ return 0, http.ErrNotSupported
+ }
+ // http://tools.ietf.org/html/rfc7540#section-6.5.2.
+ if sc.curPushedStreams+1 > sc.clientMaxStreams {
+ return 0, ErrPushLimitReached
+ }
+
+ // http://tools.ietf.org/html/rfc7540#section-5.1.1.
+ // Streams initiated by the server MUST use even-numbered identifiers.
+ // A server that is unable to establish a new stream identifier can send a GOAWAY
+ // frame so that the client is forced to open a new connection for new streams.
+ if sc.maxPushPromiseID+2 >= 1<<31 {
+ sc.startGracefulShutdownInternal()
+ return 0, ErrPushLimitReached
+ }
+ sc.maxPushPromiseID += 2
+ promisedID := sc.maxPushPromiseID
+
+ // http://tools.ietf.org/html/rfc7540#section-8.2.
+ // Strictly speaking, the new stream should start in "reserved (local)", then
+ // transition to "half closed (remote)" after sending the initial HEADERS, but
+ // we start in "half closed (remote)" for simplicity.
+ // See further comments at the definition of stateHalfClosedRemote.
+ promised := sc.newStream(promisedID, msg.parent.id, stateHalfClosedRemote)
+ rw, req, err := sc.newWriterAndRequestNoBody(promised, requestParam{
+ method: msg.method,
+ scheme: msg.url.Scheme,
+ authority: msg.url.Host,
+ path: msg.url.RequestURI(),
+ header: cloneHeader(msg.header), // clone since handler runs concurrently with writing the PUSH_PROMISE
+ })
+ if err != nil {
+ // Should not happen, since we've already validated msg.url.
+ panic(fmt.Sprintf("newWriterAndRequestNoBody(%+v): %v", msg.url, err))
+ }
+
+ go sc.runHandler(rw, req, sc.handler.ServeHTTP)
+ return promisedID, nil
+ }
+
+ sc.writeFrame(FrameWriteRequest{
+ write: &writePushPromise{
+ streamID: msg.parent.id,
+ method: msg.method,
+ url: msg.url,
+ h: msg.header,
+ allocatePromisedID: allocatePromisedID,
+ },
+ stream: msg.parent,
+ done: msg.done,
+ })
+}
+
+// foreachHeaderElement splits v according to the "#rule" construction
+// in RFC 7230 section 7 and calls fn for each non-empty element.
+func foreachHeaderElement(v string, fn func(string)) {
+ v = textproto.TrimString(v)
+ if v == "" {
+ return
+ }
+ if !strings.Contains(v, ",") {
+ fn(v)
+ return
+ }
+ for _, f := range strings.Split(v, ",") {
+ if f = textproto.TrimString(f); f != "" {
+ fn(f)
+ }
+ }
+}
+
+// From http://httpwg.org/specs/rfc7540.html#rfc.section.8.1.2.2
+var connHeaders = []string{
+ "Connection",
+ "Keep-Alive",
+ "Proxy-Connection",
+ "Transfer-Encoding",
+ "Upgrade",
+}
+
+// checkValidHTTP2RequestHeaders checks whether h is a valid HTTP/2 request,
+// per RFC 7540 Section 8.1.2.2.
+// The returned error is reported to users.
+func checkValidHTTP2RequestHeaders(h http.Header) error {
+ for _, k := range connHeaders {
+ if _, ok := h[k]; ok {
+ return fmt.Errorf("request header %q is not valid in HTTP/2", k)
+ }
+ }
+ te := h["Te"]
+ if len(te) > 0 && (len(te) > 1 || (te[0] != "trailers" && te[0] != "")) {
+ return errors.New(`request header "TE" may only be "trailers" in HTTP/2`)
+ }
+ return nil
+}
+
+func new400Handler(err error) http.HandlerFunc {
+ return func(w http.ResponseWriter, r *http.Request) {
+ http.Error(w, err.Error(), http.StatusBadRequest)
+ }
+}
+
+// h1ServerKeepAlivesDisabled reports whether hs has its keep-alives
+// disabled. See comments on h1ServerShutdownChan above for why
+// the code is written this way.
+func h1ServerKeepAlivesDisabled(hs *http.Server) bool {
+ var x interface{} = hs
+ type I interface {
+ doKeepAlives() bool
+ }
+ if hs, ok := x.(I); ok {
+ return !hs.doKeepAlives()
+ }
+ return false
+}
diff --git a/vendor/golang.org/x/net/http2/transport.go b/vendor/golang.org/x/net/http2/transport.go
new file mode 100644
index 000000000..f272e8f9f
--- /dev/null
+++ b/vendor/golang.org/x/net/http2/transport.go
@@ -0,0 +1,2603 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Transport code.
+
+package http2
+
+import (
+ "bufio"
+ "bytes"
+ "compress/gzip"
+ "context"
+ "crypto/rand"
+ "crypto/tls"
+ "errors"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "log"
+ "math"
+ mathrand "math/rand"
+ "net"
+ "net/http"
+ "net/http/httptrace"
+ "net/textproto"
+ "sort"
+ "strconv"
+ "strings"
+ "sync"
+ "time"
+
+ "golang.org/x/net/http/httpguts"
+ "golang.org/x/net/http2/hpack"
+ "golang.org/x/net/idna"
+)
+
+const (
+ // transportDefaultConnFlow is how many connection-level flow control
+ // tokens we give the server at start-up, past the default 64k.
+ transportDefaultConnFlow = 1 << 30
+
+ // transportDefaultStreamFlow is how many stream-level flow
+ // control tokens we announce to the peer, and how many bytes
+ // we buffer per stream.
+ transportDefaultStreamFlow = 4 << 20
+
+ // transportDefaultStreamMinRefresh is the minimum number of bytes we'll send
+ // a stream-level WINDOW_UPDATE for at a time.
+ transportDefaultStreamMinRefresh = 4 << 10
+
+ defaultUserAgent = "Go-http-client/2.0"
+)
+
+// Transport is an HTTP/2 Transport.
+//
+// A Transport internally caches connections to servers. It is safe
+// for concurrent use by multiple goroutines.
+type Transport struct {
+ // DialTLS specifies an optional dial function for creating
+ // TLS connections for requests.
+ //
+ // If DialTLS is nil, tls.Dial is used.
+ //
+ // If the returned net.Conn has a ConnectionState method like tls.Conn,
+ // it will be used to set http.Response.TLS.
+ DialTLS func(network, addr string, cfg *tls.Config) (net.Conn, error)
+
+ // TLSClientConfig specifies the TLS configuration to use with
+ // tls.Client. If nil, the default configuration is used.
+ TLSClientConfig *tls.Config
+
+ // ConnPool optionally specifies an alternate connection pool to use.
+ // If nil, the default is used.
+ ConnPool ClientConnPool
+
+ // DisableCompression, if true, prevents the Transport from
+ // requesting compression with an "Accept-Encoding: gzip"
+ // request header when the Request contains no existing
+ // Accept-Encoding value. If the Transport requests gzip on
+ // its own and gets a gzipped response, it's transparently
+ // decoded in the Response.Body. However, if the user
+ // explicitly requested gzip it is not automatically
+ // uncompressed.
+ DisableCompression bool
+
+ // AllowHTTP, if true, permits HTTP/2 requests using the insecure,
+ // plain-text "http" scheme. Note that this does not enable h2c support.
+ AllowHTTP bool
+
+ // MaxHeaderListSize is the http2 SETTINGS_MAX_HEADER_LIST_SIZE to
+ // send in the initial settings frame. It is how many bytes
+ // of response headers are allowed. Unlike the http2 spec, zero here
+ // means to use a default limit (currently 10MB). If you actually
+ // want to advertise an ulimited value to the peer, Transport
+ // interprets the highest possible value here (0xffffffff or 1<<32-1)
+ // to mean no limit.
+ MaxHeaderListSize uint32
+
+ // StrictMaxConcurrentStreams controls whether the server's
+ // SETTINGS_MAX_CONCURRENT_STREAMS should be respected
+ // globally. If false, new TCP connections are created to the
+ // server as needed to keep each under the per-connection
+ // SETTINGS_MAX_CONCURRENT_STREAMS limit. If true, the
+ // server's SETTINGS_MAX_CONCURRENT_STREAMS is interpreted as
+ // a global limit and callers of RoundTrip block when needed,
+ // waiting for their turn.
+ StrictMaxConcurrentStreams bool
+
+ // t1, if non-nil, is the standard library Transport using
+ // this transport. Its settings are used (but not its
+ // RoundTrip method, etc).
+ t1 *http.Transport
+
+ connPoolOnce sync.Once
+ connPoolOrDef ClientConnPool // non-nil version of ConnPool
+}
+
+func (t *Transport) maxHeaderListSize() uint32 {
+ if t.MaxHeaderListSize == 0 {
+ return 10 << 20
+ }
+ if t.MaxHeaderListSize == 0xffffffff {
+ return 0
+ }
+ return t.MaxHeaderListSize
+}
+
+func (t *Transport) disableCompression() bool {
+ return t.DisableCompression || (t.t1 != nil && t.t1.DisableCompression)
+}
+
+// ConfigureTransport configures a net/http HTTP/1 Transport to use HTTP/2.
+// It returns an error if t1 has already been HTTP/2-enabled.
+func ConfigureTransport(t1 *http.Transport) error {
+ _, err := configureTransport(t1)
+ return err
+}
+
+func configureTransport(t1 *http.Transport) (*Transport, error) {
+ connPool := new(clientConnPool)
+ t2 := &Transport{
+ ConnPool: noDialClientConnPool{connPool},
+ t1: t1,
+ }
+ connPool.t = t2
+ if err := registerHTTPSProtocol(t1, noDialH2RoundTripper{t2}); err != nil {
+ return nil, err
+ }
+ if t1.TLSClientConfig == nil {
+ t1.TLSClientConfig = new(tls.Config)
+ }
+ if !strSliceContains(t1.TLSClientConfig.NextProtos, "h2") {
+ t1.TLSClientConfig.NextProtos = append([]string{"h2"}, t1.TLSClientConfig.NextProtos...)
+ }
+ if !strSliceContains(t1.TLSClientConfig.NextProtos, "http/1.1") {
+ t1.TLSClientConfig.NextProtos = append(t1.TLSClientConfig.NextProtos, "http/1.1")
+ }
+ upgradeFn := func(authority string, c *tls.Conn) http.RoundTripper {
+ addr := authorityAddr("https", authority)
+ if used, err := connPool.addConnIfNeeded(addr, t2, c); err != nil {
+ go c.Close()
+ return erringRoundTripper{err}
+ } else if !used {
+ // Turns out we don't need this c.
+ // For example, two goroutines made requests to the same host
+ // at the same time, both kicking off TCP dials. (since protocol
+ // was unknown)
+ go c.Close()
+ }
+ return t2
+ }
+ if m := t1.TLSNextProto; len(m) == 0 {
+ t1.TLSNextProto = map[string]func(string, *tls.Conn) http.RoundTripper{
+ "h2": upgradeFn,
+ }
+ } else {
+ m["h2"] = upgradeFn
+ }
+ return t2, nil
+}
+
+func (t *Transport) connPool() ClientConnPool {
+ t.connPoolOnce.Do(t.initConnPool)
+ return t.connPoolOrDef
+}
+
+func (t *Transport) initConnPool() {
+ if t.ConnPool != nil {
+ t.connPoolOrDef = t.ConnPool
+ } else {
+ t.connPoolOrDef = &clientConnPool{t: t}
+ }
+}
+
+// ClientConn is the state of a single HTTP/2 client connection to an
+// HTTP/2 server.
+type ClientConn struct {
+ t *Transport
+ tconn net.Conn // usually *tls.Conn, except specialized impls
+ tlsState *tls.ConnectionState // nil only for specialized impls
+ singleUse bool // whether being used for a single http.Request
+
+ // readLoop goroutine fields:
+ readerDone chan struct{} // closed on error
+ readerErr error // set before readerDone is closed
+
+ idleTimeout time.Duration // or 0 for never
+ idleTimer *time.Timer
+
+ mu sync.Mutex // guards following
+ cond *sync.Cond // hold mu; broadcast on flow/closed changes
+ flow flow // our conn-level flow control quota (cs.flow is per stream)
+ inflow flow // peer's conn-level flow control
+ closing bool
+ closed bool
+ wantSettingsAck bool // we sent a SETTINGS frame and haven't heard back
+ goAway *GoAwayFrame // if non-nil, the GoAwayFrame we received
+ goAwayDebug string // goAway frame's debug data, retained as a string
+ streams map[uint32]*clientStream // client-initiated
+ nextStreamID uint32
+ pendingRequests int // requests blocked and waiting to be sent because len(streams) == maxConcurrentStreams
+ pings map[[8]byte]chan struct{} // in flight ping data to notification channel
+ bw *bufio.Writer
+ br *bufio.Reader
+ fr *Framer
+ lastActive time.Time
+ // Settings from peer: (also guarded by mu)
+ maxFrameSize uint32
+ maxConcurrentStreams uint32
+ peerMaxHeaderListSize uint64
+ initialWindowSize uint32
+
+ hbuf bytes.Buffer // HPACK encoder writes into this
+ henc *hpack.Encoder
+ freeBuf [][]byte
+
+ wmu sync.Mutex // held while writing; acquire AFTER mu if holding both
+ werr error // first write error that has occurred
+}
+
+// clientStream is the state for a single HTTP/2 stream. One of these
+// is created for each Transport.RoundTrip call.
+type clientStream struct {
+ cc *ClientConn
+ req *http.Request
+ trace *httptrace.ClientTrace // or nil
+ ID uint32
+ resc chan resAndError
+ bufPipe pipe // buffered pipe with the flow-controlled response payload
+ startedWrite bool // started request body write; guarded by cc.mu
+ requestedGzip bool
+ on100 func() // optional code to run if get a 100 continue response
+
+ flow flow // guarded by cc.mu
+ inflow flow // guarded by cc.mu
+ bytesRemain int64 // -1 means unknown; owned by transportResponseBody.Read
+ readErr error // sticky read error; owned by transportResponseBody.Read
+ stopReqBody error // if non-nil, stop writing req body; guarded by cc.mu
+ didReset bool // whether we sent a RST_STREAM to the server; guarded by cc.mu
+
+ peerReset chan struct{} // closed on peer reset
+ resetErr error // populated before peerReset is closed
+
+ done chan struct{} // closed when stream remove from cc.streams map; close calls guarded by cc.mu
+
+ // owned by clientConnReadLoop:
+ firstByte bool // got the first response byte
+ pastHeaders bool // got first MetaHeadersFrame (actual headers)
+ pastTrailers bool // got optional second MetaHeadersFrame (trailers)
+ num1xx uint8 // number of 1xx responses seen
+
+ trailer http.Header // accumulated trailers
+ resTrailer *http.Header // client's Response.Trailer
+}
+
+// awaitRequestCancel waits for the user to cancel a request or for the done
+// channel to be signaled. A non-nil error is returned only if the request was
+// canceled.
+func awaitRequestCancel(req *http.Request, done <-chan struct{}) error {
+ ctx := req.Context()
+ if req.Cancel == nil && ctx.Done() == nil {
+ return nil
+ }
+ select {
+ case <-req.Cancel:
+ return errRequestCanceled
+ case <-ctx.Done():
+ return ctx.Err()
+ case <-done:
+ return nil
+ }
+}
+
+var got1xxFuncForTests func(int, textproto.MIMEHeader) error
+
+// get1xxTraceFunc returns the value of request's httptrace.ClientTrace.Got1xxResponse func,
+// if any. It returns nil if not set or if the Go version is too old.
+func (cs *clientStream) get1xxTraceFunc() func(int, textproto.MIMEHeader) error {
+ if fn := got1xxFuncForTests; fn != nil {
+ return fn
+ }
+ return traceGot1xxResponseFunc(cs.trace)
+}
+
+// awaitRequestCancel waits for the user to cancel a request, its context to
+// expire, or for the request to be done (any way it might be removed from the
+// cc.streams map: peer reset, successful completion, TCP connection breakage,
+// etc). If the request is canceled, then cs will be canceled and closed.
+func (cs *clientStream) awaitRequestCancel(req *http.Request) {
+ if err := awaitRequestCancel(req, cs.done); err != nil {
+ cs.cancelStream()
+ cs.bufPipe.CloseWithError(err)
+ }
+}
+
+func (cs *clientStream) cancelStream() {
+ cc := cs.cc
+ cc.mu.Lock()
+ didReset := cs.didReset
+ cs.didReset = true
+ cc.mu.Unlock()
+
+ if !didReset {
+ cc.writeStreamReset(cs.ID, ErrCodeCancel, nil)
+ cc.forgetStreamID(cs.ID)
+ }
+}
+
+// checkResetOrDone reports any error sent in a RST_STREAM frame by the
+// server, or errStreamClosed if the stream is complete.
+func (cs *clientStream) checkResetOrDone() error {
+ select {
+ case <-cs.peerReset:
+ return cs.resetErr
+ case <-cs.done:
+ return errStreamClosed
+ default:
+ return nil
+ }
+}
+
+func (cs *clientStream) getStartedWrite() bool {
+ cc := cs.cc
+ cc.mu.Lock()
+ defer cc.mu.Unlock()
+ return cs.startedWrite
+}
+
+func (cs *clientStream) abortRequestBodyWrite(err error) {
+ if err == nil {
+ panic("nil error")
+ }
+ cc := cs.cc
+ cc.mu.Lock()
+ cs.stopReqBody = err
+ cc.cond.Broadcast()
+ cc.mu.Unlock()
+}
+
+type stickyErrWriter struct {
+ w io.Writer
+ err *error
+}
+
+func (sew stickyErrWriter) Write(p []byte) (n int, err error) {
+ if *sew.err != nil {
+ return 0, *sew.err
+ }
+ n, err = sew.w.Write(p)
+ *sew.err = err
+ return
+}
+
+// noCachedConnError is the concrete type of ErrNoCachedConn, which
+// needs to be detected by net/http regardless of whether it's its
+// bundled version (in h2_bundle.go with a rewritten type name) or
+// from a user's x/net/http2. As such, as it has a unique method name
+// (IsHTTP2NoCachedConnError) that net/http sniffs for via func
+// isNoCachedConnError.
+type noCachedConnError struct{}
+
+func (noCachedConnError) IsHTTP2NoCachedConnError() {}
+func (noCachedConnError) Error() string { return "http2: no cached connection was available" }
+
+// isNoCachedConnError reports whether err is of type noCachedConnError
+// or its equivalent renamed type in net/http2's h2_bundle.go. Both types
+// may coexist in the same running program.
+func isNoCachedConnError(err error) bool {
+ _, ok := err.(interface{ IsHTTP2NoCachedConnError() })
+ return ok
+}
+
+var ErrNoCachedConn error = noCachedConnError{}
+
+// RoundTripOpt are options for the Transport.RoundTripOpt method.
+type RoundTripOpt struct {
+ // OnlyCachedConn controls whether RoundTripOpt may
+ // create a new TCP connection. If set true and
+ // no cached connection is available, RoundTripOpt
+ // will return ErrNoCachedConn.
+ OnlyCachedConn bool
+}
+
+func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error) {
+ return t.RoundTripOpt(req, RoundTripOpt{})
+}
+
+// authorityAddr returns a given authority (a host/IP, or host:port / ip:port)
+// and returns a host:port. The port 443 is added if needed.
+func authorityAddr(scheme string, authority string) (addr string) {
+ host, port, err := net.SplitHostPort(authority)
+ if err != nil { // authority didn't have a port
+ port = "443"
+ if scheme == "http" {
+ port = "80"
+ }
+ host = authority
+ }
+ if a, err := idna.ToASCII(host); err == nil {
+ host = a
+ }
+ // IPv6 address literal, without a port:
+ if strings.HasPrefix(host, "[") && strings.HasSuffix(host, "]") {
+ return host + ":" + port
+ }
+ return net.JoinHostPort(host, port)
+}
+
+// RoundTripOpt is like RoundTrip, but takes options.
+func (t *Transport) RoundTripOpt(req *http.Request, opt RoundTripOpt) (*http.Response, error) {
+ if !(req.URL.Scheme == "https" || (req.URL.Scheme == "http" && t.AllowHTTP)) {
+ return nil, errors.New("http2: unsupported scheme")
+ }
+
+ addr := authorityAddr(req.URL.Scheme, req.URL.Host)
+ for retry := 0; ; retry++ {
+ cc, err := t.connPool().GetClientConn(req, addr)
+ if err != nil {
+ t.vlogf("http2: Transport failed to get client conn for %s: %v", addr, err)
+ return nil, err
+ }
+ traceGotConn(req, cc)
+ res, gotErrAfterReqBodyWrite, err := cc.roundTrip(req)
+ if err != nil && retry <= 6 {
+ if req, err = shouldRetryRequest(req, err, gotErrAfterReqBodyWrite); err == nil {
+ // After the first retry, do exponential backoff with 10% jitter.
+ if retry == 0 {
+ continue
+ }
+ backoff := float64(uint(1) << (uint(retry) - 1))
+ backoff += backoff * (0.1 * mathrand.Float64())
+ select {
+ case <-time.After(time.Second * time.Duration(backoff)):
+ continue
+ case <-req.Context().Done():
+ return nil, req.Context().Err()
+ }
+ }
+ }
+ if err != nil {
+ t.vlogf("RoundTrip failure: %v", err)
+ return nil, err
+ }
+ return res, nil
+ }
+}
+
+// CloseIdleConnections closes any connections which were previously
+// connected from previous requests but are now sitting idle.
+// It does not interrupt any connections currently in use.
+func (t *Transport) CloseIdleConnections() {
+ if cp, ok := t.connPool().(clientConnPoolIdleCloser); ok {
+ cp.closeIdleConnections()
+ }
+}
+
+var (
+ errClientConnClosed = errors.New("http2: client conn is closed")
+ errClientConnUnusable = errors.New("http2: client conn not usable")
+ errClientConnGotGoAway = errors.New("http2: Transport received Server's graceful shutdown GOAWAY")
+)
+
+// shouldRetryRequest is called by RoundTrip when a request fails to get
+// response headers. It is always called with a non-nil error.
+// It returns either a request to retry (either the same request, or a
+// modified clone), or an error if the request can't be replayed.
+func shouldRetryRequest(req *http.Request, err error, afterBodyWrite bool) (*http.Request, error) {
+ if !canRetryError(err) {
+ return nil, err
+ }
+ // If the Body is nil (or http.NoBody), it's safe to reuse
+ // this request and its Body.
+ if req.Body == nil || req.Body == http.NoBody {
+ return req, nil
+ }
+
+ // If the request body can be reset back to its original
+ // state via the optional req.GetBody, do that.
+ if req.GetBody != nil {
+ // TODO: consider a req.Body.Close here? or audit that all caller paths do?
+ body, err := req.GetBody()
+ if err != nil {
+ return nil, err
+ }
+ newReq := *req
+ newReq.Body = body
+ return &newReq, nil
+ }
+
+ // The Request.Body can't reset back to the beginning, but we
+ // don't seem to have started to read from it yet, so reuse
+ // the request directly. The "afterBodyWrite" means the
+ // bodyWrite process has started, which becomes true before
+ // the first Read.
+ if !afterBodyWrite {
+ return req, nil
+ }
+
+ return nil, fmt.Errorf("http2: Transport: cannot retry err [%v] after Request.Body was written; define Request.GetBody to avoid this error", err)
+}
+
+func canRetryError(err error) bool {
+ if err == errClientConnUnusable || err == errClientConnGotGoAway {
+ return true
+ }
+ if se, ok := err.(StreamError); ok {
+ return se.Code == ErrCodeRefusedStream
+ }
+ return false
+}
+
+func (t *Transport) dialClientConn(addr string, singleUse bool) (*ClientConn, error) {
+ host, _, err := net.SplitHostPort(addr)
+ if err != nil {
+ return nil, err
+ }
+ tconn, err := t.dialTLS()("tcp", addr, t.newTLSConfig(host))
+ if err != nil {
+ return nil, err
+ }
+ return t.newClientConn(tconn, singleUse)
+}
+
+func (t *Transport) newTLSConfig(host string) *tls.Config {
+ cfg := new(tls.Config)
+ if t.TLSClientConfig != nil {
+ *cfg = *t.TLSClientConfig.Clone()
+ }
+ if !strSliceContains(cfg.NextProtos, NextProtoTLS) {
+ cfg.NextProtos = append([]string{NextProtoTLS}, cfg.NextProtos...)
+ }
+ if cfg.ServerName == "" {
+ cfg.ServerName = host
+ }
+ return cfg
+}
+
+func (t *Transport) dialTLS() func(string, string, *tls.Config) (net.Conn, error) {
+ if t.DialTLS != nil {
+ return t.DialTLS
+ }
+ return t.dialTLSDefault
+}
+
+func (t *Transport) dialTLSDefault(network, addr string, cfg *tls.Config) (net.Conn, error) {
+ cn, err := tls.Dial(network, addr, cfg)
+ if err != nil {
+ return nil, err
+ }
+ if err := cn.Handshake(); err != nil {
+ return nil, err
+ }
+ if !cfg.InsecureSkipVerify {
+ if err := cn.VerifyHostname(cfg.ServerName); err != nil {
+ return nil, err
+ }
+ }
+ state := cn.ConnectionState()
+ if p := state.NegotiatedProtocol; p != NextProtoTLS {
+ return nil, fmt.Errorf("http2: unexpected ALPN protocol %q; want %q", p, NextProtoTLS)
+ }
+ if !state.NegotiatedProtocolIsMutual {
+ return nil, errors.New("http2: could not negotiate protocol mutually")
+ }
+ return cn, nil
+}
+
+// disableKeepAlives reports whether connections should be closed as
+// soon as possible after handling the first request.
+func (t *Transport) disableKeepAlives() bool {
+ return t.t1 != nil && t.t1.DisableKeepAlives
+}
+
+func (t *Transport) expectContinueTimeout() time.Duration {
+ if t.t1 == nil {
+ return 0
+ }
+ return t.t1.ExpectContinueTimeout
+}
+
+func (t *Transport) NewClientConn(c net.Conn) (*ClientConn, error) {
+ return t.newClientConn(c, false)
+}
+
+func (t *Transport) newClientConn(c net.Conn, singleUse bool) (*ClientConn, error) {
+ cc := &ClientConn{
+ t: t,
+ tconn: c,
+ readerDone: make(chan struct{}),
+ nextStreamID: 1,
+ maxFrameSize: 16 << 10, // spec default
+ initialWindowSize: 65535, // spec default
+ maxConcurrentStreams: 1000, // "infinite", per spec. 1000 seems good enough.
+ peerMaxHeaderListSize: 0xffffffffffffffff, // "infinite", per spec. Use 2^64-1 instead.
+ streams: make(map[uint32]*clientStream),
+ singleUse: singleUse,
+ wantSettingsAck: true,
+ pings: make(map[[8]byte]chan struct{}),
+ }
+ if d := t.idleConnTimeout(); d != 0 {
+ cc.idleTimeout = d
+ cc.idleTimer = time.AfterFunc(d, cc.onIdleTimeout)
+ }
+ if VerboseLogs {
+ t.vlogf("http2: Transport creating client conn %p to %v", cc, c.RemoteAddr())
+ }
+
+ cc.cond = sync.NewCond(&cc.mu)
+ cc.flow.add(int32(initialWindowSize))
+
+ // TODO: adjust this writer size to account for frame size +
+ // MTU + crypto/tls record padding.
+ cc.bw = bufio.NewWriter(stickyErrWriter{c, &cc.werr})
+ cc.br = bufio.NewReader(c)
+ cc.fr = NewFramer(cc.bw, cc.br)
+ cc.fr.ReadMetaHeaders = hpack.NewDecoder(initialHeaderTableSize, nil)
+ cc.fr.MaxHeaderListSize = t.maxHeaderListSize()
+
+ // TODO: SetMaxDynamicTableSize, SetMaxDynamicTableSizeLimit on
+ // henc in response to SETTINGS frames?
+ cc.henc = hpack.NewEncoder(&cc.hbuf)
+
+ if t.AllowHTTP {
+ cc.nextStreamID = 3
+ }
+
+ if cs, ok := c.(connectionStater); ok {
+ state := cs.ConnectionState()
+ cc.tlsState = &state
+ }
+
+ initialSettings := []Setting{
+ {ID: SettingEnablePush, Val: 0},
+ {ID: SettingInitialWindowSize, Val: transportDefaultStreamFlow},
+ }
+ if max := t.maxHeaderListSize(); max != 0 {
+ initialSettings = append(initialSettings, Setting{ID: SettingMaxHeaderListSize, Val: max})
+ }
+
+ cc.bw.Write(clientPreface)
+ cc.fr.WriteSettings(initialSettings...)
+ cc.fr.WriteWindowUpdate(0, transportDefaultConnFlow)
+ cc.inflow.add(transportDefaultConnFlow + initialWindowSize)
+ cc.bw.Flush()
+ if cc.werr != nil {
+ return nil, cc.werr
+ }
+
+ go cc.readLoop()
+ return cc, nil
+}
+
+func (cc *ClientConn) setGoAway(f *GoAwayFrame) {
+ cc.mu.Lock()
+ defer cc.mu.Unlock()
+
+ old := cc.goAway
+ cc.goAway = f
+
+ // Merge the previous and current GoAway error frames.
+ if cc.goAwayDebug == "" {
+ cc.goAwayDebug = string(f.DebugData())
+ }
+ if old != nil && old.ErrCode != ErrCodeNo {
+ cc.goAway.ErrCode = old.ErrCode
+ }
+ last := f.LastStreamID
+ for streamID, cs := range cc.streams {
+ if streamID > last {
+ select {
+ case cs.resc <- resAndError{err: errClientConnGotGoAway}:
+ default:
+ }
+ }
+ }
+}
+
+// CanTakeNewRequest reports whether the connection can take a new request,
+// meaning it has not been closed or received or sent a GOAWAY.
+func (cc *ClientConn) CanTakeNewRequest() bool {
+ cc.mu.Lock()
+ defer cc.mu.Unlock()
+ return cc.canTakeNewRequestLocked()
+}
+
+// clientConnIdleState describes the suitability of a client
+// connection to initiate a new RoundTrip request.
+type clientConnIdleState struct {
+ canTakeNewRequest bool
+ freshConn bool // whether it's unused by any previous request
+}
+
+func (cc *ClientConn) idleState() clientConnIdleState {
+ cc.mu.Lock()
+ defer cc.mu.Unlock()
+ return cc.idleStateLocked()
+}
+
+func (cc *ClientConn) idleStateLocked() (st clientConnIdleState) {
+ if cc.singleUse && cc.nextStreamID > 1 {
+ return
+ }
+ var maxConcurrentOkay bool
+ if cc.t.StrictMaxConcurrentStreams {
+ // We'll tell the caller we can take a new request to
+ // prevent the caller from dialing a new TCP
+ // connection, but then we'll block later before
+ // writing it.
+ maxConcurrentOkay = true
+ } else {
+ maxConcurrentOkay = int64(len(cc.streams)+1) < int64(cc.maxConcurrentStreams)
+ }
+
+ st.canTakeNewRequest = cc.goAway == nil && !cc.closed && !cc.closing && maxConcurrentOkay &&
+ int64(cc.nextStreamID)+2*int64(cc.pendingRequests) < math.MaxInt32
+ st.freshConn = cc.nextStreamID == 1 && st.canTakeNewRequest
+ return
+}
+
+func (cc *ClientConn) canTakeNewRequestLocked() bool {
+ st := cc.idleStateLocked()
+ return st.canTakeNewRequest
+}
+
+// onIdleTimeout is called from a time.AfterFunc goroutine. It will
+// only be called when we're idle, but because we're coming from a new
+// goroutine, there could be a new request coming in at the same time,
+// so this simply calls the synchronized closeIfIdle to shut down this
+// connection. The timer could just call closeIfIdle, but this is more
+// clear.
+func (cc *ClientConn) onIdleTimeout() {
+ cc.closeIfIdle()
+}
+
+func (cc *ClientConn) closeIfIdle() {
+ cc.mu.Lock()
+ if len(cc.streams) > 0 {
+ cc.mu.Unlock()
+ return
+ }
+ cc.closed = true
+ nextID := cc.nextStreamID
+ // TODO: do clients send GOAWAY too? maybe? Just Close:
+ cc.mu.Unlock()
+
+ if VerboseLogs {
+ cc.vlogf("http2: Transport closing idle conn %p (forSingleUse=%v, maxStream=%v)", cc, cc.singleUse, nextID-2)
+ }
+ cc.tconn.Close()
+}
+
+var shutdownEnterWaitStateHook = func() {}
+
+// Shutdown gracefully close the client connection, waiting for running streams to complete.
+func (cc *ClientConn) Shutdown(ctx context.Context) error {
+ if err := cc.sendGoAway(); err != nil {
+ return err
+ }
+ // Wait for all in-flight streams to complete or connection to close
+ done := make(chan error, 1)
+ cancelled := false // guarded by cc.mu
+ go func() {
+ cc.mu.Lock()
+ defer cc.mu.Unlock()
+ for {
+ if len(cc.streams) == 0 || cc.closed {
+ cc.closed = true
+ done <- cc.tconn.Close()
+ break
+ }
+ if cancelled {
+ break
+ }
+ cc.cond.Wait()
+ }
+ }()
+ shutdownEnterWaitStateHook()
+ select {
+ case err := <-done:
+ return err
+ case <-ctx.Done():
+ cc.mu.Lock()
+ // Free the goroutine above
+ cancelled = true
+ cc.cond.Broadcast()
+ cc.mu.Unlock()
+ return ctx.Err()
+ }
+}
+
+func (cc *ClientConn) sendGoAway() error {
+ cc.mu.Lock()
+ defer cc.mu.Unlock()
+ cc.wmu.Lock()
+ defer cc.wmu.Unlock()
+ if cc.closing {
+ // GOAWAY sent already
+ return nil
+ }
+ // Send a graceful shutdown frame to server
+ maxStreamID := cc.nextStreamID
+ if err := cc.fr.WriteGoAway(maxStreamID, ErrCodeNo, nil); err != nil {
+ return err
+ }
+ if err := cc.bw.Flush(); err != nil {
+ return err
+ }
+ // Prevent new requests
+ cc.closing = true
+ return nil
+}
+
+// Close closes the client connection immediately.
+//
+// In-flight requests are interrupted. For a graceful shutdown, use Shutdown instead.
+func (cc *ClientConn) Close() error {
+ cc.mu.Lock()
+ defer cc.cond.Broadcast()
+ defer cc.mu.Unlock()
+ err := errors.New("http2: client connection force closed via ClientConn.Close")
+ for id, cs := range cc.streams {
+ select {
+ case cs.resc <- resAndError{err: err}:
+ default:
+ }
+ cs.bufPipe.CloseWithError(err)
+ delete(cc.streams, id)
+ }
+ cc.closed = true
+ return cc.tconn.Close()
+}
+
+const maxAllocFrameSize = 512 << 10
+
+// frameBuffer returns a scratch buffer suitable for writing DATA frames.
+// They're capped at the min of the peer's max frame size or 512KB
+// (kinda arbitrarily), but definitely capped so we don't allocate 4GB
+// bufers.
+func (cc *ClientConn) frameScratchBuffer() []byte {
+ cc.mu.Lock()
+ size := cc.maxFrameSize
+ if size > maxAllocFrameSize {
+ size = maxAllocFrameSize
+ }
+ for i, buf := range cc.freeBuf {
+ if len(buf) >= int(size) {
+ cc.freeBuf[i] = nil
+ cc.mu.Unlock()
+ return buf[:size]
+ }
+ }
+ cc.mu.Unlock()
+ return make([]byte, size)
+}
+
+func (cc *ClientConn) putFrameScratchBuffer(buf []byte) {
+ cc.mu.Lock()
+ defer cc.mu.Unlock()
+ const maxBufs = 4 // arbitrary; 4 concurrent requests per conn? investigate.
+ if len(cc.freeBuf) < maxBufs {
+ cc.freeBuf = append(cc.freeBuf, buf)
+ return
+ }
+ for i, old := range cc.freeBuf {
+ if old == nil {
+ cc.freeBuf[i] = buf
+ return
+ }
+ }
+ // forget about it.
+}
+
+// errRequestCanceled is a copy of net/http's errRequestCanceled because it's not
+// exported. At least they'll be DeepEqual for h1-vs-h2 comparisons tests.
+var errRequestCanceled = errors.New("net/http: request canceled")
+
+func commaSeparatedTrailers(req *http.Request) (string, error) {
+ keys := make([]string, 0, len(req.Trailer))
+ for k := range req.Trailer {
+ k = http.CanonicalHeaderKey(k)
+ switch k {
+ case "Transfer-Encoding", "Trailer", "Content-Length":
+ return "", &badStringError{"invalid Trailer key", k}
+ }
+ keys = append(keys, k)
+ }
+ if len(keys) > 0 {
+ sort.Strings(keys)
+ return strings.Join(keys, ","), nil
+ }
+ return "", nil
+}
+
+func (cc *ClientConn) responseHeaderTimeout() time.Duration {
+ if cc.t.t1 != nil {
+ return cc.t.t1.ResponseHeaderTimeout
+ }
+ // No way to do this (yet?) with just an http2.Transport. Probably
+ // no need. Request.Cancel this is the new way. We only need to support
+ // this for compatibility with the old http.Transport fields when
+ // we're doing transparent http2.
+ return 0
+}
+
+// checkConnHeaders checks whether req has any invalid connection-level headers.
+// per RFC 7540 section 8.1.2.2: Connection-Specific Header Fields.
+// Certain headers are special-cased as okay but not transmitted later.
+func checkConnHeaders(req *http.Request) error {
+ if v := req.Header.Get("Upgrade"); v != "" {
+ return fmt.Errorf("http2: invalid Upgrade request header: %q", req.Header["Upgrade"])
+ }
+ if vv := req.Header["Transfer-Encoding"]; len(vv) > 0 && (len(vv) > 1 || vv[0] != "" && vv[0] != "chunked") {
+ return fmt.Errorf("http2: invalid Transfer-Encoding request header: %q", vv)
+ }
+ if vv := req.Header["Connection"]; len(vv) > 0 && (len(vv) > 1 || vv[0] != "" && !strings.EqualFold(vv[0], "close") && !strings.EqualFold(vv[0], "keep-alive")) {
+ return fmt.Errorf("http2: invalid Connection request header: %q", vv)
+ }
+ return nil
+}
+
+// actualContentLength returns a sanitized version of
+// req.ContentLength, where 0 actually means zero (not unknown) and -1
+// means unknown.
+func actualContentLength(req *http.Request) int64 {
+ if req.Body == nil || req.Body == http.NoBody {
+ return 0
+ }
+ if req.ContentLength != 0 {
+ return req.ContentLength
+ }
+ return -1
+}
+
+func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) {
+ resp, _, err := cc.roundTrip(req)
+ return resp, err
+}
+
+func (cc *ClientConn) roundTrip(req *http.Request) (res *http.Response, gotErrAfterReqBodyWrite bool, err error) {
+ if err := checkConnHeaders(req); err != nil {
+ return nil, false, err
+ }
+ if cc.idleTimer != nil {
+ cc.idleTimer.Stop()
+ }
+
+ trailers, err := commaSeparatedTrailers(req)
+ if err != nil {
+ return nil, false, err
+ }
+ hasTrailers := trailers != ""
+
+ cc.mu.Lock()
+ if err := cc.awaitOpenSlotForRequest(req); err != nil {
+ cc.mu.Unlock()
+ return nil, false, err
+ }
+
+ body := req.Body
+ contentLen := actualContentLength(req)
+ hasBody := contentLen != 0
+
+ // TODO(bradfitz): this is a copy of the logic in net/http. Unify somewhere?
+ var requestedGzip bool
+ if !cc.t.disableCompression() &&
+ req.Header.Get("Accept-Encoding") == "" &&
+ req.Header.Get("Range") == "" &&
+ req.Method != "HEAD" {
+ // Request gzip only, not deflate. Deflate is ambiguous and
+ // not as universally supported anyway.
+ // See: http://www.gzip.org/zlib/zlib_faq.html#faq38
+ //
+ // Note that we don't request this for HEAD requests,
+ // due to a bug in nginx:
+ // http://trac.nginx.org/nginx/ticket/358
+ // https://golang.org/issue/5522
+ //
+ // We don't request gzip if the request is for a range, since
+ // auto-decoding a portion of a gzipped document will just fail
+ // anyway. See https://golang.org/issue/8923
+ requestedGzip = true
+ }
+
+ // we send: HEADERS{1}, CONTINUATION{0,} + DATA{0,} (DATA is
+ // sent by writeRequestBody below, along with any Trailers,
+ // again in form HEADERS{1}, CONTINUATION{0,})
+ hdrs, err := cc.encodeHeaders(req, requestedGzip, trailers, contentLen)
+ if err != nil {
+ cc.mu.Unlock()
+ return nil, false, err
+ }
+
+ cs := cc.newStream()
+ cs.req = req
+ cs.trace = httptrace.ContextClientTrace(req.Context())
+ cs.requestedGzip = requestedGzip
+ bodyWriter := cc.t.getBodyWriterState(cs, body)
+ cs.on100 = bodyWriter.on100
+
+ cc.wmu.Lock()
+ endStream := !hasBody && !hasTrailers
+ werr := cc.writeHeaders(cs.ID, endStream, int(cc.maxFrameSize), hdrs)
+ cc.wmu.Unlock()
+ traceWroteHeaders(cs.trace)
+ cc.mu.Unlock()
+
+ if werr != nil {
+ if hasBody {
+ req.Body.Close() // per RoundTripper contract
+ bodyWriter.cancel()
+ }
+ cc.forgetStreamID(cs.ID)
+ // Don't bother sending a RST_STREAM (our write already failed;
+ // no need to keep writing)
+ traceWroteRequest(cs.trace, werr)
+ return nil, false, werr
+ }
+
+ var respHeaderTimer <-chan time.Time
+ if hasBody {
+ bodyWriter.scheduleBodyWrite()
+ } else {
+ traceWroteRequest(cs.trace, nil)
+ if d := cc.responseHeaderTimeout(); d != 0 {
+ timer := time.NewTimer(d)
+ defer timer.Stop()
+ respHeaderTimer = timer.C
+ }
+ }
+
+ readLoopResCh := cs.resc
+ bodyWritten := false
+ ctx := req.Context()
+
+ handleReadLoopResponse := func(re resAndError) (*http.Response, bool, error) {
+ res := re.res
+ if re.err != nil || res.StatusCode > 299 {
+ // On error or status code 3xx, 4xx, 5xx, etc abort any
+ // ongoing write, assuming that the server doesn't care
+ // about our request body. If the server replied with 1xx or
+ // 2xx, however, then assume the server DOES potentially
+ // want our body (e.g. full-duplex streaming:
+ // golang.org/issue/13444). If it turns out the server
+ // doesn't, they'll RST_STREAM us soon enough. This is a
+ // heuristic to avoid adding knobs to Transport. Hopefully
+ // we can keep it.
+ bodyWriter.cancel()
+ cs.abortRequestBodyWrite(errStopReqBodyWrite)
+ }
+ if re.err != nil {
+ cc.forgetStreamID(cs.ID)
+ return nil, cs.getStartedWrite(), re.err
+ }
+ res.Request = req
+ res.TLS = cc.tlsState
+ return res, false, nil
+ }
+
+ for {
+ select {
+ case re := <-readLoopResCh:
+ return handleReadLoopResponse(re)
+ case <-respHeaderTimer:
+ if !hasBody || bodyWritten {
+ cc.writeStreamReset(cs.ID, ErrCodeCancel, nil)
+ } else {
+ bodyWriter.cancel()
+ cs.abortRequestBodyWrite(errStopReqBodyWriteAndCancel)
+ }
+ cc.forgetStreamID(cs.ID)
+ return nil, cs.getStartedWrite(), errTimeout
+ case <-ctx.Done():
+ if !hasBody || bodyWritten {
+ cc.writeStreamReset(cs.ID, ErrCodeCancel, nil)
+ } else {
+ bodyWriter.cancel()
+ cs.abortRequestBodyWrite(errStopReqBodyWriteAndCancel)
+ }
+ cc.forgetStreamID(cs.ID)
+ return nil, cs.getStartedWrite(), ctx.Err()
+ case <-req.Cancel:
+ if !hasBody || bodyWritten {
+ cc.writeStreamReset(cs.ID, ErrCodeCancel, nil)
+ } else {
+ bodyWriter.cancel()
+ cs.abortRequestBodyWrite(errStopReqBodyWriteAndCancel)
+ }
+ cc.forgetStreamID(cs.ID)
+ return nil, cs.getStartedWrite(), errRequestCanceled
+ case <-cs.peerReset:
+ // processResetStream already removed the
+ // stream from the streams map; no need for
+ // forgetStreamID.
+ return nil, cs.getStartedWrite(), cs.resetErr
+ case err := <-bodyWriter.resc:
+ // Prefer the read loop's response, if available. Issue 16102.
+ select {
+ case re := <-readLoopResCh:
+ return handleReadLoopResponse(re)
+ default:
+ }
+ if err != nil {
+ cc.forgetStreamID(cs.ID)
+ return nil, cs.getStartedWrite(), err
+ }
+ bodyWritten = true
+ if d := cc.responseHeaderTimeout(); d != 0 {
+ timer := time.NewTimer(d)
+ defer timer.Stop()
+ respHeaderTimer = timer.C
+ }
+ }
+ }
+}
+
+// awaitOpenSlotForRequest waits until len(streams) < maxConcurrentStreams.
+// Must hold cc.mu.
+func (cc *ClientConn) awaitOpenSlotForRequest(req *http.Request) error {
+ var waitingForConn chan struct{}
+ var waitingForConnErr error // guarded by cc.mu
+ for {
+ cc.lastActive = time.Now()
+ if cc.closed || !cc.canTakeNewRequestLocked() {
+ if waitingForConn != nil {
+ close(waitingForConn)
+ }
+ return errClientConnUnusable
+ }
+ if int64(len(cc.streams))+1 <= int64(cc.maxConcurrentStreams) {
+ if waitingForConn != nil {
+ close(waitingForConn)
+ }
+ return nil
+ }
+ // Unfortunately, we cannot wait on a condition variable and channel at
+ // the same time, so instead, we spin up a goroutine to check if the
+ // request is canceled while we wait for a slot to open in the connection.
+ if waitingForConn == nil {
+ waitingForConn = make(chan struct{})
+ go func() {
+ if err := awaitRequestCancel(req, waitingForConn); err != nil {
+ cc.mu.Lock()
+ waitingForConnErr = err
+ cc.cond.Broadcast()
+ cc.mu.Unlock()
+ }
+ }()
+ }
+ cc.pendingRequests++
+ cc.cond.Wait()
+ cc.pendingRequests--
+ if waitingForConnErr != nil {
+ return waitingForConnErr
+ }
+ }
+}
+
+// requires cc.wmu be held
+func (cc *ClientConn) writeHeaders(streamID uint32, endStream bool, maxFrameSize int, hdrs []byte) error {
+ first := true // first frame written (HEADERS is first, then CONTINUATION)
+ for len(hdrs) > 0 && cc.werr == nil {
+ chunk := hdrs
+ if len(chunk) > maxFrameSize {
+ chunk = chunk[:maxFrameSize]
+ }
+ hdrs = hdrs[len(chunk):]
+ endHeaders := len(hdrs) == 0
+ if first {
+ cc.fr.WriteHeaders(HeadersFrameParam{
+ StreamID: streamID,
+ BlockFragment: chunk,
+ EndStream: endStream,
+ EndHeaders: endHeaders,
+ })
+ first = false
+ } else {
+ cc.fr.WriteContinuation(streamID, endHeaders, chunk)
+ }
+ }
+ // TODO(bradfitz): this Flush could potentially block (as
+ // could the WriteHeaders call(s) above), which means they
+ // wouldn't respond to Request.Cancel being readable. That's
+ // rare, but this should probably be in a goroutine.
+ cc.bw.Flush()
+ return cc.werr
+}
+
+// internal error values; they don't escape to callers
+var (
+ // abort request body write; don't send cancel
+ errStopReqBodyWrite = errors.New("http2: aborting request body write")
+
+ // abort request body write, but send stream reset of cancel.
+ errStopReqBodyWriteAndCancel = errors.New("http2: canceling request")
+)
+
+func (cs *clientStream) writeRequestBody(body io.Reader, bodyCloser io.Closer) (err error) {
+ cc := cs.cc
+ sentEnd := false // whether we sent the final DATA frame w/ END_STREAM
+ buf := cc.frameScratchBuffer()
+ defer cc.putFrameScratchBuffer(buf)
+
+ defer func() {
+ traceWroteRequest(cs.trace, err)
+ // TODO: write h12Compare test showing whether
+ // Request.Body is closed by the Transport,
+ // and in multiple cases: server replies <=299 and >299
+ // while still writing request body
+ cerr := bodyCloser.Close()
+ if err == nil {
+ err = cerr
+ }
+ }()
+
+ req := cs.req
+ hasTrailers := req.Trailer != nil
+
+ var sawEOF bool
+ for !sawEOF {
+ n, err := body.Read(buf)
+ if err == io.EOF {
+ sawEOF = true
+ err = nil
+ } else if err != nil {
+ cc.writeStreamReset(cs.ID, ErrCodeCancel, err)
+ return err
+ }
+
+ remain := buf[:n]
+ for len(remain) > 0 && err == nil {
+ var allowed int32
+ allowed, err = cs.awaitFlowControl(len(remain))
+ switch {
+ case err == errStopReqBodyWrite:
+ return err
+ case err == errStopReqBodyWriteAndCancel:
+ cc.writeStreamReset(cs.ID, ErrCodeCancel, nil)
+ return err
+ case err != nil:
+ return err
+ }
+ cc.wmu.Lock()
+ data := remain[:allowed]
+ remain = remain[allowed:]
+ sentEnd = sawEOF && len(remain) == 0 && !hasTrailers
+ err = cc.fr.WriteData(cs.ID, sentEnd, data)
+ if err == nil {
+ // TODO(bradfitz): this flush is for latency, not bandwidth.
+ // Most requests won't need this. Make this opt-in or
+ // opt-out? Use some heuristic on the body type? Nagel-like
+ // timers? Based on 'n'? Only last chunk of this for loop,
+ // unless flow control tokens are low? For now, always.
+ // If we change this, see comment below.
+ err = cc.bw.Flush()
+ }
+ cc.wmu.Unlock()
+ }
+ if err != nil {
+ return err
+ }
+ }
+
+ if sentEnd {
+ // Already sent END_STREAM (which implies we have no
+ // trailers) and flushed, because currently all
+ // WriteData frames above get a flush. So we're done.
+ return nil
+ }
+
+ var trls []byte
+ if hasTrailers {
+ cc.mu.Lock()
+ trls, err = cc.encodeTrailers(req)
+ cc.mu.Unlock()
+ if err != nil {
+ cc.writeStreamReset(cs.ID, ErrCodeInternal, err)
+ cc.forgetStreamID(cs.ID)
+ return err
+ }
+ }
+
+ cc.mu.Lock()
+ maxFrameSize := int(cc.maxFrameSize)
+ cc.mu.Unlock()
+
+ cc.wmu.Lock()
+ defer cc.wmu.Unlock()
+
+ // Two ways to send END_STREAM: either with trailers, or
+ // with an empty DATA frame.
+ if len(trls) > 0 {
+ err = cc.writeHeaders(cs.ID, true, maxFrameSize, trls)
+ } else {
+ err = cc.fr.WriteData(cs.ID, true, nil)
+ }
+ if ferr := cc.bw.Flush(); ferr != nil && err == nil {
+ err = ferr
+ }
+ return err
+}
+
+// awaitFlowControl waits for [1, min(maxBytes, cc.cs.maxFrameSize)] flow
+// control tokens from the server.
+// It returns either the non-zero number of tokens taken or an error
+// if the stream is dead.
+func (cs *clientStream) awaitFlowControl(maxBytes int) (taken int32, err error) {
+ cc := cs.cc
+ cc.mu.Lock()
+ defer cc.mu.Unlock()
+ for {
+ if cc.closed {
+ return 0, errClientConnClosed
+ }
+ if cs.stopReqBody != nil {
+ return 0, cs.stopReqBody
+ }
+ if err := cs.checkResetOrDone(); err != nil {
+ return 0, err
+ }
+ if a := cs.flow.available(); a > 0 {
+ take := a
+ if int(take) > maxBytes {
+
+ take = int32(maxBytes) // can't truncate int; take is int32
+ }
+ if take > int32(cc.maxFrameSize) {
+ take = int32(cc.maxFrameSize)
+ }
+ cs.flow.take(take)
+ return take, nil
+ }
+ cc.cond.Wait()
+ }
+}
+
+type badStringError struct {
+ what string
+ str string
+}
+
+func (e *badStringError) Error() string { return fmt.Sprintf("%s %q", e.what, e.str) }
+
+// requires cc.mu be held.
+func (cc *ClientConn) encodeHeaders(req *http.Request, addGzipHeader bool, trailers string, contentLength int64) ([]byte, error) {
+ cc.hbuf.Reset()
+
+ host := req.Host
+ if host == "" {
+ host = req.URL.Host
+ }
+ host, err := httpguts.PunycodeHostPort(host)
+ if err != nil {
+ return nil, err
+ }
+
+ var path string
+ if req.Method != "CONNECT" {
+ path = req.URL.RequestURI()
+ if !validPseudoPath(path) {
+ orig := path
+ path = strings.TrimPrefix(path, req.URL.Scheme+"://"+host)
+ if !validPseudoPath(path) {
+ if req.URL.Opaque != "" {
+ return nil, fmt.Errorf("invalid request :path %q from URL.Opaque = %q", orig, req.URL.Opaque)
+ } else {
+ return nil, fmt.Errorf("invalid request :path %q", orig)
+ }
+ }
+ }
+ }
+
+ // Check for any invalid headers and return an error before we
+ // potentially pollute our hpack state. (We want to be able to
+ // continue to reuse the hpack encoder for future requests)
+ for k, vv := range req.Header {
+ if !httpguts.ValidHeaderFieldName(k) {
+ return nil, fmt.Errorf("invalid HTTP header name %q", k)
+ }
+ for _, v := range vv {
+ if !httpguts.ValidHeaderFieldValue(v) {
+ return nil, fmt.Errorf("invalid HTTP header value %q for header %q", v, k)
+ }
+ }
+ }
+
+ enumerateHeaders := func(f func(name, value string)) {
+ // 8.1.2.3 Request Pseudo-Header Fields
+ // The :path pseudo-header field includes the path and query parts of the
+ // target URI (the path-absolute production and optionally a '?' character
+ // followed by the query production (see Sections 3.3 and 3.4 of
+ // [RFC3986]).
+ f(":authority", host)
+ f(":method", req.Method)
+ if req.Method != "CONNECT" {
+ f(":path", path)
+ f(":scheme", req.URL.Scheme)
+ }
+ if trailers != "" {
+ f("trailer", trailers)
+ }
+
+ var didUA bool
+ for k, vv := range req.Header {
+ if strings.EqualFold(k, "host") || strings.EqualFold(k, "content-length") {
+ // Host is :authority, already sent.
+ // Content-Length is automatic, set below.
+ continue
+ } else if strings.EqualFold(k, "connection") || strings.EqualFold(k, "proxy-connection") ||
+ strings.EqualFold(k, "transfer-encoding") || strings.EqualFold(k, "upgrade") ||
+ strings.EqualFold(k, "keep-alive") {
+ // Per 8.1.2.2 Connection-Specific Header
+ // Fields, don't send connection-specific
+ // fields. We have already checked if any
+ // are error-worthy so just ignore the rest.
+ continue
+ } else if strings.EqualFold(k, "user-agent") {
+ // Match Go's http1 behavior: at most one
+ // User-Agent. If set to nil or empty string,
+ // then omit it. Otherwise if not mentioned,
+ // include the default (below).
+ didUA = true
+ if len(vv) < 1 {
+ continue
+ }
+ vv = vv[:1]
+ if vv[0] == "" {
+ continue
+ }
+
+ }
+
+ for _, v := range vv {
+ f(k, v)
+ }
+ }
+ if shouldSendReqContentLength(req.Method, contentLength) {
+ f("content-length", strconv.FormatInt(contentLength, 10))
+ }
+ if addGzipHeader {
+ f("accept-encoding", "gzip")
+ }
+ if !didUA {
+ f("user-agent", defaultUserAgent)
+ }
+ }
+
+ // Do a first pass over the headers counting bytes to ensure
+ // we don't exceed cc.peerMaxHeaderListSize. This is done as a
+ // separate pass before encoding the headers to prevent
+ // modifying the hpack state.
+ hlSize := uint64(0)
+ enumerateHeaders(func(name, value string) {
+ hf := hpack.HeaderField{Name: name, Value: value}
+ hlSize += uint64(hf.Size())
+ })
+
+ if hlSize > cc.peerMaxHeaderListSize {
+ return nil, errRequestHeaderListSize
+ }
+
+ trace := httptrace.ContextClientTrace(req.Context())
+ traceHeaders := traceHasWroteHeaderField(trace)
+
+ // Header list size is ok. Write the headers.
+ enumerateHeaders(func(name, value string) {
+ name = strings.ToLower(name)
+ cc.writeHeader(name, value)
+ if traceHeaders {
+ traceWroteHeaderField(trace, name, value)
+ }
+ })
+
+ return cc.hbuf.Bytes(), nil
+}
+
+// shouldSendReqContentLength reports whether the http2.Transport should send
+// a "content-length" request header. This logic is basically a copy of the net/http
+// transferWriter.shouldSendContentLength.
+// The contentLength is the corrected contentLength (so 0 means actually 0, not unknown).
+// -1 means unknown.
+func shouldSendReqContentLength(method string, contentLength int64) bool {
+ if contentLength > 0 {
+ return true
+ }
+ if contentLength < 0 {
+ return false
+ }
+ // For zero bodies, whether we send a content-length depends on the method.
+ // It also kinda doesn't matter for http2 either way, with END_STREAM.
+ switch method {
+ case "POST", "PUT", "PATCH":
+ return true
+ default:
+ return false
+ }
+}
+
+// requires cc.mu be held.
+func (cc *ClientConn) encodeTrailers(req *http.Request) ([]byte, error) {
+ cc.hbuf.Reset()
+
+ hlSize := uint64(0)
+ for k, vv := range req.Trailer {
+ for _, v := range vv {
+ hf := hpack.HeaderField{Name: k, Value: v}
+ hlSize += uint64(hf.Size())
+ }
+ }
+ if hlSize > cc.peerMaxHeaderListSize {
+ return nil, errRequestHeaderListSize
+ }
+
+ for k, vv := range req.Trailer {
+ // Transfer-Encoding, etc.. have already been filtered at the
+ // start of RoundTrip
+ lowKey := strings.ToLower(k)
+ for _, v := range vv {
+ cc.writeHeader(lowKey, v)
+ }
+ }
+ return cc.hbuf.Bytes(), nil
+}
+
+func (cc *ClientConn) writeHeader(name, value string) {
+ if VerboseLogs {
+ log.Printf("http2: Transport encoding header %q = %q", name, value)
+ }
+ cc.henc.WriteField(hpack.HeaderField{Name: name, Value: value})
+}
+
+type resAndError struct {
+ res *http.Response
+ err error
+}
+
+// requires cc.mu be held.
+func (cc *ClientConn) newStream() *clientStream {
+ cs := &clientStream{
+ cc: cc,
+ ID: cc.nextStreamID,
+ resc: make(chan resAndError, 1),
+ peerReset: make(chan struct{}),
+ done: make(chan struct{}),
+ }
+ cs.flow.add(int32(cc.initialWindowSize))
+ cs.flow.setConnFlow(&cc.flow)
+ cs.inflow.add(transportDefaultStreamFlow)
+ cs.inflow.setConnFlow(&cc.inflow)
+ cc.nextStreamID += 2
+ cc.streams[cs.ID] = cs
+ return cs
+}
+
+func (cc *ClientConn) forgetStreamID(id uint32) {
+ cc.streamByID(id, true)
+}
+
+func (cc *ClientConn) streamByID(id uint32, andRemove bool) *clientStream {
+ cc.mu.Lock()
+ defer cc.mu.Unlock()
+ cs := cc.streams[id]
+ if andRemove && cs != nil && !cc.closed {
+ cc.lastActive = time.Now()
+ delete(cc.streams, id)
+ if len(cc.streams) == 0 && cc.idleTimer != nil {
+ cc.idleTimer.Reset(cc.idleTimeout)
+ }
+ close(cs.done)
+ // Wake up checkResetOrDone via clientStream.awaitFlowControl and
+ // wake up RoundTrip if there is a pending request.
+ cc.cond.Broadcast()
+ }
+ return cs
+}
+
+// clientConnReadLoop is the state owned by the clientConn's frame-reading readLoop.
+type clientConnReadLoop struct {
+ cc *ClientConn
+ closeWhenIdle bool
+}
+
+// readLoop runs in its own goroutine and reads and dispatches frames.
+func (cc *ClientConn) readLoop() {
+ rl := &clientConnReadLoop{cc: cc}
+ defer rl.cleanup()
+ cc.readerErr = rl.run()
+ if ce, ok := cc.readerErr.(ConnectionError); ok {
+ cc.wmu.Lock()
+ cc.fr.WriteGoAway(0, ErrCode(ce), nil)
+ cc.wmu.Unlock()
+ }
+}
+
+// GoAwayError is returned by the Transport when the server closes the
+// TCP connection after sending a GOAWAY frame.
+type GoAwayError struct {
+ LastStreamID uint32
+ ErrCode ErrCode
+ DebugData string
+}
+
+func (e GoAwayError) Error() string {
+ return fmt.Sprintf("http2: server sent GOAWAY and closed the connection; LastStreamID=%v, ErrCode=%v, debug=%q",
+ e.LastStreamID, e.ErrCode, e.DebugData)
+}
+
+func isEOFOrNetReadError(err error) bool {
+ if err == io.EOF {
+ return true
+ }
+ ne, ok := err.(*net.OpError)
+ return ok && ne.Op == "read"
+}
+
+func (rl *clientConnReadLoop) cleanup() {
+ cc := rl.cc
+ defer cc.tconn.Close()
+ defer cc.t.connPool().MarkDead(cc)
+ defer close(cc.readerDone)
+
+ if cc.idleTimer != nil {
+ cc.idleTimer.Stop()
+ }
+
+ // Close any response bodies if the server closes prematurely.
+ // TODO: also do this if we've written the headers but not
+ // gotten a response yet.
+ err := cc.readerErr
+ cc.mu.Lock()
+ if cc.goAway != nil && isEOFOrNetReadError(err) {
+ err = GoAwayError{
+ LastStreamID: cc.goAway.LastStreamID,
+ ErrCode: cc.goAway.ErrCode,
+ DebugData: cc.goAwayDebug,
+ }
+ } else if err == io.EOF {
+ err = io.ErrUnexpectedEOF
+ }
+ for _, cs := range cc.streams {
+ cs.bufPipe.CloseWithError(err) // no-op if already closed
+ select {
+ case cs.resc <- resAndError{err: err}:
+ default:
+ }
+ close(cs.done)
+ }
+ cc.closed = true
+ cc.cond.Broadcast()
+ cc.mu.Unlock()
+}
+
+func (rl *clientConnReadLoop) run() error {
+ cc := rl.cc
+ rl.closeWhenIdle = cc.t.disableKeepAlives() || cc.singleUse
+ gotReply := false // ever saw a HEADERS reply
+ gotSettings := false
+ for {
+ f, err := cc.fr.ReadFrame()
+ if err != nil {
+ cc.vlogf("http2: Transport readFrame error on conn %p: (%T) %v", cc, err, err)
+ }
+ if se, ok := err.(StreamError); ok {
+ if cs := cc.streamByID(se.StreamID, false); cs != nil {
+ cs.cc.writeStreamReset(cs.ID, se.Code, err)
+ cs.cc.forgetStreamID(cs.ID)
+ if se.Cause == nil {
+ se.Cause = cc.fr.errDetail
+ }
+ rl.endStreamError(cs, se)
+ }
+ continue
+ } else if err != nil {
+ return err
+ }
+ if VerboseLogs {
+ cc.vlogf("http2: Transport received %s", summarizeFrame(f))
+ }
+ if !gotSettings {
+ if _, ok := f.(*SettingsFrame); !ok {
+ cc.logf("protocol error: received %T before a SETTINGS frame", f)
+ return ConnectionError(ErrCodeProtocol)
+ }
+ gotSettings = true
+ }
+ maybeIdle := false // whether frame might transition us to idle
+
+ switch f := f.(type) {
+ case *MetaHeadersFrame:
+ err = rl.processHeaders(f)
+ maybeIdle = true
+ gotReply = true
+ case *DataFrame:
+ err = rl.processData(f)
+ maybeIdle = true
+ case *GoAwayFrame:
+ err = rl.processGoAway(f)
+ maybeIdle = true
+ case *RSTStreamFrame:
+ err = rl.processResetStream(f)
+ maybeIdle = true
+ case *SettingsFrame:
+ err = rl.processSettings(f)
+ case *PushPromiseFrame:
+ err = rl.processPushPromise(f)
+ case *WindowUpdateFrame:
+ err = rl.processWindowUpdate(f)
+ case *PingFrame:
+ err = rl.processPing(f)
+ default:
+ cc.logf("Transport: unhandled response frame type %T", f)
+ }
+ if err != nil {
+ if VerboseLogs {
+ cc.vlogf("http2: Transport conn %p received error from processing frame %v: %v", cc, summarizeFrame(f), err)
+ }
+ return err
+ }
+ if rl.closeWhenIdle && gotReply && maybeIdle {
+ cc.closeIfIdle()
+ }
+ }
+}
+
+func (rl *clientConnReadLoop) processHeaders(f *MetaHeadersFrame) error {
+ cc := rl.cc
+ cs := cc.streamByID(f.StreamID, false)
+ if cs == nil {
+ // We'd get here if we canceled a request while the
+ // server had its response still in flight. So if this
+ // was just something we canceled, ignore it.
+ return nil
+ }
+ if f.StreamEnded() {
+ // Issue 20521: If the stream has ended, streamByID() causes
+ // clientStream.done to be closed, which causes the request's bodyWriter
+ // to be closed with an errStreamClosed, which may be received by
+ // clientConn.RoundTrip before the result of processing these headers.
+ // Deferring stream closure allows the header processing to occur first.
+ // clientConn.RoundTrip may still receive the bodyWriter error first, but
+ // the fix for issue 16102 prioritises any response.
+ //
+ // Issue 22413: If there is no request body, we should close the
+ // stream before writing to cs.resc so that the stream is closed
+ // immediately once RoundTrip returns.
+ if cs.req.Body != nil {
+ defer cc.forgetStreamID(f.StreamID)
+ } else {
+ cc.forgetStreamID(f.StreamID)
+ }
+ }
+ if !cs.firstByte {
+ if cs.trace != nil {
+ // TODO(bradfitz): move first response byte earlier,
+ // when we first read the 9 byte header, not waiting
+ // until all the HEADERS+CONTINUATION frames have been
+ // merged. This works for now.
+ traceFirstResponseByte(cs.trace)
+ }
+ cs.firstByte = true
+ }
+ if !cs.pastHeaders {
+ cs.pastHeaders = true
+ } else {
+ return rl.processTrailers(cs, f)
+ }
+
+ res, err := rl.handleResponse(cs, f)
+ if err != nil {
+ if _, ok := err.(ConnectionError); ok {
+ return err
+ }
+ // Any other error type is a stream error.
+ cs.cc.writeStreamReset(f.StreamID, ErrCodeProtocol, err)
+ cc.forgetStreamID(cs.ID)
+ cs.resc <- resAndError{err: err}
+ return nil // return nil from process* funcs to keep conn alive
+ }
+ if res == nil {
+ // (nil, nil) special case. See handleResponse docs.
+ return nil
+ }
+ cs.resTrailer = &res.Trailer
+ cs.resc <- resAndError{res: res}
+ return nil
+}
+
+// may return error types nil, or ConnectionError. Any other error value
+// is a StreamError of type ErrCodeProtocol. The returned error in that case
+// is the detail.
+//
+// As a special case, handleResponse may return (nil, nil) to skip the
+// frame (currently only used for 1xx responses).
+func (rl *clientConnReadLoop) handleResponse(cs *clientStream, f *MetaHeadersFrame) (*http.Response, error) {
+ if f.Truncated {
+ return nil, errResponseHeaderListSize
+ }
+
+ status := f.PseudoValue("status")
+ if status == "" {
+ return nil, errors.New("malformed response from server: missing status pseudo header")
+ }
+ statusCode, err := strconv.Atoi(status)
+ if err != nil {
+ return nil, errors.New("malformed response from server: malformed non-numeric status pseudo header")
+ }
+
+ header := make(http.Header)
+ res := &http.Response{
+ Proto: "HTTP/2.0",
+ ProtoMajor: 2,
+ Header: header,
+ StatusCode: statusCode,
+ Status: status + " " + http.StatusText(statusCode),
+ }
+ for _, hf := range f.RegularFields() {
+ key := http.CanonicalHeaderKey(hf.Name)
+ if key == "Trailer" {
+ t := res.Trailer
+ if t == nil {
+ t = make(http.Header)
+ res.Trailer = t
+ }
+ foreachHeaderElement(hf.Value, func(v string) {
+ t[http.CanonicalHeaderKey(v)] = nil
+ })
+ } else {
+ header[key] = append(header[key], hf.Value)
+ }
+ }
+
+ if statusCode >= 100 && statusCode <= 199 {
+ cs.num1xx++
+ const max1xxResponses = 5 // arbitrary bound on number of informational responses, same as net/http
+ if cs.num1xx > max1xxResponses {
+ return nil, errors.New("http2: too many 1xx informational responses")
+ }
+ if fn := cs.get1xxTraceFunc(); fn != nil {
+ if err := fn(statusCode, textproto.MIMEHeader(header)); err != nil {
+ return nil, err
+ }
+ }
+ if statusCode == 100 {
+ traceGot100Continue(cs.trace)
+ if cs.on100 != nil {
+ cs.on100() // forces any write delay timer to fire
+ }
+ }
+ cs.pastHeaders = false // do it all again
+ return nil, nil
+ }
+
+ streamEnded := f.StreamEnded()
+ isHead := cs.req.Method == "HEAD"
+ if !streamEnded || isHead {
+ res.ContentLength = -1
+ if clens := res.Header["Content-Length"]; len(clens) == 1 {
+ if clen64, err := strconv.ParseInt(clens[0], 10, 64); err == nil {
+ res.ContentLength = clen64
+ } else {
+ // TODO: care? unlike http/1, it won't mess up our framing, so it's
+ // more safe smuggling-wise to ignore.
+ }
+ } else if len(clens) > 1 {
+ // TODO: care? unlike http/1, it won't mess up our framing, so it's
+ // more safe smuggling-wise to ignore.
+ }
+ }
+
+ if streamEnded || isHead {
+ res.Body = noBody
+ return res, nil
+ }
+
+ cs.bufPipe = pipe{b: &dataBuffer{expected: res.ContentLength}}
+ cs.bytesRemain = res.ContentLength
+ res.Body = transportResponseBody{cs}
+ go cs.awaitRequestCancel(cs.req)
+
+ if cs.requestedGzip && res.Header.Get("Content-Encoding") == "gzip" {
+ res.Header.Del("Content-Encoding")
+ res.Header.Del("Content-Length")
+ res.ContentLength = -1
+ res.Body = &gzipReader{body: res.Body}
+ res.Uncompressed = true
+ }
+ return res, nil
+}
+
+func (rl *clientConnReadLoop) processTrailers(cs *clientStream, f *MetaHeadersFrame) error {
+ if cs.pastTrailers {
+ // Too many HEADERS frames for this stream.
+ return ConnectionError(ErrCodeProtocol)
+ }
+ cs.pastTrailers = true
+ if !f.StreamEnded() {
+ // We expect that any headers for trailers also
+ // has END_STREAM.
+ return ConnectionError(ErrCodeProtocol)
+ }
+ if len(f.PseudoFields()) > 0 {
+ // No pseudo header fields are defined for trailers.
+ // TODO: ConnectionError might be overly harsh? Check.
+ return ConnectionError(ErrCodeProtocol)
+ }
+
+ trailer := make(http.Header)
+ for _, hf := range f.RegularFields() {
+ key := http.CanonicalHeaderKey(hf.Name)
+ trailer[key] = append(trailer[key], hf.Value)
+ }
+ cs.trailer = trailer
+
+ rl.endStream(cs)
+ return nil
+}
+
+// transportResponseBody is the concrete type of Transport.RoundTrip's
+// Response.Body. It is an io.ReadCloser. On Read, it reads from cs.body.
+// On Close it sends RST_STREAM if EOF wasn't already seen.
+type transportResponseBody struct {
+ cs *clientStream
+}
+
+func (b transportResponseBody) Read(p []byte) (n int, err error) {
+ cs := b.cs
+ cc := cs.cc
+
+ if cs.readErr != nil {
+ return 0, cs.readErr
+ }
+ n, err = b.cs.bufPipe.Read(p)
+ if cs.bytesRemain != -1 {
+ if int64(n) > cs.bytesRemain {
+ n = int(cs.bytesRemain)
+ if err == nil {
+ err = errors.New("net/http: server replied with more than declared Content-Length; truncated")
+ cc.writeStreamReset(cs.ID, ErrCodeProtocol, err)
+ }
+ cs.readErr = err
+ return int(cs.bytesRemain), err
+ }
+ cs.bytesRemain -= int64(n)
+ if err == io.EOF && cs.bytesRemain > 0 {
+ err = io.ErrUnexpectedEOF
+ cs.readErr = err
+ return n, err
+ }
+ }
+ if n == 0 {
+ // No flow control tokens to send back.
+ return
+ }
+
+ cc.mu.Lock()
+ defer cc.mu.Unlock()
+
+ var connAdd, streamAdd int32
+ // Check the conn-level first, before the stream-level.
+ if v := cc.inflow.available(); v < transportDefaultConnFlow/2 {
+ connAdd = transportDefaultConnFlow - v
+ cc.inflow.add(connAdd)
+ }
+ if err == nil { // No need to refresh if the stream is over or failed.
+ // Consider any buffered body data (read from the conn but not
+ // consumed by the client) when computing flow control for this
+ // stream.
+ v := int(cs.inflow.available()) + cs.bufPipe.Len()
+ if v < transportDefaultStreamFlow-transportDefaultStreamMinRefresh {
+ streamAdd = int32(transportDefaultStreamFlow - v)
+ cs.inflow.add(streamAdd)
+ }
+ }
+ if connAdd != 0 || streamAdd != 0 {
+ cc.wmu.Lock()
+ defer cc.wmu.Unlock()
+ if connAdd != 0 {
+ cc.fr.WriteWindowUpdate(0, mustUint31(connAdd))
+ }
+ if streamAdd != 0 {
+ cc.fr.WriteWindowUpdate(cs.ID, mustUint31(streamAdd))
+ }
+ cc.bw.Flush()
+ }
+ return
+}
+
+var errClosedResponseBody = errors.New("http2: response body closed")
+
+func (b transportResponseBody) Close() error {
+ cs := b.cs
+ cc := cs.cc
+
+ serverSentStreamEnd := cs.bufPipe.Err() == io.EOF
+ unread := cs.bufPipe.Len()
+
+ if unread > 0 || !serverSentStreamEnd {
+ cc.mu.Lock()
+ cc.wmu.Lock()
+ if !serverSentStreamEnd {
+ cc.fr.WriteRSTStream(cs.ID, ErrCodeCancel)
+ cs.didReset = true
+ }
+ // Return connection-level flow control.
+ if unread > 0 {
+ cc.inflow.add(int32(unread))
+ cc.fr.WriteWindowUpdate(0, uint32(unread))
+ }
+ cc.bw.Flush()
+ cc.wmu.Unlock()
+ cc.mu.Unlock()
+ }
+
+ cs.bufPipe.BreakWithError(errClosedResponseBody)
+ cc.forgetStreamID(cs.ID)
+ return nil
+}
+
+func (rl *clientConnReadLoop) processData(f *DataFrame) error {
+ cc := rl.cc
+ cs := cc.streamByID(f.StreamID, f.StreamEnded())
+ data := f.Data()
+ if cs == nil {
+ cc.mu.Lock()
+ neverSent := cc.nextStreamID
+ cc.mu.Unlock()
+ if f.StreamID >= neverSent {
+ // We never asked for this.
+ cc.logf("http2: Transport received unsolicited DATA frame; closing connection")
+ return ConnectionError(ErrCodeProtocol)
+ }
+ // We probably did ask for this, but canceled. Just ignore it.
+ // TODO: be stricter here? only silently ignore things which
+ // we canceled, but not things which were closed normally
+ // by the peer? Tough without accumulating too much state.
+
+ // But at least return their flow control:
+ if f.Length > 0 {
+ cc.mu.Lock()
+ cc.inflow.add(int32(f.Length))
+ cc.mu.Unlock()
+
+ cc.wmu.Lock()
+ cc.fr.WriteWindowUpdate(0, uint32(f.Length))
+ cc.bw.Flush()
+ cc.wmu.Unlock()
+ }
+ return nil
+ }
+ if !cs.firstByte {
+ cc.logf("protocol error: received DATA before a HEADERS frame")
+ rl.endStreamError(cs, StreamError{
+ StreamID: f.StreamID,
+ Code: ErrCodeProtocol,
+ })
+ return nil
+ }
+ if f.Length > 0 {
+ if cs.req.Method == "HEAD" && len(data) > 0 {
+ cc.logf("protocol error: received DATA on a HEAD request")
+ rl.endStreamError(cs, StreamError{
+ StreamID: f.StreamID,
+ Code: ErrCodeProtocol,
+ })
+ return nil
+ }
+ // Check connection-level flow control.
+ cc.mu.Lock()
+ if cs.inflow.available() >= int32(f.Length) {
+ cs.inflow.take(int32(f.Length))
+ } else {
+ cc.mu.Unlock()
+ return ConnectionError(ErrCodeFlowControl)
+ }
+ // Return any padded flow control now, since we won't
+ // refund it later on body reads.
+ var refund int
+ if pad := int(f.Length) - len(data); pad > 0 {
+ refund += pad
+ }
+ // Return len(data) now if the stream is already closed,
+ // since data will never be read.
+ didReset := cs.didReset
+ if didReset {
+ refund += len(data)
+ }
+ if refund > 0 {
+ cc.inflow.add(int32(refund))
+ cc.wmu.Lock()
+ cc.fr.WriteWindowUpdate(0, uint32(refund))
+ if !didReset {
+ cs.inflow.add(int32(refund))
+ cc.fr.WriteWindowUpdate(cs.ID, uint32(refund))
+ }
+ cc.bw.Flush()
+ cc.wmu.Unlock()
+ }
+ cc.mu.Unlock()
+
+ if len(data) > 0 && !didReset {
+ if _, err := cs.bufPipe.Write(data); err != nil {
+ rl.endStreamError(cs, err)
+ return err
+ }
+ }
+ }
+
+ if f.StreamEnded() {
+ rl.endStream(cs)
+ }
+ return nil
+}
+
+var errInvalidTrailers = errors.New("http2: invalid trailers")
+
+func (rl *clientConnReadLoop) endStream(cs *clientStream) {
+ // TODO: check that any declared content-length matches, like
+ // server.go's (*stream).endStream method.
+ rl.endStreamError(cs, nil)
+}
+
+func (rl *clientConnReadLoop) endStreamError(cs *clientStream, err error) {
+ var code func()
+ if err == nil {
+ err = io.EOF
+ code = cs.copyTrailers
+ }
+ if isConnectionCloseRequest(cs.req) {
+ rl.closeWhenIdle = true
+ }
+ cs.bufPipe.closeWithErrorAndCode(err, code)
+
+ select {
+ case cs.resc <- resAndError{err: err}:
+ default:
+ }
+}
+
+func (cs *clientStream) copyTrailers() {
+ for k, vv := range cs.trailer {
+ t := cs.resTrailer
+ if *t == nil {
+ *t = make(http.Header)
+ }
+ (*t)[k] = vv
+ }
+}
+
+func (rl *clientConnReadLoop) processGoAway(f *GoAwayFrame) error {
+ cc := rl.cc
+ cc.t.connPool().MarkDead(cc)
+ if f.ErrCode != 0 {
+ // TODO: deal with GOAWAY more. particularly the error code
+ cc.vlogf("transport got GOAWAY with error code = %v", f.ErrCode)
+ }
+ cc.setGoAway(f)
+ return nil
+}
+
+func (rl *clientConnReadLoop) processSettings(f *SettingsFrame) error {
+ cc := rl.cc
+ cc.mu.Lock()
+ defer cc.mu.Unlock()
+
+ if f.IsAck() {
+ if cc.wantSettingsAck {
+ cc.wantSettingsAck = false
+ return nil
+ }
+ return ConnectionError(ErrCodeProtocol)
+ }
+
+ err := f.ForeachSetting(func(s Setting) error {
+ switch s.ID {
+ case SettingMaxFrameSize:
+ cc.maxFrameSize = s.Val
+ case SettingMaxConcurrentStreams:
+ cc.maxConcurrentStreams = s.Val
+ case SettingMaxHeaderListSize:
+ cc.peerMaxHeaderListSize = uint64(s.Val)
+ case SettingInitialWindowSize:
+ // Values above the maximum flow-control
+ // window size of 2^31-1 MUST be treated as a
+ // connection error (Section 5.4.1) of type
+ // FLOW_CONTROL_ERROR.
+ if s.Val > math.MaxInt32 {
+ return ConnectionError(ErrCodeFlowControl)
+ }
+
+ // Adjust flow control of currently-open
+ // frames by the difference of the old initial
+ // window size and this one.
+ delta := int32(s.Val) - int32(cc.initialWindowSize)
+ for _, cs := range cc.streams {
+ cs.flow.add(delta)
+ }
+ cc.cond.Broadcast()
+
+ cc.initialWindowSize = s.Val
+ default:
+ // TODO(bradfitz): handle more settings? SETTINGS_HEADER_TABLE_SIZE probably.
+ cc.vlogf("Unhandled Setting: %v", s)
+ }
+ return nil
+ })
+ if err != nil {
+ return err
+ }
+
+ cc.wmu.Lock()
+ defer cc.wmu.Unlock()
+
+ cc.fr.WriteSettingsAck()
+ cc.bw.Flush()
+ return cc.werr
+}
+
+func (rl *clientConnReadLoop) processWindowUpdate(f *WindowUpdateFrame) error {
+ cc := rl.cc
+ cs := cc.streamByID(f.StreamID, false)
+ if f.StreamID != 0 && cs == nil {
+ return nil
+ }
+
+ cc.mu.Lock()
+ defer cc.mu.Unlock()
+
+ fl := &cc.flow
+ if cs != nil {
+ fl = &cs.flow
+ }
+ if !fl.add(int32(f.Increment)) {
+ return ConnectionError(ErrCodeFlowControl)
+ }
+ cc.cond.Broadcast()
+ return nil
+}
+
+func (rl *clientConnReadLoop) processResetStream(f *RSTStreamFrame) error {
+ cs := rl.cc.streamByID(f.StreamID, true)
+ if cs == nil {
+ // TODO: return error if server tries to RST_STEAM an idle stream
+ return nil
+ }
+ select {
+ case <-cs.peerReset:
+ // Already reset.
+ // This is the only goroutine
+ // which closes this, so there
+ // isn't a race.
+ default:
+ err := streamError(cs.ID, f.ErrCode)
+ cs.resetErr = err
+ close(cs.peerReset)
+ cs.bufPipe.CloseWithError(err)
+ cs.cc.cond.Broadcast() // wake up checkResetOrDone via clientStream.awaitFlowControl
+ }
+ return nil
+}
+
+// Ping sends a PING frame to the server and waits for the ack.
+func (cc *ClientConn) Ping(ctx context.Context) error {
+ c := make(chan struct{})
+ // Generate a random payload
+ var p [8]byte
+ for {
+ if _, err := rand.Read(p[:]); err != nil {
+ return err
+ }
+ cc.mu.Lock()
+ // check for dup before insert
+ if _, found := cc.pings[p]; !found {
+ cc.pings[p] = c
+ cc.mu.Unlock()
+ break
+ }
+ cc.mu.Unlock()
+ }
+ cc.wmu.Lock()
+ if err := cc.fr.WritePing(false, p); err != nil {
+ cc.wmu.Unlock()
+ return err
+ }
+ if err := cc.bw.Flush(); err != nil {
+ cc.wmu.Unlock()
+ return err
+ }
+ cc.wmu.Unlock()
+ select {
+ case <-c:
+ return nil
+ case <-ctx.Done():
+ return ctx.Err()
+ case <-cc.readerDone:
+ // connection closed
+ return cc.readerErr
+ }
+}
+
+func (rl *clientConnReadLoop) processPing(f *PingFrame) error {
+ if f.IsAck() {
+ cc := rl.cc
+ cc.mu.Lock()
+ defer cc.mu.Unlock()
+ // If ack, notify listener if any
+ if c, ok := cc.pings[f.Data]; ok {
+ close(c)
+ delete(cc.pings, f.Data)
+ }
+ return nil
+ }
+ cc := rl.cc
+ cc.wmu.Lock()
+ defer cc.wmu.Unlock()
+ if err := cc.fr.WritePing(true, f.Data); err != nil {
+ return err
+ }
+ return cc.bw.Flush()
+}
+
+func (rl *clientConnReadLoop) processPushPromise(f *PushPromiseFrame) error {
+ // We told the peer we don't want them.
+ // Spec says:
+ // "PUSH_PROMISE MUST NOT be sent if the SETTINGS_ENABLE_PUSH
+ // setting of the peer endpoint is set to 0. An endpoint that
+ // has set this setting and has received acknowledgement MUST
+ // treat the receipt of a PUSH_PROMISE frame as a connection
+ // error (Section 5.4.1) of type PROTOCOL_ERROR."
+ return ConnectionError(ErrCodeProtocol)
+}
+
+func (cc *ClientConn) writeStreamReset(streamID uint32, code ErrCode, err error) {
+ // TODO: map err to more interesting error codes, once the
+ // HTTP community comes up with some. But currently for
+ // RST_STREAM there's no equivalent to GOAWAY frame's debug
+ // data, and the error codes are all pretty vague ("cancel").
+ cc.wmu.Lock()
+ cc.fr.WriteRSTStream(streamID, code)
+ cc.bw.Flush()
+ cc.wmu.Unlock()
+}
+
+var (
+ errResponseHeaderListSize = errors.New("http2: response header list larger than advertised limit")
+ errRequestHeaderListSize = errors.New("http2: request header list larger than peer's advertised limit")
+ errPseudoTrailers = errors.New("http2: invalid pseudo header in trailers")
+)
+
+func (cc *ClientConn) logf(format string, args ...interface{}) {
+ cc.t.logf(format, args...)
+}
+
+func (cc *ClientConn) vlogf(format string, args ...interface{}) {
+ cc.t.vlogf(format, args...)
+}
+
+func (t *Transport) vlogf(format string, args ...interface{}) {
+ if VerboseLogs {
+ t.logf(format, args...)
+ }
+}
+
+func (t *Transport) logf(format string, args ...interface{}) {
+ log.Printf(format, args...)
+}
+
+var noBody io.ReadCloser = ioutil.NopCloser(bytes.NewReader(nil))
+
+func strSliceContains(ss []string, s string) bool {
+ for _, v := range ss {
+ if v == s {
+ return true
+ }
+ }
+ return false
+}
+
+type erringRoundTripper struct{ err error }
+
+func (rt erringRoundTripper) RoundTrip(*http.Request) (*http.Response, error) { return nil, rt.err }
+
+// gzipReader wraps a response body so it can lazily
+// call gzip.NewReader on the first call to Read
+type gzipReader struct {
+ body io.ReadCloser // underlying Response.Body
+ zr *gzip.Reader // lazily-initialized gzip reader
+ zerr error // sticky error
+}
+
+func (gz *gzipReader) Read(p []byte) (n int, err error) {
+ if gz.zerr != nil {
+ return 0, gz.zerr
+ }
+ if gz.zr == nil {
+ gz.zr, err = gzip.NewReader(gz.body)
+ if err != nil {
+ gz.zerr = err
+ return 0, err
+ }
+ }
+ return gz.zr.Read(p)
+}
+
+func (gz *gzipReader) Close() error {
+ return gz.body.Close()
+}
+
+type errorReader struct{ err error }
+
+func (r errorReader) Read(p []byte) (int, error) { return 0, r.err }
+
+// bodyWriterState encapsulates various state around the Transport's writing
+// of the request body, particularly regarding doing delayed writes of the body
+// when the request contains "Expect: 100-continue".
+type bodyWriterState struct {
+ cs *clientStream
+ timer *time.Timer // if non-nil, we're doing a delayed write
+ fnonce *sync.Once // to call fn with
+ fn func() // the code to run in the goroutine, writing the body
+ resc chan error // result of fn's execution
+ delay time.Duration // how long we should delay a delayed write for
+}
+
+func (t *Transport) getBodyWriterState(cs *clientStream, body io.Reader) (s bodyWriterState) {
+ s.cs = cs
+ if body == nil {
+ return
+ }
+ resc := make(chan error, 1)
+ s.resc = resc
+ s.fn = func() {
+ cs.cc.mu.Lock()
+ cs.startedWrite = true
+ cs.cc.mu.Unlock()
+ resc <- cs.writeRequestBody(body, cs.req.Body)
+ }
+ s.delay = t.expectContinueTimeout()
+ if s.delay == 0 ||
+ !httpguts.HeaderValuesContainsToken(
+ cs.req.Header["Expect"],
+ "100-continue") {
+ return
+ }
+ s.fnonce = new(sync.Once)
+
+ // Arm the timer with a very large duration, which we'll
+ // intentionally lower later. It has to be large now because
+ // we need a handle to it before writing the headers, but the
+ // s.delay value is defined to not start until after the
+ // request headers were written.
+ const hugeDuration = 365 * 24 * time.Hour
+ s.timer = time.AfterFunc(hugeDuration, func() {
+ s.fnonce.Do(s.fn)
+ })
+ return
+}
+
+func (s bodyWriterState) cancel() {
+ if s.timer != nil {
+ s.timer.Stop()
+ }
+}
+
+func (s bodyWriterState) on100() {
+ if s.timer == nil {
+ // If we didn't do a delayed write, ignore the server's
+ // bogus 100 continue response.
+ return
+ }
+ s.timer.Stop()
+ go func() { s.fnonce.Do(s.fn) }()
+}
+
+// scheduleBodyWrite starts writing the body, either immediately (in
+// the common case) or after the delay timeout. It should not be
+// called until after the headers have been written.
+func (s bodyWriterState) scheduleBodyWrite() {
+ if s.timer == nil {
+ // We're not doing a delayed write (see
+ // getBodyWriterState), so just start the writing
+ // goroutine immediately.
+ go s.fn()
+ return
+ }
+ traceWait100Continue(s.cs.trace)
+ if s.timer.Stop() {
+ s.timer.Reset(s.delay)
+ }
+}
+
+// isConnectionCloseRequest reports whether req should use its own
+// connection for a single request and then close the connection.
+func isConnectionCloseRequest(req *http.Request) bool {
+ return req.Close || httpguts.HeaderValuesContainsToken(req.Header["Connection"], "close")
+}
+
+// registerHTTPSProtocol calls Transport.RegisterProtocol but
+// converting panics into errors.
+func registerHTTPSProtocol(t *http.Transport, rt noDialH2RoundTripper) (err error) {
+ defer func() {
+ if e := recover(); e != nil {
+ err = fmt.Errorf("%v", e)
+ }
+ }()
+ t.RegisterProtocol("https", rt)
+ return nil
+}
+
+// noDialH2RoundTripper is a RoundTripper which only tries to complete the request
+// if there's already has a cached connection to the host.
+// (The field is exported so it can be accessed via reflect from net/http; tested
+// by TestNoDialH2RoundTripperType)
+type noDialH2RoundTripper struct{ *Transport }
+
+func (rt noDialH2RoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
+ res, err := rt.Transport.RoundTrip(req)
+ if isNoCachedConnError(err) {
+ return nil, http.ErrSkipAltProtocol
+ }
+ return res, err
+}
+
+func (t *Transport) idleConnTimeout() time.Duration {
+ if t.t1 != nil {
+ return t.t1.IdleConnTimeout
+ }
+ return 0
+}
+
+func traceGetConn(req *http.Request, hostPort string) {
+ trace := httptrace.ContextClientTrace(req.Context())
+ if trace == nil || trace.GetConn == nil {
+ return
+ }
+ trace.GetConn(hostPort)
+}
+
+func traceGotConn(req *http.Request, cc *ClientConn) {
+ trace := httptrace.ContextClientTrace(req.Context())
+ if trace == nil || trace.GotConn == nil {
+ return
+ }
+ ci := httptrace.GotConnInfo{Conn: cc.tconn}
+ cc.mu.Lock()
+ ci.Reused = cc.nextStreamID > 1
+ ci.WasIdle = len(cc.streams) == 0 && ci.Reused
+ if ci.WasIdle && !cc.lastActive.IsZero() {
+ ci.IdleTime = time.Now().Sub(cc.lastActive)
+ }
+ cc.mu.Unlock()
+
+ trace.GotConn(ci)
+}
+
+func traceWroteHeaders(trace *httptrace.ClientTrace) {
+ if trace != nil && trace.WroteHeaders != nil {
+ trace.WroteHeaders()
+ }
+}
+
+func traceGot100Continue(trace *httptrace.ClientTrace) {
+ if trace != nil && trace.Got100Continue != nil {
+ trace.Got100Continue()
+ }
+}
+
+func traceWait100Continue(trace *httptrace.ClientTrace) {
+ if trace != nil && trace.Wait100Continue != nil {
+ trace.Wait100Continue()
+ }
+}
+
+func traceWroteRequest(trace *httptrace.ClientTrace, err error) {
+ if trace != nil && trace.WroteRequest != nil {
+ trace.WroteRequest(httptrace.WroteRequestInfo{Err: err})
+ }
+}
+
+func traceFirstResponseByte(trace *httptrace.ClientTrace) {
+ if trace != nil && trace.GotFirstResponseByte != nil {
+ trace.GotFirstResponseByte()
+ }
+}
diff --git a/vendor/golang.org/x/net/http2/write.go b/vendor/golang.org/x/net/http2/write.go
new file mode 100644
index 000000000..3849bc263
--- /dev/null
+++ b/vendor/golang.org/x/net/http2/write.go
@@ -0,0 +1,365 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package http2
+
+import (
+ "bytes"
+ "fmt"
+ "log"
+ "net/http"
+ "net/url"
+
+ "golang.org/x/net/http/httpguts"
+ "golang.org/x/net/http2/hpack"
+)
+
+// writeFramer is implemented by any type that is used to write frames.
+type writeFramer interface {
+ writeFrame(writeContext) error
+
+ // staysWithinBuffer reports whether this writer promises that
+ // it will only write less than or equal to size bytes, and it
+ // won't Flush the write context.
+ staysWithinBuffer(size int) bool
+}
+
+// writeContext is the interface needed by the various frame writer
+// types below. All the writeFrame methods below are scheduled via the
+// frame writing scheduler (see writeScheduler in writesched.go).
+//
+// This interface is implemented by *serverConn.
+//
+// TODO: decide whether to a) use this in the client code (which didn't
+// end up using this yet, because it has a simpler design, not
+// currently implementing priorities), or b) delete this and
+// make the server code a bit more concrete.
+type writeContext interface {
+ Framer() *Framer
+ Flush() error
+ CloseConn() error
+ // HeaderEncoder returns an HPACK encoder that writes to the
+ // returned buffer.
+ HeaderEncoder() (*hpack.Encoder, *bytes.Buffer)
+}
+
+// writeEndsStream reports whether w writes a frame that will transition
+// the stream to a half-closed local state. This returns false for RST_STREAM,
+// which closes the entire stream (not just the local half).
+func writeEndsStream(w writeFramer) bool {
+ switch v := w.(type) {
+ case *writeData:
+ return v.endStream
+ case *writeResHeaders:
+ return v.endStream
+ case nil:
+ // This can only happen if the caller reuses w after it's
+ // been intentionally nil'ed out to prevent use. Keep this
+ // here to catch future refactoring breaking it.
+ panic("writeEndsStream called on nil writeFramer")
+ }
+ return false
+}
+
+type flushFrameWriter struct{}
+
+func (flushFrameWriter) writeFrame(ctx writeContext) error {
+ return ctx.Flush()
+}
+
+func (flushFrameWriter) staysWithinBuffer(max int) bool { return false }
+
+type writeSettings []Setting
+
+func (s writeSettings) staysWithinBuffer(max int) bool {
+ const settingSize = 6 // uint16 + uint32
+ return frameHeaderLen+settingSize*len(s) <= max
+
+}
+
+func (s writeSettings) writeFrame(ctx writeContext) error {
+ return ctx.Framer().WriteSettings([]Setting(s)...)
+}
+
+type writeGoAway struct {
+ maxStreamID uint32
+ code ErrCode
+}
+
+func (p *writeGoAway) writeFrame(ctx writeContext) error {
+ err := ctx.Framer().WriteGoAway(p.maxStreamID, p.code, nil)
+ ctx.Flush() // ignore error: we're hanging up on them anyway
+ return err
+}
+
+func (*writeGoAway) staysWithinBuffer(max int) bool { return false } // flushes
+
+type writeData struct {
+ streamID uint32
+ p []byte
+ endStream bool
+}
+
+func (w *writeData) String() string {
+ return fmt.Sprintf("writeData(stream=%d, p=%d, endStream=%v)", w.streamID, len(w.p), w.endStream)
+}
+
+func (w *writeData) writeFrame(ctx writeContext) error {
+ return ctx.Framer().WriteData(w.streamID, w.endStream, w.p)
+}
+
+func (w *writeData) staysWithinBuffer(max int) bool {
+ return frameHeaderLen+len(w.p) <= max
+}
+
+// handlerPanicRST is the message sent from handler goroutines when
+// the handler panics.
+type handlerPanicRST struct {
+ StreamID uint32
+}
+
+func (hp handlerPanicRST) writeFrame(ctx writeContext) error {
+ return ctx.Framer().WriteRSTStream(hp.StreamID, ErrCodeInternal)
+}
+
+func (hp handlerPanicRST) staysWithinBuffer(max int) bool { return frameHeaderLen+4 <= max }
+
+func (se StreamError) writeFrame(ctx writeContext) error {
+ return ctx.Framer().WriteRSTStream(se.StreamID, se.Code)
+}
+
+func (se StreamError) staysWithinBuffer(max int) bool { return frameHeaderLen+4 <= max }
+
+type writePingAck struct{ pf *PingFrame }
+
+func (w writePingAck) writeFrame(ctx writeContext) error {
+ return ctx.Framer().WritePing(true, w.pf.Data)
+}
+
+func (w writePingAck) staysWithinBuffer(max int) bool { return frameHeaderLen+len(w.pf.Data) <= max }
+
+type writeSettingsAck struct{}
+
+func (writeSettingsAck) writeFrame(ctx writeContext) error {
+ return ctx.Framer().WriteSettingsAck()
+}
+
+func (writeSettingsAck) staysWithinBuffer(max int) bool { return frameHeaderLen <= max }
+
+// splitHeaderBlock splits headerBlock into fragments so that each fragment fits
+// in a single frame, then calls fn for each fragment. firstFrag/lastFrag are true
+// for the first/last fragment, respectively.
+func splitHeaderBlock(ctx writeContext, headerBlock []byte, fn func(ctx writeContext, frag []byte, firstFrag, lastFrag bool) error) error {
+ // For now we're lazy and just pick the minimum MAX_FRAME_SIZE
+ // that all peers must support (16KB). Later we could care
+ // more and send larger frames if the peer advertised it, but
+ // there's little point. Most headers are small anyway (so we
+ // generally won't have CONTINUATION frames), and extra frames
+ // only waste 9 bytes anyway.
+ const maxFrameSize = 16384
+
+ first := true
+ for len(headerBlock) > 0 {
+ frag := headerBlock
+ if len(frag) > maxFrameSize {
+ frag = frag[:maxFrameSize]
+ }
+ headerBlock = headerBlock[len(frag):]
+ if err := fn(ctx, frag, first, len(headerBlock) == 0); err != nil {
+ return err
+ }
+ first = false
+ }
+ return nil
+}
+
+// writeResHeaders is a request to write a HEADERS and 0+ CONTINUATION frames
+// for HTTP response headers or trailers from a server handler.
+type writeResHeaders struct {
+ streamID uint32
+ httpResCode int // 0 means no ":status" line
+ h http.Header // may be nil
+ trailers []string // if non-nil, which keys of h to write. nil means all.
+ endStream bool
+
+ date string
+ contentType string
+ contentLength string
+}
+
+func encKV(enc *hpack.Encoder, k, v string) {
+ if VerboseLogs {
+ log.Printf("http2: server encoding header %q = %q", k, v)
+ }
+ enc.WriteField(hpack.HeaderField{Name: k, Value: v})
+}
+
+func (w *writeResHeaders) staysWithinBuffer(max int) bool {
+ // TODO: this is a common one. It'd be nice to return true
+ // here and get into the fast path if we could be clever and
+ // calculate the size fast enough, or at least a conservative
+ // upper bound that usually fires. (Maybe if w.h and
+ // w.trailers are nil, so we don't need to enumerate it.)
+ // Otherwise I'm afraid that just calculating the length to
+ // answer this question would be slower than the ~2µs benefit.
+ return false
+}
+
+func (w *writeResHeaders) writeFrame(ctx writeContext) error {
+ enc, buf := ctx.HeaderEncoder()
+ buf.Reset()
+
+ if w.httpResCode != 0 {
+ encKV(enc, ":status", httpCodeString(w.httpResCode))
+ }
+
+ encodeHeaders(enc, w.h, w.trailers)
+
+ if w.contentType != "" {
+ encKV(enc, "content-type", w.contentType)
+ }
+ if w.contentLength != "" {
+ encKV(enc, "content-length", w.contentLength)
+ }
+ if w.date != "" {
+ encKV(enc, "date", w.date)
+ }
+
+ headerBlock := buf.Bytes()
+ if len(headerBlock) == 0 && w.trailers == nil {
+ panic("unexpected empty hpack")
+ }
+
+ return splitHeaderBlock(ctx, headerBlock, w.writeHeaderBlock)
+}
+
+func (w *writeResHeaders) writeHeaderBlock(ctx writeContext, frag []byte, firstFrag, lastFrag bool) error {
+ if firstFrag {
+ return ctx.Framer().WriteHeaders(HeadersFrameParam{
+ StreamID: w.streamID,
+ BlockFragment: frag,
+ EndStream: w.endStream,
+ EndHeaders: lastFrag,
+ })
+ } else {
+ return ctx.Framer().WriteContinuation(w.streamID, lastFrag, frag)
+ }
+}
+
+// writePushPromise is a request to write a PUSH_PROMISE and 0+ CONTINUATION frames.
+type writePushPromise struct {
+ streamID uint32 // pusher stream
+ method string // for :method
+ url *url.URL // for :scheme, :authority, :path
+ h http.Header
+
+ // Creates an ID for a pushed stream. This runs on serveG just before
+ // the frame is written. The returned ID is copied to promisedID.
+ allocatePromisedID func() (uint32, error)
+ promisedID uint32
+}
+
+func (w *writePushPromise) staysWithinBuffer(max int) bool {
+ // TODO: see writeResHeaders.staysWithinBuffer
+ return false
+}
+
+func (w *writePushPromise) writeFrame(ctx writeContext) error {
+ enc, buf := ctx.HeaderEncoder()
+ buf.Reset()
+
+ encKV(enc, ":method", w.method)
+ encKV(enc, ":scheme", w.url.Scheme)
+ encKV(enc, ":authority", w.url.Host)
+ encKV(enc, ":path", w.url.RequestURI())
+ encodeHeaders(enc, w.h, nil)
+
+ headerBlock := buf.Bytes()
+ if len(headerBlock) == 0 {
+ panic("unexpected empty hpack")
+ }
+
+ return splitHeaderBlock(ctx, headerBlock, w.writeHeaderBlock)
+}
+
+func (w *writePushPromise) writeHeaderBlock(ctx writeContext, frag []byte, firstFrag, lastFrag bool) error {
+ if firstFrag {
+ return ctx.Framer().WritePushPromise(PushPromiseParam{
+ StreamID: w.streamID,
+ PromiseID: w.promisedID,
+ BlockFragment: frag,
+ EndHeaders: lastFrag,
+ })
+ } else {
+ return ctx.Framer().WriteContinuation(w.streamID, lastFrag, frag)
+ }
+}
+
+type write100ContinueHeadersFrame struct {
+ streamID uint32
+}
+
+func (w write100ContinueHeadersFrame) writeFrame(ctx writeContext) error {
+ enc, buf := ctx.HeaderEncoder()
+ buf.Reset()
+ encKV(enc, ":status", "100")
+ return ctx.Framer().WriteHeaders(HeadersFrameParam{
+ StreamID: w.streamID,
+ BlockFragment: buf.Bytes(),
+ EndStream: false,
+ EndHeaders: true,
+ })
+}
+
+func (w write100ContinueHeadersFrame) staysWithinBuffer(max int) bool {
+ // Sloppy but conservative:
+ return 9+2*(len(":status")+len("100")) <= max
+}
+
+type writeWindowUpdate struct {
+ streamID uint32 // or 0 for conn-level
+ n uint32
+}
+
+func (wu writeWindowUpdate) staysWithinBuffer(max int) bool { return frameHeaderLen+4 <= max }
+
+func (wu writeWindowUpdate) writeFrame(ctx writeContext) error {
+ return ctx.Framer().WriteWindowUpdate(wu.streamID, wu.n)
+}
+
+// encodeHeaders encodes an http.Header. If keys is not nil, then (k, h[k])
+// is encoded only if k is in keys.
+func encodeHeaders(enc *hpack.Encoder, h http.Header, keys []string) {
+ if keys == nil {
+ sorter := sorterPool.Get().(*sorter)
+ // Using defer here, since the returned keys from the
+ // sorter.Keys method is only valid until the sorter
+ // is returned:
+ defer sorterPool.Put(sorter)
+ keys = sorter.Keys(h)
+ }
+ for _, k := range keys {
+ vv := h[k]
+ k = lowerHeader(k)
+ if !validWireHeaderFieldName(k) {
+ // Skip it as backup paranoia. Per
+ // golang.org/issue/14048, these should
+ // already be rejected at a higher level.
+ continue
+ }
+ isTE := k == "transfer-encoding"
+ for _, v := range vv {
+ if !httpguts.ValidHeaderFieldValue(v) {
+ // TODO: return an error? golang.org/issue/14048
+ // For now just omit it.
+ continue
+ }
+ // TODO: more of "8.1.2.2 Connection-Specific Header Fields"
+ if isTE && v != "trailers" {
+ continue
+ }
+ encKV(enc, k, v)
+ }
+ }
+}
diff --git a/vendor/golang.org/x/net/http2/writesched.go b/vendor/golang.org/x/net/http2/writesched.go
new file mode 100644
index 000000000..4fe307307
--- /dev/null
+++ b/vendor/golang.org/x/net/http2/writesched.go
@@ -0,0 +1,242 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package http2
+
+import "fmt"
+
+// WriteScheduler is the interface implemented by HTTP/2 write schedulers.
+// Methods are never called concurrently.
+type WriteScheduler interface {
+ // OpenStream opens a new stream in the write scheduler.
+ // It is illegal to call this with streamID=0 or with a streamID that is
+ // already open -- the call may panic.
+ OpenStream(streamID uint32, options OpenStreamOptions)
+
+ // CloseStream closes a stream in the write scheduler. Any frames queued on
+ // this stream should be discarded. It is illegal to call this on a stream
+ // that is not open -- the call may panic.
+ CloseStream(streamID uint32)
+
+ // AdjustStream adjusts the priority of the given stream. This may be called
+ // on a stream that has not yet been opened or has been closed. Note that
+ // RFC 7540 allows PRIORITY frames to be sent on streams in any state. See:
+ // https://tools.ietf.org/html/rfc7540#section-5.1
+ AdjustStream(streamID uint32, priority PriorityParam)
+
+ // Push queues a frame in the scheduler. In most cases, this will not be
+ // called with wr.StreamID()!=0 unless that stream is currently open. The one
+ // exception is RST_STREAM frames, which may be sent on idle or closed streams.
+ Push(wr FrameWriteRequest)
+
+ // Pop dequeues the next frame to write. Returns false if no frames can
+ // be written. Frames with a given wr.StreamID() are Pop'd in the same
+ // order they are Push'd.
+ Pop() (wr FrameWriteRequest, ok bool)
+}
+
+// OpenStreamOptions specifies extra options for WriteScheduler.OpenStream.
+type OpenStreamOptions struct {
+ // PusherID is zero if the stream was initiated by the client. Otherwise,
+ // PusherID names the stream that pushed the newly opened stream.
+ PusherID uint32
+}
+
+// FrameWriteRequest is a request to write a frame.
+type FrameWriteRequest struct {
+ // write is the interface value that does the writing, once the
+ // WriteScheduler has selected this frame to write. The write
+ // functions are all defined in write.go.
+ write writeFramer
+
+ // stream is the stream on which this frame will be written.
+ // nil for non-stream frames like PING and SETTINGS.
+ stream *stream
+
+ // done, if non-nil, must be a buffered channel with space for
+ // 1 message and is sent the return value from write (or an
+ // earlier error) when the frame has been written.
+ done chan error
+}
+
+// StreamID returns the id of the stream this frame will be written to.
+// 0 is used for non-stream frames such as PING and SETTINGS.
+func (wr FrameWriteRequest) StreamID() uint32 {
+ if wr.stream == nil {
+ if se, ok := wr.write.(StreamError); ok {
+ // (*serverConn).resetStream doesn't set
+ // stream because it doesn't necessarily have
+ // one. So special case this type of write
+ // message.
+ return se.StreamID
+ }
+ return 0
+ }
+ return wr.stream.id
+}
+
+// DataSize returns the number of flow control bytes that must be consumed
+// to write this entire frame. This is 0 for non-DATA frames.
+func (wr FrameWriteRequest) DataSize() int {
+ if wd, ok := wr.write.(*writeData); ok {
+ return len(wd.p)
+ }
+ return 0
+}
+
+// Consume consumes min(n, available) bytes from this frame, where available
+// is the number of flow control bytes available on the stream. Consume returns
+// 0, 1, or 2 frames, where the integer return value gives the number of frames
+// returned.
+//
+// If flow control prevents consuming any bytes, this returns (_, _, 0). If
+// the entire frame was consumed, this returns (wr, _, 1). Otherwise, this
+// returns (consumed, rest, 2), where 'consumed' contains the consumed bytes and
+// 'rest' contains the remaining bytes. The consumed bytes are deducted from the
+// underlying stream's flow control budget.
+func (wr FrameWriteRequest) Consume(n int32) (FrameWriteRequest, FrameWriteRequest, int) {
+ var empty FrameWriteRequest
+
+ // Non-DATA frames are always consumed whole.
+ wd, ok := wr.write.(*writeData)
+ if !ok || len(wd.p) == 0 {
+ return wr, empty, 1
+ }
+
+ // Might need to split after applying limits.
+ allowed := wr.stream.flow.available()
+ if n < allowed {
+ allowed = n
+ }
+ if wr.stream.sc.maxFrameSize < allowed {
+ allowed = wr.stream.sc.maxFrameSize
+ }
+ if allowed <= 0 {
+ return empty, empty, 0
+ }
+ if len(wd.p) > int(allowed) {
+ wr.stream.flow.take(allowed)
+ consumed := FrameWriteRequest{
+ stream: wr.stream,
+ write: &writeData{
+ streamID: wd.streamID,
+ p: wd.p[:allowed],
+ // Even if the original had endStream set, there
+ // are bytes remaining because len(wd.p) > allowed,
+ // so we know endStream is false.
+ endStream: false,
+ },
+ // Our caller is blocking on the final DATA frame, not
+ // this intermediate frame, so no need to wait.
+ done: nil,
+ }
+ rest := FrameWriteRequest{
+ stream: wr.stream,
+ write: &writeData{
+ streamID: wd.streamID,
+ p: wd.p[allowed:],
+ endStream: wd.endStream,
+ },
+ done: wr.done,
+ }
+ return consumed, rest, 2
+ }
+
+ // The frame is consumed whole.
+ // NB: This cast cannot overflow because allowed is <= math.MaxInt32.
+ wr.stream.flow.take(int32(len(wd.p)))
+ return wr, empty, 1
+}
+
+// String is for debugging only.
+func (wr FrameWriteRequest) String() string {
+ var des string
+ if s, ok := wr.write.(fmt.Stringer); ok {
+ des = s.String()
+ } else {
+ des = fmt.Sprintf("%T", wr.write)
+ }
+ return fmt.Sprintf("[FrameWriteRequest stream=%d, ch=%v, writer=%v]", wr.StreamID(), wr.done != nil, des)
+}
+
+// replyToWriter sends err to wr.done and panics if the send must block
+// This does nothing if wr.done is nil.
+func (wr *FrameWriteRequest) replyToWriter(err error) {
+ if wr.done == nil {
+ return
+ }
+ select {
+ case wr.done <- err:
+ default:
+ panic(fmt.Sprintf("unbuffered done channel passed in for type %T", wr.write))
+ }
+ wr.write = nil // prevent use (assume it's tainted after wr.done send)
+}
+
+// writeQueue is used by implementations of WriteScheduler.
+type writeQueue struct {
+ s []FrameWriteRequest
+}
+
+func (q *writeQueue) empty() bool { return len(q.s) == 0 }
+
+func (q *writeQueue) push(wr FrameWriteRequest) {
+ q.s = append(q.s, wr)
+}
+
+func (q *writeQueue) shift() FrameWriteRequest {
+ if len(q.s) == 0 {
+ panic("invalid use of queue")
+ }
+ wr := q.s[0]
+ // TODO: less copy-happy queue.
+ copy(q.s, q.s[1:])
+ q.s[len(q.s)-1] = FrameWriteRequest{}
+ q.s = q.s[:len(q.s)-1]
+ return wr
+}
+
+// consume consumes up to n bytes from q.s[0]. If the frame is
+// entirely consumed, it is removed from the queue. If the frame
+// is partially consumed, the frame is kept with the consumed
+// bytes removed. Returns true iff any bytes were consumed.
+func (q *writeQueue) consume(n int32) (FrameWriteRequest, bool) {
+ if len(q.s) == 0 {
+ return FrameWriteRequest{}, false
+ }
+ consumed, rest, numresult := q.s[0].Consume(n)
+ switch numresult {
+ case 0:
+ return FrameWriteRequest{}, false
+ case 1:
+ q.shift()
+ case 2:
+ q.s[0] = rest
+ }
+ return consumed, true
+}
+
+type writeQueuePool []*writeQueue
+
+// put inserts an unused writeQueue into the pool.
+func (p *writeQueuePool) put(q *writeQueue) {
+ for i := range q.s {
+ q.s[i] = FrameWriteRequest{}
+ }
+ q.s = q.s[:0]
+ *p = append(*p, q)
+}
+
+// get returns an empty writeQueue.
+func (p *writeQueuePool) get() *writeQueue {
+ ln := len(*p)
+ if ln == 0 {
+ return new(writeQueue)
+ }
+ x := ln - 1
+ q := (*p)[x]
+ (*p)[x] = nil
+ *p = (*p)[:x]
+ return q
+}
diff --git a/vendor/golang.org/x/net/http2/writesched_priority.go b/vendor/golang.org/x/net/http2/writesched_priority.go
new file mode 100644
index 000000000..848fed6ec
--- /dev/null
+++ b/vendor/golang.org/x/net/http2/writesched_priority.go
@@ -0,0 +1,452 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package http2
+
+import (
+ "fmt"
+ "math"
+ "sort"
+)
+
+// RFC 7540, Section 5.3.5: the default weight is 16.
+const priorityDefaultWeight = 15 // 16 = 15 + 1
+
+// PriorityWriteSchedulerConfig configures a priorityWriteScheduler.
+type PriorityWriteSchedulerConfig struct {
+ // MaxClosedNodesInTree controls the maximum number of closed streams to
+ // retain in the priority tree. Setting this to zero saves a small amount
+ // of memory at the cost of performance.
+ //
+ // See RFC 7540, Section 5.3.4:
+ // "It is possible for a stream to become closed while prioritization
+ // information ... is in transit. ... This potentially creates suboptimal
+ // prioritization, since the stream could be given a priority that is
+ // different from what is intended. To avoid these problems, an endpoint
+ // SHOULD retain stream prioritization state for a period after streams
+ // become closed. The longer state is retained, the lower the chance that
+ // streams are assigned incorrect or default priority values."
+ MaxClosedNodesInTree int
+
+ // MaxIdleNodesInTree controls the maximum number of idle streams to
+ // retain in the priority tree. Setting this to zero saves a small amount
+ // of memory at the cost of performance.
+ //
+ // See RFC 7540, Section 5.3.4:
+ // Similarly, streams that are in the "idle" state can be assigned
+ // priority or become a parent of other streams. This allows for the
+ // creation of a grouping node in the dependency tree, which enables
+ // more flexible expressions of priority. Idle streams begin with a
+ // default priority (Section 5.3.5).
+ MaxIdleNodesInTree int
+
+ // ThrottleOutOfOrderWrites enables write throttling to help ensure that
+ // data is delivered in priority order. This works around a race where
+ // stream B depends on stream A and both streams are about to call Write
+ // to queue DATA frames. If B wins the race, a naive scheduler would eagerly
+ // write as much data from B as possible, but this is suboptimal because A
+ // is a higher-priority stream. With throttling enabled, we write a small
+ // amount of data from B to minimize the amount of bandwidth that B can
+ // steal from A.
+ ThrottleOutOfOrderWrites bool
+}
+
+// NewPriorityWriteScheduler constructs a WriteScheduler that schedules
+// frames by following HTTP/2 priorities as described in RFC 7540 Section 5.3.
+// If cfg is nil, default options are used.
+func NewPriorityWriteScheduler(cfg *PriorityWriteSchedulerConfig) WriteScheduler {
+ if cfg == nil {
+ // For justification of these defaults, see:
+ // https://docs.google.com/document/d/1oLhNg1skaWD4_DtaoCxdSRN5erEXrH-KnLrMwEpOtFY
+ cfg = &PriorityWriteSchedulerConfig{
+ MaxClosedNodesInTree: 10,
+ MaxIdleNodesInTree: 10,
+ ThrottleOutOfOrderWrites: false,
+ }
+ }
+
+ ws := &priorityWriteScheduler{
+ nodes: make(map[uint32]*priorityNode),
+ maxClosedNodesInTree: cfg.MaxClosedNodesInTree,
+ maxIdleNodesInTree: cfg.MaxIdleNodesInTree,
+ enableWriteThrottle: cfg.ThrottleOutOfOrderWrites,
+ }
+ ws.nodes[0] = &ws.root
+ if cfg.ThrottleOutOfOrderWrites {
+ ws.writeThrottleLimit = 1024
+ } else {
+ ws.writeThrottleLimit = math.MaxInt32
+ }
+ return ws
+}
+
+type priorityNodeState int
+
+const (
+ priorityNodeOpen priorityNodeState = iota
+ priorityNodeClosed
+ priorityNodeIdle
+)
+
+// priorityNode is a node in an HTTP/2 priority tree.
+// Each node is associated with a single stream ID.
+// See RFC 7540, Section 5.3.
+type priorityNode struct {
+ q writeQueue // queue of pending frames to write
+ id uint32 // id of the stream, or 0 for the root of the tree
+ weight uint8 // the actual weight is weight+1, so the value is in [1,256]
+ state priorityNodeState // open | closed | idle
+ bytes int64 // number of bytes written by this node, or 0 if closed
+ subtreeBytes int64 // sum(node.bytes) of all nodes in this subtree
+
+ // These links form the priority tree.
+ parent *priorityNode
+ kids *priorityNode // start of the kids list
+ prev, next *priorityNode // doubly-linked list of siblings
+}
+
+func (n *priorityNode) setParent(parent *priorityNode) {
+ if n == parent {
+ panic("setParent to self")
+ }
+ if n.parent == parent {
+ return
+ }
+ // Unlink from current parent.
+ if parent := n.parent; parent != nil {
+ if n.prev == nil {
+ parent.kids = n.next
+ } else {
+ n.prev.next = n.next
+ }
+ if n.next != nil {
+ n.next.prev = n.prev
+ }
+ }
+ // Link to new parent.
+ // If parent=nil, remove n from the tree.
+ // Always insert at the head of parent.kids (this is assumed by walkReadyInOrder).
+ n.parent = parent
+ if parent == nil {
+ n.next = nil
+ n.prev = nil
+ } else {
+ n.next = parent.kids
+ n.prev = nil
+ if n.next != nil {
+ n.next.prev = n
+ }
+ parent.kids = n
+ }
+}
+
+func (n *priorityNode) addBytes(b int64) {
+ n.bytes += b
+ for ; n != nil; n = n.parent {
+ n.subtreeBytes += b
+ }
+}
+
+// walkReadyInOrder iterates over the tree in priority order, calling f for each node
+// with a non-empty write queue. When f returns true, this funcion returns true and the
+// walk halts. tmp is used as scratch space for sorting.
+//
+// f(n, openParent) takes two arguments: the node to visit, n, and a bool that is true
+// if any ancestor p of n is still open (ignoring the root node).
+func (n *priorityNode) walkReadyInOrder(openParent bool, tmp *[]*priorityNode, f func(*priorityNode, bool) bool) bool {
+ if !n.q.empty() && f(n, openParent) {
+ return true
+ }
+ if n.kids == nil {
+ return false
+ }
+
+ // Don't consider the root "open" when updating openParent since
+ // we can't send data frames on the root stream (only control frames).
+ if n.id != 0 {
+ openParent = openParent || (n.state == priorityNodeOpen)
+ }
+
+ // Common case: only one kid or all kids have the same weight.
+ // Some clients don't use weights; other clients (like web browsers)
+ // use mostly-linear priority trees.
+ w := n.kids.weight
+ needSort := false
+ for k := n.kids.next; k != nil; k = k.next {
+ if k.weight != w {
+ needSort = true
+ break
+ }
+ }
+ if !needSort {
+ for k := n.kids; k != nil; k = k.next {
+ if k.walkReadyInOrder(openParent, tmp, f) {
+ return true
+ }
+ }
+ return false
+ }
+
+ // Uncommon case: sort the child nodes. We remove the kids from the parent,
+ // then re-insert after sorting so we can reuse tmp for future sort calls.
+ *tmp = (*tmp)[:0]
+ for n.kids != nil {
+ *tmp = append(*tmp, n.kids)
+ n.kids.setParent(nil)
+ }
+ sort.Sort(sortPriorityNodeSiblings(*tmp))
+ for i := len(*tmp) - 1; i >= 0; i-- {
+ (*tmp)[i].setParent(n) // setParent inserts at the head of n.kids
+ }
+ for k := n.kids; k != nil; k = k.next {
+ if k.walkReadyInOrder(openParent, tmp, f) {
+ return true
+ }
+ }
+ return false
+}
+
+type sortPriorityNodeSiblings []*priorityNode
+
+func (z sortPriorityNodeSiblings) Len() int { return len(z) }
+func (z sortPriorityNodeSiblings) Swap(i, k int) { z[i], z[k] = z[k], z[i] }
+func (z sortPriorityNodeSiblings) Less(i, k int) bool {
+ // Prefer the subtree that has sent fewer bytes relative to its weight.
+ // See sections 5.3.2 and 5.3.4.
+ wi, bi := float64(z[i].weight+1), float64(z[i].subtreeBytes)
+ wk, bk := float64(z[k].weight+1), float64(z[k].subtreeBytes)
+ if bi == 0 && bk == 0 {
+ return wi >= wk
+ }
+ if bk == 0 {
+ return false
+ }
+ return bi/bk <= wi/wk
+}
+
+type priorityWriteScheduler struct {
+ // root is the root of the priority tree, where root.id = 0.
+ // The root queues control frames that are not associated with any stream.
+ root priorityNode
+
+ // nodes maps stream ids to priority tree nodes.
+ nodes map[uint32]*priorityNode
+
+ // maxID is the maximum stream id in nodes.
+ maxID uint32
+
+ // lists of nodes that have been closed or are idle, but are kept in
+ // the tree for improved prioritization. When the lengths exceed either
+ // maxClosedNodesInTree or maxIdleNodesInTree, old nodes are discarded.
+ closedNodes, idleNodes []*priorityNode
+
+ // From the config.
+ maxClosedNodesInTree int
+ maxIdleNodesInTree int
+ writeThrottleLimit int32
+ enableWriteThrottle bool
+
+ // tmp is scratch space for priorityNode.walkReadyInOrder to reduce allocations.
+ tmp []*priorityNode
+
+ // pool of empty queues for reuse.
+ queuePool writeQueuePool
+}
+
+func (ws *priorityWriteScheduler) OpenStream(streamID uint32, options OpenStreamOptions) {
+ // The stream may be currently idle but cannot be opened or closed.
+ if curr := ws.nodes[streamID]; curr != nil {
+ if curr.state != priorityNodeIdle {
+ panic(fmt.Sprintf("stream %d already opened", streamID))
+ }
+ curr.state = priorityNodeOpen
+ return
+ }
+
+ // RFC 7540, Section 5.3.5:
+ // "All streams are initially assigned a non-exclusive dependency on stream 0x0.
+ // Pushed streams initially depend on their associated stream. In both cases,
+ // streams are assigned a default weight of 16."
+ parent := ws.nodes[options.PusherID]
+ if parent == nil {
+ parent = &ws.root
+ }
+ n := &priorityNode{
+ q: *ws.queuePool.get(),
+ id: streamID,
+ weight: priorityDefaultWeight,
+ state: priorityNodeOpen,
+ }
+ n.setParent(parent)
+ ws.nodes[streamID] = n
+ if streamID > ws.maxID {
+ ws.maxID = streamID
+ }
+}
+
+func (ws *priorityWriteScheduler) CloseStream(streamID uint32) {
+ if streamID == 0 {
+ panic("violation of WriteScheduler interface: cannot close stream 0")
+ }
+ if ws.nodes[streamID] == nil {
+ panic(fmt.Sprintf("violation of WriteScheduler interface: unknown stream %d", streamID))
+ }
+ if ws.nodes[streamID].state != priorityNodeOpen {
+ panic(fmt.Sprintf("violation of WriteScheduler interface: stream %d already closed", streamID))
+ }
+
+ n := ws.nodes[streamID]
+ n.state = priorityNodeClosed
+ n.addBytes(-n.bytes)
+
+ q := n.q
+ ws.queuePool.put(&q)
+ n.q.s = nil
+ if ws.maxClosedNodesInTree > 0 {
+ ws.addClosedOrIdleNode(&ws.closedNodes, ws.maxClosedNodesInTree, n)
+ } else {
+ ws.removeNode(n)
+ }
+}
+
+func (ws *priorityWriteScheduler) AdjustStream(streamID uint32, priority PriorityParam) {
+ if streamID == 0 {
+ panic("adjustPriority on root")
+ }
+
+ // If streamID does not exist, there are two cases:
+ // - A closed stream that has been removed (this will have ID <= maxID)
+ // - An idle stream that is being used for "grouping" (this will have ID > maxID)
+ n := ws.nodes[streamID]
+ if n == nil {
+ if streamID <= ws.maxID || ws.maxIdleNodesInTree == 0 {
+ return
+ }
+ ws.maxID = streamID
+ n = &priorityNode{
+ q: *ws.queuePool.get(),
+ id: streamID,
+ weight: priorityDefaultWeight,
+ state: priorityNodeIdle,
+ }
+ n.setParent(&ws.root)
+ ws.nodes[streamID] = n
+ ws.addClosedOrIdleNode(&ws.idleNodes, ws.maxIdleNodesInTree, n)
+ }
+
+ // Section 5.3.1: A dependency on a stream that is not currently in the tree
+ // results in that stream being given a default priority (Section 5.3.5).
+ parent := ws.nodes[priority.StreamDep]
+ if parent == nil {
+ n.setParent(&ws.root)
+ n.weight = priorityDefaultWeight
+ return
+ }
+
+ // Ignore if the client tries to make a node its own parent.
+ if n == parent {
+ return
+ }
+
+ // Section 5.3.3:
+ // "If a stream is made dependent on one of its own dependencies, the
+ // formerly dependent stream is first moved to be dependent on the
+ // reprioritized stream's previous parent. The moved dependency retains
+ // its weight."
+ //
+ // That is: if parent depends on n, move parent to depend on n.parent.
+ for x := parent.parent; x != nil; x = x.parent {
+ if x == n {
+ parent.setParent(n.parent)
+ break
+ }
+ }
+
+ // Section 5.3.3: The exclusive flag causes the stream to become the sole
+ // dependency of its parent stream, causing other dependencies to become
+ // dependent on the exclusive stream.
+ if priority.Exclusive {
+ k := parent.kids
+ for k != nil {
+ next := k.next
+ if k != n {
+ k.setParent(n)
+ }
+ k = next
+ }
+ }
+
+ n.setParent(parent)
+ n.weight = priority.Weight
+}
+
+func (ws *priorityWriteScheduler) Push(wr FrameWriteRequest) {
+ var n *priorityNode
+ if id := wr.StreamID(); id == 0 {
+ n = &ws.root
+ } else {
+ n = ws.nodes[id]
+ if n == nil {
+ // id is an idle or closed stream. wr should not be a HEADERS or
+ // DATA frame. However, wr can be a RST_STREAM. In this case, we
+ // push wr onto the root, rather than creating a new priorityNode,
+ // since RST_STREAM is tiny and the stream's priority is unknown
+ // anyway. See issue #17919.
+ if wr.DataSize() > 0 {
+ panic("add DATA on non-open stream")
+ }
+ n = &ws.root
+ }
+ }
+ n.q.push(wr)
+}
+
+func (ws *priorityWriteScheduler) Pop() (wr FrameWriteRequest, ok bool) {
+ ws.root.walkReadyInOrder(false, &ws.tmp, func(n *priorityNode, openParent bool) bool {
+ limit := int32(math.MaxInt32)
+ if openParent {
+ limit = ws.writeThrottleLimit
+ }
+ wr, ok = n.q.consume(limit)
+ if !ok {
+ return false
+ }
+ n.addBytes(int64(wr.DataSize()))
+ // If B depends on A and B continuously has data available but A
+ // does not, gradually increase the throttling limit to allow B to
+ // steal more and more bandwidth from A.
+ if openParent {
+ ws.writeThrottleLimit += 1024
+ if ws.writeThrottleLimit < 0 {
+ ws.writeThrottleLimit = math.MaxInt32
+ }
+ } else if ws.enableWriteThrottle {
+ ws.writeThrottleLimit = 1024
+ }
+ return true
+ })
+ return wr, ok
+}
+
+func (ws *priorityWriteScheduler) addClosedOrIdleNode(list *[]*priorityNode, maxSize int, n *priorityNode) {
+ if maxSize == 0 {
+ return
+ }
+ if len(*list) == maxSize {
+ // Remove the oldest node, then shift left.
+ ws.removeNode((*list)[0])
+ x := (*list)[1:]
+ copy(*list, x)
+ *list = (*list)[:len(x)]
+ }
+ *list = append(*list, n)
+}
+
+func (ws *priorityWriteScheduler) removeNode(n *priorityNode) {
+ for k := n.kids; k != nil; k = k.next {
+ k.setParent(n.parent)
+ }
+ n.setParent(nil)
+ delete(ws.nodes, n.id)
+}
diff --git a/vendor/golang.org/x/net/http2/writesched_random.go b/vendor/golang.org/x/net/http2/writesched_random.go
new file mode 100644
index 000000000..36d7919f1
--- /dev/null
+++ b/vendor/golang.org/x/net/http2/writesched_random.go
@@ -0,0 +1,72 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package http2
+
+import "math"
+
+// NewRandomWriteScheduler constructs a WriteScheduler that ignores HTTP/2
+// priorities. Control frames like SETTINGS and PING are written before DATA
+// frames, but if no control frames are queued and multiple streams have queued
+// HEADERS or DATA frames, Pop selects a ready stream arbitrarily.
+func NewRandomWriteScheduler() WriteScheduler {
+ return &randomWriteScheduler{sq: make(map[uint32]*writeQueue)}
+}
+
+type randomWriteScheduler struct {
+ // zero are frames not associated with a specific stream.
+ zero writeQueue
+
+ // sq contains the stream-specific queues, keyed by stream ID.
+ // When a stream is idle or closed, it's deleted from the map.
+ sq map[uint32]*writeQueue
+
+ // pool of empty queues for reuse.
+ queuePool writeQueuePool
+}
+
+func (ws *randomWriteScheduler) OpenStream(streamID uint32, options OpenStreamOptions) {
+ // no-op: idle streams are not tracked
+}
+
+func (ws *randomWriteScheduler) CloseStream(streamID uint32) {
+ q, ok := ws.sq[streamID]
+ if !ok {
+ return
+ }
+ delete(ws.sq, streamID)
+ ws.queuePool.put(q)
+}
+
+func (ws *randomWriteScheduler) AdjustStream(streamID uint32, priority PriorityParam) {
+ // no-op: priorities are ignored
+}
+
+func (ws *randomWriteScheduler) Push(wr FrameWriteRequest) {
+ id := wr.StreamID()
+ if id == 0 {
+ ws.zero.push(wr)
+ return
+ }
+ q, ok := ws.sq[id]
+ if !ok {
+ q = ws.queuePool.get()
+ ws.sq[id] = q
+ }
+ q.push(wr)
+}
+
+func (ws *randomWriteScheduler) Pop() (FrameWriteRequest, bool) {
+ // Control frames first.
+ if !ws.zero.empty() {
+ return ws.zero.shift(), true
+ }
+ // Iterate over all non-idle streams until finding one that can be consumed.
+ for _, q := range ws.sq {
+ if wr, ok := q.consume(math.MaxInt32); ok {
+ return wr, true
+ }
+ }
+ return FrameWriteRequest{}, false
+}
diff --git a/vendor/golang.org/x/net/internal/timeseries/timeseries.go b/vendor/golang.org/x/net/internal/timeseries/timeseries.go
new file mode 100644
index 000000000..685f0e7ea
--- /dev/null
+++ b/vendor/golang.org/x/net/internal/timeseries/timeseries.go
@@ -0,0 +1,525 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package timeseries implements a time series structure for stats collection.
+package timeseries // import "golang.org/x/net/internal/timeseries"
+
+import (
+ "fmt"
+ "log"
+ "time"
+)
+
+const (
+ timeSeriesNumBuckets = 64
+ minuteHourSeriesNumBuckets = 60
+)
+
+var timeSeriesResolutions = []time.Duration{
+ 1 * time.Second,
+ 10 * time.Second,
+ 1 * time.Minute,
+ 10 * time.Minute,
+ 1 * time.Hour,
+ 6 * time.Hour,
+ 24 * time.Hour, // 1 day
+ 7 * 24 * time.Hour, // 1 week
+ 4 * 7 * 24 * time.Hour, // 4 weeks
+ 16 * 7 * 24 * time.Hour, // 16 weeks
+}
+
+var minuteHourSeriesResolutions = []time.Duration{
+ 1 * time.Second,
+ 1 * time.Minute,
+}
+
+// An Observable is a kind of data that can be aggregated in a time series.
+type Observable interface {
+ Multiply(ratio float64) // Multiplies the data in self by a given ratio
+ Add(other Observable) // Adds the data from a different observation to self
+ Clear() // Clears the observation so it can be reused.
+ CopyFrom(other Observable) // Copies the contents of a given observation to self
+}
+
+// Float attaches the methods of Observable to a float64.
+type Float float64
+
+// NewFloat returns a Float.
+func NewFloat() Observable {
+ f := Float(0)
+ return &f
+}
+
+// String returns the float as a string.
+func (f *Float) String() string { return fmt.Sprintf("%g", f.Value()) }
+
+// Value returns the float's value.
+func (f *Float) Value() float64 { return float64(*f) }
+
+func (f *Float) Multiply(ratio float64) { *f *= Float(ratio) }
+
+func (f *Float) Add(other Observable) {
+ o := other.(*Float)
+ *f += *o
+}
+
+func (f *Float) Clear() { *f = 0 }
+
+func (f *Float) CopyFrom(other Observable) {
+ o := other.(*Float)
+ *f = *o
+}
+
+// A Clock tells the current time.
+type Clock interface {
+ Time() time.Time
+}
+
+type defaultClock int
+
+var defaultClockInstance defaultClock
+
+func (defaultClock) Time() time.Time { return time.Now() }
+
+// Information kept per level. Each level consists of a circular list of
+// observations. The start of the level may be derived from end and the
+// len(buckets) * sizeInMillis.
+type tsLevel struct {
+ oldest int // index to oldest bucketed Observable
+ newest int // index to newest bucketed Observable
+ end time.Time // end timestamp for this level
+ size time.Duration // duration of the bucketed Observable
+ buckets []Observable // collections of observations
+ provider func() Observable // used for creating new Observable
+}
+
+func (l *tsLevel) Clear() {
+ l.oldest = 0
+ l.newest = len(l.buckets) - 1
+ l.end = time.Time{}
+ for i := range l.buckets {
+ if l.buckets[i] != nil {
+ l.buckets[i].Clear()
+ l.buckets[i] = nil
+ }
+ }
+}
+
+func (l *tsLevel) InitLevel(size time.Duration, numBuckets int, f func() Observable) {
+ l.size = size
+ l.provider = f
+ l.buckets = make([]Observable, numBuckets)
+}
+
+// Keeps a sequence of levels. Each level is responsible for storing data at
+// a given resolution. For example, the first level stores data at a one
+// minute resolution while the second level stores data at a one hour
+// resolution.
+
+// Each level is represented by a sequence of buckets. Each bucket spans an
+// interval equal to the resolution of the level. New observations are added
+// to the last bucket.
+type timeSeries struct {
+ provider func() Observable // make more Observable
+ numBuckets int // number of buckets in each level
+ levels []*tsLevel // levels of bucketed Observable
+ lastAdd time.Time // time of last Observable tracked
+ total Observable // convenient aggregation of all Observable
+ clock Clock // Clock for getting current time
+ pending Observable // observations not yet bucketed
+ pendingTime time.Time // what time are we keeping in pending
+ dirty bool // if there are pending observations
+}
+
+// init initializes a level according to the supplied criteria.
+func (ts *timeSeries) init(resolutions []time.Duration, f func() Observable, numBuckets int, clock Clock) {
+ ts.provider = f
+ ts.numBuckets = numBuckets
+ ts.clock = clock
+ ts.levels = make([]*tsLevel, len(resolutions))
+
+ for i := range resolutions {
+ if i > 0 && resolutions[i-1] >= resolutions[i] {
+ log.Print("timeseries: resolutions must be monotonically increasing")
+ break
+ }
+ newLevel := new(tsLevel)
+ newLevel.InitLevel(resolutions[i], ts.numBuckets, ts.provider)
+ ts.levels[i] = newLevel
+ }
+
+ ts.Clear()
+}
+
+// Clear removes all observations from the time series.
+func (ts *timeSeries) Clear() {
+ ts.lastAdd = time.Time{}
+ ts.total = ts.resetObservation(ts.total)
+ ts.pending = ts.resetObservation(ts.pending)
+ ts.pendingTime = time.Time{}
+ ts.dirty = false
+
+ for i := range ts.levels {
+ ts.levels[i].Clear()
+ }
+}
+
+// Add records an observation at the current time.
+func (ts *timeSeries) Add(observation Observable) {
+ ts.AddWithTime(observation, ts.clock.Time())
+}
+
+// AddWithTime records an observation at the specified time.
+func (ts *timeSeries) AddWithTime(observation Observable, t time.Time) {
+
+ smallBucketDuration := ts.levels[0].size
+
+ if t.After(ts.lastAdd) {
+ ts.lastAdd = t
+ }
+
+ if t.After(ts.pendingTime) {
+ ts.advance(t)
+ ts.mergePendingUpdates()
+ ts.pendingTime = ts.levels[0].end
+ ts.pending.CopyFrom(observation)
+ ts.dirty = true
+ } else if t.After(ts.pendingTime.Add(-1 * smallBucketDuration)) {
+ // The observation is close enough to go into the pending bucket.
+ // This compensates for clock skewing and small scheduling delays
+ // by letting the update stay in the fast path.
+ ts.pending.Add(observation)
+ ts.dirty = true
+ } else {
+ ts.mergeValue(observation, t)
+ }
+}
+
+// mergeValue inserts the observation at the specified time in the past into all levels.
+func (ts *timeSeries) mergeValue(observation Observable, t time.Time) {
+ for _, level := range ts.levels {
+ index := (ts.numBuckets - 1) - int(level.end.Sub(t)/level.size)
+ if 0 <= index && index < ts.numBuckets {
+ bucketNumber := (level.oldest + index) % ts.numBuckets
+ if level.buckets[bucketNumber] == nil {
+ level.buckets[bucketNumber] = level.provider()
+ }
+ level.buckets[bucketNumber].Add(observation)
+ }
+ }
+ ts.total.Add(observation)
+}
+
+// mergePendingUpdates applies the pending updates into all levels.
+func (ts *timeSeries) mergePendingUpdates() {
+ if ts.dirty {
+ ts.mergeValue(ts.pending, ts.pendingTime)
+ ts.pending = ts.resetObservation(ts.pending)
+ ts.dirty = false
+ }
+}
+
+// advance cycles the buckets at each level until the latest bucket in
+// each level can hold the time specified.
+func (ts *timeSeries) advance(t time.Time) {
+ if !t.After(ts.levels[0].end) {
+ return
+ }
+ for i := 0; i < len(ts.levels); i++ {
+ level := ts.levels[i]
+ if !level.end.Before(t) {
+ break
+ }
+
+ // If the time is sufficiently far, just clear the level and advance
+ // directly.
+ if !t.Before(level.end.Add(level.size * time.Duration(ts.numBuckets))) {
+ for _, b := range level.buckets {
+ ts.resetObservation(b)
+ }
+ level.end = time.Unix(0, (t.UnixNano()/level.size.Nanoseconds())*level.size.Nanoseconds())
+ }
+
+ for t.After(level.end) {
+ level.end = level.end.Add(level.size)
+ level.newest = level.oldest
+ level.oldest = (level.oldest + 1) % ts.numBuckets
+ ts.resetObservation(level.buckets[level.newest])
+ }
+
+ t = level.end
+ }
+}
+
+// Latest returns the sum of the num latest buckets from the level.
+func (ts *timeSeries) Latest(level, num int) Observable {
+ now := ts.clock.Time()
+ if ts.levels[0].end.Before(now) {
+ ts.advance(now)
+ }
+
+ ts.mergePendingUpdates()
+
+ result := ts.provider()
+ l := ts.levels[level]
+ index := l.newest
+
+ for i := 0; i < num; i++ {
+ if l.buckets[index] != nil {
+ result.Add(l.buckets[index])
+ }
+ if index == 0 {
+ index = ts.numBuckets
+ }
+ index--
+ }
+
+ return result
+}
+
+// LatestBuckets returns a copy of the num latest buckets from level.
+func (ts *timeSeries) LatestBuckets(level, num int) []Observable {
+ if level < 0 || level > len(ts.levels) {
+ log.Print("timeseries: bad level argument: ", level)
+ return nil
+ }
+ if num < 0 || num >= ts.numBuckets {
+ log.Print("timeseries: bad num argument: ", num)
+ return nil
+ }
+
+ results := make([]Observable, num)
+ now := ts.clock.Time()
+ if ts.levels[0].end.Before(now) {
+ ts.advance(now)
+ }
+
+ ts.mergePendingUpdates()
+
+ l := ts.levels[level]
+ index := l.newest
+
+ for i := 0; i < num; i++ {
+ result := ts.provider()
+ results[i] = result
+ if l.buckets[index] != nil {
+ result.CopyFrom(l.buckets[index])
+ }
+
+ if index == 0 {
+ index = ts.numBuckets
+ }
+ index -= 1
+ }
+ return results
+}
+
+// ScaleBy updates observations by scaling by factor.
+func (ts *timeSeries) ScaleBy(factor float64) {
+ for _, l := range ts.levels {
+ for i := 0; i < ts.numBuckets; i++ {
+ l.buckets[i].Multiply(factor)
+ }
+ }
+
+ ts.total.Multiply(factor)
+ ts.pending.Multiply(factor)
+}
+
+// Range returns the sum of observations added over the specified time range.
+// If start or finish times don't fall on bucket boundaries of the same
+// level, then return values are approximate answers.
+func (ts *timeSeries) Range(start, finish time.Time) Observable {
+ return ts.ComputeRange(start, finish, 1)[0]
+}
+
+// Recent returns the sum of observations from the last delta.
+func (ts *timeSeries) Recent(delta time.Duration) Observable {
+ now := ts.clock.Time()
+ return ts.Range(now.Add(-delta), now)
+}
+
+// Total returns the total of all observations.
+func (ts *timeSeries) Total() Observable {
+ ts.mergePendingUpdates()
+ return ts.total
+}
+
+// ComputeRange computes a specified number of values into a slice using
+// the observations recorded over the specified time period. The return
+// values are approximate if the start or finish times don't fall on the
+// bucket boundaries at the same level or if the number of buckets spanning
+// the range is not an integral multiple of num.
+func (ts *timeSeries) ComputeRange(start, finish time.Time, num int) []Observable {
+ if start.After(finish) {
+ log.Printf("timeseries: start > finish, %v>%v", start, finish)
+ return nil
+ }
+
+ if num < 0 {
+ log.Printf("timeseries: num < 0, %v", num)
+ return nil
+ }
+
+ results := make([]Observable, num)
+
+ for _, l := range ts.levels {
+ if !start.Before(l.end.Add(-l.size * time.Duration(ts.numBuckets))) {
+ ts.extract(l, start, finish, num, results)
+ return results
+ }
+ }
+
+ // Failed to find a level that covers the desired range. So just
+ // extract from the last level, even if it doesn't cover the entire
+ // desired range.
+ ts.extract(ts.levels[len(ts.levels)-1], start, finish, num, results)
+
+ return results
+}
+
+// RecentList returns the specified number of values in slice over the most
+// recent time period of the specified range.
+func (ts *timeSeries) RecentList(delta time.Duration, num int) []Observable {
+ if delta < 0 {
+ return nil
+ }
+ now := ts.clock.Time()
+ return ts.ComputeRange(now.Add(-delta), now, num)
+}
+
+// extract returns a slice of specified number of observations from a given
+// level over a given range.
+func (ts *timeSeries) extract(l *tsLevel, start, finish time.Time, num int, results []Observable) {
+ ts.mergePendingUpdates()
+
+ srcInterval := l.size
+ dstInterval := finish.Sub(start) / time.Duration(num)
+ dstStart := start
+ srcStart := l.end.Add(-srcInterval * time.Duration(ts.numBuckets))
+
+ srcIndex := 0
+
+ // Where should scanning start?
+ if dstStart.After(srcStart) {
+ advance := dstStart.Sub(srcStart) / srcInterval
+ srcIndex += int(advance)
+ srcStart = srcStart.Add(advance * srcInterval)
+ }
+
+ // The i'th value is computed as show below.
+ // interval = (finish/start)/num
+ // i'th value = sum of observation in range
+ // [ start + i * interval,
+ // start + (i + 1) * interval )
+ for i := 0; i < num; i++ {
+ results[i] = ts.resetObservation(results[i])
+ dstEnd := dstStart.Add(dstInterval)
+ for srcIndex < ts.numBuckets && srcStart.Before(dstEnd) {
+ srcEnd := srcStart.Add(srcInterval)
+ if srcEnd.After(ts.lastAdd) {
+ srcEnd = ts.lastAdd
+ }
+
+ if !srcEnd.Before(dstStart) {
+ srcValue := l.buckets[(srcIndex+l.oldest)%ts.numBuckets]
+ if !srcStart.Before(dstStart) && !srcEnd.After(dstEnd) {
+ // dst completely contains src.
+ if srcValue != nil {
+ results[i].Add(srcValue)
+ }
+ } else {
+ // dst partially overlaps src.
+ overlapStart := maxTime(srcStart, dstStart)
+ overlapEnd := minTime(srcEnd, dstEnd)
+ base := srcEnd.Sub(srcStart)
+ fraction := overlapEnd.Sub(overlapStart).Seconds() / base.Seconds()
+
+ used := ts.provider()
+ if srcValue != nil {
+ used.CopyFrom(srcValue)
+ }
+ used.Multiply(fraction)
+ results[i].Add(used)
+ }
+
+ if srcEnd.After(dstEnd) {
+ break
+ }
+ }
+ srcIndex++
+ srcStart = srcStart.Add(srcInterval)
+ }
+ dstStart = dstStart.Add(dstInterval)
+ }
+}
+
+// resetObservation clears the content so the struct may be reused.
+func (ts *timeSeries) resetObservation(observation Observable) Observable {
+ if observation == nil {
+ observation = ts.provider()
+ } else {
+ observation.Clear()
+ }
+ return observation
+}
+
+// TimeSeries tracks data at granularities from 1 second to 16 weeks.
+type TimeSeries struct {
+ timeSeries
+}
+
+// NewTimeSeries creates a new TimeSeries using the function provided for creating new Observable.
+func NewTimeSeries(f func() Observable) *TimeSeries {
+ return NewTimeSeriesWithClock(f, defaultClockInstance)
+}
+
+// NewTimeSeriesWithClock creates a new TimeSeries using the function provided for creating new Observable and the clock for
+// assigning timestamps.
+func NewTimeSeriesWithClock(f func() Observable, clock Clock) *TimeSeries {
+ ts := new(TimeSeries)
+ ts.timeSeries.init(timeSeriesResolutions, f, timeSeriesNumBuckets, clock)
+ return ts
+}
+
+// MinuteHourSeries tracks data at granularities of 1 minute and 1 hour.
+type MinuteHourSeries struct {
+ timeSeries
+}
+
+// NewMinuteHourSeries creates a new MinuteHourSeries using the function provided for creating new Observable.
+func NewMinuteHourSeries(f func() Observable) *MinuteHourSeries {
+ return NewMinuteHourSeriesWithClock(f, defaultClockInstance)
+}
+
+// NewMinuteHourSeriesWithClock creates a new MinuteHourSeries using the function provided for creating new Observable and the clock for
+// assigning timestamps.
+func NewMinuteHourSeriesWithClock(f func() Observable, clock Clock) *MinuteHourSeries {
+ ts := new(MinuteHourSeries)
+ ts.timeSeries.init(minuteHourSeriesResolutions, f,
+ minuteHourSeriesNumBuckets, clock)
+ return ts
+}
+
+func (ts *MinuteHourSeries) Minute() Observable {
+ return ts.timeSeries.Latest(0, 60)
+}
+
+func (ts *MinuteHourSeries) Hour() Observable {
+ return ts.timeSeries.Latest(1, 60)
+}
+
+func minTime(a, b time.Time) time.Time {
+ if a.Before(b) {
+ return a
+ }
+ return b
+}
+
+func maxTime(a, b time.Time) time.Time {
+ if a.After(b) {
+ return a
+ }
+ return b
+}
diff --git a/vendor/golang.org/x/net/trace/events.go b/vendor/golang.org/x/net/trace/events.go
new file mode 100644
index 000000000..c646a6952
--- /dev/null
+++ b/vendor/golang.org/x/net/trace/events.go
@@ -0,0 +1,532 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package trace
+
+import (
+ "bytes"
+ "fmt"
+ "html/template"
+ "io"
+ "log"
+ "net/http"
+ "runtime"
+ "sort"
+ "strconv"
+ "strings"
+ "sync"
+ "sync/atomic"
+ "text/tabwriter"
+ "time"
+)
+
+const maxEventsPerLog = 100
+
+type bucket struct {
+ MaxErrAge time.Duration
+ String string
+}
+
+var buckets = []bucket{
+ {0, "total"},
+ {10 * time.Second, "errs<10s"},
+ {1 * time.Minute, "errs<1m"},
+ {10 * time.Minute, "errs<10m"},
+ {1 * time.Hour, "errs<1h"},
+ {10 * time.Hour, "errs<10h"},
+ {24000 * time.Hour, "errors"},
+}
+
+// RenderEvents renders the HTML page typically served at /debug/events.
+// It does not do any auth checking. The request may be nil.
+//
+// Most users will use the Events handler.
+func RenderEvents(w http.ResponseWriter, req *http.Request, sensitive bool) {
+ now := time.Now()
+ data := &struct {
+ Families []string // family names
+ Buckets []bucket
+ Counts [][]int // eventLog count per family/bucket
+
+ // Set when a bucket has been selected.
+ Family string
+ Bucket int
+ EventLogs eventLogs
+ Expanded bool
+ }{
+ Buckets: buckets,
+ }
+
+ data.Families = make([]string, 0, len(families))
+ famMu.RLock()
+ for name := range families {
+ data.Families = append(data.Families, name)
+ }
+ famMu.RUnlock()
+ sort.Strings(data.Families)
+
+ // Count the number of eventLogs in each family for each error age.
+ data.Counts = make([][]int, len(data.Families))
+ for i, name := range data.Families {
+ // TODO(sameer): move this loop under the family lock.
+ f := getEventFamily(name)
+ data.Counts[i] = make([]int, len(data.Buckets))
+ for j, b := range data.Buckets {
+ data.Counts[i][j] = f.Count(now, b.MaxErrAge)
+ }
+ }
+
+ if req != nil {
+ var ok bool
+ data.Family, data.Bucket, ok = parseEventsArgs(req)
+ if !ok {
+ // No-op
+ } else {
+ data.EventLogs = getEventFamily(data.Family).Copy(now, buckets[data.Bucket].MaxErrAge)
+ }
+ if data.EventLogs != nil {
+ defer data.EventLogs.Free()
+ sort.Sort(data.EventLogs)
+ }
+ if exp, err := strconv.ParseBool(req.FormValue("exp")); err == nil {
+ data.Expanded = exp
+ }
+ }
+
+ famMu.RLock()
+ defer famMu.RUnlock()
+ if err := eventsTmpl().Execute(w, data); err != nil {
+ log.Printf("net/trace: Failed executing template: %v", err)
+ }
+}
+
+func parseEventsArgs(req *http.Request) (fam string, b int, ok bool) {
+ fam, bStr := req.FormValue("fam"), req.FormValue("b")
+ if fam == "" || bStr == "" {
+ return "", 0, false
+ }
+ b, err := strconv.Atoi(bStr)
+ if err != nil || b < 0 || b >= len(buckets) {
+ return "", 0, false
+ }
+ return fam, b, true
+}
+
+// An EventLog provides a log of events associated with a specific object.
+type EventLog interface {
+ // Printf formats its arguments with fmt.Sprintf and adds the
+ // result to the event log.
+ Printf(format string, a ...interface{})
+
+ // Errorf is like Printf, but it marks this event as an error.
+ Errorf(format string, a ...interface{})
+
+ // Finish declares that this event log is complete.
+ // The event log should not be used after calling this method.
+ Finish()
+}
+
+// NewEventLog returns a new EventLog with the specified family name
+// and title.
+func NewEventLog(family, title string) EventLog {
+ el := newEventLog()
+ el.ref()
+ el.Family, el.Title = family, title
+ el.Start = time.Now()
+ el.events = make([]logEntry, 0, maxEventsPerLog)
+ el.stack = make([]uintptr, 32)
+ n := runtime.Callers(2, el.stack)
+ el.stack = el.stack[:n]
+
+ getEventFamily(family).add(el)
+ return el
+}
+
+func (el *eventLog) Finish() {
+ getEventFamily(el.Family).remove(el)
+ el.unref() // matches ref in New
+}
+
+var (
+ famMu sync.RWMutex
+ families = make(map[string]*eventFamily) // family name => family
+)
+
+func getEventFamily(fam string) *eventFamily {
+ famMu.Lock()
+ defer famMu.Unlock()
+ f := families[fam]
+ if f == nil {
+ f = &eventFamily{}
+ families[fam] = f
+ }
+ return f
+}
+
+type eventFamily struct {
+ mu sync.RWMutex
+ eventLogs eventLogs
+}
+
+func (f *eventFamily) add(el *eventLog) {
+ f.mu.Lock()
+ f.eventLogs = append(f.eventLogs, el)
+ f.mu.Unlock()
+}
+
+func (f *eventFamily) remove(el *eventLog) {
+ f.mu.Lock()
+ defer f.mu.Unlock()
+ for i, el0 := range f.eventLogs {
+ if el == el0 {
+ copy(f.eventLogs[i:], f.eventLogs[i+1:])
+ f.eventLogs = f.eventLogs[:len(f.eventLogs)-1]
+ return
+ }
+ }
+}
+
+func (f *eventFamily) Count(now time.Time, maxErrAge time.Duration) (n int) {
+ f.mu.RLock()
+ defer f.mu.RUnlock()
+ for _, el := range f.eventLogs {
+ if el.hasRecentError(now, maxErrAge) {
+ n++
+ }
+ }
+ return
+}
+
+func (f *eventFamily) Copy(now time.Time, maxErrAge time.Duration) (els eventLogs) {
+ f.mu.RLock()
+ defer f.mu.RUnlock()
+ els = make(eventLogs, 0, len(f.eventLogs))
+ for _, el := range f.eventLogs {
+ if el.hasRecentError(now, maxErrAge) {
+ el.ref()
+ els = append(els, el)
+ }
+ }
+ return
+}
+
+type eventLogs []*eventLog
+
+// Free calls unref on each element of the list.
+func (els eventLogs) Free() {
+ for _, el := range els {
+ el.unref()
+ }
+}
+
+// eventLogs may be sorted in reverse chronological order.
+func (els eventLogs) Len() int { return len(els) }
+func (els eventLogs) Less(i, j int) bool { return els[i].Start.After(els[j].Start) }
+func (els eventLogs) Swap(i, j int) { els[i], els[j] = els[j], els[i] }
+
+// A logEntry is a timestamped log entry in an event log.
+type logEntry struct {
+ When time.Time
+ Elapsed time.Duration // since previous event in log
+ NewDay bool // whether this event is on a different day to the previous event
+ What string
+ IsErr bool
+}
+
+// WhenString returns a string representation of the elapsed time of the event.
+// It will include the date if midnight was crossed.
+func (e logEntry) WhenString() string {
+ if e.NewDay {
+ return e.When.Format("2006/01/02 15:04:05.000000")
+ }
+ return e.When.Format("15:04:05.000000")
+}
+
+// An eventLog represents an active event log.
+type eventLog struct {
+ // Family is the top-level grouping of event logs to which this belongs.
+ Family string
+
+ // Title is the title of this event log.
+ Title string
+
+ // Timing information.
+ Start time.Time
+
+ // Call stack where this event log was created.
+ stack []uintptr
+
+ // Append-only sequence of events.
+ //
+ // TODO(sameer): change this to a ring buffer to avoid the array copy
+ // when we hit maxEventsPerLog.
+ mu sync.RWMutex
+ events []logEntry
+ LastErrorTime time.Time
+ discarded int
+
+ refs int32 // how many buckets this is in
+}
+
+func (el *eventLog) reset() {
+ // Clear all but the mutex. Mutexes may not be copied, even when unlocked.
+ el.Family = ""
+ el.Title = ""
+ el.Start = time.Time{}
+ el.stack = nil
+ el.events = nil
+ el.LastErrorTime = time.Time{}
+ el.discarded = 0
+ el.refs = 0
+}
+
+func (el *eventLog) hasRecentError(now time.Time, maxErrAge time.Duration) bool {
+ if maxErrAge == 0 {
+ return true
+ }
+ el.mu.RLock()
+ defer el.mu.RUnlock()
+ return now.Sub(el.LastErrorTime) < maxErrAge
+}
+
+// delta returns the elapsed time since the last event or the log start,
+// and whether it spans midnight.
+// L >= el.mu
+func (el *eventLog) delta(t time.Time) (time.Duration, bool) {
+ if len(el.events) == 0 {
+ return t.Sub(el.Start), false
+ }
+ prev := el.events[len(el.events)-1].When
+ return t.Sub(prev), prev.Day() != t.Day()
+
+}
+
+func (el *eventLog) Printf(format string, a ...interface{}) {
+ el.printf(false, format, a...)
+}
+
+func (el *eventLog) Errorf(format string, a ...interface{}) {
+ el.printf(true, format, a...)
+}
+
+func (el *eventLog) printf(isErr bool, format string, a ...interface{}) {
+ e := logEntry{When: time.Now(), IsErr: isErr, What: fmt.Sprintf(format, a...)}
+ el.mu.Lock()
+ e.Elapsed, e.NewDay = el.delta(e.When)
+ if len(el.events) < maxEventsPerLog {
+ el.events = append(el.events, e)
+ } else {
+ // Discard the oldest event.
+ if el.discarded == 0 {
+ // el.discarded starts at two to count for the event it
+ // is replacing, plus the next one that we are about to
+ // drop.
+ el.discarded = 2
+ } else {
+ el.discarded++
+ }
+ // TODO(sameer): if this causes allocations on a critical path,
+ // change eventLog.What to be a fmt.Stringer, as in trace.go.
+ el.events[0].What = fmt.Sprintf("(%d events discarded)", el.discarded)
+ // The timestamp of the discarded meta-event should be
+ // the time of the last event it is representing.
+ el.events[0].When = el.events[1].When
+ copy(el.events[1:], el.events[2:])
+ el.events[maxEventsPerLog-1] = e
+ }
+ if e.IsErr {
+ el.LastErrorTime = e.When
+ }
+ el.mu.Unlock()
+}
+
+func (el *eventLog) ref() {
+ atomic.AddInt32(&el.refs, 1)
+}
+
+func (el *eventLog) unref() {
+ if atomic.AddInt32(&el.refs, -1) == 0 {
+ freeEventLog(el)
+ }
+}
+
+func (el *eventLog) When() string {
+ return el.Start.Format("2006/01/02 15:04:05.000000")
+}
+
+func (el *eventLog) ElapsedTime() string {
+ elapsed := time.Since(el.Start)
+ return fmt.Sprintf("%.6f", elapsed.Seconds())
+}
+
+func (el *eventLog) Stack() string {
+ buf := new(bytes.Buffer)
+ tw := tabwriter.NewWriter(buf, 1, 8, 1, '\t', 0)
+ printStackRecord(tw, el.stack)
+ tw.Flush()
+ return buf.String()
+}
+
+// printStackRecord prints the function + source line information
+// for a single stack trace.
+// Adapted from runtime/pprof/pprof.go.
+func printStackRecord(w io.Writer, stk []uintptr) {
+ for _, pc := range stk {
+ f := runtime.FuncForPC(pc)
+ if f == nil {
+ continue
+ }
+ file, line := f.FileLine(pc)
+ name := f.Name()
+ // Hide runtime.goexit and any runtime functions at the beginning.
+ if strings.HasPrefix(name, "runtime.") {
+ continue
+ }
+ fmt.Fprintf(w, "# %s\t%s:%d\n", name, file, line)
+ }
+}
+
+func (el *eventLog) Events() []logEntry {
+ el.mu.RLock()
+ defer el.mu.RUnlock()
+ return el.events
+}
+
+// freeEventLogs is a freelist of *eventLog
+var freeEventLogs = make(chan *eventLog, 1000)
+
+// newEventLog returns a event log ready to use.
+func newEventLog() *eventLog {
+ select {
+ case el := <-freeEventLogs:
+ return el
+ default:
+ return new(eventLog)
+ }
+}
+
+// freeEventLog adds el to freeEventLogs if there's room.
+// This is non-blocking.
+func freeEventLog(el *eventLog) {
+ el.reset()
+ select {
+ case freeEventLogs <- el:
+ default:
+ }
+}
+
+var eventsTmplCache *template.Template
+var eventsTmplOnce sync.Once
+
+func eventsTmpl() *template.Template {
+ eventsTmplOnce.Do(func() {
+ eventsTmplCache = template.Must(template.New("events").Funcs(template.FuncMap{
+ "elapsed": elapsed,
+ "trimSpace": strings.TrimSpace,
+ }).Parse(eventsHTML))
+ })
+ return eventsTmplCache
+}
+
+const eventsHTML = `
+<html>
+ <head>
+ <title>events</title>
+ </head>
+ <style type="text/css">
+ body {
+ font-family: sans-serif;
+ }
+ table#req-status td.family {
+ padding-right: 2em;
+ }
+ table#req-status td.active {
+ padding-right: 1em;
+ }
+ table#req-status td.empty {
+ color: #aaa;
+ }
+ table#reqs {
+ margin-top: 1em;
+ }
+ table#reqs tr.first {
+ {{if $.Expanded}}font-weight: bold;{{end}}
+ }
+ table#reqs td {
+ font-family: monospace;
+ }
+ table#reqs td.when {
+ text-align: right;
+ white-space: nowrap;
+ }
+ table#reqs td.elapsed {
+ padding: 0 0.5em;
+ text-align: right;
+ white-space: pre;
+ width: 10em;
+ }
+ address {
+ font-size: smaller;
+ margin-top: 5em;
+ }
+ </style>
+ <body>
+
+<h1>/debug/events</h1>
+
+<table id="req-status">
+ {{range $i, $fam := .Families}}
+ <tr>
+ <td class="family">{{$fam}}</td>
+
+ {{range $j, $bucket := $.Buckets}}
+ {{$n := index $.Counts $i $j}}
+ <td class="{{if not $bucket.MaxErrAge}}active{{end}}{{if not $n}}empty{{end}}">
+ {{if $n}}<a href="?fam={{$fam}}&b={{$j}}{{if $.Expanded}}&exp=1{{end}}">{{end}}
+ [{{$n}} {{$bucket.String}}]
+ {{if $n}}</a>{{end}}
+ </td>
+ {{end}}
+
+ </tr>{{end}}
+</table>
+
+{{if $.EventLogs}}
+<hr />
+<h3>Family: {{$.Family}}</h3>
+
+{{if $.Expanded}}<a href="?fam={{$.Family}}&b={{$.Bucket}}">{{end}}
+[Summary]{{if $.Expanded}}</a>{{end}}
+
+{{if not $.Expanded}}<a href="?fam={{$.Family}}&b={{$.Bucket}}&exp=1">{{end}}
+[Expanded]{{if not $.Expanded}}</a>{{end}}
+
+<table id="reqs">
+ <tr><th>When</th><th>Elapsed</th></tr>
+ {{range $el := $.EventLogs}}
+ <tr class="first">
+ <td class="when">{{$el.When}}</td>
+ <td class="elapsed">{{$el.ElapsedTime}}</td>
+ <td>{{$el.Title}}
+ </tr>
+ {{if $.Expanded}}
+ <tr>
+ <td class="when"></td>
+ <td class="elapsed"></td>
+ <td><pre>{{$el.Stack|trimSpace}}</pre></td>
+ </tr>
+ {{range $el.Events}}
+ <tr>
+ <td class="when">{{.WhenString}}</td>
+ <td class="elapsed">{{elapsed .Elapsed}}</td>
+ <td>.{{if .IsErr}}E{{else}}.{{end}}. {{.What}}</td>
+ </tr>
+ {{end}}
+ {{end}}
+ {{end}}
+</table>
+{{end}}
+ </body>
+</html>
+`
diff --git a/vendor/golang.org/x/net/trace/histogram.go b/vendor/golang.org/x/net/trace/histogram.go
new file mode 100644
index 000000000..9bf4286c7
--- /dev/null
+++ b/vendor/golang.org/x/net/trace/histogram.go
@@ -0,0 +1,365 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package trace
+
+// This file implements histogramming for RPC statistics collection.
+
+import (
+ "bytes"
+ "fmt"
+ "html/template"
+ "log"
+ "math"
+ "sync"
+
+ "golang.org/x/net/internal/timeseries"
+)
+
+const (
+ bucketCount = 38
+)
+
+// histogram keeps counts of values in buckets that are spaced
+// out in powers of 2: 0-1, 2-3, 4-7...
+// histogram implements timeseries.Observable
+type histogram struct {
+ sum int64 // running total of measurements
+ sumOfSquares float64 // square of running total
+ buckets []int64 // bucketed values for histogram
+ value int // holds a single value as an optimization
+ valueCount int64 // number of values recorded for single value
+}
+
+// AddMeasurement records a value measurement observation to the histogram.
+func (h *histogram) addMeasurement(value int64) {
+ // TODO: assert invariant
+ h.sum += value
+ h.sumOfSquares += float64(value) * float64(value)
+
+ bucketIndex := getBucket(value)
+
+ if h.valueCount == 0 || (h.valueCount > 0 && h.value == bucketIndex) {
+ h.value = bucketIndex
+ h.valueCount++
+ } else {
+ h.allocateBuckets()
+ h.buckets[bucketIndex]++
+ }
+}
+
+func (h *histogram) allocateBuckets() {
+ if h.buckets == nil {
+ h.buckets = make([]int64, bucketCount)
+ h.buckets[h.value] = h.valueCount
+ h.value = 0
+ h.valueCount = -1
+ }
+}
+
+func log2(i int64) int {
+ n := 0
+ for ; i >= 0x100; i >>= 8 {
+ n += 8
+ }
+ for ; i > 0; i >>= 1 {
+ n += 1
+ }
+ return n
+}
+
+func getBucket(i int64) (index int) {
+ index = log2(i) - 1
+ if index < 0 {
+ index = 0
+ }
+ if index >= bucketCount {
+ index = bucketCount - 1
+ }
+ return
+}
+
+// Total returns the number of recorded observations.
+func (h *histogram) total() (total int64) {
+ if h.valueCount >= 0 {
+ total = h.valueCount
+ }
+ for _, val := range h.buckets {
+ total += int64(val)
+ }
+ return
+}
+
+// Average returns the average value of recorded observations.
+func (h *histogram) average() float64 {
+ t := h.total()
+ if t == 0 {
+ return 0
+ }
+ return float64(h.sum) / float64(t)
+}
+
+// Variance returns the variance of recorded observations.
+func (h *histogram) variance() float64 {
+ t := float64(h.total())
+ if t == 0 {
+ return 0
+ }
+ s := float64(h.sum) / t
+ return h.sumOfSquares/t - s*s
+}
+
+// StandardDeviation returns the standard deviation of recorded observations.
+func (h *histogram) standardDeviation() float64 {
+ return math.Sqrt(h.variance())
+}
+
+// PercentileBoundary estimates the value that the given fraction of recorded
+// observations are less than.
+func (h *histogram) percentileBoundary(percentile float64) int64 {
+ total := h.total()
+
+ // Corner cases (make sure result is strictly less than Total())
+ if total == 0 {
+ return 0
+ } else if total == 1 {
+ return int64(h.average())
+ }
+
+ percentOfTotal := round(float64(total) * percentile)
+ var runningTotal int64
+
+ for i := range h.buckets {
+ value := h.buckets[i]
+ runningTotal += value
+ if runningTotal == percentOfTotal {
+ // We hit an exact bucket boundary. If the next bucket has data, it is a
+ // good estimate of the value. If the bucket is empty, we interpolate the
+ // midpoint between the next bucket's boundary and the next non-zero
+ // bucket. If the remaining buckets are all empty, then we use the
+ // boundary for the next bucket as the estimate.
+ j := uint8(i + 1)
+ min := bucketBoundary(j)
+ if runningTotal < total {
+ for h.buckets[j] == 0 {
+ j++
+ }
+ }
+ max := bucketBoundary(j)
+ return min + round(float64(max-min)/2)
+ } else if runningTotal > percentOfTotal {
+ // The value is in this bucket. Interpolate the value.
+ delta := runningTotal - percentOfTotal
+ percentBucket := float64(value-delta) / float64(value)
+ bucketMin := bucketBoundary(uint8(i))
+ nextBucketMin := bucketBoundary(uint8(i + 1))
+ bucketSize := nextBucketMin - bucketMin
+ return bucketMin + round(percentBucket*float64(bucketSize))
+ }
+ }
+ return bucketBoundary(bucketCount - 1)
+}
+
+// Median returns the estimated median of the observed values.
+func (h *histogram) median() int64 {
+ return h.percentileBoundary(0.5)
+}
+
+// Add adds other to h.
+func (h *histogram) Add(other timeseries.Observable) {
+ o := other.(*histogram)
+ if o.valueCount == 0 {
+ // Other histogram is empty
+ } else if h.valueCount >= 0 && o.valueCount > 0 && h.value == o.value {
+ // Both have a single bucketed value, aggregate them
+ h.valueCount += o.valueCount
+ } else {
+ // Two different values necessitate buckets in this histogram
+ h.allocateBuckets()
+ if o.valueCount >= 0 {
+ h.buckets[o.value] += o.valueCount
+ } else {
+ for i := range h.buckets {
+ h.buckets[i] += o.buckets[i]
+ }
+ }
+ }
+ h.sumOfSquares += o.sumOfSquares
+ h.sum += o.sum
+}
+
+// Clear resets the histogram to an empty state, removing all observed values.
+func (h *histogram) Clear() {
+ h.buckets = nil
+ h.value = 0
+ h.valueCount = 0
+ h.sum = 0
+ h.sumOfSquares = 0
+}
+
+// CopyFrom copies from other, which must be a *histogram, into h.
+func (h *histogram) CopyFrom(other timeseries.Observable) {
+ o := other.(*histogram)
+ if o.valueCount == -1 {
+ h.allocateBuckets()
+ copy(h.buckets, o.buckets)
+ }
+ h.sum = o.sum
+ h.sumOfSquares = o.sumOfSquares
+ h.value = o.value
+ h.valueCount = o.valueCount
+}
+
+// Multiply scales the histogram by the specified ratio.
+func (h *histogram) Multiply(ratio float64) {
+ if h.valueCount == -1 {
+ for i := range h.buckets {
+ h.buckets[i] = int64(float64(h.buckets[i]) * ratio)
+ }
+ } else {
+ h.valueCount = int64(float64(h.valueCount) * ratio)
+ }
+ h.sum = int64(float64(h.sum) * ratio)
+ h.sumOfSquares = h.sumOfSquares * ratio
+}
+
+// New creates a new histogram.
+func (h *histogram) New() timeseries.Observable {
+ r := new(histogram)
+ r.Clear()
+ return r
+}
+
+func (h *histogram) String() string {
+ return fmt.Sprintf("%d, %f, %d, %d, %v",
+ h.sum, h.sumOfSquares, h.value, h.valueCount, h.buckets)
+}
+
+// round returns the closest int64 to the argument
+func round(in float64) int64 {
+ return int64(math.Floor(in + 0.5))
+}
+
+// bucketBoundary returns the first value in the bucket.
+func bucketBoundary(bucket uint8) int64 {
+ if bucket == 0 {
+ return 0
+ }
+ return 1 << bucket
+}
+
+// bucketData holds data about a specific bucket for use in distTmpl.
+type bucketData struct {
+ Lower, Upper int64
+ N int64
+ Pct, CumulativePct float64
+ GraphWidth int
+}
+
+// data holds data about a Distribution for use in distTmpl.
+type data struct {
+ Buckets []*bucketData
+ Count, Median int64
+ Mean, StandardDeviation float64
+}
+
+// maxHTMLBarWidth is the maximum width of the HTML bar for visualizing buckets.
+const maxHTMLBarWidth = 350.0
+
+// newData returns data representing h for use in distTmpl.
+func (h *histogram) newData() *data {
+ // Force the allocation of buckets to simplify the rendering implementation
+ h.allocateBuckets()
+ // We scale the bars on the right so that the largest bar is
+ // maxHTMLBarWidth pixels in width.
+ maxBucket := int64(0)
+ for _, n := range h.buckets {
+ if n > maxBucket {
+ maxBucket = n
+ }
+ }
+ total := h.total()
+ barsizeMult := maxHTMLBarWidth / float64(maxBucket)
+ var pctMult float64
+ if total == 0 {
+ pctMult = 1.0
+ } else {
+ pctMult = 100.0 / float64(total)
+ }
+
+ buckets := make([]*bucketData, len(h.buckets))
+ runningTotal := int64(0)
+ for i, n := range h.buckets {
+ if n == 0 {
+ continue
+ }
+ runningTotal += n
+ var upperBound int64
+ if i < bucketCount-1 {
+ upperBound = bucketBoundary(uint8(i + 1))
+ } else {
+ upperBound = math.MaxInt64
+ }
+ buckets[i] = &bucketData{
+ Lower: bucketBoundary(uint8(i)),
+ Upper: upperBound,
+ N: n,
+ Pct: float64(n) * pctMult,
+ CumulativePct: float64(runningTotal) * pctMult,
+ GraphWidth: int(float64(n) * barsizeMult),
+ }
+ }
+ return &data{
+ Buckets: buckets,
+ Count: total,
+ Median: h.median(),
+ Mean: h.average(),
+ StandardDeviation: h.standardDeviation(),
+ }
+}
+
+func (h *histogram) html() template.HTML {
+ buf := new(bytes.Buffer)
+ if err := distTmpl().Execute(buf, h.newData()); err != nil {
+ buf.Reset()
+ log.Printf("net/trace: couldn't execute template: %v", err)
+ }
+ return template.HTML(buf.String())
+}
+
+var distTmplCache *template.Template
+var distTmplOnce sync.Once
+
+func distTmpl() *template.Template {
+ distTmplOnce.Do(func() {
+ // Input: data
+ distTmplCache = template.Must(template.New("distTmpl").Parse(`
+<table>
+<tr>
+ <td style="padding:0.25em">Count: {{.Count}}</td>
+ <td style="padding:0.25em">Mean: {{printf "%.0f" .Mean}}</td>
+ <td style="padding:0.25em">StdDev: {{printf "%.0f" .StandardDeviation}}</td>
+ <td style="padding:0.25em">Median: {{.Median}}</td>
+</tr>
+</table>
+<hr>
+<table>
+{{range $b := .Buckets}}
+{{if $b}}
+ <tr>
+ <td style="padding:0 0 0 0.25em">[</td>
+ <td style="text-align:right;padding:0 0.25em">{{.Lower}},</td>
+ <td style="text-align:right;padding:0 0.25em">{{.Upper}})</td>
+ <td style="text-align:right;padding:0 0.25em">{{.N}}</td>
+ <td style="text-align:right;padding:0 0.25em">{{printf "%#.3f" .Pct}}%</td>
+ <td style="text-align:right;padding:0 0.25em">{{printf "%#.3f" .CumulativePct}}%</td>
+ <td><div style="background-color: blue; height: 1em; width: {{.GraphWidth}};"></div></td>
+ </tr>
+{{end}}
+{{end}}
+</table>
+`))
+ })
+ return distTmplCache
+}
diff --git a/vendor/golang.org/x/net/trace/trace.go b/vendor/golang.org/x/net/trace/trace.go
new file mode 100644
index 000000000..bb72a527e
--- /dev/null
+++ b/vendor/golang.org/x/net/trace/trace.go
@@ -0,0 +1,1082 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+/*
+Package trace implements tracing of requests and long-lived objects.
+It exports HTTP interfaces on /debug/requests and /debug/events.
+
+A trace.Trace provides tracing for short-lived objects, usually requests.
+A request handler might be implemented like this:
+
+ func fooHandler(w http.ResponseWriter, req *http.Request) {
+ tr := trace.New("mypkg.Foo", req.URL.Path)
+ defer tr.Finish()
+ ...
+ tr.LazyPrintf("some event %q happened", str)
+ ...
+ if err := somethingImportant(); err != nil {
+ tr.LazyPrintf("somethingImportant failed: %v", err)
+ tr.SetError()
+ }
+ }
+
+The /debug/requests HTTP endpoint organizes the traces by family,
+errors, and duration. It also provides histogram of request duration
+for each family.
+
+A trace.EventLog provides tracing for long-lived objects, such as RPC
+connections.
+
+ // A Fetcher fetches URL paths for a single domain.
+ type Fetcher struct {
+ domain string
+ events trace.EventLog
+ }
+
+ func NewFetcher(domain string) *Fetcher {
+ return &Fetcher{
+ domain,
+ trace.NewEventLog("mypkg.Fetcher", domain),
+ }
+ }
+
+ func (f *Fetcher) Fetch(path string) (string, error) {
+ resp, err := http.Get("http://" + f.domain + "/" + path)
+ if err != nil {
+ f.events.Errorf("Get(%q) = %v", path, err)
+ return "", err
+ }
+ f.events.Printf("Get(%q) = %s", path, resp.Status)
+ ...
+ }
+
+ func (f *Fetcher) Close() error {
+ f.events.Finish()
+ return nil
+ }
+
+The /debug/events HTTP endpoint organizes the event logs by family and
+by time since the last error. The expanded view displays recent log
+entries and the log's call stack.
+*/
+package trace // import "golang.org/x/net/trace"
+
+import (
+ "bytes"
+ "fmt"
+ "html/template"
+ "io"
+ "log"
+ "net"
+ "net/http"
+ "runtime"
+ "sort"
+ "strconv"
+ "sync"
+ "sync/atomic"
+ "time"
+
+ "golang.org/x/net/internal/timeseries"
+)
+
+// DebugUseAfterFinish controls whether to debug uses of Trace values after finishing.
+// FOR DEBUGGING ONLY. This will slow down the program.
+var DebugUseAfterFinish = false
+
+// AuthRequest determines whether a specific request is permitted to load the
+// /debug/requests or /debug/events pages.
+//
+// It returns two bools; the first indicates whether the page may be viewed at all,
+// and the second indicates whether sensitive events will be shown.
+//
+// AuthRequest may be replaced by a program to customize its authorization requirements.
+//
+// The default AuthRequest function returns (true, true) if and only if the request
+// comes from localhost/127.0.0.1/[::1].
+var AuthRequest = func(req *http.Request) (any, sensitive bool) {
+ // RemoteAddr is commonly in the form "IP" or "IP:port".
+ // If it is in the form "IP:port", split off the port.
+ host, _, err := net.SplitHostPort(req.RemoteAddr)
+ if err != nil {
+ host = req.RemoteAddr
+ }
+ switch host {
+ case "localhost", "127.0.0.1", "::1":
+ return true, true
+ default:
+ return false, false
+ }
+}
+
+func init() {
+ // TODO(jbd): Serve Traces from /debug/traces in the future?
+ // There is no requirement for a request to be present to have traces.
+ http.HandleFunc("/debug/requests", Traces)
+ http.HandleFunc("/debug/events", Events)
+}
+
+// Traces responds with traces from the program.
+// The package initialization registers it in http.DefaultServeMux
+// at /debug/requests.
+//
+// It performs authorization by running AuthRequest.
+func Traces(w http.ResponseWriter, req *http.Request) {
+ any, sensitive := AuthRequest(req)
+ if !any {
+ http.Error(w, "not allowed", http.StatusUnauthorized)
+ return
+ }
+ w.Header().Set("Content-Type", "text/html; charset=utf-8")
+ Render(w, req, sensitive)
+}
+
+// Events responds with a page of events collected by EventLogs.
+// The package initialization registers it in http.DefaultServeMux
+// at /debug/events.
+//
+// It performs authorization by running AuthRequest.
+func Events(w http.ResponseWriter, req *http.Request) {
+ any, sensitive := AuthRequest(req)
+ if !any {
+ http.Error(w, "not allowed", http.StatusUnauthorized)
+ return
+ }
+ w.Header().Set("Content-Type", "text/html; charset=utf-8")
+ RenderEvents(w, req, sensitive)
+}
+
+// Render renders the HTML page typically served at /debug/requests.
+// It does not do any auth checking. The request may be nil.
+//
+// Most users will use the Traces handler.
+func Render(w io.Writer, req *http.Request, sensitive bool) {
+ data := &struct {
+ Families []string
+ ActiveTraceCount map[string]int
+ CompletedTraces map[string]*family
+
+ // Set when a bucket has been selected.
+ Traces traceList
+ Family string
+ Bucket int
+ Expanded bool
+ Traced bool
+ Active bool
+ ShowSensitive bool // whether to show sensitive events
+
+ Histogram template.HTML
+ HistogramWindow string // e.g. "last minute", "last hour", "all time"
+
+ // If non-zero, the set of traces is a partial set,
+ // and this is the total number.
+ Total int
+ }{
+ CompletedTraces: completedTraces,
+ }
+
+ data.ShowSensitive = sensitive
+ if req != nil {
+ // Allow show_sensitive=0 to force hiding of sensitive data for testing.
+ // This only goes one way; you can't use show_sensitive=1 to see things.
+ if req.FormValue("show_sensitive") == "0" {
+ data.ShowSensitive = false
+ }
+
+ if exp, err := strconv.ParseBool(req.FormValue("exp")); err == nil {
+ data.Expanded = exp
+ }
+ if exp, err := strconv.ParseBool(req.FormValue("rtraced")); err == nil {
+ data.Traced = exp
+ }
+ }
+
+ completedMu.RLock()
+ data.Families = make([]string, 0, len(completedTraces))
+ for fam := range completedTraces {
+ data.Families = append(data.Families, fam)
+ }
+ completedMu.RUnlock()
+ sort.Strings(data.Families)
+
+ // We are careful here to minimize the time spent locking activeMu,
+ // since that lock is required every time an RPC starts and finishes.
+ data.ActiveTraceCount = make(map[string]int, len(data.Families))
+ activeMu.RLock()
+ for fam, s := range activeTraces {
+ data.ActiveTraceCount[fam] = s.Len()
+ }
+ activeMu.RUnlock()
+
+ var ok bool
+ data.Family, data.Bucket, ok = parseArgs(req)
+ switch {
+ case !ok:
+ // No-op
+ case data.Bucket == -1:
+ data.Active = true
+ n := data.ActiveTraceCount[data.Family]
+ data.Traces = getActiveTraces(data.Family)
+ if len(data.Traces) < n {
+ data.Total = n
+ }
+ case data.Bucket < bucketsPerFamily:
+ if b := lookupBucket(data.Family, data.Bucket); b != nil {
+ data.Traces = b.Copy(data.Traced)
+ }
+ default:
+ if f := getFamily(data.Family, false); f != nil {
+ var obs timeseries.Observable
+ f.LatencyMu.RLock()
+ switch o := data.Bucket - bucketsPerFamily; o {
+ case 0:
+ obs = f.Latency.Minute()
+ data.HistogramWindow = "last minute"
+ case 1:
+ obs = f.Latency.Hour()
+ data.HistogramWindow = "last hour"
+ case 2:
+ obs = f.Latency.Total()
+ data.HistogramWindow = "all time"
+ }
+ f.LatencyMu.RUnlock()
+ if obs != nil {
+ data.Histogram = obs.(*histogram).html()
+ }
+ }
+ }
+
+ if data.Traces != nil {
+ defer data.Traces.Free()
+ sort.Sort(data.Traces)
+ }
+
+ completedMu.RLock()
+ defer completedMu.RUnlock()
+ if err := pageTmpl().ExecuteTemplate(w, "Page", data); err != nil {
+ log.Printf("net/trace: Failed executing template: %v", err)
+ }
+}
+
+func parseArgs(req *http.Request) (fam string, b int, ok bool) {
+ if req == nil {
+ return "", 0, false
+ }
+ fam, bStr := req.FormValue("fam"), req.FormValue("b")
+ if fam == "" || bStr == "" {
+ return "", 0, false
+ }
+ b, err := strconv.Atoi(bStr)
+ if err != nil || b < -1 {
+ return "", 0, false
+ }
+
+ return fam, b, true
+}
+
+func lookupBucket(fam string, b int) *traceBucket {
+ f := getFamily(fam, false)
+ if f == nil || b < 0 || b >= len(f.Buckets) {
+ return nil
+ }
+ return f.Buckets[b]
+}
+
+type contextKeyT string
+
+var contextKey = contextKeyT("golang.org/x/net/trace.Trace")
+
+// Trace represents an active request.
+type Trace interface {
+ // LazyLog adds x to the event log. It will be evaluated each time the
+ // /debug/requests page is rendered. Any memory referenced by x will be
+ // pinned until the trace is finished and later discarded.
+ LazyLog(x fmt.Stringer, sensitive bool)
+
+ // LazyPrintf evaluates its arguments with fmt.Sprintf each time the
+ // /debug/requests page is rendered. Any memory referenced by a will be
+ // pinned until the trace is finished and later discarded.
+ LazyPrintf(format string, a ...interface{})
+
+ // SetError declares that this trace resulted in an error.
+ SetError()
+
+ // SetRecycler sets a recycler for the trace.
+ // f will be called for each event passed to LazyLog at a time when
+ // it is no longer required, whether while the trace is still active
+ // and the event is discarded, or when a completed trace is discarded.
+ SetRecycler(f func(interface{}))
+
+ // SetTraceInfo sets the trace info for the trace.
+ // This is currently unused.
+ SetTraceInfo(traceID, spanID uint64)
+
+ // SetMaxEvents sets the maximum number of events that will be stored
+ // in the trace. This has no effect if any events have already been
+ // added to the trace.
+ SetMaxEvents(m int)
+
+ // Finish declares that this trace is complete.
+ // The trace should not be used after calling this method.
+ Finish()
+}
+
+type lazySprintf struct {
+ format string
+ a []interface{}
+}
+
+func (l *lazySprintf) String() string {
+ return fmt.Sprintf(l.format, l.a...)
+}
+
+// New returns a new Trace with the specified family and title.
+func New(family, title string) Trace {
+ tr := newTrace()
+ tr.ref()
+ tr.Family, tr.Title = family, title
+ tr.Start = time.Now()
+ tr.maxEvents = maxEventsPerTrace
+ tr.events = tr.eventsBuf[:0]
+
+ activeMu.RLock()
+ s := activeTraces[tr.Family]
+ activeMu.RUnlock()
+ if s == nil {
+ activeMu.Lock()
+ s = activeTraces[tr.Family] // check again
+ if s == nil {
+ s = new(traceSet)
+ activeTraces[tr.Family] = s
+ }
+ activeMu.Unlock()
+ }
+ s.Add(tr)
+
+ // Trigger allocation of the completed trace structure for this family.
+ // This will cause the family to be present in the request page during
+ // the first trace of this family. We don't care about the return value,
+ // nor is there any need for this to run inline, so we execute it in its
+ // own goroutine, but only if the family isn't allocated yet.
+ completedMu.RLock()
+ if _, ok := completedTraces[tr.Family]; !ok {
+ go allocFamily(tr.Family)
+ }
+ completedMu.RUnlock()
+
+ return tr
+}
+
+func (tr *trace) Finish() {
+ tr.Elapsed = time.Now().Sub(tr.Start)
+ if DebugUseAfterFinish {
+ buf := make([]byte, 4<<10) // 4 KB should be enough
+ n := runtime.Stack(buf, false)
+ tr.finishStack = buf[:n]
+ }
+
+ activeMu.RLock()
+ m := activeTraces[tr.Family]
+ activeMu.RUnlock()
+ m.Remove(tr)
+
+ f := getFamily(tr.Family, true)
+ for _, b := range f.Buckets {
+ if b.Cond.match(tr) {
+ b.Add(tr)
+ }
+ }
+ // Add a sample of elapsed time as microseconds to the family's timeseries
+ h := new(histogram)
+ h.addMeasurement(tr.Elapsed.Nanoseconds() / 1e3)
+ f.LatencyMu.Lock()
+ f.Latency.Add(h)
+ f.LatencyMu.Unlock()
+
+ tr.unref() // matches ref in New
+}
+
+const (
+ bucketsPerFamily = 9
+ tracesPerBucket = 10
+ maxActiveTraces = 20 // Maximum number of active traces to show.
+ maxEventsPerTrace = 10
+ numHistogramBuckets = 38
+)
+
+var (
+ // The active traces.
+ activeMu sync.RWMutex
+ activeTraces = make(map[string]*traceSet) // family -> traces
+
+ // Families of completed traces.
+ completedMu sync.RWMutex
+ completedTraces = make(map[string]*family) // family -> traces
+)
+
+type traceSet struct {
+ mu sync.RWMutex
+ m map[*trace]bool
+
+ // We could avoid the entire map scan in FirstN by having a slice of all the traces
+ // ordered by start time, and an index into that from the trace struct, with a periodic
+ // repack of the slice after enough traces finish; we could also use a skip list or similar.
+ // However, that would shift some of the expense from /debug/requests time to RPC time,
+ // which is probably the wrong trade-off.
+}
+
+func (ts *traceSet) Len() int {
+ ts.mu.RLock()
+ defer ts.mu.RUnlock()
+ return len(ts.m)
+}
+
+func (ts *traceSet) Add(tr *trace) {
+ ts.mu.Lock()
+ if ts.m == nil {
+ ts.m = make(map[*trace]bool)
+ }
+ ts.m[tr] = true
+ ts.mu.Unlock()
+}
+
+func (ts *traceSet) Remove(tr *trace) {
+ ts.mu.Lock()
+ delete(ts.m, tr)
+ ts.mu.Unlock()
+}
+
+// FirstN returns the first n traces ordered by time.
+func (ts *traceSet) FirstN(n int) traceList {
+ ts.mu.RLock()
+ defer ts.mu.RUnlock()
+
+ if n > len(ts.m) {
+ n = len(ts.m)
+ }
+ trl := make(traceList, 0, n)
+
+ // Fast path for when no selectivity is needed.
+ if n == len(ts.m) {
+ for tr := range ts.m {
+ tr.ref()
+ trl = append(trl, tr)
+ }
+ sort.Sort(trl)
+ return trl
+ }
+
+ // Pick the oldest n traces.
+ // This is inefficient. See the comment in the traceSet struct.
+ for tr := range ts.m {
+ // Put the first n traces into trl in the order they occur.
+ // When we have n, sort trl, and thereafter maintain its order.
+ if len(trl) < n {
+ tr.ref()
+ trl = append(trl, tr)
+ if len(trl) == n {
+ // This is guaranteed to happen exactly once during this loop.
+ sort.Sort(trl)
+ }
+ continue
+ }
+ if tr.Start.After(trl[n-1].Start) {
+ continue
+ }
+
+ // Find where to insert this one.
+ tr.ref()
+ i := sort.Search(n, func(i int) bool { return trl[i].Start.After(tr.Start) })
+ trl[n-1].unref()
+ copy(trl[i+1:], trl[i:])
+ trl[i] = tr
+ }
+
+ return trl
+}
+
+func getActiveTraces(fam string) traceList {
+ activeMu.RLock()
+ s := activeTraces[fam]
+ activeMu.RUnlock()
+ if s == nil {
+ return nil
+ }
+ return s.FirstN(maxActiveTraces)
+}
+
+func getFamily(fam string, allocNew bool) *family {
+ completedMu.RLock()
+ f := completedTraces[fam]
+ completedMu.RUnlock()
+ if f == nil && allocNew {
+ f = allocFamily(fam)
+ }
+ return f
+}
+
+func allocFamily(fam string) *family {
+ completedMu.Lock()
+ defer completedMu.Unlock()
+ f := completedTraces[fam]
+ if f == nil {
+ f = newFamily()
+ completedTraces[fam] = f
+ }
+ return f
+}
+
+// family represents a set of trace buckets and associated latency information.
+type family struct {
+ // traces may occur in multiple buckets.
+ Buckets [bucketsPerFamily]*traceBucket
+
+ // latency time series
+ LatencyMu sync.RWMutex
+ Latency *timeseries.MinuteHourSeries
+}
+
+func newFamily() *family {
+ return &family{
+ Buckets: [bucketsPerFamily]*traceBucket{
+ {Cond: minCond(0)},
+ {Cond: minCond(50 * time.Millisecond)},
+ {Cond: minCond(100 * time.Millisecond)},
+ {Cond: minCond(200 * time.Millisecond)},
+ {Cond: minCond(500 * time.Millisecond)},
+ {Cond: minCond(1 * time.Second)},
+ {Cond: minCond(10 * time.Second)},
+ {Cond: minCond(100 * time.Second)},
+ {Cond: errorCond{}},
+ },
+ Latency: timeseries.NewMinuteHourSeries(func() timeseries.Observable { return new(histogram) }),
+ }
+}
+
+// traceBucket represents a size-capped bucket of historic traces,
+// along with a condition for a trace to belong to the bucket.
+type traceBucket struct {
+ Cond cond
+
+ // Ring buffer implementation of a fixed-size FIFO queue.
+ mu sync.RWMutex
+ buf [tracesPerBucket]*trace
+ start int // < tracesPerBucket
+ length int // <= tracesPerBucket
+}
+
+func (b *traceBucket) Add(tr *trace) {
+ b.mu.Lock()
+ defer b.mu.Unlock()
+
+ i := b.start + b.length
+ if i >= tracesPerBucket {
+ i -= tracesPerBucket
+ }
+ if b.length == tracesPerBucket {
+ // "Remove" an element from the bucket.
+ b.buf[i].unref()
+ b.start++
+ if b.start == tracesPerBucket {
+ b.start = 0
+ }
+ }
+ b.buf[i] = tr
+ if b.length < tracesPerBucket {
+ b.length++
+ }
+ tr.ref()
+}
+
+// Copy returns a copy of the traces in the bucket.
+// If tracedOnly is true, only the traces with trace information will be returned.
+// The logs will be ref'd before returning; the caller should call
+// the Free method when it is done with them.
+// TODO(dsymonds): keep track of traced requests in separate buckets.
+func (b *traceBucket) Copy(tracedOnly bool) traceList {
+ b.mu.RLock()
+ defer b.mu.RUnlock()
+
+ trl := make(traceList, 0, b.length)
+ for i, x := 0, b.start; i < b.length; i++ {
+ tr := b.buf[x]
+ if !tracedOnly || tr.spanID != 0 {
+ tr.ref()
+ trl = append(trl, tr)
+ }
+ x++
+ if x == b.length {
+ x = 0
+ }
+ }
+ return trl
+}
+
+func (b *traceBucket) Empty() bool {
+ b.mu.RLock()
+ defer b.mu.RUnlock()
+ return b.length == 0
+}
+
+// cond represents a condition on a trace.
+type cond interface {
+ match(t *trace) bool
+ String() string
+}
+
+type minCond time.Duration
+
+func (m minCond) match(t *trace) bool { return t.Elapsed >= time.Duration(m) }
+func (m minCond) String() string { return fmt.Sprintf("≥%gs", time.Duration(m).Seconds()) }
+
+type errorCond struct{}
+
+func (e errorCond) match(t *trace) bool { return t.IsError }
+func (e errorCond) String() string { return "errors" }
+
+type traceList []*trace
+
+// Free calls unref on each element of the list.
+func (trl traceList) Free() {
+ for _, t := range trl {
+ t.unref()
+ }
+}
+
+// traceList may be sorted in reverse chronological order.
+func (trl traceList) Len() int { return len(trl) }
+func (trl traceList) Less(i, j int) bool { return trl[i].Start.After(trl[j].Start) }
+func (trl traceList) Swap(i, j int) { trl[i], trl[j] = trl[j], trl[i] }
+
+// An event is a timestamped log entry in a trace.
+type event struct {
+ When time.Time
+ Elapsed time.Duration // since previous event in trace
+ NewDay bool // whether this event is on a different day to the previous event
+ Recyclable bool // whether this event was passed via LazyLog
+ Sensitive bool // whether this event contains sensitive information
+ What interface{} // string or fmt.Stringer
+}
+
+// WhenString returns a string representation of the elapsed time of the event.
+// It will include the date if midnight was crossed.
+func (e event) WhenString() string {
+ if e.NewDay {
+ return e.When.Format("2006/01/02 15:04:05.000000")
+ }
+ return e.When.Format("15:04:05.000000")
+}
+
+// discarded represents a number of discarded events.
+// It is stored as *discarded to make it easier to update in-place.
+type discarded int
+
+func (d *discarded) String() string {
+ return fmt.Sprintf("(%d events discarded)", int(*d))
+}
+
+// trace represents an active or complete request,
+// either sent or received by this program.
+type trace struct {
+ // Family is the top-level grouping of traces to which this belongs.
+ Family string
+
+ // Title is the title of this trace.
+ Title string
+
+ // Timing information.
+ Start time.Time
+ Elapsed time.Duration // zero while active
+
+ // Trace information if non-zero.
+ traceID uint64
+ spanID uint64
+
+ // Whether this trace resulted in an error.
+ IsError bool
+
+ // Append-only sequence of events (modulo discards).
+ mu sync.RWMutex
+ events []event
+ maxEvents int
+
+ refs int32 // how many buckets this is in
+ recycler func(interface{})
+ disc discarded // scratch space to avoid allocation
+
+ finishStack []byte // where finish was called, if DebugUseAfterFinish is set
+
+ eventsBuf [4]event // preallocated buffer in case we only log a few events
+}
+
+func (tr *trace) reset() {
+ // Clear all but the mutex. Mutexes may not be copied, even when unlocked.
+ tr.Family = ""
+ tr.Title = ""
+ tr.Start = time.Time{}
+ tr.Elapsed = 0
+ tr.traceID = 0
+ tr.spanID = 0
+ tr.IsError = false
+ tr.maxEvents = 0
+ tr.events = nil
+ tr.refs = 0
+ tr.recycler = nil
+ tr.disc = 0
+ tr.finishStack = nil
+ for i := range tr.eventsBuf {
+ tr.eventsBuf[i] = event{}
+ }
+}
+
+// delta returns the elapsed time since the last event or the trace start,
+// and whether it spans midnight.
+// L >= tr.mu
+func (tr *trace) delta(t time.Time) (time.Duration, bool) {
+ if len(tr.events) == 0 {
+ return t.Sub(tr.Start), false
+ }
+ prev := tr.events[len(tr.events)-1].When
+ return t.Sub(prev), prev.Day() != t.Day()
+}
+
+func (tr *trace) addEvent(x interface{}, recyclable, sensitive bool) {
+ if DebugUseAfterFinish && tr.finishStack != nil {
+ buf := make([]byte, 4<<10) // 4 KB should be enough
+ n := runtime.Stack(buf, false)
+ log.Printf("net/trace: trace used after finish:\nFinished at:\n%s\nUsed at:\n%s", tr.finishStack, buf[:n])
+ }
+
+ /*
+ NOTE TO DEBUGGERS
+
+ If you are here because your program panicked in this code,
+ it is almost definitely the fault of code using this package,
+ and very unlikely to be the fault of this code.
+
+ The most likely scenario is that some code elsewhere is using
+ a trace.Trace after its Finish method is called.
+ You can temporarily set the DebugUseAfterFinish var
+ to help discover where that is; do not leave that var set,
+ since it makes this package much less efficient.
+ */
+
+ e := event{When: time.Now(), What: x, Recyclable: recyclable, Sensitive: sensitive}
+ tr.mu.Lock()
+ e.Elapsed, e.NewDay = tr.delta(e.When)
+ if len(tr.events) < tr.maxEvents {
+ tr.events = append(tr.events, e)
+ } else {
+ // Discard the middle events.
+ di := int((tr.maxEvents - 1) / 2)
+ if d, ok := tr.events[di].What.(*discarded); ok {
+ (*d)++
+ } else {
+ // disc starts at two to count for the event it is replacing,
+ // plus the next one that we are about to drop.
+ tr.disc = 2
+ if tr.recycler != nil && tr.events[di].Recyclable {
+ go tr.recycler(tr.events[di].What)
+ }
+ tr.events[di].What = &tr.disc
+ }
+ // The timestamp of the discarded meta-event should be
+ // the time of the last event it is representing.
+ tr.events[di].When = tr.events[di+1].When
+
+ if tr.recycler != nil && tr.events[di+1].Recyclable {
+ go tr.recycler(tr.events[di+1].What)
+ }
+ copy(tr.events[di+1:], tr.events[di+2:])
+ tr.events[tr.maxEvents-1] = e
+ }
+ tr.mu.Unlock()
+}
+
+func (tr *trace) LazyLog(x fmt.Stringer, sensitive bool) {
+ tr.addEvent(x, true, sensitive)
+}
+
+func (tr *trace) LazyPrintf(format string, a ...interface{}) {
+ tr.addEvent(&lazySprintf{format, a}, false, false)
+}
+
+func (tr *trace) SetError() { tr.IsError = true }
+
+func (tr *trace) SetRecycler(f func(interface{})) {
+ tr.recycler = f
+}
+
+func (tr *trace) SetTraceInfo(traceID, spanID uint64) {
+ tr.traceID, tr.spanID = traceID, spanID
+}
+
+func (tr *trace) SetMaxEvents(m int) {
+ // Always keep at least three events: first, discarded count, last.
+ if len(tr.events) == 0 && m > 3 {
+ tr.maxEvents = m
+ }
+}
+
+func (tr *trace) ref() {
+ atomic.AddInt32(&tr.refs, 1)
+}
+
+func (tr *trace) unref() {
+ if atomic.AddInt32(&tr.refs, -1) == 0 {
+ if tr.recycler != nil {
+ // freeTrace clears tr, so we hold tr.recycler and tr.events here.
+ go func(f func(interface{}), es []event) {
+ for _, e := range es {
+ if e.Recyclable {
+ f(e.What)
+ }
+ }
+ }(tr.recycler, tr.events)
+ }
+
+ freeTrace(tr)
+ }
+}
+
+func (tr *trace) When() string {
+ return tr.Start.Format("2006/01/02 15:04:05.000000")
+}
+
+func (tr *trace) ElapsedTime() string {
+ t := tr.Elapsed
+ if t == 0 {
+ // Active trace.
+ t = time.Since(tr.Start)
+ }
+ return fmt.Sprintf("%.6f", t.Seconds())
+}
+
+func (tr *trace) Events() []event {
+ tr.mu.RLock()
+ defer tr.mu.RUnlock()
+ return tr.events
+}
+
+var traceFreeList = make(chan *trace, 1000) // TODO(dsymonds): Use sync.Pool?
+
+// newTrace returns a trace ready to use.
+func newTrace() *trace {
+ select {
+ case tr := <-traceFreeList:
+ return tr
+ default:
+ return new(trace)
+ }
+}
+
+// freeTrace adds tr to traceFreeList if there's room.
+// This is non-blocking.
+func freeTrace(tr *trace) {
+ if DebugUseAfterFinish {
+ return // never reuse
+ }
+ tr.reset()
+ select {
+ case traceFreeList <- tr:
+ default:
+ }
+}
+
+func elapsed(d time.Duration) string {
+ b := []byte(fmt.Sprintf("%.6f", d.Seconds()))
+
+ // For subsecond durations, blank all zeros before decimal point,
+ // and all zeros between the decimal point and the first non-zero digit.
+ if d < time.Second {
+ dot := bytes.IndexByte(b, '.')
+ for i := 0; i < dot; i++ {
+ b[i] = ' '
+ }
+ for i := dot + 1; i < len(b); i++ {
+ if b[i] == '0' {
+ b[i] = ' '
+ } else {
+ break
+ }
+ }
+ }
+
+ return string(b)
+}
+
+var pageTmplCache *template.Template
+var pageTmplOnce sync.Once
+
+func pageTmpl() *template.Template {
+ pageTmplOnce.Do(func() {
+ pageTmplCache = template.Must(template.New("Page").Funcs(template.FuncMap{
+ "elapsed": elapsed,
+ "add": func(a, b int) int { return a + b },
+ }).Parse(pageHTML))
+ })
+ return pageTmplCache
+}
+
+const pageHTML = `
+{{template "Prolog" .}}
+{{template "StatusTable" .}}
+{{template "Epilog" .}}
+
+{{define "Prolog"}}
+<html>
+ <head>
+ <title>/debug/requests</title>
+ <style type="text/css">
+ body {
+ font-family: sans-serif;
+ }
+ table#tr-status td.family {
+ padding-right: 2em;
+ }
+ table#tr-status td.active {
+ padding-right: 1em;
+ }
+ table#tr-status td.latency-first {
+ padding-left: 1em;
+ }
+ table#tr-status td.empty {
+ color: #aaa;
+ }
+ table#reqs {
+ margin-top: 1em;
+ }
+ table#reqs tr.first {
+ {{if $.Expanded}}font-weight: bold;{{end}}
+ }
+ table#reqs td {
+ font-family: monospace;
+ }
+ table#reqs td.when {
+ text-align: right;
+ white-space: nowrap;
+ }
+ table#reqs td.elapsed {
+ padding: 0 0.5em;
+ text-align: right;
+ white-space: pre;
+ width: 10em;
+ }
+ address {
+ font-size: smaller;
+ margin-top: 5em;
+ }
+ </style>
+ </head>
+ <body>
+
+<h1>/debug/requests</h1>
+{{end}} {{/* end of Prolog */}}
+
+{{define "StatusTable"}}
+<table id="tr-status">
+ {{range $fam := .Families}}
+ <tr>
+ <td class="family">{{$fam}}</td>
+
+ {{$n := index $.ActiveTraceCount $fam}}
+ <td class="active {{if not $n}}empty{{end}}">
+ {{if $n}}<a href="?fam={{$fam}}&b=-1{{if $.Expanded}}&exp=1{{end}}">{{end}}
+ [{{$n}} active]
+ {{if $n}}</a>{{end}}
+ </td>
+
+ {{$f := index $.CompletedTraces $fam}}
+ {{range $i, $b := $f.Buckets}}
+ {{$empty := $b.Empty}}
+ <td {{if $empty}}class="empty"{{end}}>
+ {{if not $empty}}<a href="?fam={{$fam}}&b={{$i}}{{if $.Expanded}}&exp=1{{end}}">{{end}}
+ [{{.Cond}}]
+ {{if not $empty}}</a>{{end}}
+ </td>
+ {{end}}
+
+ {{$nb := len $f.Buckets}}
+ <td class="latency-first">
+ <a href="?fam={{$fam}}&b={{$nb}}">[minute]</a>
+ </td>
+ <td>
+ <a href="?fam={{$fam}}&b={{add $nb 1}}">[hour]</a>
+ </td>
+ <td>
+ <a href="?fam={{$fam}}&b={{add $nb 2}}">[total]</a>
+ </td>
+
+ </tr>
+ {{end}}
+</table>
+{{end}} {{/* end of StatusTable */}}
+
+{{define "Epilog"}}
+{{if $.Traces}}
+<hr />
+<h3>Family: {{$.Family}}</h3>
+
+{{if or $.Expanded $.Traced}}
+ <a href="?fam={{$.Family}}&b={{$.Bucket}}">[Normal/Summary]</a>
+{{else}}
+ [Normal/Summary]
+{{end}}
+
+{{if or (not $.Expanded) $.Traced}}
+ <a href="?fam={{$.Family}}&b={{$.Bucket}}&exp=1">[Normal/Expanded]</a>
+{{else}}
+ [Normal/Expanded]
+{{end}}
+
+{{if not $.Active}}
+ {{if or $.Expanded (not $.Traced)}}
+ <a href="?fam={{$.Family}}&b={{$.Bucket}}&rtraced=1">[Traced/Summary]</a>
+ {{else}}
+ [Traced/Summary]
+ {{end}}
+ {{if or (not $.Expanded) (not $.Traced)}}
+ <a href="?fam={{$.Family}}&b={{$.Bucket}}&exp=1&rtraced=1">[Traced/Expanded]</a>
+ {{else}}
+ [Traced/Expanded]
+ {{end}}
+{{end}}
+
+{{if $.Total}}
+<p><em>Showing <b>{{len $.Traces}}</b> of <b>{{$.Total}}</b> traces.</em></p>
+{{end}}
+
+<table id="reqs">
+ <caption>
+ {{if $.Active}}Active{{else}}Completed{{end}} Requests
+ </caption>
+ <tr><th>When</th><th>Elapsed&nbsp;(s)</th></tr>
+ {{range $tr := $.Traces}}
+ <tr class="first">
+ <td class="when">{{$tr.When}}</td>
+ <td class="elapsed">{{$tr.ElapsedTime}}</td>
+ <td>{{$tr.Title}}</td>
+ {{/* TODO: include traceID/spanID */}}
+ </tr>
+ {{if $.Expanded}}
+ {{range $tr.Events}}
+ <tr>
+ <td class="when">{{.WhenString}}</td>
+ <td class="elapsed">{{elapsed .Elapsed}}</td>
+ <td>{{if or $.ShowSensitive (not .Sensitive)}}... {{.What}}{{else}}<em>[redacted]</em>{{end}}</td>
+ </tr>
+ {{end}}
+ {{end}}
+ {{end}}
+</table>
+{{end}} {{/* if $.Traces */}}
+
+{{if $.Histogram}}
+<h4>Latency (&micro;s) of {{$.Family}} over {{$.HistogramWindow}}</h4>
+{{$.Histogram}}
+{{end}} {{/* if $.Histogram */}}
+
+ </body>
+</html>
+{{end}} {{/* end of Epilog */}}
+`
diff --git a/vendor/golang.org/x/net/trace/trace_go16.go b/vendor/golang.org/x/net/trace/trace_go16.go
new file mode 100644
index 000000000..d60819118
--- /dev/null
+++ b/vendor/golang.org/x/net/trace/trace_go16.go
@@ -0,0 +1,21 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !go1.7
+
+package trace
+
+import "golang.org/x/net/context"
+
+// NewContext returns a copy of the parent context
+// and associates it with a Trace.
+func NewContext(ctx context.Context, tr Trace) context.Context {
+ return context.WithValue(ctx, contextKey, tr)
+}
+
+// FromContext returns the Trace bound to the context, if any.
+func FromContext(ctx context.Context) (tr Trace, ok bool) {
+ tr, ok = ctx.Value(contextKey).(Trace)
+ return
+}
diff --git a/vendor/golang.org/x/net/trace/trace_go17.go b/vendor/golang.org/x/net/trace/trace_go17.go
new file mode 100644
index 000000000..df6e1fba7
--- /dev/null
+++ b/vendor/golang.org/x/net/trace/trace_go17.go
@@ -0,0 +1,21 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build go1.7
+
+package trace
+
+import "context"
+
+// NewContext returns a copy of the parent context
+// and associates it with a Trace.
+func NewContext(ctx context.Context, tr Trace) context.Context {
+ return context.WithValue(ctx, contextKey, tr)
+}
+
+// FromContext returns the Trace bound to the context, if any.
+func FromContext(ctx context.Context) (tr Trace, ok bool) {
+ tr, ok = ctx.Value(contextKey).(Trace)
+ return
+}
diff --git a/vendor/golang.org/x/oauth2/AUTHORS b/vendor/golang.org/x/oauth2/AUTHORS
new file mode 100644
index 000000000..15167cd74
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/AUTHORS
@@ -0,0 +1,3 @@
+# This source code refers to The Go Authors for copyright purposes.
+# The master list of authors is in the main Go distribution,
+# visible at http://tip.golang.org/AUTHORS.
diff --git a/vendor/golang.org/x/oauth2/CONTRIBUTING.md b/vendor/golang.org/x/oauth2/CONTRIBUTING.md
new file mode 100644
index 000000000..dfbed62cf
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/CONTRIBUTING.md
@@ -0,0 +1,26 @@
+# Contributing to Go
+
+Go is an open source project.
+
+It is the work of hundreds of contributors. We appreciate your help!
+
+## Filing issues
+
+When [filing an issue](https://github.com/golang/oauth2/issues), make sure to answer these five questions:
+
+1. What version of Go are you using (`go version`)?
+2. What operating system and processor architecture are you using?
+3. What did you do?
+4. What did you expect to see?
+5. What did you see instead?
+
+General questions should go to the [golang-nuts mailing list](https://groups.google.com/group/golang-nuts) instead of the issue tracker.
+The gophers there will answer or ask you to file an issue if you've tripped over a bug.
+
+## Contributing code
+
+Please read the [Contribution Guidelines](https://golang.org/doc/contribute.html)
+before sending patches.
+
+Unless otherwise noted, the Go source files are distributed under
+the BSD-style license found in the LICENSE file.
diff --git a/vendor/golang.org/x/oauth2/CONTRIBUTORS b/vendor/golang.org/x/oauth2/CONTRIBUTORS
new file mode 100644
index 000000000..1c4577e96
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/CONTRIBUTORS
@@ -0,0 +1,3 @@
+# This source code was written by the Go contributors.
+# The master list of contributors is in the main Go distribution,
+# visible at http://tip.golang.org/CONTRIBUTORS.
diff --git a/vendor/golang.org/x/oauth2/LICENSE b/vendor/golang.org/x/oauth2/LICENSE
new file mode 100644
index 000000000..6a66aea5e
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/LICENSE
@@ -0,0 +1,27 @@
+Copyright (c) 2009 The Go Authors. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/vendor/golang.org/x/oauth2/README.md b/vendor/golang.org/x/oauth2/README.md
new file mode 100644
index 000000000..68f436ed9
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/README.md
@@ -0,0 +1,86 @@
+# OAuth2 for Go
+
+[![Build Status](https://travis-ci.org/golang/oauth2.svg?branch=master)](https://travis-ci.org/golang/oauth2)
+[![GoDoc](https://godoc.org/golang.org/x/oauth2?status.svg)](https://godoc.org/golang.org/x/oauth2)
+
+oauth2 package contains a client implementation for OAuth 2.0 spec.
+
+## Installation
+
+~~~~
+go get golang.org/x/oauth2
+~~~~
+
+Or you can manually git clone the repository to
+`$(go env GOPATH)/src/golang.org/x/oauth2`.
+
+See godoc for further documentation and examples.
+
+* [godoc.org/golang.org/x/oauth2](http://godoc.org/golang.org/x/oauth2)
+* [godoc.org/golang.org/x/oauth2/google](http://godoc.org/golang.org/x/oauth2/google)
+
+
+## App Engine
+
+In change 96e89be (March 2015), we removed the `oauth2.Context2` type in favor
+of the [`context.Context`](https://golang.org/x/net/context#Context) type from
+the `golang.org/x/net/context` package. Later replaced by the standard `context` package
+of the [`context.Context`](https://golang.org/pkg/context#Context) type.
+
+
+This means it's no longer possible to use the "Classic App Engine"
+`appengine.Context` type with the `oauth2` package. (You're using
+Classic App Engine if you import the package `"appengine"`.)
+
+To work around this, you may use the new `"google.golang.org/appengine"`
+package. This package has almost the same API as the `"appengine"` package,
+but it can be fetched with `go get` and used on "Managed VMs" and well as
+Classic App Engine.
+
+See the [new `appengine` package's readme](https://github.com/golang/appengine#updating-a-go-app-engine-app)
+for information on updating your app.
+
+If you don't want to update your entire app to use the new App Engine packages,
+you may use both sets of packages in parallel, using only the new packages
+with the `oauth2` package.
+
+```go
+import (
+ "context"
+ "golang.org/x/oauth2"
+ "golang.org/x/oauth2/google"
+ newappengine "google.golang.org/appengine"
+ newurlfetch "google.golang.org/appengine/urlfetch"
+
+ "appengine"
+)
+
+func handler(w http.ResponseWriter, r *http.Request) {
+ var c appengine.Context = appengine.NewContext(r)
+ c.Infof("Logging a message with the old package")
+
+ var ctx context.Context = newappengine.NewContext(r)
+ client := &http.Client{
+ Transport: &oauth2.Transport{
+ Source: google.AppEngineTokenSource(ctx, "scope"),
+ Base: &newurlfetch.Transport{Context: ctx},
+ },
+ }
+ client.Get("...")
+}
+```
+
+## Policy for new packages
+
+We no longer accept new provider-specific packages in this repo. For
+defining provider endpoints and provider-specific OAuth2 behavior, we
+encourage you to create packages elsewhere. We'll keep the existing
+packages for compatibility.
+
+## Report Issues / Send Patches
+
+This repository uses Gerrit for code changes. To learn how to submit changes to
+this repository, see https://golang.org/doc/contribute.html.
+
+The main issue tracker for the oauth2 repository is located at
+https://github.com/golang/oauth2/issues.
diff --git a/vendor/golang.org/x/oauth2/google/appengine.go b/vendor/golang.org/x/oauth2/google/appengine.go
new file mode 100644
index 000000000..feb1157b1
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/google/appengine.go
@@ -0,0 +1,38 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package google
+
+import (
+ "context"
+ "time"
+
+ "golang.org/x/oauth2"
+)
+
+// Set at init time by appengine_gen1.go. If nil, we're not on App Engine standard first generation (<= Go 1.9) or App Engine flexible.
+var appengineTokenFunc func(c context.Context, scopes ...string) (token string, expiry time.Time, err error)
+
+// Set at init time by appengine_gen1.go. If nil, we're not on App Engine standard first generation (<= Go 1.9) or App Engine flexible.
+var appengineAppIDFunc func(c context.Context) string
+
+// AppEngineTokenSource returns a token source that fetches tokens from either
+// the current application's service account or from the metadata server,
+// depending on the App Engine environment. See below for environment-specific
+// details. If you are implementing a 3-legged OAuth 2.0 flow on App Engine that
+// involves user accounts, see oauth2.Config instead.
+//
+// First generation App Engine runtimes (<= Go 1.9):
+// AppEngineTokenSource returns a token source that fetches tokens issued to the
+// current App Engine application's service account. The provided context must have
+// come from appengine.NewContext.
+//
+// Second generation App Engine runtimes (>= Go 1.11) and App Engine flexible:
+// AppEngineTokenSource is DEPRECATED on second generation runtimes and on the
+// flexible environment. It delegates to ComputeTokenSource, and the provided
+// context and scopes are not used. Please use DefaultTokenSource (or ComputeTokenSource,
+// which DefaultTokenSource will use in this case) instead.
+func AppEngineTokenSource(ctx context.Context, scope ...string) oauth2.TokenSource {
+ return appEngineTokenSource(ctx, scope...)
+}
diff --git a/vendor/golang.org/x/oauth2/google/appengine_gen1.go b/vendor/golang.org/x/oauth2/google/appengine_gen1.go
new file mode 100644
index 000000000..83dacac32
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/google/appengine_gen1.go
@@ -0,0 +1,77 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build appengine
+
+// This file applies to App Engine first generation runtimes (<= Go 1.9).
+
+package google
+
+import (
+ "context"
+ "sort"
+ "strings"
+ "sync"
+
+ "golang.org/x/oauth2"
+ "google.golang.org/appengine"
+)
+
+func init() {
+ appengineTokenFunc = appengine.AccessToken
+ appengineAppIDFunc = appengine.AppID
+}
+
+// See comment on AppEngineTokenSource in appengine.go.
+func appEngineTokenSource(ctx context.Context, scope ...string) oauth2.TokenSource {
+ scopes := append([]string{}, scope...)
+ sort.Strings(scopes)
+ return &gaeTokenSource{
+ ctx: ctx,
+ scopes: scopes,
+ key: strings.Join(scopes, " "),
+ }
+}
+
+// aeTokens helps the fetched tokens to be reused until their expiration.
+var (
+ aeTokensMu sync.Mutex
+ aeTokens = make(map[string]*tokenLock) // key is space-separated scopes
+)
+
+type tokenLock struct {
+ mu sync.Mutex // guards t; held while fetching or updating t
+ t *oauth2.Token
+}
+
+type gaeTokenSource struct {
+ ctx context.Context
+ scopes []string
+ key string // to aeTokens map; space-separated scopes
+}
+
+func (ts *gaeTokenSource) Token() (*oauth2.Token, error) {
+ aeTokensMu.Lock()
+ tok, ok := aeTokens[ts.key]
+ if !ok {
+ tok = &tokenLock{}
+ aeTokens[ts.key] = tok
+ }
+ aeTokensMu.Unlock()
+
+ tok.mu.Lock()
+ defer tok.mu.Unlock()
+ if tok.t.Valid() {
+ return tok.t, nil
+ }
+ access, exp, err := appengineTokenFunc(ts.ctx, ts.scopes...)
+ if err != nil {
+ return nil, err
+ }
+ tok.t = &oauth2.Token{
+ AccessToken: access,
+ Expiry: exp,
+ }
+ return tok.t, nil
+}
diff --git a/vendor/golang.org/x/oauth2/google/appengine_gen2_flex.go b/vendor/golang.org/x/oauth2/google/appengine_gen2_flex.go
new file mode 100644
index 000000000..04c2c2216
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/google/appengine_gen2_flex.go
@@ -0,0 +1,27 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !appengine
+
+// This file applies to App Engine second generation runtimes (>= Go 1.11) and App Engine flexible.
+
+package google
+
+import (
+ "context"
+ "log"
+ "sync"
+
+ "golang.org/x/oauth2"
+)
+
+var logOnce sync.Once // only spam about deprecation once
+
+// See comment on AppEngineTokenSource in appengine.go.
+func appEngineTokenSource(ctx context.Context, scope ...string) oauth2.TokenSource {
+ logOnce.Do(func() {
+ log.Print("google: AppEngineTokenSource is deprecated on App Engine standard second generation runtimes (>= Go 1.11) and App Engine flexible. Please use DefaultTokenSource or ComputeTokenSource.")
+ })
+ return ComputeTokenSource("")
+}
diff --git a/vendor/golang.org/x/oauth2/google/default.go b/vendor/golang.org/x/oauth2/google/default.go
new file mode 100644
index 000000000..5087d845f
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/google/default.go
@@ -0,0 +1,155 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package google
+
+import (
+ "context"
+ "encoding/json"
+ "fmt"
+ "io/ioutil"
+ "net/http"
+ "os"
+ "path/filepath"
+ "runtime"
+
+ "cloud.google.com/go/compute/metadata"
+ "golang.org/x/oauth2"
+)
+
+// Credentials holds Google credentials, including "Application Default Credentials".
+// For more details, see:
+// https://developers.google.com/accounts/docs/application-default-credentials
+type Credentials struct {
+ ProjectID string // may be empty
+ TokenSource oauth2.TokenSource
+
+ // JSON contains the raw bytes from a JSON credentials file.
+ // This field may be nil if authentication is provided by the
+ // environment and not with a credentials file, e.g. when code is
+ // running on Google Cloud Platform.
+ JSON []byte
+}
+
+// DefaultCredentials is the old name of Credentials.
+//
+// Deprecated: use Credentials instead.
+type DefaultCredentials = Credentials
+
+// DefaultClient returns an HTTP Client that uses the
+// DefaultTokenSource to obtain authentication credentials.
+func DefaultClient(ctx context.Context, scope ...string) (*http.Client, error) {
+ ts, err := DefaultTokenSource(ctx, scope...)
+ if err != nil {
+ return nil, err
+ }
+ return oauth2.NewClient(ctx, ts), nil
+}
+
+// DefaultTokenSource returns the token source for
+// "Application Default Credentials".
+// It is a shortcut for FindDefaultCredentials(ctx, scope).TokenSource.
+func DefaultTokenSource(ctx context.Context, scope ...string) (oauth2.TokenSource, error) {
+ creds, err := FindDefaultCredentials(ctx, scope...)
+ if err != nil {
+ return nil, err
+ }
+ return creds.TokenSource, nil
+}
+
+// FindDefaultCredentials searches for "Application Default Credentials".
+//
+// It looks for credentials in the following places,
+// preferring the first location found:
+//
+// 1. A JSON file whose path is specified by the
+// GOOGLE_APPLICATION_CREDENTIALS environment variable.
+// 2. A JSON file in a location known to the gcloud command-line tool.
+// On Windows, this is %APPDATA%/gcloud/application_default_credentials.json.
+// On other systems, $HOME/.config/gcloud/application_default_credentials.json.
+// 3. On Google App Engine standard first generation runtimes (<= Go 1.9) it uses
+// the appengine.AccessToken function.
+// 4. On Google Compute Engine, Google App Engine standard second generation runtimes
+// (>= Go 1.11), and Google App Engine flexible environment, it fetches
+// credentials from the metadata server.
+// (In this final case any provided scopes are ignored.)
+func FindDefaultCredentials(ctx context.Context, scopes ...string) (*Credentials, error) {
+ // First, try the environment variable.
+ const envVar = "GOOGLE_APPLICATION_CREDENTIALS"
+ if filename := os.Getenv(envVar); filename != "" {
+ creds, err := readCredentialsFile(ctx, filename, scopes)
+ if err != nil {
+ return nil, fmt.Errorf("google: error getting credentials using %v environment variable: %v", envVar, err)
+ }
+ return creds, nil
+ }
+
+ // Second, try a well-known file.
+ filename := wellKnownFile()
+ if creds, err := readCredentialsFile(ctx, filename, scopes); err == nil {
+ return creds, nil
+ } else if !os.IsNotExist(err) {
+ return nil, fmt.Errorf("google: error getting credentials using well-known file (%v): %v", filename, err)
+ }
+
+ // Third, if we're on a Google App Engine standard first generation runtime (<= Go 1.9)
+ // use those credentials. App Engine standard second generation runtimes (>= Go 1.11)
+ // and App Engine flexible use ComputeTokenSource and the metadata server.
+ if appengineTokenFunc != nil {
+ return &DefaultCredentials{
+ ProjectID: appengineAppIDFunc(ctx),
+ TokenSource: AppEngineTokenSource(ctx, scopes...),
+ }, nil
+ }
+
+ // Fourth, if we're on Google Compute Engine, an App Engine standard second generation runtime,
+ // or App Engine flexible, use the metadata server.
+ if metadata.OnGCE() {
+ id, _ := metadata.ProjectID()
+ return &DefaultCredentials{
+ ProjectID: id,
+ TokenSource: ComputeTokenSource(""),
+ }, nil
+ }
+
+ // None are found; return helpful error.
+ const url = "https://developers.google.com/accounts/docs/application-default-credentials"
+ return nil, fmt.Errorf("google: could not find default credentials. See %v for more information.", url)
+}
+
+// CredentialsFromJSON obtains Google credentials from a JSON value. The JSON can
+// represent either a Google Developers Console client_credentials.json file (as in
+// ConfigFromJSON) or a Google Developers service account key file (as in
+// JWTConfigFromJSON).
+func CredentialsFromJSON(ctx context.Context, jsonData []byte, scopes ...string) (*Credentials, error) {
+ var f credentialsFile
+ if err := json.Unmarshal(jsonData, &f); err != nil {
+ return nil, err
+ }
+ ts, err := f.tokenSource(ctx, append([]string(nil), scopes...))
+ if err != nil {
+ return nil, err
+ }
+ return &DefaultCredentials{
+ ProjectID: f.ProjectID,
+ TokenSource: ts,
+ JSON: jsonData,
+ }, nil
+}
+
+func wellKnownFile() string {
+ const f = "application_default_credentials.json"
+ if runtime.GOOS == "windows" {
+ return filepath.Join(os.Getenv("APPDATA"), "gcloud", f)
+ }
+ return filepath.Join(guessUnixHomeDir(), ".config", "gcloud", f)
+}
+
+func readCredentialsFile(ctx context.Context, filename string, scopes []string) (*DefaultCredentials, error) {
+ b, err := ioutil.ReadFile(filename)
+ if err != nil {
+ return nil, err
+ }
+ return CredentialsFromJSON(ctx, b, scopes...)
+}
diff --git a/vendor/golang.org/x/oauth2/google/doc.go b/vendor/golang.org/x/oauth2/google/doc.go
new file mode 100644
index 000000000..73be62903
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/google/doc.go
@@ -0,0 +1,40 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package google provides support for making OAuth2 authorized and authenticated
+// HTTP requests to Google APIs. It supports the Web server flow, client-side
+// credentials, service accounts, Google Compute Engine service accounts, and Google
+// App Engine service accounts.
+//
+// A brief overview of the package follows. For more information, please read
+// https://developers.google.com/accounts/docs/OAuth2
+// and
+// https://developers.google.com/accounts/docs/application-default-credentials.
+//
+// OAuth2 Configs
+//
+// Two functions in this package return golang.org/x/oauth2.Config values from Google credential
+// data. Google supports two JSON formats for OAuth2 credentials: one is handled by ConfigFromJSON,
+// the other by JWTConfigFromJSON. The returned Config can be used to obtain a TokenSource or
+// create an http.Client.
+//
+//
+// Credentials
+//
+// The Credentials type represents Google credentials, including Application Default
+// Credentials.
+//
+// Use FindDefaultCredentials to obtain Application Default Credentials.
+// FindDefaultCredentials looks in some well-known places for a credentials file, and
+// will call AppEngineTokenSource or ComputeTokenSource as needed.
+//
+// DefaultClient and DefaultTokenSource are convenience methods. They first call FindDefaultCredentials,
+// then use the credentials to construct an http.Client or an oauth2.TokenSource.
+//
+// Use CredentialsFromJSON to obtain credentials from either of the two JSON formats
+// described in OAuth2 Configs, above. The TokenSource in the returned value is the
+// same as the one obtained from the oauth2.Config returned from ConfigFromJSON or
+// JWTConfigFromJSON, but the Credentials may contain additional information
+// that is useful is some circumstances.
+package google // import "golang.org/x/oauth2/google"
diff --git a/vendor/golang.org/x/oauth2/google/google.go b/vendor/golang.org/x/oauth2/google/google.go
new file mode 100644
index 000000000..ca7d208d7
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/google/google.go
@@ -0,0 +1,192 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package google
+
+import (
+ "context"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "strings"
+ "time"
+
+ "cloud.google.com/go/compute/metadata"
+ "golang.org/x/oauth2"
+ "golang.org/x/oauth2/jwt"
+)
+
+// Endpoint is Google's OAuth 2.0 endpoint.
+var Endpoint = oauth2.Endpoint{
+ AuthURL: "https://accounts.google.com/o/oauth2/auth",
+ TokenURL: "https://accounts.google.com/o/oauth2/token",
+}
+
+// JWTTokenURL is Google's OAuth 2.0 token URL to use with the JWT flow.
+const JWTTokenURL = "https://accounts.google.com/o/oauth2/token"
+
+// ConfigFromJSON uses a Google Developers Console client_credentials.json
+// file to construct a config.
+// client_credentials.json can be downloaded from
+// https://console.developers.google.com, under "Credentials". Download the Web
+// application credentials in the JSON format and provide the contents of the
+// file as jsonKey.
+func ConfigFromJSON(jsonKey []byte, scope ...string) (*oauth2.Config, error) {
+ type cred struct {
+ ClientID string `json:"client_id"`
+ ClientSecret string `json:"client_secret"`
+ RedirectURIs []string `json:"redirect_uris"`
+ AuthURI string `json:"auth_uri"`
+ TokenURI string `json:"token_uri"`
+ }
+ var j struct {
+ Web *cred `json:"web"`
+ Installed *cred `json:"installed"`
+ }
+ if err := json.Unmarshal(jsonKey, &j); err != nil {
+ return nil, err
+ }
+ var c *cred
+ switch {
+ case j.Web != nil:
+ c = j.Web
+ case j.Installed != nil:
+ c = j.Installed
+ default:
+ return nil, fmt.Errorf("oauth2/google: no credentials found")
+ }
+ if len(c.RedirectURIs) < 1 {
+ return nil, errors.New("oauth2/google: missing redirect URL in the client_credentials.json")
+ }
+ return &oauth2.Config{
+ ClientID: c.ClientID,
+ ClientSecret: c.ClientSecret,
+ RedirectURL: c.RedirectURIs[0],
+ Scopes: scope,
+ Endpoint: oauth2.Endpoint{
+ AuthURL: c.AuthURI,
+ TokenURL: c.TokenURI,
+ },
+ }, nil
+}
+
+// JWTConfigFromJSON uses a Google Developers service account JSON key file to read
+// the credentials that authorize and authenticate the requests.
+// Create a service account on "Credentials" for your project at
+// https://console.developers.google.com to download a JSON key file.
+func JWTConfigFromJSON(jsonKey []byte, scope ...string) (*jwt.Config, error) {
+ var f credentialsFile
+ if err := json.Unmarshal(jsonKey, &f); err != nil {
+ return nil, err
+ }
+ if f.Type != serviceAccountKey {
+ return nil, fmt.Errorf("google: read JWT from JSON credentials: 'type' field is %q (expected %q)", f.Type, serviceAccountKey)
+ }
+ scope = append([]string(nil), scope...) // copy
+ return f.jwtConfig(scope), nil
+}
+
+// JSON key file types.
+const (
+ serviceAccountKey = "service_account"
+ userCredentialsKey = "authorized_user"
+)
+
+// credentialsFile is the unmarshalled representation of a credentials file.
+type credentialsFile struct {
+ Type string `json:"type"` // serviceAccountKey or userCredentialsKey
+
+ // Service Account fields
+ ClientEmail string `json:"client_email"`
+ PrivateKeyID string `json:"private_key_id"`
+ PrivateKey string `json:"private_key"`
+ TokenURL string `json:"token_uri"`
+ ProjectID string `json:"project_id"`
+
+ // User Credential fields
+ // (These typically come from gcloud auth.)
+ ClientSecret string `json:"client_secret"`
+ ClientID string `json:"client_id"`
+ RefreshToken string `json:"refresh_token"`
+}
+
+func (f *credentialsFile) jwtConfig(scopes []string) *jwt.Config {
+ cfg := &jwt.Config{
+ Email: f.ClientEmail,
+ PrivateKey: []byte(f.PrivateKey),
+ PrivateKeyID: f.PrivateKeyID,
+ Scopes: scopes,
+ TokenURL: f.TokenURL,
+ }
+ if cfg.TokenURL == "" {
+ cfg.TokenURL = JWTTokenURL
+ }
+ return cfg
+}
+
+func (f *credentialsFile) tokenSource(ctx context.Context, scopes []string) (oauth2.TokenSource, error) {
+ switch f.Type {
+ case serviceAccountKey:
+ cfg := f.jwtConfig(scopes)
+ return cfg.TokenSource(ctx), nil
+ case userCredentialsKey:
+ cfg := &oauth2.Config{
+ ClientID: f.ClientID,
+ ClientSecret: f.ClientSecret,
+ Scopes: scopes,
+ Endpoint: Endpoint,
+ }
+ tok := &oauth2.Token{RefreshToken: f.RefreshToken}
+ return cfg.TokenSource(ctx, tok), nil
+ case "":
+ return nil, errors.New("missing 'type' field in credentials")
+ default:
+ return nil, fmt.Errorf("unknown credential type: %q", f.Type)
+ }
+}
+
+// ComputeTokenSource returns a token source that fetches access tokens
+// from Google Compute Engine (GCE)'s metadata server. It's only valid to use
+// this token source if your program is running on a GCE instance.
+// If no account is specified, "default" is used.
+// Further information about retrieving access tokens from the GCE metadata
+// server can be found at https://cloud.google.com/compute/docs/authentication.
+func ComputeTokenSource(account string) oauth2.TokenSource {
+ return oauth2.ReuseTokenSource(nil, computeSource{account: account})
+}
+
+type computeSource struct {
+ account string
+}
+
+func (cs computeSource) Token() (*oauth2.Token, error) {
+ if !metadata.OnGCE() {
+ return nil, errors.New("oauth2/google: can't get a token from the metadata service; not running on GCE")
+ }
+ acct := cs.account
+ if acct == "" {
+ acct = "default"
+ }
+ tokenJSON, err := metadata.Get("instance/service-accounts/" + acct + "/token")
+ if err != nil {
+ return nil, err
+ }
+ var res struct {
+ AccessToken string `json:"access_token"`
+ ExpiresInSec int `json:"expires_in"`
+ TokenType string `json:"token_type"`
+ }
+ err = json.NewDecoder(strings.NewReader(tokenJSON)).Decode(&res)
+ if err != nil {
+ return nil, fmt.Errorf("oauth2/google: invalid token JSON from metadata: %v", err)
+ }
+ if res.ExpiresInSec == 0 || res.AccessToken == "" {
+ return nil, fmt.Errorf("oauth2/google: incomplete token received from metadata")
+ }
+ return &oauth2.Token{
+ AccessToken: res.AccessToken,
+ TokenType: res.TokenType,
+ Expiry: time.Now().Add(time.Duration(res.ExpiresInSec) * time.Second),
+ }, nil
+}
diff --git a/vendor/golang.org/x/oauth2/google/jwt.go b/vendor/golang.org/x/oauth2/google/jwt.go
new file mode 100644
index 000000000..b0fdb3a88
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/google/jwt.go
@@ -0,0 +1,74 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package google
+
+import (
+ "crypto/rsa"
+ "fmt"
+ "time"
+
+ "golang.org/x/oauth2"
+ "golang.org/x/oauth2/internal"
+ "golang.org/x/oauth2/jws"
+)
+
+// JWTAccessTokenSourceFromJSON uses a Google Developers service account JSON
+// key file to read the credentials that authorize and authenticate the
+// requests, and returns a TokenSource that does not use any OAuth2 flow but
+// instead creates a JWT and sends that as the access token.
+// The audience is typically a URL that specifies the scope of the credentials.
+//
+// Note that this is not a standard OAuth flow, but rather an
+// optimization supported by a few Google services.
+// Unless you know otherwise, you should use JWTConfigFromJSON instead.
+func JWTAccessTokenSourceFromJSON(jsonKey []byte, audience string) (oauth2.TokenSource, error) {
+ cfg, err := JWTConfigFromJSON(jsonKey)
+ if err != nil {
+ return nil, fmt.Errorf("google: could not parse JSON key: %v", err)
+ }
+ pk, err := internal.ParseKey(cfg.PrivateKey)
+ if err != nil {
+ return nil, fmt.Errorf("google: could not parse key: %v", err)
+ }
+ ts := &jwtAccessTokenSource{
+ email: cfg.Email,
+ audience: audience,
+ pk: pk,
+ pkID: cfg.PrivateKeyID,
+ }
+ tok, err := ts.Token()
+ if err != nil {
+ return nil, err
+ }
+ return oauth2.ReuseTokenSource(tok, ts), nil
+}
+
+type jwtAccessTokenSource struct {
+ email, audience string
+ pk *rsa.PrivateKey
+ pkID string
+}
+
+func (ts *jwtAccessTokenSource) Token() (*oauth2.Token, error) {
+ iat := time.Now()
+ exp := iat.Add(time.Hour)
+ cs := &jws.ClaimSet{
+ Iss: ts.email,
+ Sub: ts.email,
+ Aud: ts.audience,
+ Iat: iat.Unix(),
+ Exp: exp.Unix(),
+ }
+ hdr := &jws.Header{
+ Algorithm: "RS256",
+ Typ: "JWT",
+ KeyID: string(ts.pkID),
+ }
+ msg, err := jws.Encode(hdr, cs, ts.pk)
+ if err != nil {
+ return nil, fmt.Errorf("google: could not encode JWT: %v", err)
+ }
+ return &oauth2.Token{AccessToken: msg, TokenType: "Bearer", Expiry: exp}, nil
+}
diff --git a/vendor/golang.org/x/oauth2/google/sdk.go b/vendor/golang.org/x/oauth2/google/sdk.go
new file mode 100644
index 000000000..456224bc7
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/google/sdk.go
@@ -0,0 +1,201 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package google
+
+import (
+ "bufio"
+ "context"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "io"
+ "net/http"
+ "os"
+ "os/user"
+ "path/filepath"
+ "runtime"
+ "strings"
+ "time"
+
+ "golang.org/x/oauth2"
+)
+
+type sdkCredentials struct {
+ Data []struct {
+ Credential struct {
+ ClientID string `json:"client_id"`
+ ClientSecret string `json:"client_secret"`
+ AccessToken string `json:"access_token"`
+ RefreshToken string `json:"refresh_token"`
+ TokenExpiry *time.Time `json:"token_expiry"`
+ } `json:"credential"`
+ Key struct {
+ Account string `json:"account"`
+ Scope string `json:"scope"`
+ } `json:"key"`
+ }
+}
+
+// An SDKConfig provides access to tokens from an account already
+// authorized via the Google Cloud SDK.
+type SDKConfig struct {
+ conf oauth2.Config
+ initialToken *oauth2.Token
+}
+
+// NewSDKConfig creates an SDKConfig for the given Google Cloud SDK
+// account. If account is empty, the account currently active in
+// Google Cloud SDK properties is used.
+// Google Cloud SDK credentials must be created by running `gcloud auth`
+// before using this function.
+// The Google Cloud SDK is available at https://cloud.google.com/sdk/.
+func NewSDKConfig(account string) (*SDKConfig, error) {
+ configPath, err := sdkConfigPath()
+ if err != nil {
+ return nil, fmt.Errorf("oauth2/google: error getting SDK config path: %v", err)
+ }
+ credentialsPath := filepath.Join(configPath, "credentials")
+ f, err := os.Open(credentialsPath)
+ if err != nil {
+ return nil, fmt.Errorf("oauth2/google: failed to load SDK credentials: %v", err)
+ }
+ defer f.Close()
+
+ var c sdkCredentials
+ if err := json.NewDecoder(f).Decode(&c); err != nil {
+ return nil, fmt.Errorf("oauth2/google: failed to decode SDK credentials from %q: %v", credentialsPath, err)
+ }
+ if len(c.Data) == 0 {
+ return nil, fmt.Errorf("oauth2/google: no credentials found in %q, run `gcloud auth login` to create one", credentialsPath)
+ }
+ if account == "" {
+ propertiesPath := filepath.Join(configPath, "properties")
+ f, err := os.Open(propertiesPath)
+ if err != nil {
+ return nil, fmt.Errorf("oauth2/google: failed to load SDK properties: %v", err)
+ }
+ defer f.Close()
+ ini, err := parseINI(f)
+ if err != nil {
+ return nil, fmt.Errorf("oauth2/google: failed to parse SDK properties %q: %v", propertiesPath, err)
+ }
+ core, ok := ini["core"]
+ if !ok {
+ return nil, fmt.Errorf("oauth2/google: failed to find [core] section in %v", ini)
+ }
+ active, ok := core["account"]
+ if !ok {
+ return nil, fmt.Errorf("oauth2/google: failed to find %q attribute in %v", "account", core)
+ }
+ account = active
+ }
+
+ for _, d := range c.Data {
+ if account == "" || d.Key.Account == account {
+ if d.Credential.AccessToken == "" && d.Credential.RefreshToken == "" {
+ return nil, fmt.Errorf("oauth2/google: no token available for account %q", account)
+ }
+ var expiry time.Time
+ if d.Credential.TokenExpiry != nil {
+ expiry = *d.Credential.TokenExpiry
+ }
+ return &SDKConfig{
+ conf: oauth2.Config{
+ ClientID: d.Credential.ClientID,
+ ClientSecret: d.Credential.ClientSecret,
+ Scopes: strings.Split(d.Key.Scope, " "),
+ Endpoint: Endpoint,
+ RedirectURL: "oob",
+ },
+ initialToken: &oauth2.Token{
+ AccessToken: d.Credential.AccessToken,
+ RefreshToken: d.Credential.RefreshToken,
+ Expiry: expiry,
+ },
+ }, nil
+ }
+ }
+ return nil, fmt.Errorf("oauth2/google: no such credentials for account %q", account)
+}
+
+// Client returns an HTTP client using Google Cloud SDK credentials to
+// authorize requests. The token will auto-refresh as necessary. The
+// underlying http.RoundTripper will be obtained using the provided
+// context. The returned client and its Transport should not be
+// modified.
+func (c *SDKConfig) Client(ctx context.Context) *http.Client {
+ return &http.Client{
+ Transport: &oauth2.Transport{
+ Source: c.TokenSource(ctx),
+ },
+ }
+}
+
+// TokenSource returns an oauth2.TokenSource that retrieve tokens from
+// Google Cloud SDK credentials using the provided context.
+// It will returns the current access token stored in the credentials,
+// and refresh it when it expires, but it won't update the credentials
+// with the new access token.
+func (c *SDKConfig) TokenSource(ctx context.Context) oauth2.TokenSource {
+ return c.conf.TokenSource(ctx, c.initialToken)
+}
+
+// Scopes are the OAuth 2.0 scopes the current account is authorized for.
+func (c *SDKConfig) Scopes() []string {
+ return c.conf.Scopes
+}
+
+func parseINI(ini io.Reader) (map[string]map[string]string, error) {
+ result := map[string]map[string]string{
+ "": {}, // root section
+ }
+ scanner := bufio.NewScanner(ini)
+ currentSection := ""
+ for scanner.Scan() {
+ line := strings.TrimSpace(scanner.Text())
+ if strings.HasPrefix(line, ";") {
+ // comment.
+ continue
+ }
+ if strings.HasPrefix(line, "[") && strings.HasSuffix(line, "]") {
+ currentSection = strings.TrimSpace(line[1 : len(line)-1])
+ result[currentSection] = map[string]string{}
+ continue
+ }
+ parts := strings.SplitN(line, "=", 2)
+ if len(parts) == 2 && parts[0] != "" {
+ result[currentSection][strings.TrimSpace(parts[0])] = strings.TrimSpace(parts[1])
+ }
+ }
+ if err := scanner.Err(); err != nil {
+ return nil, fmt.Errorf("error scanning ini: %v", err)
+ }
+ return result, nil
+}
+
+// sdkConfigPath tries to guess where the gcloud config is located.
+// It can be overridden during tests.
+var sdkConfigPath = func() (string, error) {
+ if runtime.GOOS == "windows" {
+ return filepath.Join(os.Getenv("APPDATA"), "gcloud"), nil
+ }
+ homeDir := guessUnixHomeDir()
+ if homeDir == "" {
+ return "", errors.New("unable to get current user home directory: os/user lookup failed; $HOME is empty")
+ }
+ return filepath.Join(homeDir, ".config", "gcloud"), nil
+}
+
+func guessUnixHomeDir() string {
+ // Prefer $HOME over user.Current due to glibc bug: golang.org/issue/13470
+ if v := os.Getenv("HOME"); v != "" {
+ return v
+ }
+ // Else, fall back to user.Current:
+ if u, err := user.Current(); err == nil {
+ return u.HomeDir
+ }
+ return ""
+}
diff --git a/vendor/golang.org/x/oauth2/internal/client_appengine.go b/vendor/golang.org/x/oauth2/internal/client_appengine.go
new file mode 100644
index 000000000..743487188
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/internal/client_appengine.go
@@ -0,0 +1,13 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build appengine
+
+package internal
+
+import "google.golang.org/appengine/urlfetch"
+
+func init() {
+ appengineClientHook = urlfetch.Client
+}
diff --git a/vendor/golang.org/x/oauth2/internal/doc.go b/vendor/golang.org/x/oauth2/internal/doc.go
new file mode 100644
index 000000000..03265e888
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/internal/doc.go
@@ -0,0 +1,6 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package internal contains support packages for oauth2 package.
+package internal
diff --git a/vendor/golang.org/x/oauth2/internal/oauth2.go b/vendor/golang.org/x/oauth2/internal/oauth2.go
new file mode 100644
index 000000000..c0ab196cf
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/internal/oauth2.go
@@ -0,0 +1,37 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package internal
+
+import (
+ "crypto/rsa"
+ "crypto/x509"
+ "encoding/pem"
+ "errors"
+ "fmt"
+)
+
+// ParseKey converts the binary contents of a private key file
+// to an *rsa.PrivateKey. It detects whether the private key is in a
+// PEM container or not. If so, it extracts the the private key
+// from PEM container before conversion. It only supports PEM
+// containers with no passphrase.
+func ParseKey(key []byte) (*rsa.PrivateKey, error) {
+ block, _ := pem.Decode(key)
+ if block != nil {
+ key = block.Bytes
+ }
+ parsedKey, err := x509.ParsePKCS8PrivateKey(key)
+ if err != nil {
+ parsedKey, err = x509.ParsePKCS1PrivateKey(key)
+ if err != nil {
+ return nil, fmt.Errorf("private key should be a PEM or plain PKCS1 or PKCS8; parse error: %v", err)
+ }
+ }
+ parsed, ok := parsedKey.(*rsa.PrivateKey)
+ if !ok {
+ return nil, errors.New("private key is invalid")
+ }
+ return parsed, nil
+}
diff --git a/vendor/golang.org/x/oauth2/internal/token.go b/vendor/golang.org/x/oauth2/internal/token.go
new file mode 100644
index 000000000..a831b7746
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/internal/token.go
@@ -0,0 +1,277 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package internal
+
+import (
+ "context"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "mime"
+ "net/http"
+ "net/url"
+ "strconv"
+ "strings"
+ "time"
+
+ "golang.org/x/net/context/ctxhttp"
+)
+
+// Token represents the credentials used to authorize
+// the requests to access protected resources on the OAuth 2.0
+// provider's backend.
+//
+// This type is a mirror of oauth2.Token and exists to break
+// an otherwise-circular dependency. Other internal packages
+// should convert this Token into an oauth2.Token before use.
+type Token struct {
+ // AccessToken is the token that authorizes and authenticates
+ // the requests.
+ AccessToken string
+
+ // TokenType is the type of token.
+ // The Type method returns either this or "Bearer", the default.
+ TokenType string
+
+ // RefreshToken is a token that's used by the application
+ // (as opposed to the user) to refresh the access token
+ // if it expires.
+ RefreshToken string
+
+ // Expiry is the optional expiration time of the access token.
+ //
+ // If zero, TokenSource implementations will reuse the same
+ // token forever and RefreshToken or equivalent
+ // mechanisms for that TokenSource will not be used.
+ Expiry time.Time
+
+ // Raw optionally contains extra metadata from the server
+ // when updating a token.
+ Raw interface{}
+}
+
+// tokenJSON is the struct representing the HTTP response from OAuth2
+// providers returning a token in JSON form.
+type tokenJSON struct {
+ AccessToken string `json:"access_token"`
+ TokenType string `json:"token_type"`
+ RefreshToken string `json:"refresh_token"`
+ ExpiresIn expirationTime `json:"expires_in"` // at least PayPal returns string, while most return number
+ Expires expirationTime `json:"expires"` // broken Facebook spelling of expires_in
+}
+
+func (e *tokenJSON) expiry() (t time.Time) {
+ if v := e.ExpiresIn; v != 0 {
+ return time.Now().Add(time.Duration(v) * time.Second)
+ }
+ if v := e.Expires; v != 0 {
+ return time.Now().Add(time.Duration(v) * time.Second)
+ }
+ return
+}
+
+type expirationTime int32
+
+func (e *expirationTime) UnmarshalJSON(b []byte) error {
+ var n json.Number
+ err := json.Unmarshal(b, &n)
+ if err != nil {
+ return err
+ }
+ i, err := n.Int64()
+ if err != nil {
+ return err
+ }
+ *e = expirationTime(i)
+ return nil
+}
+
+var brokenAuthHeaderProviders = []string{
+ "https://accounts.google.com/",
+ "https://api.codeswholesale.com/oauth/token",
+ "https://api.dropbox.com/",
+ "https://api.dropboxapi.com/",
+ "https://api.instagram.com/",
+ "https://api.netatmo.net/",
+ "https://api.odnoklassniki.ru/",
+ "https://api.pushbullet.com/",
+ "https://api.soundcloud.com/",
+ "https://api.twitch.tv/",
+ "https://id.twitch.tv/",
+ "https://app.box.com/",
+ "https://api.box.com/",
+ "https://connect.stripe.com/",
+ "https://login.mailchimp.com/",
+ "https://login.microsoftonline.com/",
+ "https://login.salesforce.com/",
+ "https://login.windows.net",
+ "https://login.live.com/",
+ "https://login.live-int.com/",
+ "https://oauth.sandbox.trainingpeaks.com/",
+ "https://oauth.trainingpeaks.com/",
+ "https://oauth.vk.com/",
+ "https://openapi.baidu.com/",
+ "https://slack.com/",
+ "https://test-sandbox.auth.corp.google.com",
+ "https://test.salesforce.com/",
+ "https://user.gini.net/",
+ "https://www.douban.com/",
+ "https://www.googleapis.com/",
+ "https://www.linkedin.com/",
+ "https://www.strava.com/oauth/",
+ "https://www.wunderlist.com/oauth/",
+ "https://api.patreon.com/",
+ "https://sandbox.codeswholesale.com/oauth/token",
+ "https://api.sipgate.com/v1/authorization/oauth",
+ "https://api.medium.com/v1/tokens",
+ "https://log.finalsurge.com/oauth/token",
+ "https://multisport.todaysplan.com.au/rest/oauth/access_token",
+ "https://whats.todaysplan.com.au/rest/oauth/access_token",
+ "https://stackoverflow.com/oauth/access_token",
+ "https://account.health.nokia.com",
+ "https://accounts.zoho.com",
+ "https://gitter.im/login/oauth/token",
+ "https://openid-connect.onelogin.com/oidc",
+ "https://api.dailymotion.com/oauth/token",
+}
+
+// brokenAuthHeaderDomains lists broken providers that issue dynamic endpoints.
+var brokenAuthHeaderDomains = []string{
+ ".auth0.com",
+ ".force.com",
+ ".myshopify.com",
+ ".okta.com",
+ ".oktapreview.com",
+}
+
+func RegisterBrokenAuthHeaderProvider(tokenURL string) {
+ brokenAuthHeaderProviders = append(brokenAuthHeaderProviders, tokenURL)
+}
+
+// providerAuthHeaderWorks reports whether the OAuth2 server identified by the tokenURL
+// implements the OAuth2 spec correctly
+// See https://code.google.com/p/goauth2/issues/detail?id=31 for background.
+// In summary:
+// - Reddit only accepts client secret in the Authorization header
+// - Dropbox accepts either it in URL param or Auth header, but not both.
+// - Google only accepts URL param (not spec compliant?), not Auth header
+// - Stripe only accepts client secret in Auth header with Bearer method, not Basic
+func providerAuthHeaderWorks(tokenURL string) bool {
+ for _, s := range brokenAuthHeaderProviders {
+ if strings.HasPrefix(tokenURL, s) {
+ // Some sites fail to implement the OAuth2 spec fully.
+ return false
+ }
+ }
+
+ if u, err := url.Parse(tokenURL); err == nil {
+ for _, s := range brokenAuthHeaderDomains {
+ if strings.HasSuffix(u.Host, s) {
+ return false
+ }
+ }
+ }
+
+ // Assume the provider implements the spec properly
+ // otherwise. We can add more exceptions as they're
+ // discovered. We will _not_ be adding configurable hooks
+ // to this package to let users select server bugs.
+ return true
+}
+
+func RetrieveToken(ctx context.Context, clientID, clientSecret, tokenURL string, v url.Values) (*Token, error) {
+ bustedAuth := !providerAuthHeaderWorks(tokenURL)
+ if bustedAuth {
+ if clientID != "" {
+ v.Set("client_id", clientID)
+ }
+ if clientSecret != "" {
+ v.Set("client_secret", clientSecret)
+ }
+ }
+ req, err := http.NewRequest("POST", tokenURL, strings.NewReader(v.Encode()))
+ if err != nil {
+ return nil, err
+ }
+ req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
+ if !bustedAuth {
+ req.SetBasicAuth(url.QueryEscape(clientID), url.QueryEscape(clientSecret))
+ }
+ r, err := ctxhttp.Do(ctx, ContextClient(ctx), req)
+ if err != nil {
+ return nil, err
+ }
+ defer r.Body.Close()
+ body, err := ioutil.ReadAll(io.LimitReader(r.Body, 1<<20))
+ if err != nil {
+ return nil, fmt.Errorf("oauth2: cannot fetch token: %v", err)
+ }
+ if code := r.StatusCode; code < 200 || code > 299 {
+ return nil, &RetrieveError{
+ Response: r,
+ Body: body,
+ }
+ }
+
+ var token *Token
+ content, _, _ := mime.ParseMediaType(r.Header.Get("Content-Type"))
+ switch content {
+ case "application/x-www-form-urlencoded", "text/plain":
+ vals, err := url.ParseQuery(string(body))
+ if err != nil {
+ return nil, err
+ }
+ token = &Token{
+ AccessToken: vals.Get("access_token"),
+ TokenType: vals.Get("token_type"),
+ RefreshToken: vals.Get("refresh_token"),
+ Raw: vals,
+ }
+ e := vals.Get("expires_in")
+ if e == "" {
+ // TODO(jbd): Facebook's OAuth2 implementation is broken and
+ // returns expires_in field in expires. Remove the fallback to expires,
+ // when Facebook fixes their implementation.
+ e = vals.Get("expires")
+ }
+ expires, _ := strconv.Atoi(e)
+ if expires != 0 {
+ token.Expiry = time.Now().Add(time.Duration(expires) * time.Second)
+ }
+ default:
+ var tj tokenJSON
+ if err = json.Unmarshal(body, &tj); err != nil {
+ return nil, err
+ }
+ token = &Token{
+ AccessToken: tj.AccessToken,
+ TokenType: tj.TokenType,
+ RefreshToken: tj.RefreshToken,
+ Expiry: tj.expiry(),
+ Raw: make(map[string]interface{}),
+ }
+ json.Unmarshal(body, &token.Raw) // no error checks for optional fields
+ }
+ // Don't overwrite `RefreshToken` with an empty value
+ // if this was a token refreshing request.
+ if token.RefreshToken == "" {
+ token.RefreshToken = v.Get("refresh_token")
+ }
+ if token.AccessToken == "" {
+ return token, errors.New("oauth2: server response missing access_token")
+ }
+ return token, nil
+}
+
+type RetrieveError struct {
+ Response *http.Response
+ Body []byte
+}
+
+func (r *RetrieveError) Error() string {
+ return fmt.Sprintf("oauth2: cannot fetch token: %v\nResponse: %s", r.Response.Status, r.Body)
+}
diff --git a/vendor/golang.org/x/oauth2/internal/transport.go b/vendor/golang.org/x/oauth2/internal/transport.go
new file mode 100644
index 000000000..572074a63
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/internal/transport.go
@@ -0,0 +1,33 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package internal
+
+import (
+ "context"
+ "net/http"
+)
+
+// HTTPClient is the context key to use with golang.org/x/net/context's
+// WithValue function to associate an *http.Client value with a context.
+var HTTPClient ContextKey
+
+// ContextKey is just an empty struct. It exists so HTTPClient can be
+// an immutable public variable with a unique type. It's immutable
+// because nobody else can create a ContextKey, being unexported.
+type ContextKey struct{}
+
+var appengineClientHook func(context.Context) *http.Client
+
+func ContextClient(ctx context.Context) *http.Client {
+ if ctx != nil {
+ if hc, ok := ctx.Value(HTTPClient).(*http.Client); ok {
+ return hc
+ }
+ }
+ if appengineClientHook != nil {
+ return appengineClientHook(ctx)
+ }
+ return http.DefaultClient
+}
diff --git a/vendor/golang.org/x/oauth2/jws/jws.go b/vendor/golang.org/x/oauth2/jws/jws.go
new file mode 100644
index 000000000..683d2d271
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/jws/jws.go
@@ -0,0 +1,182 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package jws provides a partial implementation
+// of JSON Web Signature encoding and decoding.
+// It exists to support the golang.org/x/oauth2 package.
+//
+// See RFC 7515.
+//
+// Deprecated: this package is not intended for public use and might be
+// removed in the future. It exists for internal use only.
+// Please switch to another JWS package or copy this package into your own
+// source tree.
+package jws // import "golang.org/x/oauth2/jws"
+
+import (
+ "bytes"
+ "crypto"
+ "crypto/rand"
+ "crypto/rsa"
+ "crypto/sha256"
+ "encoding/base64"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "strings"
+ "time"
+)
+
+// ClaimSet contains information about the JWT signature including the
+// permissions being requested (scopes), the target of the token, the issuer,
+// the time the token was issued, and the lifetime of the token.
+type ClaimSet struct {
+ Iss string `json:"iss"` // email address of the client_id of the application making the access token request
+ Scope string `json:"scope,omitempty"` // space-delimited list of the permissions the application requests
+ Aud string `json:"aud"` // descriptor of the intended target of the assertion (Optional).
+ Exp int64 `json:"exp"` // the expiration time of the assertion (seconds since Unix epoch)
+ Iat int64 `json:"iat"` // the time the assertion was issued (seconds since Unix epoch)
+ Typ string `json:"typ,omitempty"` // token type (Optional).
+
+ // Email for which the application is requesting delegated access (Optional).
+ Sub string `json:"sub,omitempty"`
+
+ // The old name of Sub. Client keeps setting Prn to be
+ // complaint with legacy OAuth 2.0 providers. (Optional)
+ Prn string `json:"prn,omitempty"`
+
+ // See http://tools.ietf.org/html/draft-jones-json-web-token-10#section-4.3
+ // This array is marshalled using custom code (see (c *ClaimSet) encode()).
+ PrivateClaims map[string]interface{} `json:"-"`
+}
+
+func (c *ClaimSet) encode() (string, error) {
+ // Reverting time back for machines whose time is not perfectly in sync.
+ // If client machine's time is in the future according
+ // to Google servers, an access token will not be issued.
+ now := time.Now().Add(-10 * time.Second)
+ if c.Iat == 0 {
+ c.Iat = now.Unix()
+ }
+ if c.Exp == 0 {
+ c.Exp = now.Add(time.Hour).Unix()
+ }
+ if c.Exp < c.Iat {
+ return "", fmt.Errorf("jws: invalid Exp = %v; must be later than Iat = %v", c.Exp, c.Iat)
+ }
+
+ b, err := json.Marshal(c)
+ if err != nil {
+ return "", err
+ }
+
+ if len(c.PrivateClaims) == 0 {
+ return base64.RawURLEncoding.EncodeToString(b), nil
+ }
+
+ // Marshal private claim set and then append it to b.
+ prv, err := json.Marshal(c.PrivateClaims)
+ if err != nil {
+ return "", fmt.Errorf("jws: invalid map of private claims %v", c.PrivateClaims)
+ }
+
+ // Concatenate public and private claim JSON objects.
+ if !bytes.HasSuffix(b, []byte{'}'}) {
+ return "", fmt.Errorf("jws: invalid JSON %s", b)
+ }
+ if !bytes.HasPrefix(prv, []byte{'{'}) {
+ return "", fmt.Errorf("jws: invalid JSON %s", prv)
+ }
+ b[len(b)-1] = ',' // Replace closing curly brace with a comma.
+ b = append(b, prv[1:]...) // Append private claims.
+ return base64.RawURLEncoding.EncodeToString(b), nil
+}
+
+// Header represents the header for the signed JWS payloads.
+type Header struct {
+ // The algorithm used for signature.
+ Algorithm string `json:"alg"`
+
+ // Represents the token type.
+ Typ string `json:"typ"`
+
+ // The optional hint of which key is being used.
+ KeyID string `json:"kid,omitempty"`
+}
+
+func (h *Header) encode() (string, error) {
+ b, err := json.Marshal(h)
+ if err != nil {
+ return "", err
+ }
+ return base64.RawURLEncoding.EncodeToString(b), nil
+}
+
+// Decode decodes a claim set from a JWS payload.
+func Decode(payload string) (*ClaimSet, error) {
+ // decode returned id token to get expiry
+ s := strings.Split(payload, ".")
+ if len(s) < 2 {
+ // TODO(jbd): Provide more context about the error.
+ return nil, errors.New("jws: invalid token received")
+ }
+ decoded, err := base64.RawURLEncoding.DecodeString(s[1])
+ if err != nil {
+ return nil, err
+ }
+ c := &ClaimSet{}
+ err = json.NewDecoder(bytes.NewBuffer(decoded)).Decode(c)
+ return c, err
+}
+
+// Signer returns a signature for the given data.
+type Signer func(data []byte) (sig []byte, err error)
+
+// EncodeWithSigner encodes a header and claim set with the provided signer.
+func EncodeWithSigner(header *Header, c *ClaimSet, sg Signer) (string, error) {
+ head, err := header.encode()
+ if err != nil {
+ return "", err
+ }
+ cs, err := c.encode()
+ if err != nil {
+ return "", err
+ }
+ ss := fmt.Sprintf("%s.%s", head, cs)
+ sig, err := sg([]byte(ss))
+ if err != nil {
+ return "", err
+ }
+ return fmt.Sprintf("%s.%s", ss, base64.RawURLEncoding.EncodeToString(sig)), nil
+}
+
+// Encode encodes a signed JWS with provided header and claim set.
+// This invokes EncodeWithSigner using crypto/rsa.SignPKCS1v15 with the given RSA private key.
+func Encode(header *Header, c *ClaimSet, key *rsa.PrivateKey) (string, error) {
+ sg := func(data []byte) (sig []byte, err error) {
+ h := sha256.New()
+ h.Write(data)
+ return rsa.SignPKCS1v15(rand.Reader, key, crypto.SHA256, h.Sum(nil))
+ }
+ return EncodeWithSigner(header, c, sg)
+}
+
+// Verify tests whether the provided JWT token's signature was produced by the private key
+// associated with the supplied public key.
+func Verify(token string, key *rsa.PublicKey) error {
+ parts := strings.Split(token, ".")
+ if len(parts) != 3 {
+ return errors.New("jws: invalid token received, token must have 3 parts")
+ }
+
+ signedContent := parts[0] + "." + parts[1]
+ signatureString, err := base64.RawURLEncoding.DecodeString(parts[2])
+ if err != nil {
+ return err
+ }
+
+ h := sha256.New()
+ h.Write([]byte(signedContent))
+ return rsa.VerifyPKCS1v15(key, crypto.SHA256, h.Sum(nil), []byte(signatureString))
+}
diff --git a/vendor/golang.org/x/oauth2/jwt/jwt.go b/vendor/golang.org/x/oauth2/jwt/jwt.go
new file mode 100644
index 000000000..0783a94c4
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/jwt/jwt.go
@@ -0,0 +1,162 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package jwt implements the OAuth 2.0 JSON Web Token flow, commonly
+// known as "two-legged OAuth 2.0".
+//
+// See: https://tools.ietf.org/html/draft-ietf-oauth-jwt-bearer-12
+package jwt
+
+import (
+ "context"
+ "encoding/json"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "net/http"
+ "net/url"
+ "strings"
+ "time"
+
+ "golang.org/x/oauth2"
+ "golang.org/x/oauth2/internal"
+ "golang.org/x/oauth2/jws"
+)
+
+var (
+ defaultGrantType = "urn:ietf:params:oauth:grant-type:jwt-bearer"
+ defaultHeader = &jws.Header{Algorithm: "RS256", Typ: "JWT"}
+)
+
+// Config is the configuration for using JWT to fetch tokens,
+// commonly known as "two-legged OAuth 2.0".
+type Config struct {
+ // Email is the OAuth client identifier used when communicating with
+ // the configured OAuth provider.
+ Email string
+
+ // PrivateKey contains the contents of an RSA private key or the
+ // contents of a PEM file that contains a private key. The provided
+ // private key is used to sign JWT payloads.
+ // PEM containers with a passphrase are not supported.
+ // Use the following command to convert a PKCS 12 file into a PEM.
+ //
+ // $ openssl pkcs12 -in key.p12 -out key.pem -nodes
+ //
+ PrivateKey []byte
+
+ // PrivateKeyID contains an optional hint indicating which key is being
+ // used.
+ PrivateKeyID string
+
+ // Subject is the optional user to impersonate.
+ Subject string
+
+ // Scopes optionally specifies a list of requested permission scopes.
+ Scopes []string
+
+ // TokenURL is the endpoint required to complete the 2-legged JWT flow.
+ TokenURL string
+
+ // Expires optionally specifies how long the token is valid for.
+ Expires time.Duration
+}
+
+// TokenSource returns a JWT TokenSource using the configuration
+// in c and the HTTP client from the provided context.
+func (c *Config) TokenSource(ctx context.Context) oauth2.TokenSource {
+ return oauth2.ReuseTokenSource(nil, jwtSource{ctx, c})
+}
+
+// Client returns an HTTP client wrapping the context's
+// HTTP transport and adding Authorization headers with tokens
+// obtained from c.
+//
+// The returned client and its Transport should not be modified.
+func (c *Config) Client(ctx context.Context) *http.Client {
+ return oauth2.NewClient(ctx, c.TokenSource(ctx))
+}
+
+// jwtSource is a source that always does a signed JWT request for a token.
+// It should typically be wrapped with a reuseTokenSource.
+type jwtSource struct {
+ ctx context.Context
+ conf *Config
+}
+
+func (js jwtSource) Token() (*oauth2.Token, error) {
+ pk, err := internal.ParseKey(js.conf.PrivateKey)
+ if err != nil {
+ return nil, err
+ }
+ hc := oauth2.NewClient(js.ctx, nil)
+ claimSet := &jws.ClaimSet{
+ Iss: js.conf.Email,
+ Scope: strings.Join(js.conf.Scopes, " "),
+ Aud: js.conf.TokenURL,
+ }
+ if subject := js.conf.Subject; subject != "" {
+ claimSet.Sub = subject
+ // prn is the old name of sub. Keep setting it
+ // to be compatible with legacy OAuth 2.0 providers.
+ claimSet.Prn = subject
+ }
+ if t := js.conf.Expires; t > 0 {
+ claimSet.Exp = time.Now().Add(t).Unix()
+ }
+ h := *defaultHeader
+ h.KeyID = js.conf.PrivateKeyID
+ payload, err := jws.Encode(&h, claimSet, pk)
+ if err != nil {
+ return nil, err
+ }
+ v := url.Values{}
+ v.Set("grant_type", defaultGrantType)
+ v.Set("assertion", payload)
+ resp, err := hc.PostForm(js.conf.TokenURL, v)
+ if err != nil {
+ return nil, fmt.Errorf("oauth2: cannot fetch token: %v", err)
+ }
+ defer resp.Body.Close()
+ body, err := ioutil.ReadAll(io.LimitReader(resp.Body, 1<<20))
+ if err != nil {
+ return nil, fmt.Errorf("oauth2: cannot fetch token: %v", err)
+ }
+ if c := resp.StatusCode; c < 200 || c > 299 {
+ return nil, &oauth2.RetrieveError{
+ Response: resp,
+ Body: body,
+ }
+ }
+ // tokenRes is the JSON response body.
+ var tokenRes struct {
+ AccessToken string `json:"access_token"`
+ TokenType string `json:"token_type"`
+ IDToken string `json:"id_token"`
+ ExpiresIn int64 `json:"expires_in"` // relative seconds from now
+ }
+ if err := json.Unmarshal(body, &tokenRes); err != nil {
+ return nil, fmt.Errorf("oauth2: cannot fetch token: %v", err)
+ }
+ token := &oauth2.Token{
+ AccessToken: tokenRes.AccessToken,
+ TokenType: tokenRes.TokenType,
+ }
+ raw := make(map[string]interface{})
+ json.Unmarshal(body, &raw) // no error checks for optional fields
+ token = token.WithExtra(raw)
+
+ if secs := tokenRes.ExpiresIn; secs > 0 {
+ token.Expiry = time.Now().Add(time.Duration(secs) * time.Second)
+ }
+ if v := tokenRes.IDToken; v != "" {
+ // decode returned id token to get expiry
+ claimSet, err := jws.Decode(v)
+ if err != nil {
+ return nil, fmt.Errorf("oauth2: error decoding JWT token: %v", err)
+ }
+ token.Expiry = time.Unix(claimSet.Exp, 0)
+ }
+ return token, nil
+}
diff --git a/vendor/golang.org/x/oauth2/oauth2.go b/vendor/golang.org/x/oauth2/oauth2.go
new file mode 100644
index 000000000..1e8e1b741
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/oauth2.go
@@ -0,0 +1,360 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package oauth2 provides support for making
+// OAuth2 authorized and authenticated HTTP requests,
+// as specified in RFC 6749.
+// It can additionally grant authorization with Bearer JWT.
+package oauth2 // import "golang.org/x/oauth2"
+
+import (
+ "bytes"
+ "context"
+ "errors"
+ "net/http"
+ "net/url"
+ "strings"
+ "sync"
+
+ "golang.org/x/oauth2/internal"
+)
+
+// NoContext is the default context you should supply if not using
+// your own context.Context (see https://golang.org/x/net/context).
+//
+// Deprecated: Use context.Background() or context.TODO() instead.
+var NoContext = context.TODO()
+
+// RegisterBrokenAuthHeaderProvider registers an OAuth2 server
+// identified by the tokenURL prefix as an OAuth2 implementation
+// which doesn't support the HTTP Basic authentication
+// scheme to authenticate with the authorization server.
+// Once a server is registered, credentials (client_id and client_secret)
+// will be passed as query parameters rather than being present
+// in the Authorization header.
+// See https://code.google.com/p/goauth2/issues/detail?id=31 for background.
+func RegisterBrokenAuthHeaderProvider(tokenURL string) {
+ internal.RegisterBrokenAuthHeaderProvider(tokenURL)
+}
+
+// Config describes a typical 3-legged OAuth2 flow, with both the
+// client application information and the server's endpoint URLs.
+// For the client credentials 2-legged OAuth2 flow, see the clientcredentials
+// package (https://golang.org/x/oauth2/clientcredentials).
+type Config struct {
+ // ClientID is the application's ID.
+ ClientID string
+
+ // ClientSecret is the application's secret.
+ ClientSecret string
+
+ // Endpoint contains the resource server's token endpoint
+ // URLs. These are constants specific to each server and are
+ // often available via site-specific packages, such as
+ // google.Endpoint or github.Endpoint.
+ Endpoint Endpoint
+
+ // RedirectURL is the URL to redirect users going through
+ // the OAuth flow, after the resource owner's URLs.
+ RedirectURL string
+
+ // Scope specifies optional requested permissions.
+ Scopes []string
+}
+
+// A TokenSource is anything that can return a token.
+type TokenSource interface {
+ // Token returns a token or an error.
+ // Token must be safe for concurrent use by multiple goroutines.
+ // The returned Token must not be modified.
+ Token() (*Token, error)
+}
+
+// Endpoint contains the OAuth 2.0 provider's authorization and token
+// endpoint URLs.
+type Endpoint struct {
+ AuthURL string
+ TokenURL string
+}
+
+var (
+ // AccessTypeOnline and AccessTypeOffline are options passed
+ // to the Options.AuthCodeURL method. They modify the
+ // "access_type" field that gets sent in the URL returned by
+ // AuthCodeURL.
+ //
+ // Online is the default if neither is specified. If your
+ // application needs to refresh access tokens when the user
+ // is not present at the browser, then use offline. This will
+ // result in your application obtaining a refresh token the
+ // first time your application exchanges an authorization
+ // code for a user.
+ AccessTypeOnline AuthCodeOption = SetAuthURLParam("access_type", "online")
+ AccessTypeOffline AuthCodeOption = SetAuthURLParam("access_type", "offline")
+
+ // ApprovalForce forces the users to view the consent dialog
+ // and confirm the permissions request at the URL returned
+ // from AuthCodeURL, even if they've already done so.
+ ApprovalForce AuthCodeOption = SetAuthURLParam("approval_prompt", "force")
+)
+
+// An AuthCodeOption is passed to Config.AuthCodeURL.
+type AuthCodeOption interface {
+ setValue(url.Values)
+}
+
+type setParam struct{ k, v string }
+
+func (p setParam) setValue(m url.Values) { m.Set(p.k, p.v) }
+
+// SetAuthURLParam builds an AuthCodeOption which passes key/value parameters
+// to a provider's authorization endpoint.
+func SetAuthURLParam(key, value string) AuthCodeOption {
+ return setParam{key, value}
+}
+
+// AuthCodeURL returns a URL to OAuth 2.0 provider's consent page
+// that asks for permissions for the required scopes explicitly.
+//
+// State is a token to protect the user from CSRF attacks. You must
+// always provide a non-empty string and validate that it matches the
+// the state query parameter on your redirect callback.
+// See http://tools.ietf.org/html/rfc6749#section-10.12 for more info.
+//
+// Opts may include AccessTypeOnline or AccessTypeOffline, as well
+// as ApprovalForce.
+// It can also be used to pass the PKCE challange.
+// See https://www.oauth.com/oauth2-servers/pkce/ for more info.
+func (c *Config) AuthCodeURL(state string, opts ...AuthCodeOption) string {
+ var buf bytes.Buffer
+ buf.WriteString(c.Endpoint.AuthURL)
+ v := url.Values{
+ "response_type": {"code"},
+ "client_id": {c.ClientID},
+ }
+ if c.RedirectURL != "" {
+ v.Set("redirect_uri", c.RedirectURL)
+ }
+ if len(c.Scopes) > 0 {
+ v.Set("scope", strings.Join(c.Scopes, " "))
+ }
+ if state != "" {
+ // TODO(light): Docs say never to omit state; don't allow empty.
+ v.Set("state", state)
+ }
+ for _, opt := range opts {
+ opt.setValue(v)
+ }
+ if strings.Contains(c.Endpoint.AuthURL, "?") {
+ buf.WriteByte('&')
+ } else {
+ buf.WriteByte('?')
+ }
+ buf.WriteString(v.Encode())
+ return buf.String()
+}
+
+// PasswordCredentialsToken converts a resource owner username and password
+// pair into a token.
+//
+// Per the RFC, this grant type should only be used "when there is a high
+// degree of trust between the resource owner and the client (e.g., the client
+// is part of the device operating system or a highly privileged application),
+// and when other authorization grant types are not available."
+// See https://tools.ietf.org/html/rfc6749#section-4.3 for more info.
+//
+// The provided context optionally controls which HTTP client is used. See the HTTPClient variable.
+func (c *Config) PasswordCredentialsToken(ctx context.Context, username, password string) (*Token, error) {
+ v := url.Values{
+ "grant_type": {"password"},
+ "username": {username},
+ "password": {password},
+ }
+ if len(c.Scopes) > 0 {
+ v.Set("scope", strings.Join(c.Scopes, " "))
+ }
+ return retrieveToken(ctx, c, v)
+}
+
+// Exchange converts an authorization code into a token.
+//
+// It is used after a resource provider redirects the user back
+// to the Redirect URI (the URL obtained from AuthCodeURL).
+//
+// The provided context optionally controls which HTTP client is used. See the HTTPClient variable.
+//
+// The code will be in the *http.Request.FormValue("code"). Before
+// calling Exchange, be sure to validate FormValue("state").
+//
+// Opts may include the PKCE verifier code if previously used in AuthCodeURL.
+// See https://www.oauth.com/oauth2-servers/pkce/ for more info.
+func (c *Config) Exchange(ctx context.Context, code string, opts ...AuthCodeOption) (*Token, error) {
+ v := url.Values{
+ "grant_type": {"authorization_code"},
+ "code": {code},
+ }
+ if c.RedirectURL != "" {
+ v.Set("redirect_uri", c.RedirectURL)
+ }
+ for _, opt := range opts {
+ opt.setValue(v)
+ }
+ return retrieveToken(ctx, c, v)
+}
+
+// Client returns an HTTP client using the provided token.
+// The token will auto-refresh as necessary. The underlying
+// HTTP transport will be obtained using the provided context.
+// The returned client and its Transport should not be modified.
+func (c *Config) Client(ctx context.Context, t *Token) *http.Client {
+ return NewClient(ctx, c.TokenSource(ctx, t))
+}
+
+// TokenSource returns a TokenSource that returns t until t expires,
+// automatically refreshing it as necessary using the provided context.
+//
+// Most users will use Config.Client instead.
+func (c *Config) TokenSource(ctx context.Context, t *Token) TokenSource {
+ tkr := &tokenRefresher{
+ ctx: ctx,
+ conf: c,
+ }
+ if t != nil {
+ tkr.refreshToken = t.RefreshToken
+ }
+ return &reuseTokenSource{
+ t: t,
+ new: tkr,
+ }
+}
+
+// tokenRefresher is a TokenSource that makes "grant_type"=="refresh_token"
+// HTTP requests to renew a token using a RefreshToken.
+type tokenRefresher struct {
+ ctx context.Context // used to get HTTP requests
+ conf *Config
+ refreshToken string
+}
+
+// WARNING: Token is not safe for concurrent access, as it
+// updates the tokenRefresher's refreshToken field.
+// Within this package, it is used by reuseTokenSource which
+// synchronizes calls to this method with its own mutex.
+func (tf *tokenRefresher) Token() (*Token, error) {
+ if tf.refreshToken == "" {
+ return nil, errors.New("oauth2: token expired and refresh token is not set")
+ }
+
+ tk, err := retrieveToken(tf.ctx, tf.conf, url.Values{
+ "grant_type": {"refresh_token"},
+ "refresh_token": {tf.refreshToken},
+ })
+
+ if err != nil {
+ return nil, err
+ }
+ if tf.refreshToken != tk.RefreshToken {
+ tf.refreshToken = tk.RefreshToken
+ }
+ return tk, err
+}
+
+// reuseTokenSource is a TokenSource that holds a single token in memory
+// and validates its expiry before each call to retrieve it with
+// Token. If it's expired, it will be auto-refreshed using the
+// new TokenSource.
+type reuseTokenSource struct {
+ new TokenSource // called when t is expired.
+
+ mu sync.Mutex // guards t
+ t *Token
+}
+
+// Token returns the current token if it's still valid, else will
+// refresh the current token (using r.Context for HTTP client
+// information) and return the new one.
+func (s *reuseTokenSource) Token() (*Token, error) {
+ s.mu.Lock()
+ defer s.mu.Unlock()
+ if s.t.Valid() {
+ return s.t, nil
+ }
+ t, err := s.new.Token()
+ if err != nil {
+ return nil, err
+ }
+ s.t = t
+ return t, nil
+}
+
+// StaticTokenSource returns a TokenSource that always returns the same token.
+// Because the provided token t is never refreshed, StaticTokenSource is only
+// useful for tokens that never expire.
+func StaticTokenSource(t *Token) TokenSource {
+ return staticTokenSource{t}
+}
+
+// staticTokenSource is a TokenSource that always returns the same Token.
+type staticTokenSource struct {
+ t *Token
+}
+
+func (s staticTokenSource) Token() (*Token, error) {
+ return s.t, nil
+}
+
+// HTTPClient is the context key to use with golang.org/x/net/context's
+// WithValue function to associate an *http.Client value with a context.
+var HTTPClient internal.ContextKey
+
+// NewClient creates an *http.Client from a Context and TokenSource.
+// The returned client is not valid beyond the lifetime of the context.
+//
+// Note that if a custom *http.Client is provided via the Context it
+// is used only for token acquisition and is not used to configure the
+// *http.Client returned from NewClient.
+//
+// As a special case, if src is nil, a non-OAuth2 client is returned
+// using the provided context. This exists to support related OAuth2
+// packages.
+func NewClient(ctx context.Context, src TokenSource) *http.Client {
+ if src == nil {
+ return internal.ContextClient(ctx)
+ }
+ return &http.Client{
+ Transport: &Transport{
+ Base: internal.ContextClient(ctx).Transport,
+ Source: ReuseTokenSource(nil, src),
+ },
+ }
+}
+
+// ReuseTokenSource returns a TokenSource which repeatedly returns the
+// same token as long as it's valid, starting with t.
+// When its cached token is invalid, a new token is obtained from src.
+//
+// ReuseTokenSource is typically used to reuse tokens from a cache
+// (such as a file on disk) between runs of a program, rather than
+// obtaining new tokens unnecessarily.
+//
+// The initial token t may be nil, in which case the TokenSource is
+// wrapped in a caching version if it isn't one already. This also
+// means it's always safe to wrap ReuseTokenSource around any other
+// TokenSource without adverse effects.
+func ReuseTokenSource(t *Token, src TokenSource) TokenSource {
+ // Don't wrap a reuseTokenSource in itself. That would work,
+ // but cause an unnecessary number of mutex operations.
+ // Just build the equivalent one.
+ if rt, ok := src.(*reuseTokenSource); ok {
+ if t == nil {
+ // Just use it directly.
+ return rt
+ }
+ src = rt.new
+ }
+ return &reuseTokenSource{
+ t: t,
+ new: src,
+ }
+}
diff --git a/vendor/golang.org/x/oauth2/token.go b/vendor/golang.org/x/oauth2/token.go
new file mode 100644
index 000000000..9be1ae537
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/token.go
@@ -0,0 +1,175 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package oauth2
+
+import (
+ "context"
+ "fmt"
+ "net/http"
+ "net/url"
+ "strconv"
+ "strings"
+ "time"
+
+ "golang.org/x/oauth2/internal"
+)
+
+// expiryDelta determines how earlier a token should be considered
+// expired than its actual expiration time. It is used to avoid late
+// expirations due to client-server time mismatches.
+const expiryDelta = 10 * time.Second
+
+// Token represents the credentials used to authorize
+// the requests to access protected resources on the OAuth 2.0
+// provider's backend.
+//
+// Most users of this package should not access fields of Token
+// directly. They're exported mostly for use by related packages
+// implementing derivative OAuth2 flows.
+type Token struct {
+ // AccessToken is the token that authorizes and authenticates
+ // the requests.
+ AccessToken string `json:"access_token"`
+
+ // TokenType is the type of token.
+ // The Type method returns either this or "Bearer", the default.
+ TokenType string `json:"token_type,omitempty"`
+
+ // RefreshToken is a token that's used by the application
+ // (as opposed to the user) to refresh the access token
+ // if it expires.
+ RefreshToken string `json:"refresh_token,omitempty"`
+
+ // Expiry is the optional expiration time of the access token.
+ //
+ // If zero, TokenSource implementations will reuse the same
+ // token forever and RefreshToken or equivalent
+ // mechanisms for that TokenSource will not be used.
+ Expiry time.Time `json:"expiry,omitempty"`
+
+ // raw optionally contains extra metadata from the server
+ // when updating a token.
+ raw interface{}
+}
+
+// Type returns t.TokenType if non-empty, else "Bearer".
+func (t *Token) Type() string {
+ if strings.EqualFold(t.TokenType, "bearer") {
+ return "Bearer"
+ }
+ if strings.EqualFold(t.TokenType, "mac") {
+ return "MAC"
+ }
+ if strings.EqualFold(t.TokenType, "basic") {
+ return "Basic"
+ }
+ if t.TokenType != "" {
+ return t.TokenType
+ }
+ return "Bearer"
+}
+
+// SetAuthHeader sets the Authorization header to r using the access
+// token in t.
+//
+// This method is unnecessary when using Transport or an HTTP Client
+// returned by this package.
+func (t *Token) SetAuthHeader(r *http.Request) {
+ r.Header.Set("Authorization", t.Type()+" "+t.AccessToken)
+}
+
+// WithExtra returns a new Token that's a clone of t, but using the
+// provided raw extra map. This is only intended for use by packages
+// implementing derivative OAuth2 flows.
+func (t *Token) WithExtra(extra interface{}) *Token {
+ t2 := new(Token)
+ *t2 = *t
+ t2.raw = extra
+ return t2
+}
+
+// Extra returns an extra field.
+// Extra fields are key-value pairs returned by the server as a
+// part of the token retrieval response.
+func (t *Token) Extra(key string) interface{} {
+ if raw, ok := t.raw.(map[string]interface{}); ok {
+ return raw[key]
+ }
+
+ vals, ok := t.raw.(url.Values)
+ if !ok {
+ return nil
+ }
+
+ v := vals.Get(key)
+ switch s := strings.TrimSpace(v); strings.Count(s, ".") {
+ case 0: // Contains no "."; try to parse as int
+ if i, err := strconv.ParseInt(s, 10, 64); err == nil {
+ return i
+ }
+ case 1: // Contains a single "."; try to parse as float
+ if f, err := strconv.ParseFloat(s, 64); err == nil {
+ return f
+ }
+ }
+
+ return v
+}
+
+// expired reports whether the token is expired.
+// t must be non-nil.
+func (t *Token) expired() bool {
+ if t.Expiry.IsZero() {
+ return false
+ }
+ return t.Expiry.Round(0).Add(-expiryDelta).Before(time.Now())
+}
+
+// Valid reports whether t is non-nil, has an AccessToken, and is not expired.
+func (t *Token) Valid() bool {
+ return t != nil && t.AccessToken != "" && !t.expired()
+}
+
+// tokenFromInternal maps an *internal.Token struct into
+// a *Token struct.
+func tokenFromInternal(t *internal.Token) *Token {
+ if t == nil {
+ return nil
+ }
+ return &Token{
+ AccessToken: t.AccessToken,
+ TokenType: t.TokenType,
+ RefreshToken: t.RefreshToken,
+ Expiry: t.Expiry,
+ raw: t.Raw,
+ }
+}
+
+// retrieveToken takes a *Config and uses that to retrieve an *internal.Token.
+// This token is then mapped from *internal.Token into an *oauth2.Token which is returned along
+// with an error..
+func retrieveToken(ctx context.Context, c *Config, v url.Values) (*Token, error) {
+ tk, err := internal.RetrieveToken(ctx, c.ClientID, c.ClientSecret, c.Endpoint.TokenURL, v)
+ if err != nil {
+ if rErr, ok := err.(*internal.RetrieveError); ok {
+ return nil, (*RetrieveError)(rErr)
+ }
+ return nil, err
+ }
+ return tokenFromInternal(tk), nil
+}
+
+// RetrieveError is the error returned when the token endpoint returns a
+// non-2XX HTTP status code.
+type RetrieveError struct {
+ Response *http.Response
+ // Body is the body that was consumed by reading Response.Body.
+ // It may be truncated.
+ Body []byte
+}
+
+func (r *RetrieveError) Error() string {
+ return fmt.Sprintf("oauth2: cannot fetch token: %v\nResponse: %s", r.Response.Status, r.Body)
+}
diff --git a/vendor/golang.org/x/oauth2/transport.go b/vendor/golang.org/x/oauth2/transport.go
new file mode 100644
index 000000000..aa0d34f1e
--- /dev/null
+++ b/vendor/golang.org/x/oauth2/transport.go
@@ -0,0 +1,144 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package oauth2
+
+import (
+ "errors"
+ "io"
+ "net/http"
+ "sync"
+)
+
+// Transport is an http.RoundTripper that makes OAuth 2.0 HTTP requests,
+// wrapping a base RoundTripper and adding an Authorization header
+// with a token from the supplied Sources.
+//
+// Transport is a low-level mechanism. Most code will use the
+// higher-level Config.Client method instead.
+type Transport struct {
+ // Source supplies the token to add to outgoing requests'
+ // Authorization headers.
+ Source TokenSource
+
+ // Base is the base RoundTripper used to make HTTP requests.
+ // If nil, http.DefaultTransport is used.
+ Base http.RoundTripper
+
+ mu sync.Mutex // guards modReq
+ modReq map[*http.Request]*http.Request // original -> modified
+}
+
+// RoundTrip authorizes and authenticates the request with an
+// access token from Transport's Source.
+func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error) {
+ reqBodyClosed := false
+ if req.Body != nil {
+ defer func() {
+ if !reqBodyClosed {
+ req.Body.Close()
+ }
+ }()
+ }
+
+ if t.Source == nil {
+ return nil, errors.New("oauth2: Transport's Source is nil")
+ }
+ token, err := t.Source.Token()
+ if err != nil {
+ return nil, err
+ }
+
+ req2 := cloneRequest(req) // per RoundTripper contract
+ token.SetAuthHeader(req2)
+ t.setModReq(req, req2)
+ res, err := t.base().RoundTrip(req2)
+
+ // req.Body is assumed to have been closed by the base RoundTripper.
+ reqBodyClosed = true
+
+ if err != nil {
+ t.setModReq(req, nil)
+ return nil, err
+ }
+ res.Body = &onEOFReader{
+ rc: res.Body,
+ fn: func() { t.setModReq(req, nil) },
+ }
+ return res, nil
+}
+
+// CancelRequest cancels an in-flight request by closing its connection.
+func (t *Transport) CancelRequest(req *http.Request) {
+ type canceler interface {
+ CancelRequest(*http.Request)
+ }
+ if cr, ok := t.base().(canceler); ok {
+ t.mu.Lock()
+ modReq := t.modReq[req]
+ delete(t.modReq, req)
+ t.mu.Unlock()
+ cr.CancelRequest(modReq)
+ }
+}
+
+func (t *Transport) base() http.RoundTripper {
+ if t.Base != nil {
+ return t.Base
+ }
+ return http.DefaultTransport
+}
+
+func (t *Transport) setModReq(orig, mod *http.Request) {
+ t.mu.Lock()
+ defer t.mu.Unlock()
+ if t.modReq == nil {
+ t.modReq = make(map[*http.Request]*http.Request)
+ }
+ if mod == nil {
+ delete(t.modReq, orig)
+ } else {
+ t.modReq[orig] = mod
+ }
+}
+
+// cloneRequest returns a clone of the provided *http.Request.
+// The clone is a shallow copy of the struct and its Header map.
+func cloneRequest(r *http.Request) *http.Request {
+ // shallow copy of the struct
+ r2 := new(http.Request)
+ *r2 = *r
+ // deep copy of the Header
+ r2.Header = make(http.Header, len(r.Header))
+ for k, s := range r.Header {
+ r2.Header[k] = append([]string(nil), s...)
+ }
+ return r2
+}
+
+type onEOFReader struct {
+ rc io.ReadCloser
+ fn func()
+}
+
+func (r *onEOFReader) Read(p []byte) (n int, err error) {
+ n, err = r.rc.Read(p)
+ if err == io.EOF {
+ r.runFunc()
+ }
+ return
+}
+
+func (r *onEOFReader) Close() error {
+ err := r.rc.Close()
+ r.runFunc()
+ return err
+}
+
+func (r *onEOFReader) runFunc() {
+ if fn := r.fn; fn != nil {
+ fn()
+ r.fn = nil
+ }
+}
diff --git a/vendor/golang.org/x/sys/unix/mksyscall_aix_ppc.pl b/vendor/golang.org/x/sys/unix/mksyscall_aix_ppc.pl
new file mode 100755
index 000000000..c44de8d31
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/mksyscall_aix_ppc.pl
@@ -0,0 +1,384 @@
+#!/usr/bin/env perl
+# Copyright 2018 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+# This program reads a file containing function prototypes
+# (like syscall_aix.go) and generates system call bodies.
+# The prototypes are marked by lines beginning with "//sys"
+# and read like func declarations if //sys is replaced by func, but:
+# * The parameter lists must give a name for each argument.
+# This includes return parameters.
+# * The parameter lists must give a type for each argument:
+# the (x, y, z int) shorthand is not allowed.
+# * If the return parameter is an error number, it must be named err.
+# * If go func name needs to be different than its libc name,
+# * or the function is not in libc, name could be specified
+# * at the end, after "=" sign, like
+# //sys getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (err error) = libsocket.getsockopt
+
+use strict;
+
+my $cmdline = "mksyscall_aix_ppc.pl " . join(' ', @ARGV);
+my $errors = 0;
+my $_32bit = "";
+my $tags = ""; # build tags
+my $aix = 0;
+my $solaris = 0;
+
+binmode STDOUT;
+
+if($ARGV[0] eq "-b32") {
+ $_32bit = "big-endian";
+ shift;
+} elsif($ARGV[0] eq "-l32") {
+ $_32bit = "little-endian";
+ shift;
+}
+if($ARGV[0] eq "-aix") {
+ $aix = 1;
+ shift;
+}
+if($ARGV[0] eq "-tags") {
+ shift;
+ $tags = $ARGV[0];
+ shift;
+}
+
+if($ARGV[0] =~ /^-/) {
+ print STDERR "usage: mksyscall_aix.pl [-b32 | -l32] [-tags x,y] [file ...]\n";
+ exit 1;
+}
+
+sub parseparamlist($) {
+ my ($list) = @_;
+ $list =~ s/^\s*//;
+ $list =~ s/\s*$//;
+ if($list eq "") {
+ return ();
+ }
+ return split(/\s*,\s*/, $list);
+}
+
+sub parseparam($) {
+ my ($p) = @_;
+ if($p !~ /^(\S*) (\S*)$/) {
+ print STDERR "$ARGV:$.: malformed parameter: $p\n";
+ $errors = 1;
+ return ("xx", "int");
+ }
+ return ($1, $2);
+}
+
+my $package = "";
+my $text = "";
+my $c_extern = "/*\n#include <stdint.h>\n#include <stddef.h>\n";
+my @vars = ();
+while(<>) {
+ chomp;
+ s/\s+/ /g;
+ s/^\s+//;
+ s/\s+$//;
+ $package = $1 if !$package && /^package (\S+)$/;
+ my $nonblock = /^\/\/sysnb /;
+ next if !/^\/\/sys / && !$nonblock;
+
+ # Line must be of the form
+ # func Open(path string, mode int, perm int) (fd int, err error)
+ # Split into name, in params, out params.
+ if(!/^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*(?:(\w*)\.)?(\w*))?$/) {
+ print STDERR "$ARGV:$.: malformed //sys declaration\n";
+ $errors = 1;
+ next;
+ }
+ my ($nb, $func, $in, $out, $modname, $sysname) = ($1, $2, $3, $4, $5, $6);
+
+ # Split argument lists on comma.
+ my @in = parseparamlist($in);
+ my @out = parseparamlist($out);
+
+ $in = join(', ', @in);
+ $out = join(', ', @out);
+
+ # Try in vain to keep people from editing this file.
+ # The theory is that they jump into the middle of the file
+ # without reading the header.
+ $text .= "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n";
+
+ # Check if value return, err return available
+ my $errvar = "";
+ my $retvar = "";
+ my $rettype = "";
+ foreach my $p (@out) {
+ my ($name, $type) = parseparam($p);
+ if($type eq "error") {
+ $errvar = $name;
+ } else {
+ $retvar = $name;
+ $rettype = $type;
+ }
+ }
+
+ # System call name.
+ #if($func ne "fcntl") {
+
+ if($sysname eq "") {
+ $sysname = "$func";
+ }
+
+ $sysname =~ s/([a-z])([A-Z])/${1}_$2/g;
+ $sysname =~ y/A-Z/a-z/; # All libc functions are lowercase.
+
+ my $C_rettype = "";
+ if($rettype eq "unsafe.Pointer") {
+ $C_rettype = "uintptr_t";
+ } elsif($rettype eq "uintptr") {
+ $C_rettype = "uintptr_t";
+ } elsif($rettype =~ /^_/) {
+ $C_rettype = "uintptr_t";
+ } elsif($rettype eq "int") {
+ $C_rettype = "int";
+ } elsif($rettype eq "int32") {
+ $C_rettype = "int";
+ } elsif($rettype eq "int64") {
+ $C_rettype = "long long";
+ } elsif($rettype eq "uint32") {
+ $C_rettype = "unsigned int";
+ } elsif($rettype eq "uint64") {
+ $C_rettype = "unsigned long long";
+ } else {
+ $C_rettype = "int";
+ }
+ if($sysname eq "exit") {
+ $C_rettype = "void";
+ }
+
+ # Change types to c
+ my @c_in = ();
+ foreach my $p (@in) {
+ my ($name, $type) = parseparam($p);
+ if($type =~ /^\*/) {
+ push @c_in, "uintptr_t";
+ } elsif($type eq "string") {
+ push @c_in, "uintptr_t";
+ } elsif($type =~ /^\[\](.*)/) {
+ push @c_in, "uintptr_t", "size_t";
+ } elsif($type eq "unsafe.Pointer") {
+ push @c_in, "uintptr_t";
+ } elsif($type eq "uintptr") {
+ push @c_in, "uintptr_t";
+ } elsif($type =~ /^_/) {
+ push @c_in, "uintptr_t";
+ } elsif($type eq "int") {
+ push @c_in, "int";
+ } elsif($type eq "int32") {
+ push @c_in, "int";
+ } elsif($type eq "int64") {
+ push @c_in, "long long";
+ } elsif($type eq "uint32") {
+ push @c_in, "unsigned int";
+ } elsif($type eq "uint64") {
+ push @c_in, "unsigned long long";
+ } else {
+ push @c_in, "int";
+ }
+ }
+
+ if ($func ne "fcntl" && $func ne "FcntlInt" && $func ne "readlen" && $func ne "writelen") {
+ # Imports of system calls from libc
+ $c_extern .= "$C_rettype $sysname";
+ my $c_in = join(', ', @c_in);
+ $c_extern .= "($c_in);\n";
+ }
+
+ # So file name.
+ if($aix) {
+ if($modname eq "") {
+ $modname = "libc.a/shr_64.o";
+ } else {
+ print STDERR "$func: only syscall using libc are available\n";
+ $errors = 1;
+ next;
+ }
+ }
+
+ my $strconvfunc = "C.CString";
+ my $strconvtype = "*byte";
+
+ # Go function header.
+ if($out ne "") {
+ $out = " ($out)";
+ }
+ if($text ne "") {
+ $text .= "\n"
+ }
+
+ $text .= sprintf "func %s(%s)%s {\n", $func, join(', ', @in), $out ;
+
+ # Prepare arguments to call.
+ my @args = ();
+ my $n = 0;
+ my $arg_n = 0;
+ foreach my $p (@in) {
+ my ($name, $type) = parseparam($p);
+ if($type =~ /^\*/) {
+ push @args, "C.uintptr_t(uintptr(unsafe.Pointer($name)))";
+ } elsif($type eq "string" && $errvar ne "") {
+ $text .= "\t_p$n := uintptr(unsafe.Pointer($strconvfunc($name)))\n";
+ push @args, "C.uintptr_t(_p$n)";
+ $n++;
+ } elsif($type eq "string") {
+ print STDERR "$ARGV:$.: $func uses string arguments, but has no error return\n";
+ $text .= "\t_p$n := uintptr(unsafe.Pointer($strconvfunc($name)))\n";
+ push @args, "C.uintptr_t(_p$n)";
+ $n++;
+ } elsif($type =~ /^\[\](.*)/) {
+ # Convert slice into pointer, length.
+ # Have to be careful not to take address of &a[0] if len == 0:
+ # pass nil in that case.
+ $text .= "\tvar _p$n *$1\n";
+ $text .= "\tif len($name) > 0 {\n\t\t_p$n = \&$name\[0]\n\t}\n";
+ push @args, "C.uintptr_t(uintptr(unsafe.Pointer(_p$n)))";
+ $n++;
+ $text .= "\tvar _p$n int\n";
+ $text .= "\t_p$n = len($name)\n";
+ push @args, "C.size_t(_p$n)";
+ $n++;
+ } elsif($type eq "int64" && $_32bit ne "") {
+ if($_32bit eq "big-endian") {
+ push @args, "uintptr($name >> 32)", "uintptr($name)";
+ } else {
+ push @args, "uintptr($name)", "uintptr($name >> 32)";
+ }
+ $n++;
+ } elsif($type eq "bool") {
+ $text .= "\tvar _p$n uint32\n";
+ $text .= "\tif $name {\n\t\t_p$n = 1\n\t} else {\n\t\t_p$n = 0\n\t}\n";
+ push @args, "_p$n";
+ $n++;
+ } elsif($type =~ /^_/) {
+ push @args, "C.uintptr_t(uintptr($name))";
+ } elsif($type eq "unsafe.Pointer") {
+ push @args, "C.uintptr_t(uintptr($name))";
+ } elsif($type eq "int") {
+ if (($arg_n == 2) && (($func eq "readlen") || ($func eq "writelen"))) {
+ push @args, "C.size_t($name)";
+ } elsif ($arg_n == 0 && $func eq "fcntl") {
+ push @args, "C.uintptr_t($name)";
+ } elsif (($arg_n == 2) && (($func eq "fcntl") || ($func eq "FcntlInt"))) {
+ push @args, "C.uintptr_t($name)";
+ } else {
+ push @args, "C.int($name)";
+ }
+ } elsif($type eq "int32") {
+ push @args, "C.int($name)";
+ } elsif($type eq "int64") {
+ push @args, "C.longlong($name)";
+ } elsif($type eq "uint32") {
+ push @args, "C.uint($name)";
+ } elsif($type eq "uint64") {
+ push @args, "C.ulonglong($name)";
+ } elsif($type eq "uintptr") {
+ push @args, "C.uintptr_t($name)";
+ } else {
+ push @args, "C.int($name)";
+ }
+ $arg_n++;
+ }
+ my $nargs = @args;
+
+
+ # Determine which form to use; pad args with zeros.
+ if ($nonblock) {
+ }
+
+ my $args = join(', ', @args);
+ my $call = "";
+ if ($sysname eq "exit") {
+ if ($errvar ne "") {
+ $call .= "er :=";
+ } else {
+ $call .= "";
+ }
+ } elsif ($errvar ne "") {
+ $call .= "r0,er :=";
+ } elsif ($retvar ne "") {
+ $call .= "r0,_ :=";
+ } else {
+ $call .= ""
+ }
+ $call .= "C.$sysname($args)";
+
+ # Assign return values.
+ my $body = "";
+ my $failexpr = "";
+
+ for(my $i=0; $i<@out; $i++) {
+ my $p = $out[$i];
+ my ($name, $type) = parseparam($p);
+ my $reg = "";
+ if($name eq "err") {
+ $reg = "e1";
+ } else {
+ $reg = "r0";
+ }
+ if($reg ne "e1" ) {
+ $body .= "\t$name = $type($reg)\n";
+ }
+ }
+
+ # verify return
+ if ($sysname ne "exit" && $errvar ne "") {
+ if ($C_rettype =~ /^uintptr/) {
+ $body .= "\tif \(uintptr\(r0\) ==\^uintptr\(0\) && er != nil\) {\n";
+ $body .= "\t\t$errvar = er\n";
+ $body .= "\t}\n";
+ } else {
+ $body .= "\tif \(r0 ==-1 && er != nil\) {\n";
+ $body .= "\t\t$errvar = er\n";
+ $body .= "\t}\n";
+ }
+ } elsif ($errvar ne "") {
+ $body .= "\tif \(er != nil\) {\n";
+ $body .= "\t\t$errvar = er\n";
+ $body .= "\t}\n";
+ }
+
+ $text .= "\t$call\n";
+ $text .= $body;
+
+ $text .= "\treturn\n";
+ $text .= "}\n";
+}
+
+if($errors) {
+ exit 1;
+}
+
+print <<EOF;
+// $cmdline
+// Code generated by the command above; see README.md. DO NOT EDIT.
+
+// +build $tags
+
+package $package
+
+
+$c_extern
+*/
+import "C"
+import (
+ "unsafe"
+)
+
+
+EOF
+
+print "import \"golang.org/x/sys/unix\"\n" if $package ne "unix";
+
+chomp($_=<<EOF);
+
+$text
+EOF
+print $_;
+exit 0;
diff --git a/vendor/golang.org/x/sys/unix/mksyscall_aix_ppc64.pl b/vendor/golang.org/x/sys/unix/mksyscall_aix_ppc64.pl
new file mode 100755
index 000000000..53df26bb9
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/mksyscall_aix_ppc64.pl
@@ -0,0 +1,579 @@
+#!/usr/bin/env perl
+# Copyright 2018 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+# This program reads a file containing function prototypes
+# (like syscall_aix.go) and generates system call bodies.
+# The prototypes are marked by lines beginning with "//sys"
+# and read like func declarations if //sys is replaced by func, but:
+# * The parameter lists must give a name for each argument.
+# This includes return parameters.
+# * The parameter lists must give a type for each argument:
+# the (x, y, z int) shorthand is not allowed.
+# * If the return parameter is an error number, it must be named err.
+# * If go func name needs to be different than its libc name,
+# * or the function is not in libc, name could be specified
+# * at the end, after "=" sign, like
+# //sys getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (err error) = libsocket.getsockopt
+
+# This program will generate three files and handle both gc and gccgo implementation:
+# - zsyscall_aix_ppc64.go: the common part of each implementation (error handler, pointer creation)
+# - zsyscall_aix_ppc64_gc.go: gc part with //go_cgo_import_dynamic and a call to syscall6
+# - zsyscall_aix_ppc64_gccgo.go: gccgo part with C function and conversion to C type.
+
+# The generated code looks like this
+#
+# zsyscall_aix_ppc64.go
+# func asyscall(...) (n int, err error) {
+# // Pointer Creation
+# r1, e1 := callasyscall(...)
+# // Type Conversion
+# // Error Handler
+# return
+# }
+#
+# zsyscall_aix_ppc64_gc.go
+# //go:cgo_import_dynamic libc_asyscall asyscall "libc.a/shr_64.o"
+# //go:linkname libc_asyscall libc_asyscall
+# var asyscall syscallFunc
+#
+# func callasyscall(...) (r1 uintptr, e1 Errno) {
+# r1, _, e1 = syscall6(uintptr(unsafe.Pointer(&libc_asyscall)), "nb_args", ... )
+# return
+# }
+#
+# zsyscall_aix_ppc64_ggcgo.go
+# /*
+# int asyscall(...)
+#
+# */
+# import "C"
+#
+# func callasyscall(...) (r1 uintptr, e1 Errno) {
+# r1 = uintptr(C.asyscall(...))
+# e1 = syscall.GetErrno()
+# return
+# }
+
+
+
+use strict;
+
+my $cmdline = "mksyscall_aix_ppc64.pl " . join(' ', @ARGV);
+my $errors = 0;
+my $_32bit = "";
+my $tags = ""; # build tags
+my $aix = 0;
+my $solaris = 0;
+
+binmode STDOUT;
+
+if($ARGV[0] eq "-b32") {
+ $_32bit = "big-endian";
+ shift;
+} elsif($ARGV[0] eq "-l32") {
+ $_32bit = "little-endian";
+ shift;
+}
+if($ARGV[0] eq "-aix") {
+ $aix = 1;
+ shift;
+}
+if($ARGV[0] eq "-tags") {
+ shift;
+ $tags = $ARGV[0];
+ shift;
+}
+
+if($ARGV[0] =~ /^-/) {
+ print STDERR "usage: mksyscall_aix.pl [-b32 | -l32] [-tags x,y] [file ...]\n";
+ exit 1;
+}
+
+sub parseparamlist($) {
+ my ($list) = @_;
+ $list =~ s/^\s*//;
+ $list =~ s/\s*$//;
+ if($list eq "") {
+ return ();
+ }
+ return split(/\s*,\s*/, $list);
+}
+
+sub parseparam($) {
+ my ($p) = @_;
+ if($p !~ /^(\S*) (\S*)$/) {
+ print STDERR "$ARGV:$.: malformed parameter: $p\n";
+ $errors = 1;
+ return ("xx", "int");
+ }
+ return ($1, $2);
+}
+
+my $package = "";
+# GCCGO
+my $textgccgo = "";
+my $c_extern = "/*\n#include <stdint.h>\n";
+# GC
+my $textgc = "";
+my $dynimports = "";
+my $linknames = "";
+my @vars = ();
+# COMMUN
+my $textcommon = "";
+
+while(<>) {
+ chomp;
+ s/\s+/ /g;
+ s/^\s+//;
+ s/\s+$//;
+ $package = $1 if !$package && /^package (\S+)$/;
+ my $nonblock = /^\/\/sysnb /;
+ next if !/^\/\/sys / && !$nonblock;
+
+ # Line must be of the form
+ # func Open(path string, mode int, perm int) (fd int, err error)
+ # Split into name, in params, out params.
+ if(!/^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*(?:(\w*)\.)?(\w*))?$/) {
+ print STDERR "$ARGV:$.: malformed //sys declaration\n";
+ $errors = 1;
+ next;
+ }
+ my ($nb, $func, $in, $out, $modname, $sysname) = ($1, $2, $3, $4, $5, $6);
+
+ # Split argument lists on comma.
+ my @in = parseparamlist($in);
+ my @out = parseparamlist($out);
+
+ $in = join(', ', @in);
+ $out = join(', ', @out);
+
+ if($sysname eq "") {
+ $sysname = "$func";
+ }
+
+ my $onlyCommon = 0;
+ if ($func eq "readlen" || $func eq "writelen" || $func eq "FcntlInt" || $func eq "FcntlFlock") {
+ # This function call another syscall which is already implemented.
+ # Therefore, the gc and gccgo part must not be generated.
+ $onlyCommon = 1
+ }
+
+ # Try in vain to keep people from editing this file.
+ # The theory is that they jump into the middle of the file
+ # without reading the header.
+
+ $textcommon .= "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n";
+ if (!$onlyCommon) {
+ $textgccgo .= "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n";
+ $textgc .= "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n";
+ }
+
+
+ # Check if value return, err return available
+ my $errvar = "";
+ my $retvar = "";
+ my $rettype = "";
+ foreach my $p (@out) {
+ my ($name, $type) = parseparam($p);
+ if($type eq "error") {
+ $errvar = $name;
+ } else {
+ $retvar = $name;
+ $rettype = $type;
+ }
+ }
+
+
+ $sysname =~ s/([a-z])([A-Z])/${1}_$2/g;
+ $sysname =~ y/A-Z/a-z/; # All libc functions are lowercase.
+
+ # GCCGO Prototype return type
+ my $C_rettype = "";
+ if($rettype eq "unsafe.Pointer") {
+ $C_rettype = "uintptr_t";
+ } elsif($rettype eq "uintptr") {
+ $C_rettype = "uintptr_t";
+ } elsif($rettype =~ /^_/) {
+ $C_rettype = "uintptr_t";
+ } elsif($rettype eq "int") {
+ $C_rettype = "int";
+ } elsif($rettype eq "int32") {
+ $C_rettype = "int";
+ } elsif($rettype eq "int64") {
+ $C_rettype = "long long";
+ } elsif($rettype eq "uint32") {
+ $C_rettype = "unsigned int";
+ } elsif($rettype eq "uint64") {
+ $C_rettype = "unsigned long long";
+ } else {
+ $C_rettype = "int";
+ }
+ if($sysname eq "exit") {
+ $C_rettype = "void";
+ }
+
+ # GCCGO Prototype arguments type
+ my @c_in = ();
+ foreach my $i (0 .. $#in) {
+ my ($name, $type) = parseparam($in[$i]);
+ if($type =~ /^\*/) {
+ push @c_in, "uintptr_t";
+ } elsif($type eq "string") {
+ push @c_in, "uintptr_t";
+ } elsif($type =~ /^\[\](.*)/) {
+ push @c_in, "uintptr_t", "size_t";
+ } elsif($type eq "unsafe.Pointer") {
+ push @c_in, "uintptr_t";
+ } elsif($type eq "uintptr") {
+ push @c_in, "uintptr_t";
+ } elsif($type =~ /^_/) {
+ push @c_in, "uintptr_t";
+ } elsif($type eq "int") {
+ if (($i == 0 || $i == 2) && $func eq "fcntl"){
+ # These fcntl arguments needs to be uintptr to be able to call FcntlInt and FcntlFlock
+ push @c_in, "uintptr_t";
+ } else {
+ push @c_in, "int";
+ }
+ } elsif($type eq "int32") {
+ push @c_in, "int";
+ } elsif($type eq "int64") {
+ push @c_in, "long long";
+ } elsif($type eq "uint32") {
+ push @c_in, "unsigned int";
+ } elsif($type eq "uint64") {
+ push @c_in, "unsigned long long";
+ } else {
+ push @c_in, "int";
+ }
+ }
+
+ if (!$onlyCommon){
+ # GCCGO Prototype Generation
+ # Imports of system calls from libc
+ $c_extern .= "$C_rettype $sysname";
+ my $c_in = join(', ', @c_in);
+ $c_extern .= "($c_in);\n";
+ }
+
+ # GC Library name
+ if($modname eq "") {
+ $modname = "libc.a/shr_64.o";
+ } else {
+ print STDERR "$func: only syscall using libc are available\n";
+ $errors = 1;
+ next;
+ }
+ my $sysvarname = "libc_${sysname}";
+
+ if (!$onlyCommon){
+ # GC Runtime import of function to allow cross-platform builds.
+ $dynimports .= "//go:cgo_import_dynamic ${sysvarname} ${sysname} \"$modname\"\n";
+ # GC Link symbol to proc address variable.
+ $linknames .= "//go:linkname ${sysvarname} ${sysvarname}\n";
+ # GC Library proc address variable.
+ push @vars, $sysvarname;
+ }
+
+ my $strconvfunc ="BytePtrFromString";
+ my $strconvtype = "*byte";
+
+ # Go function header.
+ if($out ne "") {
+ $out = " ($out)";
+ }
+ if($textcommon ne "") {
+ $textcommon .= "\n"
+ }
+
+ $textcommon .= sprintf "func %s(%s)%s {\n", $func, join(', ', @in), $out ;
+
+ # Prepare arguments to call.
+ my @argscommun = (); # Arguments in the commun part
+ my @argscall = (); # Arguments for call prototype
+ my @argsgc = (); # Arguments for gc call (with syscall6)
+ my @argsgccgo = (); # Arguments for gccgo call (with C.name_of_syscall)
+ my $n = 0;
+ my $arg_n = 0;
+ foreach my $p (@in) {
+ my ($name, $type) = parseparam($p);
+ if($type =~ /^\*/) {
+ push @argscommun, "uintptr(unsafe.Pointer($name))";
+ push @argscall, "$name uintptr";
+ push @argsgc, "$name";
+ push @argsgccgo, "C.uintptr_t($name)";
+ } elsif($type eq "string" && $errvar ne "") {
+ $textcommon .= "\tvar _p$n $strconvtype\n";
+ $textcommon .= "\t_p$n, $errvar = $strconvfunc($name)\n";
+ $textcommon .= "\tif $errvar != nil {\n\t\treturn\n\t}\n";
+
+ push @argscommun, "uintptr(unsafe.Pointer(_p$n))";
+ push @argscall, "_p$n uintptr ";
+ push @argsgc, "_p$n";
+ push @argsgccgo, "C.uintptr_t(_p$n)";
+ $n++;
+ } elsif($type eq "string") {
+ print STDERR "$ARGV:$.: $func uses string arguments, but has no error return\n";
+ $textcommon .= "\tvar _p$n $strconvtype\n";
+ $textcommon .= "\t_p$n, $errvar = $strconvfunc($name)\n";
+ $textcommon .= "\tif $errvar != nil {\n\t\treturn\n\t}\n";
+
+ push @argscommun, "uintptr(unsafe.Pointer(_p$n))";
+ push @argscall, "_p$n uintptr";
+ push @argsgc, "_p$n";
+ push @argsgccgo, "C.uintptr_t(_p$n)";
+ $n++;
+ } elsif($type =~ /^\[\](.*)/) {
+ # Convert slice into pointer, length.
+ # Have to be careful not to take address of &a[0] if len == 0:
+ # pass nil in that case.
+ $textcommon .= "\tvar _p$n *$1\n";
+ $textcommon .= "\tif len($name) > 0 {\n\t\t_p$n = \&$name\[0]\n\t}\n";
+ push @argscommun, "uintptr(unsafe.Pointer(_p$n))", "len($name)";
+ push @argscall, "_p$n uintptr", "_lenp$n int";
+ push @argsgc, "_p$n", "uintptr(_lenp$n)";
+ push @argsgccgo, "C.uintptr_t(_p$n)", "C.size_t(_lenp$n)";
+ $n++;
+ } elsif($type eq "int64" && $_32bit ne "") {
+ print STDERR "$ARGV:$.: $func uses int64 with 32 bits mode. Case not yet implemented\n";
+ # if($_32bit eq "big-endian") {
+ # push @args, "uintptr($name >> 32)", "uintptr($name)";
+ # } else {
+ # push @args, "uintptr($name)", "uintptr($name >> 32)";
+ # }
+ # $n++;
+ } elsif($type eq "bool") {
+ print STDERR "$ARGV:$.: $func uses bool. Case not yet implemented\n";
+ # $text .= "\tvar _p$n uint32\n";
+ # $text .= "\tif $name {\n\t\t_p$n = 1\n\t} else {\n\t\t_p$n = 0\n\t}\n";
+ # push @args, "_p$n";
+ # $n++;
+ } elsif($type =~ /^_/ ||$type eq "unsafe.Pointer") {
+ push @argscommun, "uintptr($name)";
+ push @argscall, "$name uintptr";
+ push @argsgc, "$name";
+ push @argsgccgo, "C.uintptr_t($name)";
+ } elsif($type eq "int") {
+ if (($arg_n == 0 || $arg_n == 2) && ($func eq "fcntl" || $func eq "FcntlInt" || $func eq "FcntlFlock")) {
+ # These fcntl arguments need to be uintptr to be able to call FcntlInt and FcntlFlock
+ push @argscommun, "uintptr($name)";
+ push @argscall, "$name uintptr";
+ push @argsgc, "$name";
+ push @argsgccgo, "C.uintptr_t($name)";
+ } else {
+ push @argscommun, "$name";
+ push @argscall, "$name int";
+ push @argsgc, "uintptr($name)";
+ push @argsgccgo, "C.int($name)";
+ }
+ } elsif($type eq "int32") {
+ push @argscommun, "$name";
+ push @argscall, "$name int32";
+ push @argsgc, "uintptr($name)";
+ push @argsgccgo, "C.int($name)";
+ } elsif($type eq "int64") {
+ push @argscommun, "$name";
+ push @argscall, "$name int64";
+ push @argsgc, "uintptr($name)";
+ push @argsgccgo, "C.longlong($name)";
+ } elsif($type eq "uint32") {
+ push @argscommun, "$name";
+ push @argscall, "$name uint32";
+ push @argsgc, "uintptr($name)";
+ push @argsgccgo, "C.uint($name)";
+ } elsif($type eq "uint64") {
+ push @argscommun, "$name";
+ push @argscall, "$name uint64";
+ push @argsgc, "uintptr($name)";
+ push @argsgccgo, "C.ulonglong($name)";
+ } elsif($type eq "uintptr") {
+ push @argscommun, "$name";
+ push @argscall, "$name uintptr";
+ push @argsgc, "$name";
+ push @argsgccgo, "C.uintptr_t($name)";
+ } else {
+ push @argscommun, "int($name)";
+ push @argscall, "$name int";
+ push @argsgc, "uintptr($name)";
+ push @argsgccgo, "C.int($name)";
+ }
+ $arg_n++;
+ }
+ my $nargs = @argsgc;
+
+ # COMMUN function generation
+ my $argscommun = join(', ', @argscommun);
+ my $callcommun = "call$sysname($argscommun)";
+ my @ret = ("_", "_");
+ my $body = "";
+ my $do_errno = 0;
+ for(my $i=0; $i<@out; $i++) {
+ my $p = $out[$i];
+ my ($name, $type) = parseparam($p);
+ my $reg = "";
+ if($name eq "err") {
+ $reg = "e1";
+ $ret[1] = $reg;
+ $do_errno = 1;
+ } else {
+ $reg = "r0";
+ $ret[0] = $reg;
+ }
+ if($type eq "bool") {
+ $reg = "$reg != 0";
+ }
+ if($reg ne "e1") {
+ $body .= "\t$name = $type($reg)\n";
+ }
+ }
+ if ($ret[0] eq "_" && $ret[1] eq "_") {
+ $textcommon .= "\t$callcommun\n";
+ } else {
+ $textcommon .= "\t$ret[0], $ret[1] := $callcommun\n";
+ }
+ $textcommon .= $body;
+
+ if ($do_errno) {
+ $textcommon .= "\tif e1 != 0 {\n";
+ $textcommon .= "\t\terr = errnoErr(e1)\n";
+ $textcommon .= "\t}\n";
+ }
+ $textcommon .= "\treturn\n";
+ $textcommon .= "}\n";
+
+ if ($onlyCommon){
+ next
+ }
+ # CALL Prototype
+ my $callProto = sprintf "func call%s(%s) (r1 uintptr, e1 Errno) {\n", $sysname, join(', ', @argscall);
+
+ # GC function generation
+ my $asm = "syscall6";
+ if ($nonblock) {
+ $asm = "rawSyscall6";
+ }
+
+ if(@argsgc <= 6) {
+ while(@argsgc < 6) {
+ push @argsgc, "0";
+ }
+ } else {
+ print STDERR "$ARGV:$.: too many arguments to system call\n";
+ }
+ my $argsgc = join(', ', @argsgc);
+ my $callgc = "$asm(uintptr(unsafe.Pointer(&$sysvarname)), $nargs, $argsgc)";
+
+ $textgc .= $callProto;
+ $textgc .= "\tr1, _, e1 = $callgc\n";
+ $textgc .= "\treturn\n}\n";
+
+ # GCCGO function generation
+ my $argsgccgo = join(', ', @argsgccgo);
+ my $callgccgo = "C.$sysname($argsgccgo)";
+ $textgccgo .= $callProto;
+ $textgccgo .= "\tr1 = uintptr($callgccgo)\n";
+ $textgccgo .= "\te1 = syscall.GetErrno()\n";
+ $textgccgo .= "\treturn\n}\n";
+}
+
+if($errors) {
+ exit 1;
+}
+
+# Print zsyscall_aix_ppc64.go
+open(my $fcommun, '>', 'zsyscall_aix_ppc64.go');
+my $tofcommun = <<EOF;
+// $cmdline
+// Code generated by the command above; see README.md. DO NOT EDIT.
+
+// +build $tags
+
+package $package
+
+import (
+ "unsafe"
+)
+
+EOF
+
+$tofcommun .= "import \"golang.org/x/sys/unix\"\n" if $package ne "unix";
+
+$tofcommun .=<<EOF;
+
+$textcommon
+EOF
+print $fcommun $tofcommun;
+
+
+# Print zsyscall_aix_ppc64_gc.go
+open(my $fgc, '>', 'zsyscall_aix_ppc64_gc.go');
+my $tofgc = <<EOF;
+// $cmdline
+// Code generated by the command above; see README.md. DO NOT EDIT.
+
+// +build $tags
+// +build !gccgo
+
+package $package
+
+import (
+ "unsafe"
+)
+
+
+EOF
+
+$tofgc .= "import \"golang.org/x/sys/unix\"\n" if $package ne "unix";
+
+my $vardecls = "\t" . join(",\n\t", @vars);
+$vardecls .= " syscallFunc";
+
+$tofgc .=<<EOF;
+$dynimports
+$linknames
+type syscallFunc uintptr
+
+var (
+$vardecls
+)
+
+// Implemented in runtime/syscall_aix.go.
+func rawSyscall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
+func syscall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
+
+$textgc
+EOF
+print $fgc $tofgc;
+
+# Print zsyscall_aix_ppc64_gc.go
+open(my $fgccgo, '>', 'zsyscall_aix_ppc64_gccgo.go');
+my $tofgccgo = <<EOF;
+// $cmdline
+// Code generated by the command above; see README.md. DO NOT EDIT.
+
+// +build $tags
+// +build gccgo
+
+package $package
+
+
+$c_extern
+*/
+import "C"
+import (
+ "syscall"
+)
+
+
+EOF
+
+$tofgccgo .= "import \"golang.org/x/sys/unix\"\n" if $package ne "unix";
+
+$tofgccgo .=<<EOF;
+
+$textgccgo
+EOF
+print $fgccgo $tofgccgo;
+exit 0;
diff --git a/vendor/golang.org/x/sys/unix/mksyscall_solaris.pl b/vendor/golang.org/x/sys/unix/mksyscall_solaris.pl
new file mode 100755
index 000000000..a354df5a6
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/mksyscall_solaris.pl
@@ -0,0 +1,294 @@
+#!/usr/bin/env perl
+# Copyright 2009 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+# This program reads a file containing function prototypes
+# (like syscall_solaris.go) and generates system call bodies.
+# The prototypes are marked by lines beginning with "//sys"
+# and read like func declarations if //sys is replaced by func, but:
+# * The parameter lists must give a name for each argument.
+# This includes return parameters.
+# * The parameter lists must give a type for each argument:
+# the (x, y, z int) shorthand is not allowed.
+# * If the return parameter is an error number, it must be named err.
+# * If go func name needs to be different than its libc name,
+# * or the function is not in libc, name could be specified
+# * at the end, after "=" sign, like
+# //sys getsockopt(s int, level int, name int, val uintptr, vallen *_Socklen) (err error) = libsocket.getsockopt
+
+use strict;
+
+my $cmdline = "mksyscall_solaris.pl " . join(' ', @ARGV);
+my $errors = 0;
+my $_32bit = "";
+my $tags = ""; # build tags
+
+binmode STDOUT;
+
+if($ARGV[0] eq "-b32") {
+ $_32bit = "big-endian";
+ shift;
+} elsif($ARGV[0] eq "-l32") {
+ $_32bit = "little-endian";
+ shift;
+}
+if($ARGV[0] eq "-tags") {
+ shift;
+ $tags = $ARGV[0];
+ shift;
+}
+
+if($ARGV[0] =~ /^-/) {
+ print STDERR "usage: mksyscall_solaris.pl [-b32 | -l32] [-tags x,y] [file ...]\n";
+ exit 1;
+}
+
+sub parseparamlist($) {
+ my ($list) = @_;
+ $list =~ s/^\s*//;
+ $list =~ s/\s*$//;
+ if($list eq "") {
+ return ();
+ }
+ return split(/\s*,\s*/, $list);
+}
+
+sub parseparam($) {
+ my ($p) = @_;
+ if($p !~ /^(\S*) (\S*)$/) {
+ print STDERR "$ARGV:$.: malformed parameter: $p\n";
+ $errors = 1;
+ return ("xx", "int");
+ }
+ return ($1, $2);
+}
+
+my $package = "";
+my $text = "";
+my $dynimports = "";
+my $linknames = "";
+my @vars = ();
+while(<>) {
+ chomp;
+ s/\s+/ /g;
+ s/^\s+//;
+ s/\s+$//;
+ $package = $1 if !$package && /^package (\S+)$/;
+ my $nonblock = /^\/\/sysnb /;
+ next if !/^\/\/sys / && !$nonblock;
+
+ # Line must be of the form
+ # func Open(path string, mode int, perm int) (fd int, err error)
+ # Split into name, in params, out params.
+ if(!/^\/\/sys(nb)? (\w+)\(([^()]*)\)\s*(?:\(([^()]+)\))?\s*(?:=\s*(?:(\w*)\.)?(\w*))?$/) {
+ print STDERR "$ARGV:$.: malformed //sys declaration\n";
+ $errors = 1;
+ next;
+ }
+ my ($nb, $func, $in, $out, $modname, $sysname) = ($1, $2, $3, $4, $5, $6);
+
+ # Split argument lists on comma.
+ my @in = parseparamlist($in);
+ my @out = parseparamlist($out);
+
+ # Try in vain to keep people from editing this file.
+ # The theory is that they jump into the middle of the file
+ # without reading the header.
+ $text .= "// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT\n\n";
+
+ # So file name.
+ if($modname eq "") {
+ $modname = "libc";
+ }
+
+ # System call name.
+ if($sysname eq "") {
+ $sysname = "$func";
+ }
+
+ # System call pointer variable name.
+ my $sysvarname = "proc$sysname";
+
+ my $strconvfunc = "BytePtrFromString";
+ my $strconvtype = "*byte";
+
+ $sysname =~ y/A-Z/a-z/; # All libc functions are lowercase.
+
+ # Runtime import of function to allow cross-platform builds.
+ $dynimports .= "//go:cgo_import_dynamic libc_${sysname} ${sysname} \"$modname.so\"\n";
+ # Link symbol to proc address variable.
+ $linknames .= "//go:linkname ${sysvarname} libc_${sysname}\n";
+ # Library proc address variable.
+ push @vars, $sysvarname;
+
+ # Go function header.
+ $out = join(', ', @out);
+ if($out ne "") {
+ $out = " ($out)";
+ }
+ if($text ne "") {
+ $text .= "\n"
+ }
+ $text .= sprintf "func %s(%s)%s {\n", $func, join(', ', @in), $out;
+
+ # Check if err return available
+ my $errvar = "";
+ foreach my $p (@out) {
+ my ($name, $type) = parseparam($p);
+ if($type eq "error") {
+ $errvar = $name;
+ last;
+ }
+ }
+
+ # Prepare arguments to Syscall.
+ my @args = ();
+ my $n = 0;
+ foreach my $p (@in) {
+ my ($name, $type) = parseparam($p);
+ if($type =~ /^\*/) {
+ push @args, "uintptr(unsafe.Pointer($name))";
+ } elsif($type eq "string" && $errvar ne "") {
+ $text .= "\tvar _p$n $strconvtype\n";
+ $text .= "\t_p$n, $errvar = $strconvfunc($name)\n";
+ $text .= "\tif $errvar != nil {\n\t\treturn\n\t}\n";
+ push @args, "uintptr(unsafe.Pointer(_p$n))";
+ $n++;
+ } elsif($type eq "string") {
+ print STDERR "$ARGV:$.: $func uses string arguments, but has no error return\n";
+ $text .= "\tvar _p$n $strconvtype\n";
+ $text .= "\t_p$n, _ = $strconvfunc($name)\n";
+ push @args, "uintptr(unsafe.Pointer(_p$n))";
+ $n++;
+ } elsif($type =~ /^\[\](.*)/) {
+ # Convert slice into pointer, length.
+ # Have to be careful not to take address of &a[0] if len == 0:
+ # pass nil in that case.
+ $text .= "\tvar _p$n *$1\n";
+ $text .= "\tif len($name) > 0 {\n\t\t_p$n = \&$name\[0]\n\t}\n";
+ push @args, "uintptr(unsafe.Pointer(_p$n))", "uintptr(len($name))";
+ $n++;
+ } elsif($type eq "int64" && $_32bit ne "") {
+ if($_32bit eq "big-endian") {
+ push @args, "uintptr($name >> 32)", "uintptr($name)";
+ } else {
+ push @args, "uintptr($name)", "uintptr($name >> 32)";
+ }
+ } elsif($type eq "bool") {
+ $text .= "\tvar _p$n uint32\n";
+ $text .= "\tif $name {\n\t\t_p$n = 1\n\t} else {\n\t\t_p$n = 0\n\t}\n";
+ push @args, "uintptr(_p$n)";
+ $n++;
+ } else {
+ push @args, "uintptr($name)";
+ }
+ }
+ my $nargs = @args;
+
+ # Determine which form to use; pad args with zeros.
+ my $asm = "sysvicall6";
+ if ($nonblock) {
+ $asm = "rawSysvicall6";
+ }
+ if(@args <= 6) {
+ while(@args < 6) {
+ push @args, "0";
+ }
+ } else {
+ print STDERR "$ARGV:$.: too many arguments to system call\n";
+ }
+
+ # Actual call.
+ my $args = join(', ', @args);
+ my $call = "$asm(uintptr(unsafe.Pointer(&$sysvarname)), $nargs, $args)";
+
+ # Assign return values.
+ my $body = "";
+ my $failexpr = "";
+ my @ret = ("_", "_", "_");
+ my @pout= ();
+ my $do_errno = 0;
+ for(my $i=0; $i<@out; $i++) {
+ my $p = $out[$i];
+ my ($name, $type) = parseparam($p);
+ my $reg = "";
+ if($name eq "err") {
+ $reg = "e1";
+ $ret[2] = $reg;
+ $do_errno = 1;
+ } else {
+ $reg = sprintf("r%d", $i);
+ $ret[$i] = $reg;
+ }
+ if($type eq "bool") {
+ $reg = "$reg != 0";
+ }
+ if($type eq "int64" && $_32bit ne "") {
+ # 64-bit number in r1:r0 or r0:r1.
+ if($i+2 > @out) {
+ print STDERR "$ARGV:$.: not enough registers for int64 return\n";
+ }
+ if($_32bit eq "big-endian") {
+ $reg = sprintf("int64(r%d)<<32 | int64(r%d)", $i, $i+1);
+ } else {
+ $reg = sprintf("int64(r%d)<<32 | int64(r%d)", $i+1, $i);
+ }
+ $ret[$i] = sprintf("r%d", $i);
+ $ret[$i+1] = sprintf("r%d", $i+1);
+ }
+ if($reg ne "e1") {
+ $body .= "\t$name = $type($reg)\n";
+ }
+ }
+ if ($ret[0] eq "_" && $ret[1] eq "_" && $ret[2] eq "_") {
+ $text .= "\t$call\n";
+ } else {
+ $text .= "\t$ret[0], $ret[1], $ret[2] := $call\n";
+ }
+ $text .= $body;
+
+ if ($do_errno) {
+ $text .= "\tif e1 != 0 {\n";
+ $text .= "\t\terr = e1\n";
+ $text .= "\t}\n";
+ }
+ $text .= "\treturn\n";
+ $text .= "}\n";
+}
+
+if($errors) {
+ exit 1;
+}
+
+print <<EOF;
+// $cmdline
+// Code generated by the command above; see README.md. DO NOT EDIT.
+
+// +build $tags
+
+package $package
+
+import (
+ "syscall"
+ "unsafe"
+)
+EOF
+
+print "import \"golang.org/x/sys/unix\"\n" if $package ne "unix";
+
+my $vardecls = "\t" . join(",\n\t", @vars);
+$vardecls .= " syscallFunc";
+
+chomp($_=<<EOF);
+
+$dynimports
+$linknames
+var (
+$vardecls
+)
+
+$text
+EOF
+print $_;
+exit 0;
diff --git a/vendor/golang.org/x/sys/unix/mksysnum_freebsd.pl b/vendor/golang.org/x/sys/unix/mksysnum_freebsd.pl
new file mode 100755
index 000000000..198993d09
--- /dev/null
+++ b/vendor/golang.org/x/sys/unix/mksysnum_freebsd.pl
@@ -0,0 +1,50 @@
+#!/usr/bin/env perl
+# Copyright 2009 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+#
+# Generate system call table for FreeBSD from master list
+# (for example, /usr/src/sys/kern/syscalls.master).
+
+use strict;
+
+if($ENV{'GOARCH'} eq "" || $ENV{'GOOS'} eq "") {
+ print STDERR "GOARCH or GOOS not defined in environment\n";
+ exit 1;
+}
+
+my $command = "mksysnum_freebsd.pl " . join(' ', @ARGV);
+
+print <<EOF;
+// $command
+// Code generated by the command above; see README.md. DO NOT EDIT.
+
+// +build $ENV{'GOARCH'},$ENV{'GOOS'}
+
+package unix
+
+const (
+EOF
+
+while(<>){
+ if(/^([0-9]+)\s+\S+\s+(?:NO)?STD\s+({ \S+\s+(\w+).*)$/){
+ my $num = $1;
+ my $proto = $2;
+ my $name = "SYS_$3";
+ $name =~ y/a-z/A-Z/;
+
+ # There are multiple entries for enosys and nosys, so comment them out.
+ if($name =~ /^SYS_E?NOSYS$/){
+ $name = "// $name";
+ }
+ if($name eq 'SYS_SYS_EXIT'){
+ $name = 'SYS_EXIT';
+ }
+
+ print " $name = $num; // $proto\n";
+ }
+}
+
+print <<EOF;
+)
+EOF
diff --git a/vendor/google.golang.org/api/LICENSE b/vendor/google.golang.org/api/LICENSE
new file mode 100644
index 000000000..263aa7a0c
--- /dev/null
+++ b/vendor/google.golang.org/api/LICENSE
@@ -0,0 +1,27 @@
+Copyright (c) 2011 Google Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/vendor/google.golang.org/api/gensupport/backoff.go b/vendor/google.golang.org/api/gensupport/backoff.go
new file mode 100644
index 000000000..94b7789ee
--- /dev/null
+++ b/vendor/google.golang.org/api/gensupport/backoff.go
@@ -0,0 +1,51 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package gensupport
+
+import (
+ "math/rand"
+ "time"
+)
+
+// BackoffStrategy defines the set of functions that a backoff-er must
+// implement.
+type BackoffStrategy interface {
+ // Pause returns the duration of the next pause and true if the operation should be
+ // retried, or false if no further retries should be attempted.
+ Pause() (time.Duration, bool)
+
+ // Reset restores the strategy to its initial state.
+ Reset()
+}
+
+// ExponentialBackoff performs exponential backoff as per https://en.wikipedia.org/wiki/Exponential_backoff.
+// The initial pause time is given by Base.
+// Once the total pause time exceeds Max, Pause will indicate no further retries.
+type ExponentialBackoff struct {
+ Base time.Duration
+ Max time.Duration
+ total time.Duration
+ n uint
+}
+
+// Pause returns the amount of time the caller should wait.
+func (eb *ExponentialBackoff) Pause() (time.Duration, bool) {
+ if eb.total > eb.Max {
+ return 0, false
+ }
+
+ // The next pause is selected from randomly from [0, 2^n * Base).
+ d := time.Duration(rand.Int63n((1 << eb.n) * int64(eb.Base)))
+ eb.total += d
+ eb.n++
+ return d, true
+}
+
+// Reset resets the backoff strategy such that the next Pause call will begin
+// counting from the start. It is not safe to call concurrently with Pause.
+func (eb *ExponentialBackoff) Reset() {
+ eb.n = 0
+ eb.total = 0
+}
diff --git a/vendor/google.golang.org/api/gensupport/buffer.go b/vendor/google.golang.org/api/gensupport/buffer.go
new file mode 100644
index 000000000..3d0817ede
--- /dev/null
+++ b/vendor/google.golang.org/api/gensupport/buffer.go
@@ -0,0 +1,79 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package gensupport
+
+import (
+ "bytes"
+ "io"
+
+ "google.golang.org/api/googleapi"
+)
+
+// MediaBuffer buffers data from an io.Reader to support uploading media in
+// retryable chunks. It should be created with NewMediaBuffer.
+type MediaBuffer struct {
+ media io.Reader
+
+ chunk []byte // The current chunk which is pending upload. The capacity is the chunk size.
+ err error // Any error generated when populating chunk by reading media.
+
+ // The absolute position of chunk in the underlying media.
+ off int64
+}
+
+// NewMediaBuffer initializes a MediaBuffer.
+func NewMediaBuffer(media io.Reader, chunkSize int) *MediaBuffer {
+ return &MediaBuffer{media: media, chunk: make([]byte, 0, chunkSize)}
+}
+
+// Chunk returns the current buffered chunk, the offset in the underlying media
+// from which the chunk is drawn, and the size of the chunk.
+// Successive calls to Chunk return the same chunk between calls to Next.
+func (mb *MediaBuffer) Chunk() (chunk io.Reader, off int64, size int, err error) {
+ // There may already be data in chunk if Next has not been called since the previous call to Chunk.
+ if mb.err == nil && len(mb.chunk) == 0 {
+ mb.err = mb.loadChunk()
+ }
+ return bytes.NewReader(mb.chunk), mb.off, len(mb.chunk), mb.err
+}
+
+// loadChunk will read from media into chunk, up to the capacity of chunk.
+func (mb *MediaBuffer) loadChunk() error {
+ bufSize := cap(mb.chunk)
+ mb.chunk = mb.chunk[:bufSize]
+
+ read := 0
+ var err error
+ for err == nil && read < bufSize {
+ var n int
+ n, err = mb.media.Read(mb.chunk[read:])
+ read += n
+ }
+ mb.chunk = mb.chunk[:read]
+ return err
+}
+
+// Next advances to the next chunk, which will be returned by the next call to Chunk.
+// Calls to Next without a corresponding prior call to Chunk will have no effect.
+func (mb *MediaBuffer) Next() {
+ mb.off += int64(len(mb.chunk))
+ mb.chunk = mb.chunk[0:0]
+}
+
+type readerTyper struct {
+ io.Reader
+ googleapi.ContentTyper
+}
+
+// ReaderAtToReader adapts a ReaderAt to be used as a Reader.
+// If ra implements googleapi.ContentTyper, then the returned reader
+// will also implement googleapi.ContentTyper, delegating to ra.
+func ReaderAtToReader(ra io.ReaderAt, size int64) io.Reader {
+ r := io.NewSectionReader(ra, 0, size)
+ if typer, ok := ra.(googleapi.ContentTyper); ok {
+ return readerTyper{r, typer}
+ }
+ return r
+}
diff --git a/vendor/google.golang.org/api/gensupport/doc.go b/vendor/google.golang.org/api/gensupport/doc.go
new file mode 100644
index 000000000..752c4b411
--- /dev/null
+++ b/vendor/google.golang.org/api/gensupport/doc.go
@@ -0,0 +1,10 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package gensupport is an internal implementation detail used by code
+// generated by the google-api-go-generator tool.
+//
+// This package may be modified at any time without regard for backwards
+// compatibility. It should not be used directly by API users.
+package gensupport
diff --git a/vendor/google.golang.org/api/gensupport/header.go b/vendor/google.golang.org/api/gensupport/header.go
new file mode 100644
index 000000000..cb5e67c77
--- /dev/null
+++ b/vendor/google.golang.org/api/gensupport/header.go
@@ -0,0 +1,22 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package gensupport
+
+import (
+ "fmt"
+ "runtime"
+ "strings"
+)
+
+// GoogleClientHeader returns the value to use for the x-goog-api-client
+// header, which is used internally by Google.
+func GoogleClientHeader(generatorVersion, clientElement string) string {
+ elts := []string{"gl-go/" + strings.Replace(runtime.Version(), " ", "_", -1)}
+ if clientElement != "" {
+ elts = append(elts, clientElement)
+ }
+ elts = append(elts, fmt.Sprintf("gdcl/%s", generatorVersion))
+ return strings.Join(elts, " ")
+}
diff --git a/vendor/google.golang.org/api/gensupport/json.go b/vendor/google.golang.org/api/gensupport/json.go
new file mode 100644
index 000000000..c01e32189
--- /dev/null
+++ b/vendor/google.golang.org/api/gensupport/json.go
@@ -0,0 +1,211 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package gensupport
+
+import (
+ "encoding/json"
+ "fmt"
+ "reflect"
+ "strings"
+)
+
+// MarshalJSON returns a JSON encoding of schema containing only selected fields.
+// A field is selected if any of the following is true:
+// * it has a non-empty value
+// * its field name is present in forceSendFields and it is not a nil pointer or nil interface
+// * its field name is present in nullFields.
+// The JSON key for each selected field is taken from the field's json: struct tag.
+func MarshalJSON(schema interface{}, forceSendFields, nullFields []string) ([]byte, error) {
+ if len(forceSendFields) == 0 && len(nullFields) == 0 {
+ return json.Marshal(schema)
+ }
+
+ mustInclude := make(map[string]bool)
+ for _, f := range forceSendFields {
+ mustInclude[f] = true
+ }
+ useNull := make(map[string]bool)
+ useNullMaps := make(map[string]map[string]bool)
+ for _, nf := range nullFields {
+ parts := strings.SplitN(nf, ".", 2)
+ field := parts[0]
+ if len(parts) == 1 {
+ useNull[field] = true
+ } else {
+ if useNullMaps[field] == nil {
+ useNullMaps[field] = map[string]bool{}
+ }
+ useNullMaps[field][parts[1]] = true
+ }
+ }
+
+ dataMap, err := schemaToMap(schema, mustInclude, useNull, useNullMaps)
+ if err != nil {
+ return nil, err
+ }
+ return json.Marshal(dataMap)
+}
+
+func schemaToMap(schema interface{}, mustInclude, useNull map[string]bool, useNullMaps map[string]map[string]bool) (map[string]interface{}, error) {
+ m := make(map[string]interface{})
+ s := reflect.ValueOf(schema)
+ st := s.Type()
+
+ for i := 0; i < s.NumField(); i++ {
+ jsonTag := st.Field(i).Tag.Get("json")
+ if jsonTag == "" {
+ continue
+ }
+ tag, err := parseJSONTag(jsonTag)
+ if err != nil {
+ return nil, err
+ }
+ if tag.ignore {
+ continue
+ }
+
+ v := s.Field(i)
+ f := st.Field(i)
+
+ if useNull[f.Name] {
+ if !isEmptyValue(v) {
+ return nil, fmt.Errorf("field %q in NullFields has non-empty value", f.Name)
+ }
+ m[tag.apiName] = nil
+ continue
+ }
+
+ if !includeField(v, f, mustInclude) {
+ continue
+ }
+
+ // If map fields are explicitly set to null, use a map[string]interface{}.
+ if f.Type.Kind() == reflect.Map && useNullMaps[f.Name] != nil {
+ ms, ok := v.Interface().(map[string]string)
+ if !ok {
+ return nil, fmt.Errorf("field %q has keys in NullFields but is not a map[string]string", f.Name)
+ }
+ mi := map[string]interface{}{}
+ for k, v := range ms {
+ mi[k] = v
+ }
+ for k := range useNullMaps[f.Name] {
+ mi[k] = nil
+ }
+ m[tag.apiName] = mi
+ continue
+ }
+
+ // nil maps are treated as empty maps.
+ if f.Type.Kind() == reflect.Map && v.IsNil() {
+ m[tag.apiName] = map[string]string{}
+ continue
+ }
+
+ // nil slices are treated as empty slices.
+ if f.Type.Kind() == reflect.Slice && v.IsNil() {
+ m[tag.apiName] = []bool{}
+ continue
+ }
+
+ if tag.stringFormat {
+ m[tag.apiName] = formatAsString(v, f.Type.Kind())
+ } else {
+ m[tag.apiName] = v.Interface()
+ }
+ }
+ return m, nil
+}
+
+// formatAsString returns a string representation of v, dereferencing it first if possible.
+func formatAsString(v reflect.Value, kind reflect.Kind) string {
+ if kind == reflect.Ptr && !v.IsNil() {
+ v = v.Elem()
+ }
+
+ return fmt.Sprintf("%v", v.Interface())
+}
+
+// jsonTag represents a restricted version of the struct tag format used by encoding/json.
+// It is used to describe the JSON encoding of fields in a Schema struct.
+type jsonTag struct {
+ apiName string
+ stringFormat bool
+ ignore bool
+}
+
+// parseJSONTag parses a restricted version of the struct tag format used by encoding/json.
+// The format of the tag must match that generated by the Schema.writeSchemaStruct method
+// in the api generator.
+func parseJSONTag(val string) (jsonTag, error) {
+ if val == "-" {
+ return jsonTag{ignore: true}, nil
+ }
+
+ var tag jsonTag
+
+ i := strings.Index(val, ",")
+ if i == -1 || val[:i] == "" {
+ return tag, fmt.Errorf("malformed json tag: %s", val)
+ }
+
+ tag = jsonTag{
+ apiName: val[:i],
+ }
+
+ switch val[i+1:] {
+ case "omitempty":
+ case "omitempty,string":
+ tag.stringFormat = true
+ default:
+ return tag, fmt.Errorf("malformed json tag: %s", val)
+ }
+
+ return tag, nil
+}
+
+// Reports whether the struct field "f" with value "v" should be included in JSON output.
+func includeField(v reflect.Value, f reflect.StructField, mustInclude map[string]bool) bool {
+ // The regular JSON encoding of a nil pointer is "null", which means "delete this field".
+ // Therefore, we could enable field deletion by honoring pointer fields' presence in the mustInclude set.
+ // However, many fields are not pointers, so there would be no way to delete these fields.
+ // Rather than partially supporting field deletion, we ignore mustInclude for nil pointer fields.
+ // Deletion will be handled by a separate mechanism.
+ if f.Type.Kind() == reflect.Ptr && v.IsNil() {
+ return false
+ }
+
+ // The "any" type is represented as an interface{}. If this interface
+ // is nil, there is no reasonable representation to send. We ignore
+ // these fields, for the same reasons as given above for pointers.
+ if f.Type.Kind() == reflect.Interface && v.IsNil() {
+ return false
+ }
+
+ return mustInclude[f.Name] || !isEmptyValue(v)
+}
+
+// isEmptyValue reports whether v is the empty value for its type. This
+// implementation is based on that of the encoding/json package, but its
+// correctness does not depend on it being identical. What's important is that
+// this function return false in situations where v should not be sent as part
+// of a PATCH operation.
+func isEmptyValue(v reflect.Value) bool {
+ switch v.Kind() {
+ case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
+ return v.Len() == 0
+ case reflect.Bool:
+ return !v.Bool()
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ return v.Int() == 0
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ return v.Uint() == 0
+ case reflect.Float32, reflect.Float64:
+ return v.Float() == 0
+ case reflect.Interface, reflect.Ptr:
+ return v.IsNil()
+ }
+ return false
+}
diff --git a/vendor/google.golang.org/api/gensupport/jsonfloat.go b/vendor/google.golang.org/api/gensupport/jsonfloat.go
new file mode 100644
index 000000000..837785081
--- /dev/null
+++ b/vendor/google.golang.org/api/gensupport/jsonfloat.go
@@ -0,0 +1,57 @@
+// Copyright 2016 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package gensupport
+
+import (
+ "encoding/json"
+ "errors"
+ "fmt"
+ "math"
+)
+
+// JSONFloat64 is a float64 that supports proper unmarshaling of special float
+// values in JSON, according to
+// https://developers.google.com/protocol-buffers/docs/proto3#json. Although
+// that is a proto-to-JSON spec, it applies to all Google APIs.
+//
+// The jsonpb package
+// (https://github.com/golang/protobuf/blob/master/jsonpb/jsonpb.go) has
+// similar functionality, but only for direct translation from proto messages
+// to JSON.
+type JSONFloat64 float64
+
+func (f *JSONFloat64) UnmarshalJSON(data []byte) error {
+ var ff float64
+ if err := json.Unmarshal(data, &ff); err == nil {
+ *f = JSONFloat64(ff)
+ return nil
+ }
+ var s string
+ if err := json.Unmarshal(data, &s); err == nil {
+ switch s {
+ case "NaN":
+ ff = math.NaN()
+ case "Infinity":
+ ff = math.Inf(1)
+ case "-Infinity":
+ ff = math.Inf(-1)
+ default:
+ return fmt.Errorf("google.golang.org/api/internal: bad float string %q", s)
+ }
+ *f = JSONFloat64(ff)
+ return nil
+ }
+ return errors.New("google.golang.org/api/internal: data not float or string")
+}
diff --git a/vendor/google.golang.org/api/gensupport/media.go b/vendor/google.golang.org/api/gensupport/media.go
new file mode 100644
index 000000000..4cef4adbb
--- /dev/null
+++ b/vendor/google.golang.org/api/gensupport/media.go
@@ -0,0 +1,342 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package gensupport
+
+import (
+ "bytes"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "mime/multipart"
+ "net/http"
+ "net/textproto"
+ "strings"
+ "sync"
+
+ "google.golang.org/api/googleapi"
+)
+
+const sniffBuffSize = 512
+
+func newContentSniffer(r io.Reader) *contentSniffer {
+ return &contentSniffer{r: r}
+}
+
+// contentSniffer wraps a Reader, and reports the content type determined by sniffing up to 512 bytes from the Reader.
+type contentSniffer struct {
+ r io.Reader
+ start []byte // buffer for the sniffed bytes.
+ err error // set to any error encountered while reading bytes to be sniffed.
+
+ ctype string // set on first sniff.
+ sniffed bool // set to true on first sniff.
+}
+
+func (cs *contentSniffer) Read(p []byte) (n int, err error) {
+ // Ensure that the content type is sniffed before any data is consumed from Reader.
+ _, _ = cs.ContentType()
+
+ if len(cs.start) > 0 {
+ n := copy(p, cs.start)
+ cs.start = cs.start[n:]
+ return n, nil
+ }
+
+ // We may have read some bytes into start while sniffing, even if the read ended in an error.
+ // We should first return those bytes, then the error.
+ if cs.err != nil {
+ return 0, cs.err
+ }
+
+ // Now we have handled all bytes that were buffered while sniffing. Now just delegate to the underlying reader.
+ return cs.r.Read(p)
+}
+
+// ContentType returns the sniffed content type, and whether the content type was succesfully sniffed.
+func (cs *contentSniffer) ContentType() (string, bool) {
+ if cs.sniffed {
+ return cs.ctype, cs.ctype != ""
+ }
+ cs.sniffed = true
+ // If ReadAll hits EOF, it returns err==nil.
+ cs.start, cs.err = ioutil.ReadAll(io.LimitReader(cs.r, sniffBuffSize))
+
+ // Don't try to detect the content type based on possibly incomplete data.
+ if cs.err != nil {
+ return "", false
+ }
+
+ cs.ctype = http.DetectContentType(cs.start)
+ return cs.ctype, true
+}
+
+// DetermineContentType determines the content type of the supplied reader.
+// If the content type is already known, it can be specified via ctype.
+// Otherwise, the content of media will be sniffed to determine the content type.
+// If media implements googleapi.ContentTyper (deprecated), this will be used
+// instead of sniffing the content.
+// After calling DetectContentType the caller must not perform further reads on
+// media, but rather read from the Reader that is returned.
+func DetermineContentType(media io.Reader, ctype string) (io.Reader, string) {
+ // Note: callers could avoid calling DetectContentType if ctype != "",
+ // but doing the check inside this function reduces the amount of
+ // generated code.
+ if ctype != "" {
+ return media, ctype
+ }
+
+ // For backwards compatability, allow clients to set content
+ // type by providing a ContentTyper for media.
+ if typer, ok := media.(googleapi.ContentTyper); ok {
+ return media, typer.ContentType()
+ }
+
+ sniffer := newContentSniffer(media)
+ if ctype, ok := sniffer.ContentType(); ok {
+ return sniffer, ctype
+ }
+ // If content type could not be sniffed, reads from sniffer will eventually fail with an error.
+ return sniffer, ""
+}
+
+type typeReader struct {
+ io.Reader
+ typ string
+}
+
+// multipartReader combines the contents of multiple readers to create a multipart/related HTTP body.
+// Close must be called if reads from the multipartReader are abandoned before reaching EOF.
+type multipartReader struct {
+ pr *io.PipeReader
+ ctype string
+ mu sync.Mutex
+ pipeOpen bool
+}
+
+func newMultipartReader(parts []typeReader) *multipartReader {
+ mp := &multipartReader{pipeOpen: true}
+ var pw *io.PipeWriter
+ mp.pr, pw = io.Pipe()
+ mpw := multipart.NewWriter(pw)
+ mp.ctype = "multipart/related; boundary=" + mpw.Boundary()
+ go func() {
+ for _, part := range parts {
+ w, err := mpw.CreatePart(typeHeader(part.typ))
+ if err != nil {
+ mpw.Close()
+ pw.CloseWithError(fmt.Errorf("googleapi: CreatePart failed: %v", err))
+ return
+ }
+ _, err = io.Copy(w, part.Reader)
+ if err != nil {
+ mpw.Close()
+ pw.CloseWithError(fmt.Errorf("googleapi: Copy failed: %v", err))
+ return
+ }
+ }
+
+ mpw.Close()
+ pw.Close()
+ }()
+ return mp
+}
+
+func (mp *multipartReader) Read(data []byte) (n int, err error) {
+ return mp.pr.Read(data)
+}
+
+func (mp *multipartReader) Close() error {
+ mp.mu.Lock()
+ if !mp.pipeOpen {
+ mp.mu.Unlock()
+ return nil
+ }
+ mp.pipeOpen = false
+ mp.mu.Unlock()
+ return mp.pr.Close()
+}
+
+// CombineBodyMedia combines a json body with media content to create a multipart/related HTTP body.
+// It returns a ReadCloser containing the combined body, and the overall "multipart/related" content type, with random boundary.
+//
+// The caller must call Close on the returned ReadCloser if reads are abandoned before reaching EOF.
+func CombineBodyMedia(body io.Reader, bodyContentType string, media io.Reader, mediaContentType string) (io.ReadCloser, string) {
+ mp := newMultipartReader([]typeReader{
+ {body, bodyContentType},
+ {media, mediaContentType},
+ })
+ return mp, mp.ctype
+}
+
+func typeHeader(contentType string) textproto.MIMEHeader {
+ h := make(textproto.MIMEHeader)
+ if contentType != "" {
+ h.Set("Content-Type", contentType)
+ }
+ return h
+}
+
+// PrepareUpload determines whether the data in the supplied reader should be
+// uploaded in a single request, or in sequential chunks.
+// chunkSize is the size of the chunk that media should be split into.
+//
+// If chunkSize is zero, media is returned as the first value, and the other
+// two return values are nil, true.
+//
+// Otherwise, a MediaBuffer is returned, along with a bool indicating whether the
+// contents of media fit in a single chunk.
+//
+// After PrepareUpload has been called, media should no longer be used: the
+// media content should be accessed via one of the return values.
+func PrepareUpload(media io.Reader, chunkSize int) (r io.Reader, mb *MediaBuffer, singleChunk bool) {
+ if chunkSize == 0 { // do not chunk
+ return media, nil, true
+ }
+ mb = NewMediaBuffer(media, chunkSize)
+ _, _, _, err := mb.Chunk()
+ // If err is io.EOF, we can upload this in a single request. Otherwise, err is
+ // either nil or a non-EOF error. If it is the latter, then the next call to
+ // mb.Chunk will return the same error. Returning a MediaBuffer ensures that this
+ // error will be handled at some point.
+ return nil, mb, err == io.EOF
+}
+
+// MediaInfo holds information for media uploads. It is intended for use by generated
+// code only.
+type MediaInfo struct {
+ // At most one of Media and MediaBuffer will be set.
+ media io.Reader
+ buffer *MediaBuffer
+ singleChunk bool
+ mType string
+ size int64 // mediaSize, if known. Used only for calls to progressUpdater_.
+ progressUpdater googleapi.ProgressUpdater
+}
+
+// NewInfoFromMedia should be invoked from the Media method of a call. It returns a
+// MediaInfo populated with chunk size and content type, and a reader or MediaBuffer
+// if needed.
+func NewInfoFromMedia(r io.Reader, options []googleapi.MediaOption) *MediaInfo {
+ mi := &MediaInfo{}
+ opts := googleapi.ProcessMediaOptions(options)
+ if !opts.ForceEmptyContentType {
+ r, mi.mType = DetermineContentType(r, opts.ContentType)
+ }
+ mi.media, mi.buffer, mi.singleChunk = PrepareUpload(r, opts.ChunkSize)
+ return mi
+}
+
+// NewInfoFromResumableMedia should be invoked from the ResumableMedia method of a
+// call. It returns a MediaInfo using the given reader, size and media type.
+func NewInfoFromResumableMedia(r io.ReaderAt, size int64, mediaType string) *MediaInfo {
+ rdr := ReaderAtToReader(r, size)
+ rdr, mType := DetermineContentType(rdr, mediaType)
+ return &MediaInfo{
+ size: size,
+ mType: mType,
+ buffer: NewMediaBuffer(rdr, googleapi.DefaultUploadChunkSize),
+ media: nil,
+ singleChunk: false,
+ }
+}
+
+// SetProgressUpdater sets the progress updater for the media info.
+func (mi *MediaInfo) SetProgressUpdater(pu googleapi.ProgressUpdater) {
+ if mi != nil {
+ mi.progressUpdater = pu
+ }
+}
+
+// UploadType determines the type of upload: a single request, or a resumable
+// series of requests.
+func (mi *MediaInfo) UploadType() string {
+ if mi.singleChunk {
+ return "multipart"
+ }
+ return "resumable"
+}
+
+// UploadRequest sets up an HTTP request for media upload. It adds headers
+// as necessary, and returns a replacement for the body and a function for http.Request.GetBody.
+func (mi *MediaInfo) UploadRequest(reqHeaders http.Header, body io.Reader) (newBody io.Reader, getBody func() (io.ReadCloser, error), cleanup func()) {
+ cleanup = func() {}
+ if mi == nil {
+ return body, nil, cleanup
+ }
+ var media io.Reader
+ if mi.media != nil {
+ // This only happens when the caller has turned off chunking. In that
+ // case, we write all of media in a single non-retryable request.
+ media = mi.media
+ } else if mi.singleChunk {
+ // The data fits in a single chunk, which has now been read into the MediaBuffer.
+ // We obtain that chunk so we can write it in a single request. The request can
+ // be retried because the data is stored in the MediaBuffer.
+ media, _, _, _ = mi.buffer.Chunk()
+ }
+ if media != nil {
+ fb := readerFunc(body)
+ fm := readerFunc(media)
+ combined, ctype := CombineBodyMedia(body, "application/json", media, mi.mType)
+ if fb != nil && fm != nil {
+ getBody = func() (io.ReadCloser, error) {
+ rb := ioutil.NopCloser(fb())
+ rm := ioutil.NopCloser(fm())
+ r, _ := CombineBodyMedia(rb, "application/json", rm, mi.mType)
+ return r, nil
+ }
+ }
+ cleanup = func() { combined.Close() }
+ reqHeaders.Set("Content-Type", ctype)
+ body = combined
+ }
+ if mi.buffer != nil && mi.mType != "" && !mi.singleChunk {
+ reqHeaders.Set("X-Upload-Content-Type", mi.mType)
+ }
+ return body, getBody, cleanup
+}
+
+// readerFunc returns a function that always returns an io.Reader that has the same
+// contents as r, provided that can be done without consuming r. Otherwise, it
+// returns nil.
+// See http.NewRequest (in net/http/request.go).
+func readerFunc(r io.Reader) func() io.Reader {
+ switch r := r.(type) {
+ case *bytes.Buffer:
+ buf := r.Bytes()
+ return func() io.Reader { return bytes.NewReader(buf) }
+ case *bytes.Reader:
+ snapshot := *r
+ return func() io.Reader { r := snapshot; return &r }
+ case *strings.Reader:
+ snapshot := *r
+ return func() io.Reader { r := snapshot; return &r }
+ default:
+ return nil
+ }
+}
+
+// ResumableUpload returns an appropriately configured ResumableUpload value if the
+// upload is resumable, or nil otherwise.
+func (mi *MediaInfo) ResumableUpload(locURI string) *ResumableUpload {
+ if mi == nil || mi.singleChunk {
+ return nil
+ }
+ return &ResumableUpload{
+ URI: locURI,
+ Media: mi.buffer,
+ MediaType: mi.mType,
+ Callback: func(curr int64) {
+ if mi.progressUpdater != nil {
+ mi.progressUpdater(curr, mi.size)
+ }
+ },
+ }
+}
+
+// SetGetBody sets the GetBody field of req to f.
+func SetGetBody(req *http.Request, f func() (io.ReadCloser, error)) {
+ req.GetBody = f
+}
diff --git a/vendor/google.golang.org/api/gensupport/params.go b/vendor/google.golang.org/api/gensupport/params.go
new file mode 100644
index 000000000..0e878a425
--- /dev/null
+++ b/vendor/google.golang.org/api/gensupport/params.go
@@ -0,0 +1,51 @@
+// Copyright 2015 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package gensupport
+
+import (
+ "net/url"
+
+ "google.golang.org/api/googleapi"
+)
+
+// URLParams is a simplified replacement for url.Values
+// that safely builds up URL parameters for encoding.
+type URLParams map[string][]string
+
+// Get returns the first value for the given key, or "".
+func (u URLParams) Get(key string) string {
+ vs := u[key]
+ if len(vs) == 0 {
+ return ""
+ }
+ return vs[0]
+}
+
+// Set sets the key to value.
+// It replaces any existing values.
+func (u URLParams) Set(key, value string) {
+ u[key] = []string{value}
+}
+
+// SetMulti sets the key to an array of values.
+// It replaces any existing values.
+// Note that values must not be modified after calling SetMulti
+// so the caller is responsible for making a copy if necessary.
+func (u URLParams) SetMulti(key string, values []string) {
+ u[key] = values
+}
+
+// Encode encodes the values into ``URL encoded'' form
+// ("bar=baz&foo=quux") sorted by key.
+func (u URLParams) Encode() string {
+ return url.Values(u).Encode()
+}
+
+// SetOptions sets the URL params and any additional call options.
+func SetOptions(u URLParams, opts ...googleapi.CallOption) {
+ for _, o := range opts {
+ u.Set(o.Get())
+ }
+}
diff --git a/vendor/google.golang.org/api/gensupport/resumable.go b/vendor/google.golang.org/api/gensupport/resumable.go
new file mode 100644
index 000000000..2552a6aca
--- /dev/null
+++ b/vendor/google.golang.org/api/gensupport/resumable.go
@@ -0,0 +1,216 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package gensupport
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "io"
+ "net/http"
+ "sync"
+ "time"
+)
+
+const (
+ // statusTooManyRequests is returned by the storage API if the
+ // per-project limits have been temporarily exceeded. The request
+ // should be retried.
+ // https://cloud.google.com/storage/docs/json_api/v1/status-codes#standardcodes
+ statusTooManyRequests = 429
+)
+
+// ResumableUpload is used by the generated APIs to provide resumable uploads.
+// It is not used by developers directly.
+type ResumableUpload struct {
+ Client *http.Client
+ // URI is the resumable resource destination provided by the server after specifying "&uploadType=resumable".
+ URI string
+ UserAgent string // User-Agent for header of the request
+ // Media is the object being uploaded.
+ Media *MediaBuffer
+ // MediaType defines the media type, e.g. "image/jpeg".
+ MediaType string
+
+ mu sync.Mutex // guards progress
+ progress int64 // number of bytes uploaded so far
+
+ // Callback is an optional function that will be periodically called with the cumulative number of bytes uploaded.
+ Callback func(int64)
+
+ // If not specified, a default exponential backoff strategy will be used.
+ Backoff BackoffStrategy
+}
+
+// Progress returns the number of bytes uploaded at this point.
+func (rx *ResumableUpload) Progress() int64 {
+ rx.mu.Lock()
+ defer rx.mu.Unlock()
+ return rx.progress
+}
+
+// doUploadRequest performs a single HTTP request to upload data.
+// off specifies the offset in rx.Media from which data is drawn.
+// size is the number of bytes in data.
+// final specifies whether data is the final chunk to be uploaded.
+func (rx *ResumableUpload) doUploadRequest(ctx context.Context, data io.Reader, off, size int64, final bool) (*http.Response, error) {
+ req, err := http.NewRequest("POST", rx.URI, data)
+ if err != nil {
+ return nil, err
+ }
+
+ req.ContentLength = size
+ var contentRange string
+ if final {
+ if size == 0 {
+ contentRange = fmt.Sprintf("bytes */%v", off)
+ } else {
+ contentRange = fmt.Sprintf("bytes %v-%v/%v", off, off+size-1, off+size)
+ }
+ } else {
+ contentRange = fmt.Sprintf("bytes %v-%v/*", off, off+size-1)
+ }
+ req.Header.Set("Content-Range", contentRange)
+ req.Header.Set("Content-Type", rx.MediaType)
+ req.Header.Set("User-Agent", rx.UserAgent)
+
+ // Google's upload endpoint uses status code 308 for a
+ // different purpose than the "308 Permanent Redirect"
+ // since-standardized in RFC 7238. Because of the conflict in
+ // semantics, Google added this new request header which
+ // causes it to not use "308" and instead reply with 200 OK
+ // and sets the upload-specific "X-HTTP-Status-Code-Override:
+ // 308" response header.
+ req.Header.Set("X-GUploader-No-308", "yes")
+
+ return SendRequest(ctx, rx.Client, req)
+}
+
+func statusResumeIncomplete(resp *http.Response) bool {
+ // This is how the server signals "status resume incomplete"
+ // when X-GUploader-No-308 is set to "yes":
+ return resp != nil && resp.Header.Get("X-Http-Status-Code-Override") == "308"
+}
+
+// reportProgress calls a user-supplied callback to report upload progress.
+// If old==updated, the callback is not called.
+func (rx *ResumableUpload) reportProgress(old, updated int64) {
+ if updated-old == 0 {
+ return
+ }
+ rx.mu.Lock()
+ rx.progress = updated
+ rx.mu.Unlock()
+ if rx.Callback != nil {
+ rx.Callback(updated)
+ }
+}
+
+// transferChunk performs a single HTTP request to upload a single chunk from rx.Media.
+func (rx *ResumableUpload) transferChunk(ctx context.Context) (*http.Response, error) {
+ chunk, off, size, err := rx.Media.Chunk()
+
+ done := err == io.EOF
+ if !done && err != nil {
+ return nil, err
+ }
+
+ res, err := rx.doUploadRequest(ctx, chunk, off, int64(size), done)
+ if err != nil {
+ return res, err
+ }
+
+ // We sent "X-GUploader-No-308: yes" (see comment elsewhere in
+ // this file), so we don't expect to get a 308.
+ if res.StatusCode == 308 {
+ return nil, errors.New("unexpected 308 response status code")
+ }
+
+ if res.StatusCode == http.StatusOK {
+ rx.reportProgress(off, off+int64(size))
+ }
+
+ if statusResumeIncomplete(res) {
+ rx.Media.Next()
+ }
+ return res, nil
+}
+
+func contextDone(ctx context.Context) bool {
+ select {
+ case <-ctx.Done():
+ return true
+ default:
+ return false
+ }
+}
+
+// Upload starts the process of a resumable upload with a cancellable context.
+// It retries using the provided back off strategy until cancelled or the
+// strategy indicates to stop retrying.
+// It is called from the auto-generated API code and is not visible to the user.
+// Before sending an HTTP request, Upload calls any registered hook functions,
+// and calls the returned functions after the request returns (see send.go).
+// rx is private to the auto-generated API code.
+// Exactly one of resp or err will be nil. If resp is non-nil, the caller must call resp.Body.Close.
+func (rx *ResumableUpload) Upload(ctx context.Context) (resp *http.Response, err error) {
+ var pause time.Duration
+ backoff := rx.Backoff
+ if backoff == nil {
+ backoff = DefaultBackoffStrategy()
+ }
+
+ for {
+ // Ensure that we return in the case of cancelled context, even if pause is 0.
+ if contextDone(ctx) {
+ return nil, ctx.Err()
+ }
+ select {
+ case <-ctx.Done():
+ return nil, ctx.Err()
+ case <-time.After(pause):
+ }
+
+ resp, err = rx.transferChunk(ctx)
+
+ var status int
+ if resp != nil {
+ status = resp.StatusCode
+ }
+
+ // Check if we should retry the request.
+ if shouldRetry(status, err) {
+ var retry bool
+ pause, retry = backoff.Pause()
+ if retry {
+ if resp != nil && resp.Body != nil {
+ resp.Body.Close()
+ }
+ continue
+ }
+ }
+
+ // If the chunk was uploaded successfully, but there's still
+ // more to go, upload the next chunk without any delay.
+ if statusResumeIncomplete(resp) {
+ pause = 0
+ backoff.Reset()
+ resp.Body.Close()
+ continue
+ }
+
+ // It's possible for err and resp to both be non-nil here, but we expose a simpler
+ // contract to our callers: exactly one of resp and err will be non-nil. This means
+ // that any response body must be closed here before returning a non-nil error.
+ if err != nil {
+ if resp != nil && resp.Body != nil {
+ resp.Body.Close()
+ }
+ return nil, err
+ }
+
+ return resp, nil
+ }
+}
diff --git a/vendor/google.golang.org/api/gensupport/retry.go b/vendor/google.golang.org/api/gensupport/retry.go
new file mode 100644
index 000000000..fdde3f42c
--- /dev/null
+++ b/vendor/google.golang.org/api/gensupport/retry.go
@@ -0,0 +1,84 @@
+// Copyright 2017 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package gensupport
+
+import (
+ "context"
+ "io"
+ "net"
+ "net/http"
+ "time"
+)
+
+// Retry invokes the given function, retrying it multiple times if the connection failed or
+// the HTTP status response indicates the request should be attempted again. ctx may be nil.
+func Retry(ctx context.Context, f func() (*http.Response, error), backoff BackoffStrategy) (*http.Response, error) {
+ for {
+ resp, err := f()
+
+ var status int
+ if resp != nil {
+ status = resp.StatusCode
+ }
+
+ // Return if we shouldn't retry.
+ pause, retry := backoff.Pause()
+ if !shouldRetry(status, err) || !retry {
+ return resp, err
+ }
+
+ // Ensure the response body is closed, if any.
+ if resp != nil && resp.Body != nil {
+ resp.Body.Close()
+ }
+
+ // Pause, but still listen to ctx.Done if context is not nil.
+ var done <-chan struct{}
+ if ctx != nil {
+ done = ctx.Done()
+ }
+ select {
+ case <-done:
+ return nil, ctx.Err()
+ case <-time.After(pause):
+ }
+ }
+}
+
+// DefaultBackoffStrategy returns a default strategy to use for retrying failed upload requests.
+func DefaultBackoffStrategy() BackoffStrategy {
+ return &ExponentialBackoff{
+ Base: 250 * time.Millisecond,
+ Max: 16 * time.Second,
+ }
+}
+
+// shouldRetry returns true if the HTTP response / error indicates that the
+// request should be attempted again.
+func shouldRetry(status int, err error) bool {
+ if 500 <= status && status <= 599 {
+ return true
+ }
+ if status == statusTooManyRequests {
+ return true
+ }
+ if err == io.ErrUnexpectedEOF {
+ return true
+ }
+ if err, ok := err.(net.Error); ok {
+ return err.Temporary()
+ }
+ return false
+}
diff --git a/vendor/google.golang.org/api/gensupport/send.go b/vendor/google.golang.org/api/gensupport/send.go
new file mode 100644
index 000000000..579939309
--- /dev/null
+++ b/vendor/google.golang.org/api/gensupport/send.go
@@ -0,0 +1,87 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package gensupport
+
+import (
+ "context"
+ "encoding/json"
+ "errors"
+ "net/http"
+)
+
+// Hook is the type of a function that is called once before each HTTP request
+// that is sent by a generated API. It returns a function that is called after
+// the request returns.
+// Hooks are not called if the context is nil.
+type Hook func(ctx context.Context, req *http.Request) func(resp *http.Response)
+
+var hooks []Hook
+
+// RegisterHook registers a Hook to be called before each HTTP request by a
+// generated API. Hooks are called in the order they are registered. Each
+// hook can return a function; if it is non-nil, it is called after the HTTP
+// request returns. These functions are called in the reverse order.
+// RegisterHook should not be called concurrently with itself or SendRequest.
+func RegisterHook(h Hook) {
+ hooks = append(hooks, h)
+}
+
+// SendRequest sends a single HTTP request using the given client.
+// If ctx is non-nil, it calls all hooks, then sends the request with
+// req.WithContext, then calls any functions returned by the hooks in
+// reverse order.
+func SendRequest(ctx context.Context, client *http.Client, req *http.Request) (*http.Response, error) {
+ // Disallow Accept-Encoding because it interferes with the automatic gzip handling
+ // done by the default http.Transport. See https://github.com/google/google-api-go-client/issues/219.
+ if _, ok := req.Header["Accept-Encoding"]; ok {
+ return nil, errors.New("google api: custom Accept-Encoding headers not allowed")
+ }
+ if ctx == nil {
+ return client.Do(req)
+ }
+ // Call hooks in order of registration, store returned funcs.
+ post := make([]func(resp *http.Response), len(hooks))
+ for i, h := range hooks {
+ fn := h(ctx, req)
+ post[i] = fn
+ }
+
+ // Send request.
+ resp, err := send(ctx, client, req)
+
+ // Call returned funcs in reverse order.
+ for i := len(post) - 1; i >= 0; i-- {
+ if fn := post[i]; fn != nil {
+ fn(resp)
+ }
+ }
+ return resp, err
+}
+
+func send(ctx context.Context, client *http.Client, req *http.Request) (*http.Response, error) {
+ if client == nil {
+ client = http.DefaultClient
+ }
+ resp, err := client.Do(req.WithContext(ctx))
+ // If we got an error, and the context has been canceled,
+ // the context's error is probably more useful.
+ if err != nil {
+ select {
+ case <-ctx.Done():
+ err = ctx.Err()
+ default:
+ }
+ }
+ return resp, err
+}
+
+// DecodeResponse decodes the body of res into target. If there is no body,
+// target is unchanged.
+func DecodeResponse(target interface{}, res *http.Response) error {
+ if res.StatusCode == http.StatusNoContent {
+ return nil
+ }
+ return json.NewDecoder(res.Body).Decode(target)
+}
diff --git a/vendor/google.golang.org/api/googleapi/googleapi.go b/vendor/google.golang.org/api/googleapi/googleapi.go
new file mode 100644
index 000000000..8cdb03bb3
--- /dev/null
+++ b/vendor/google.golang.org/api/googleapi/googleapi.go
@@ -0,0 +1,429 @@
+// Copyright 2011 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package googleapi contains the common code shared by all Google API
+// libraries.
+package googleapi // import "google.golang.org/api/googleapi"
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "net/http"
+ "net/url"
+ "strings"
+
+ "google.golang.org/api/googleapi/internal/uritemplates"
+)
+
+// ContentTyper is an interface for Readers which know (or would like
+// to override) their Content-Type. If a media body doesn't implement
+// ContentTyper, the type is sniffed from the content using
+// http.DetectContentType.
+type ContentTyper interface {
+ ContentType() string
+}
+
+// A SizeReaderAt is a ReaderAt with a Size method.
+// An io.SectionReader implements SizeReaderAt.
+type SizeReaderAt interface {
+ io.ReaderAt
+ Size() int64
+}
+
+// ServerResponse is embedded in each Do response and
+// provides the HTTP status code and header sent by the server.
+type ServerResponse struct {
+ // HTTPStatusCode is the server's response status code. When using a
+ // resource method's Do call, this will always be in the 2xx range.
+ HTTPStatusCode int
+ // Header contains the response header fields from the server.
+ Header http.Header
+}
+
+const (
+ // Version defines the gax version being used. This is typically sent
+ // in an HTTP header to services.
+ Version = "0.5"
+
+ // UserAgent is the header string used to identify this package.
+ UserAgent = "google-api-go-client/" + Version
+
+ // DefaultUploadChunkSize is the default chunk size to use for resumable
+ // uploads if not specified by the user.
+ DefaultUploadChunkSize = 8 * 1024 * 1024
+
+ // MinUploadChunkSize is the minimum chunk size that can be used for
+ // resumable uploads. All user-specified chunk sizes must be multiple of
+ // this value.
+ MinUploadChunkSize = 256 * 1024
+)
+
+// Error contains an error response from the server.
+type Error struct {
+ // Code is the HTTP response status code and will always be populated.
+ Code int `json:"code"`
+ // Message is the server response message and is only populated when
+ // explicitly referenced by the JSON server response.
+ Message string `json:"message"`
+ // Body is the raw response returned by the server.
+ // It is often but not always JSON, depending on how the request fails.
+ Body string
+ // Header contains the response header fields from the server.
+ Header http.Header
+
+ Errors []ErrorItem
+}
+
+// ErrorItem is a detailed error code & message from the Google API frontend.
+type ErrorItem struct {
+ // Reason is the typed error code. For example: "some_example".
+ Reason string `json:"reason"`
+ // Message is the human-readable description of the error.
+ Message string `json:"message"`
+}
+
+func (e *Error) Error() string {
+ if len(e.Errors) == 0 && e.Message == "" {
+ return fmt.Sprintf("googleapi: got HTTP response code %d with body: %v", e.Code, e.Body)
+ }
+ var buf bytes.Buffer
+ fmt.Fprintf(&buf, "googleapi: Error %d: ", e.Code)
+ if e.Message != "" {
+ fmt.Fprintf(&buf, "%s", e.Message)
+ }
+ if len(e.Errors) == 0 {
+ return strings.TrimSpace(buf.String())
+ }
+ if len(e.Errors) == 1 && e.Errors[0].Message == e.Message {
+ fmt.Fprintf(&buf, ", %s", e.Errors[0].Reason)
+ return buf.String()
+ }
+ fmt.Fprintln(&buf, "\nMore details:")
+ for _, v := range e.Errors {
+ fmt.Fprintf(&buf, "Reason: %s, Message: %s\n", v.Reason, v.Message)
+ }
+ return buf.String()
+}
+
+type errorReply struct {
+ Error *Error `json:"error"`
+}
+
+// CheckResponse returns an error (of type *Error) if the response
+// status code is not 2xx.
+func CheckResponse(res *http.Response) error {
+ if res.StatusCode >= 200 && res.StatusCode <= 299 {
+ return nil
+ }
+ slurp, err := ioutil.ReadAll(res.Body)
+ if err == nil {
+ jerr := new(errorReply)
+ err = json.Unmarshal(slurp, jerr)
+ if err == nil && jerr.Error != nil {
+ if jerr.Error.Code == 0 {
+ jerr.Error.Code = res.StatusCode
+ }
+ jerr.Error.Body = string(slurp)
+ return jerr.Error
+ }
+ }
+ return &Error{
+ Code: res.StatusCode,
+ Body: string(slurp),
+ Header: res.Header,
+ }
+}
+
+// IsNotModified reports whether err is the result of the
+// server replying with http.StatusNotModified.
+// Such error values are sometimes returned by "Do" methods
+// on calls when If-None-Match is used.
+func IsNotModified(err error) bool {
+ if err == nil {
+ return false
+ }
+ ae, ok := err.(*Error)
+ return ok && ae.Code == http.StatusNotModified
+}
+
+// CheckMediaResponse returns an error (of type *Error) if the response
+// status code is not 2xx. Unlike CheckResponse it does not assume the
+// body is a JSON error document.
+// It is the caller's responsibility to close res.Body.
+func CheckMediaResponse(res *http.Response) error {
+ if res.StatusCode >= 200 && res.StatusCode <= 299 {
+ return nil
+ }
+ slurp, _ := ioutil.ReadAll(io.LimitReader(res.Body, 1<<20))
+ return &Error{
+ Code: res.StatusCode,
+ Body: string(slurp),
+ }
+}
+
+// MarshalStyle defines whether to marshal JSON with a {"data": ...} wrapper.
+type MarshalStyle bool
+
+// WithDataWrapper marshals JSON with a {"data": ...} wrapper.
+var WithDataWrapper = MarshalStyle(true)
+
+// WithoutDataWrapper marshals JSON without a {"data": ...} wrapper.
+var WithoutDataWrapper = MarshalStyle(false)
+
+func (wrap MarshalStyle) JSONReader(v interface{}) (io.Reader, error) {
+ buf := new(bytes.Buffer)
+ if wrap {
+ buf.Write([]byte(`{"data": `))
+ }
+ err := json.NewEncoder(buf).Encode(v)
+ if err != nil {
+ return nil, err
+ }
+ if wrap {
+ buf.Write([]byte(`}`))
+ }
+ return buf, nil
+}
+
+// endingWithErrorReader from r until it returns an error. If the
+// final error from r is io.EOF and e is non-nil, e is used instead.
+type endingWithErrorReader struct {
+ r io.Reader
+ e error
+}
+
+func (er endingWithErrorReader) Read(p []byte) (n int, err error) {
+ n, err = er.r.Read(p)
+ if err == io.EOF && er.e != nil {
+ err = er.e
+ }
+ return
+}
+
+// countingWriter counts the number of bytes it receives to write, but
+// discards them.
+type countingWriter struct {
+ n *int64
+}
+
+func (w countingWriter) Write(p []byte) (int, error) {
+ *w.n += int64(len(p))
+ return len(p), nil
+}
+
+// ProgressUpdater is a function that is called upon every progress update of a resumable upload.
+// This is the only part of a resumable upload (from googleapi) that is usable by the developer.
+// The remaining usable pieces of resumable uploads is exposed in each auto-generated API.
+type ProgressUpdater func(current, total int64)
+
+// MediaOption defines the interface for setting media options.
+type MediaOption interface {
+ setOptions(o *MediaOptions)
+}
+
+type contentTypeOption string
+
+func (ct contentTypeOption) setOptions(o *MediaOptions) {
+ o.ContentType = string(ct)
+ if o.ContentType == "" {
+ o.ForceEmptyContentType = true
+ }
+}
+
+// ContentType returns a MediaOption which sets the Content-Type header for media uploads.
+// If ctype is empty, the Content-Type header will be omitted.
+func ContentType(ctype string) MediaOption {
+ return contentTypeOption(ctype)
+}
+
+type chunkSizeOption int
+
+func (cs chunkSizeOption) setOptions(o *MediaOptions) {
+ size := int(cs)
+ if size%MinUploadChunkSize != 0 {
+ size += MinUploadChunkSize - (size % MinUploadChunkSize)
+ }
+ o.ChunkSize = size
+}
+
+// ChunkSize returns a MediaOption which sets the chunk size for media uploads.
+// size will be rounded up to the nearest multiple of 256K.
+// Media which contains fewer than size bytes will be uploaded in a single request.
+// Media which contains size bytes or more will be uploaded in separate chunks.
+// If size is zero, media will be uploaded in a single request.
+func ChunkSize(size int) MediaOption {
+ return chunkSizeOption(size)
+}
+
+// MediaOptions stores options for customizing media upload. It is not used by developers directly.
+type MediaOptions struct {
+ ContentType string
+ ForceEmptyContentType bool
+
+ ChunkSize int
+}
+
+// ProcessMediaOptions stores options from opts in a MediaOptions.
+// It is not used by developers directly.
+func ProcessMediaOptions(opts []MediaOption) *MediaOptions {
+ mo := &MediaOptions{ChunkSize: DefaultUploadChunkSize}
+ for _, o := range opts {
+ o.setOptions(mo)
+ }
+ return mo
+}
+
+// ResolveRelative resolves relatives such as "http://www.golang.org/" and
+// "topics/myproject/mytopic" into a single string, such as
+// "http://www.golang.org/topics/myproject/mytopic". It strips all parent
+// references (e.g. ../..) as well as anything after the host
+// (e.g. /bar/gaz gets stripped out of foo.com/bar/gaz).
+func ResolveRelative(basestr, relstr string) string {
+ u, _ := url.Parse(basestr)
+ afterColonPath := ""
+ if i := strings.IndexRune(relstr, ':'); i > 0 {
+ afterColonPath = relstr[i+1:]
+ relstr = relstr[:i]
+ }
+ rel, _ := url.Parse(relstr)
+ u = u.ResolveReference(rel)
+ us := u.String()
+ if afterColonPath != "" {
+ us = fmt.Sprintf("%s:%s", us, afterColonPath)
+ }
+ us = strings.Replace(us, "%7B", "{", -1)
+ us = strings.Replace(us, "%7D", "}", -1)
+ us = strings.Replace(us, "%2A", "*", -1)
+ return us
+}
+
+// Expand subsitutes any {encoded} strings in the URL passed in using
+// the map supplied.
+//
+// This calls SetOpaque to avoid encoding of the parameters in the URL path.
+func Expand(u *url.URL, expansions map[string]string) {
+ escaped, unescaped, err := uritemplates.Expand(u.Path, expansions)
+ if err == nil {
+ u.Path = unescaped
+ u.RawPath = escaped
+ }
+}
+
+// CloseBody is used to close res.Body.
+// Prior to calling Close, it also tries to Read a small amount to see an EOF.
+// Not seeing an EOF can prevent HTTP Transports from reusing connections.
+func CloseBody(res *http.Response) {
+ if res == nil || res.Body == nil {
+ return
+ }
+ // Justification for 3 byte reads: two for up to "\r\n" after
+ // a JSON/XML document, and then 1 to see EOF if we haven't yet.
+ // TODO(bradfitz): detect Go 1.3+ and skip these reads.
+ // See https://codereview.appspot.com/58240043
+ // and https://codereview.appspot.com/49570044
+ buf := make([]byte, 1)
+ for i := 0; i < 3; i++ {
+ _, err := res.Body.Read(buf)
+ if err != nil {
+ break
+ }
+ }
+ res.Body.Close()
+
+}
+
+// VariantType returns the type name of the given variant.
+// If the map doesn't contain the named key or the value is not a []interface{}, "" is returned.
+// This is used to support "variant" APIs that can return one of a number of different types.
+func VariantType(t map[string]interface{}) string {
+ s, _ := t["type"].(string)
+ return s
+}
+
+// ConvertVariant uses the JSON encoder/decoder to fill in the struct 'dst' with the fields found in variant 'v'.
+// This is used to support "variant" APIs that can return one of a number of different types.
+// It reports whether the conversion was successful.
+func ConvertVariant(v map[string]interface{}, dst interface{}) bool {
+ var buf bytes.Buffer
+ err := json.NewEncoder(&buf).Encode(v)
+ if err != nil {
+ return false
+ }
+ return json.Unmarshal(buf.Bytes(), dst) == nil
+}
+
+// A Field names a field to be retrieved with a partial response.
+// See https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
+//
+// Partial responses can dramatically reduce the amount of data that must be sent to your application.
+// In order to request partial responses, you can specify the full list of fields
+// that your application needs by adding the Fields option to your request.
+//
+// Field strings use camelCase with leading lower-case characters to identify fields within the response.
+//
+// For example, if your response has a "NextPageToken" and a slice of "Items" with "Id" fields,
+// you could request just those fields like this:
+//
+// svc.Events.List().Fields("nextPageToken", "items/id").Do()
+//
+// or if you were also interested in each Item's "Updated" field, you can combine them like this:
+//
+// svc.Events.List().Fields("nextPageToken", "items(id,updated)").Do()
+//
+// More information about field formatting can be found here:
+// https://developers.google.com/+/api/#fields-syntax
+//
+// Another way to find field names is through the Google API explorer:
+// https://developers.google.com/apis-explorer/#p/
+type Field string
+
+// CombineFields combines fields into a single string.
+func CombineFields(s []Field) string {
+ r := make([]string, len(s))
+ for i, v := range s {
+ r[i] = string(v)
+ }
+ return strings.Join(r, ",")
+}
+
+// A CallOption is an optional argument to an API call.
+// It should be treated as an opaque value by users of Google APIs.
+//
+// A CallOption is something that configures an API call in a way that is
+// not specific to that API; for instance, controlling the quota user for
+// an API call is common across many APIs, and is thus a CallOption.
+type CallOption interface {
+ Get() (key, value string)
+}
+
+// QuotaUser returns a CallOption that will set the quota user for a call.
+// The quota user can be used by server-side applications to control accounting.
+// It can be an arbitrary string up to 40 characters, and will override UserIP
+// if both are provided.
+func QuotaUser(u string) CallOption { return quotaUser(u) }
+
+type quotaUser string
+
+func (q quotaUser) Get() (string, string) { return "quotaUser", string(q) }
+
+// UserIP returns a CallOption that will set the "userIp" parameter of a call.
+// This should be the IP address of the originating request.
+func UserIP(ip string) CallOption { return userIP(ip) }
+
+type userIP string
+
+func (i userIP) Get() (string, string) { return "userIp", string(i) }
+
+// Trace returns a CallOption that enables diagnostic tracing for a call.
+// traceToken is an ID supplied by Google support.
+func Trace(traceToken string) CallOption { return traceTok(traceToken) }
+
+type traceTok string
+
+func (t traceTok) Get() (string, string) { return "trace", "token:" + string(t) }
+
+// TODO: Fields too
diff --git a/vendor/google.golang.org/api/googleapi/internal/uritemplates/LICENSE b/vendor/google.golang.org/api/googleapi/internal/uritemplates/LICENSE
new file mode 100644
index 000000000..de9c88cb6
--- /dev/null
+++ b/vendor/google.golang.org/api/googleapi/internal/uritemplates/LICENSE
@@ -0,0 +1,18 @@
+Copyright (c) 2013 Joshua Tacoma
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/vendor/google.golang.org/api/googleapi/internal/uritemplates/uritemplates.go b/vendor/google.golang.org/api/googleapi/internal/uritemplates/uritemplates.go
new file mode 100644
index 000000000..63bf05383
--- /dev/null
+++ b/vendor/google.golang.org/api/googleapi/internal/uritemplates/uritemplates.go
@@ -0,0 +1,248 @@
+// Copyright 2013 Joshua Tacoma. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package uritemplates is a level 3 implementation of RFC 6570 (URI
+// Template, http://tools.ietf.org/html/rfc6570).
+// uritemplates does not support composite values (in Go: slices or maps)
+// and so does not qualify as a level 4 implementation.
+package uritemplates
+
+import (
+ "bytes"
+ "errors"
+ "regexp"
+ "strconv"
+ "strings"
+)
+
+var (
+ unreserved = regexp.MustCompile("[^A-Za-z0-9\\-._~]")
+ reserved = regexp.MustCompile("[^A-Za-z0-9\\-._~:/?#[\\]@!$&'()*+,;=]")
+ validname = regexp.MustCompile("^([A-Za-z0-9_\\.]|%[0-9A-Fa-f][0-9A-Fa-f])+$")
+ hex = []byte("0123456789ABCDEF")
+)
+
+func pctEncode(src []byte) []byte {
+ dst := make([]byte, len(src)*3)
+ for i, b := range src {
+ buf := dst[i*3 : i*3+3]
+ buf[0] = 0x25
+ buf[1] = hex[b/16]
+ buf[2] = hex[b%16]
+ }
+ return dst
+}
+
+// pairWriter is a convenience struct which allows escaped and unescaped
+// versions of the template to be written in parallel.
+type pairWriter struct {
+ escaped, unescaped bytes.Buffer
+}
+
+// Write writes the provided string directly without any escaping.
+func (w *pairWriter) Write(s string) {
+ w.escaped.WriteString(s)
+ w.unescaped.WriteString(s)
+}
+
+// Escape writes the provided string, escaping the string for the
+// escaped output.
+func (w *pairWriter) Escape(s string, allowReserved bool) {
+ w.unescaped.WriteString(s)
+ if allowReserved {
+ w.escaped.Write(reserved.ReplaceAllFunc([]byte(s), pctEncode))
+ } else {
+ w.escaped.Write(unreserved.ReplaceAllFunc([]byte(s), pctEncode))
+ }
+}
+
+// Escaped returns the escaped string.
+func (w *pairWriter) Escaped() string {
+ return w.escaped.String()
+}
+
+// Unescaped returns the unescaped string.
+func (w *pairWriter) Unescaped() string {
+ return w.unescaped.String()
+}
+
+// A uriTemplate is a parsed representation of a URI template.
+type uriTemplate struct {
+ raw string
+ parts []templatePart
+}
+
+// parse parses a URI template string into a uriTemplate object.
+func parse(rawTemplate string) (*uriTemplate, error) {
+ split := strings.Split(rawTemplate, "{")
+ parts := make([]templatePart, len(split)*2-1)
+ for i, s := range split {
+ if i == 0 {
+ if strings.Contains(s, "}") {
+ return nil, errors.New("unexpected }")
+ }
+ parts[i].raw = s
+ continue
+ }
+ subsplit := strings.Split(s, "}")
+ if len(subsplit) != 2 {
+ return nil, errors.New("malformed template")
+ }
+ expression := subsplit[0]
+ var err error
+ parts[i*2-1], err = parseExpression(expression)
+ if err != nil {
+ return nil, err
+ }
+ parts[i*2].raw = subsplit[1]
+ }
+ return &uriTemplate{
+ raw: rawTemplate,
+ parts: parts,
+ }, nil
+}
+
+type templatePart struct {
+ raw string
+ terms []templateTerm
+ first string
+ sep string
+ named bool
+ ifemp string
+ allowReserved bool
+}
+
+type templateTerm struct {
+ name string
+ explode bool
+ truncate int
+}
+
+func parseExpression(expression string) (result templatePart, err error) {
+ switch expression[0] {
+ case '+':
+ result.sep = ","
+ result.allowReserved = true
+ expression = expression[1:]
+ case '.':
+ result.first = "."
+ result.sep = "."
+ expression = expression[1:]
+ case '/':
+ result.first = "/"
+ result.sep = "/"
+ expression = expression[1:]
+ case ';':
+ result.first = ";"
+ result.sep = ";"
+ result.named = true
+ expression = expression[1:]
+ case '?':
+ result.first = "?"
+ result.sep = "&"
+ result.named = true
+ result.ifemp = "="
+ expression = expression[1:]
+ case '&':
+ result.first = "&"
+ result.sep = "&"
+ result.named = true
+ result.ifemp = "="
+ expression = expression[1:]
+ case '#':
+ result.first = "#"
+ result.sep = ","
+ result.allowReserved = true
+ expression = expression[1:]
+ default:
+ result.sep = ","
+ }
+ rawterms := strings.Split(expression, ",")
+ result.terms = make([]templateTerm, len(rawterms))
+ for i, raw := range rawterms {
+ result.terms[i], err = parseTerm(raw)
+ if err != nil {
+ break
+ }
+ }
+ return result, err
+}
+
+func parseTerm(term string) (result templateTerm, err error) {
+ // TODO(djd): Remove "*" suffix parsing once we check that no APIs have
+ // mistakenly used that attribute.
+ if strings.HasSuffix(term, "*") {
+ result.explode = true
+ term = term[:len(term)-1]
+ }
+ split := strings.Split(term, ":")
+ if len(split) == 1 {
+ result.name = term
+ } else if len(split) == 2 {
+ result.name = split[0]
+ var parsed int64
+ parsed, err = strconv.ParseInt(split[1], 10, 0)
+ result.truncate = int(parsed)
+ } else {
+ err = errors.New("multiple colons in same term")
+ }
+ if !validname.MatchString(result.name) {
+ err = errors.New("not a valid name: " + result.name)
+ }
+ if result.explode && result.truncate > 0 {
+ err = errors.New("both explode and prefix modifers on same term")
+ }
+ return result, err
+}
+
+// Expand expands a URI template with a set of values to produce the
+// resultant URI. Two forms of the result are returned: one with all the
+// elements escaped, and one with the elements unescaped.
+func (t *uriTemplate) Expand(values map[string]string) (escaped, unescaped string) {
+ var w pairWriter
+ for _, p := range t.parts {
+ p.expand(&w, values)
+ }
+ return w.Escaped(), w.Unescaped()
+}
+
+func (tp *templatePart) expand(w *pairWriter, values map[string]string) {
+ if len(tp.raw) > 0 {
+ w.Write(tp.raw)
+ return
+ }
+ var first = true
+ for _, term := range tp.terms {
+ value, exists := values[term.name]
+ if !exists {
+ continue
+ }
+ if first {
+ w.Write(tp.first)
+ first = false
+ } else {
+ w.Write(tp.sep)
+ }
+ tp.expandString(w, term, value)
+ }
+}
+
+func (tp *templatePart) expandName(w *pairWriter, name string, empty bool) {
+ if tp.named {
+ w.Write(name)
+ if empty {
+ w.Write(tp.ifemp)
+ } else {
+ w.Write("=")
+ }
+ }
+}
+
+func (tp *templatePart) expandString(w *pairWriter, t templateTerm, s string) {
+ if len(s) > t.truncate && t.truncate > 0 {
+ s = s[:t.truncate]
+ }
+ tp.expandName(w, t.name, len(s) == 0)
+ w.Escape(s, tp.allowReserved)
+}
diff --git a/vendor/google.golang.org/api/googleapi/internal/uritemplates/utils.go b/vendor/google.golang.org/api/googleapi/internal/uritemplates/utils.go
new file mode 100644
index 000000000..2e70b8154
--- /dev/null
+++ b/vendor/google.golang.org/api/googleapi/internal/uritemplates/utils.go
@@ -0,0 +1,17 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package uritemplates
+
+// Expand parses then expands a URI template with a set of values to produce
+// the resultant URI. Two forms of the result are returned: one with all the
+// elements escaped, and one with the elements unescaped.
+func Expand(path string, values map[string]string) (escaped, unescaped string, err error) {
+ template, err := parse(path)
+ if err != nil {
+ return "", "", err
+ }
+ escaped, unescaped = template.Expand(values)
+ return escaped, unescaped, nil
+}
diff --git a/vendor/google.golang.org/api/googleapi/transport/apikey.go b/vendor/google.golang.org/api/googleapi/transport/apikey.go
new file mode 100644
index 000000000..eca1ea250
--- /dev/null
+++ b/vendor/google.golang.org/api/googleapi/transport/apikey.go
@@ -0,0 +1,38 @@
+// Copyright 2012 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package transport contains HTTP transports used to make
+// authenticated API requests.
+package transport
+
+import (
+ "errors"
+ "net/http"
+)
+
+// APIKey is an HTTP Transport which wraps an underlying transport and
+// appends an API Key "key" parameter to the URL of outgoing requests.
+type APIKey struct {
+ // Key is the API Key to set on requests.
+ Key string
+
+ // Transport is the underlying HTTP transport.
+ // If nil, http.DefaultTransport is used.
+ Transport http.RoundTripper
+}
+
+func (t *APIKey) RoundTrip(req *http.Request) (*http.Response, error) {
+ rt := t.Transport
+ if rt == nil {
+ rt = http.DefaultTransport
+ if rt == nil {
+ return nil, errors.New("googleapi/transport: no Transport specified or available")
+ }
+ }
+ newReq := *req
+ args := newReq.URL.Query()
+ args.Set("key", t.Key)
+ newReq.URL.RawQuery = args.Encode()
+ return rt.RoundTrip(&newReq)
+}
diff --git a/vendor/google.golang.org/api/googleapi/types.go b/vendor/google.golang.org/api/googleapi/types.go
new file mode 100644
index 000000000..a280e3021
--- /dev/null
+++ b/vendor/google.golang.org/api/googleapi/types.go
@@ -0,0 +1,202 @@
+// Copyright 2013 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package googleapi
+
+import (
+ "encoding/json"
+ "errors"
+ "strconv"
+)
+
+// Int64s is a slice of int64s that marshal as quoted strings in JSON.
+type Int64s []int64
+
+func (q *Int64s) UnmarshalJSON(raw []byte) error {
+ *q = (*q)[:0]
+ var ss []string
+ if err := json.Unmarshal(raw, &ss); err != nil {
+ return err
+ }
+ for _, s := range ss {
+ v, err := strconv.ParseInt(s, 10, 64)
+ if err != nil {
+ return err
+ }
+ *q = append(*q, int64(v))
+ }
+ return nil
+}
+
+// Int32s is a slice of int32s that marshal as quoted strings in JSON.
+type Int32s []int32
+
+func (q *Int32s) UnmarshalJSON(raw []byte) error {
+ *q = (*q)[:0]
+ var ss []string
+ if err := json.Unmarshal(raw, &ss); err != nil {
+ return err
+ }
+ for _, s := range ss {
+ v, err := strconv.ParseInt(s, 10, 32)
+ if err != nil {
+ return err
+ }
+ *q = append(*q, int32(v))
+ }
+ return nil
+}
+
+// Uint64s is a slice of uint64s that marshal as quoted strings in JSON.
+type Uint64s []uint64
+
+func (q *Uint64s) UnmarshalJSON(raw []byte) error {
+ *q = (*q)[:0]
+ var ss []string
+ if err := json.Unmarshal(raw, &ss); err != nil {
+ return err
+ }
+ for _, s := range ss {
+ v, err := strconv.ParseUint(s, 10, 64)
+ if err != nil {
+ return err
+ }
+ *q = append(*q, uint64(v))
+ }
+ return nil
+}
+
+// Uint32s is a slice of uint32s that marshal as quoted strings in JSON.
+type Uint32s []uint32
+
+func (q *Uint32s) UnmarshalJSON(raw []byte) error {
+ *q = (*q)[:0]
+ var ss []string
+ if err := json.Unmarshal(raw, &ss); err != nil {
+ return err
+ }
+ for _, s := range ss {
+ v, err := strconv.ParseUint(s, 10, 32)
+ if err != nil {
+ return err
+ }
+ *q = append(*q, uint32(v))
+ }
+ return nil
+}
+
+// Float64s is a slice of float64s that marshal as quoted strings in JSON.
+type Float64s []float64
+
+func (q *Float64s) UnmarshalJSON(raw []byte) error {
+ *q = (*q)[:0]
+ var ss []string
+ if err := json.Unmarshal(raw, &ss); err != nil {
+ return err
+ }
+ for _, s := range ss {
+ v, err := strconv.ParseFloat(s, 64)
+ if err != nil {
+ return err
+ }
+ *q = append(*q, float64(v))
+ }
+ return nil
+}
+
+func quotedList(n int, fn func(dst []byte, i int) []byte) ([]byte, error) {
+ dst := make([]byte, 0, 2+n*10) // somewhat arbitrary
+ dst = append(dst, '[')
+ for i := 0; i < n; i++ {
+ if i > 0 {
+ dst = append(dst, ',')
+ }
+ dst = append(dst, '"')
+ dst = fn(dst, i)
+ dst = append(dst, '"')
+ }
+ dst = append(dst, ']')
+ return dst, nil
+}
+
+func (q Int64s) MarshalJSON() ([]byte, error) {
+ return quotedList(len(q), func(dst []byte, i int) []byte {
+ return strconv.AppendInt(dst, q[i], 10)
+ })
+}
+
+func (q Int32s) MarshalJSON() ([]byte, error) {
+ return quotedList(len(q), func(dst []byte, i int) []byte {
+ return strconv.AppendInt(dst, int64(q[i]), 10)
+ })
+}
+
+func (q Uint64s) MarshalJSON() ([]byte, error) {
+ return quotedList(len(q), func(dst []byte, i int) []byte {
+ return strconv.AppendUint(dst, q[i], 10)
+ })
+}
+
+func (q Uint32s) MarshalJSON() ([]byte, error) {
+ return quotedList(len(q), func(dst []byte, i int) []byte {
+ return strconv.AppendUint(dst, uint64(q[i]), 10)
+ })
+}
+
+func (q Float64s) MarshalJSON() ([]byte, error) {
+ return quotedList(len(q), func(dst []byte, i int) []byte {
+ return strconv.AppendFloat(dst, q[i], 'g', -1, 64)
+ })
+}
+
+// RawMessage is a raw encoded JSON value.
+// It is identical to json.RawMessage, except it does not suffer from
+// https://golang.org/issue/14493.
+type RawMessage []byte
+
+// MarshalJSON returns m.
+func (m RawMessage) MarshalJSON() ([]byte, error) {
+ return m, nil
+}
+
+// UnmarshalJSON sets *m to a copy of data.
+func (m *RawMessage) UnmarshalJSON(data []byte) error {
+ if m == nil {
+ return errors.New("googleapi.RawMessage: UnmarshalJSON on nil pointer")
+ }
+ *m = append((*m)[:0], data...)
+ return nil
+}
+
+/*
+ * Helper routines for simplifying the creation of optional fields of basic type.
+ */
+
+// Bool is a helper routine that allocates a new bool value
+// to store v and returns a pointer to it.
+func Bool(v bool) *bool { return &v }
+
+// Int32 is a helper routine that allocates a new int32 value
+// to store v and returns a pointer to it.
+func Int32(v int32) *int32 { return &v }
+
+// Int64 is a helper routine that allocates a new int64 value
+// to store v and returns a pointer to it.
+func Int64(v int64) *int64 { return &v }
+
+// Float64 is a helper routine that allocates a new float64 value
+// to store v and returns a pointer to it.
+func Float64(v float64) *float64 { return &v }
+
+// Uint32 is a helper routine that allocates a new uint32 value
+// to store v and returns a pointer to it.
+func Uint32(v uint32) *uint32 { return &v }
+
+// Uint64 is a helper routine that allocates a new uint64 value
+// to store v and returns a pointer to it.
+func Uint64(v uint64) *uint64 { return &v }
+
+// String is a helper routine that allocates a new string value
+// to store v and returns a pointer to it.
+func String(v string) *string { return &v }
diff --git a/vendor/google.golang.org/api/internal/creds.go b/vendor/google.golang.org/api/internal/creds.go
new file mode 100644
index 000000000..e5b849bff
--- /dev/null
+++ b/vendor/google.golang.org/api/internal/creds.go
@@ -0,0 +1,45 @@
+// Copyright 2017 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package internal
+
+import (
+ "context"
+ "fmt"
+ "io/ioutil"
+
+ "golang.org/x/oauth2/google"
+)
+
+// Creds returns credential information obtained from DialSettings, or if none, then
+// it returns default credential information.
+func Creds(ctx context.Context, ds *DialSettings) (*google.DefaultCredentials, error) {
+ if ds.Credentials != nil {
+ return ds.Credentials, nil
+ }
+ if ds.CredentialsJSON != nil {
+ return google.CredentialsFromJSON(ctx, ds.CredentialsJSON, ds.Scopes...)
+ }
+ if ds.CredentialsFile != "" {
+ data, err := ioutil.ReadFile(ds.CredentialsFile)
+ if err != nil {
+ return nil, fmt.Errorf("cannot read credentials file: %v", err)
+ }
+ return google.CredentialsFromJSON(ctx, data, ds.Scopes...)
+ }
+ if ds.TokenSource != nil {
+ return &google.DefaultCredentials{TokenSource: ds.TokenSource}, nil
+ }
+ return google.FindDefaultCredentials(ctx, ds.Scopes...)
+}
diff --git a/vendor/google.golang.org/api/internal/pool.go b/vendor/google.golang.org/api/internal/pool.go
new file mode 100644
index 000000000..ba406247f
--- /dev/null
+++ b/vendor/google.golang.org/api/internal/pool.go
@@ -0,0 +1,61 @@
+// Copyright 2016 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package internal
+
+import (
+ "errors"
+
+ "google.golang.org/grpc/naming"
+)
+
+// PoolResolver provides a fixed list of addresses to load balance between
+// and does not provide further updates.
+type PoolResolver struct {
+ poolSize int
+ dialOpt *DialSettings
+ ch chan []*naming.Update
+}
+
+// NewPoolResolver returns a PoolResolver
+// This is an EXPERIMENTAL API and may be changed or removed in the future.
+func NewPoolResolver(size int, o *DialSettings) *PoolResolver {
+ return &PoolResolver{poolSize: size, dialOpt: o}
+}
+
+// Resolve returns a Watcher for the endpoint defined by the DialSettings
+// provided to NewPoolResolver.
+func (r *PoolResolver) Resolve(target string) (naming.Watcher, error) {
+ if r.dialOpt.Endpoint == "" {
+ return nil, errors.New("No endpoint configured")
+ }
+ addrs := make([]*naming.Update, 0, r.poolSize)
+ for i := 0; i < r.poolSize; i++ {
+ addrs = append(addrs, &naming.Update{Op: naming.Add, Addr: r.dialOpt.Endpoint, Metadata: i})
+ }
+ r.ch = make(chan []*naming.Update, 1)
+ r.ch <- addrs
+ return r, nil
+}
+
+// Next returns a static list of updates on the first call,
+// and blocks indefinitely until Close is called on subsequent calls.
+func (r *PoolResolver) Next() ([]*naming.Update, error) {
+ return <-r.ch, nil
+}
+
+// Close releases resources associated with the pool and causes Next to unblock.
+func (r *PoolResolver) Close() {
+ close(r.ch)
+}
diff --git a/vendor/google.golang.org/api/internal/service-account.json b/vendor/google.golang.org/api/internal/service-account.json
new file mode 100644
index 000000000..2cb54c292
--- /dev/null
+++ b/vendor/google.golang.org/api/internal/service-account.json
@@ -0,0 +1,12 @@
+{
+ "type": "service_account",
+ "project_id": "project_id",
+ "private_key_id": "private_key_id",
+ "private_key": "private_key",
+ "client_email": "xyz@developer.gserviceaccount.com",
+ "client_id": "123",
+ "auth_uri": "https://accounts.google.com/o/oauth2/auth",
+ "token_uri": "https://accounts.google.com/o/oauth2/token",
+ "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
+ "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/xyz%40developer.gserviceaccount.com"
+}
diff --git a/vendor/google.golang.org/api/internal/settings.go b/vendor/google.golang.org/api/internal/settings.go
new file mode 100644
index 000000000..afabdc423
--- /dev/null
+++ b/vendor/google.golang.org/api/internal/settings.go
@@ -0,0 +1,81 @@
+// Copyright 2017 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package internal supports the options and transport packages.
+package internal
+
+import (
+ "errors"
+ "net/http"
+
+ "golang.org/x/oauth2"
+ "golang.org/x/oauth2/google"
+ "google.golang.org/grpc"
+)
+
+// DialSettings holds information needed to establish a connection with a
+// Google API service.
+type DialSettings struct {
+ Endpoint string
+ Scopes []string
+ TokenSource oauth2.TokenSource
+ Credentials *google.DefaultCredentials
+ CredentialsFile string // if set, Token Source is ignored.
+ CredentialsJSON []byte
+ UserAgent string
+ APIKey string
+ HTTPClient *http.Client
+ GRPCDialOpts []grpc.DialOption
+ GRPCConn *grpc.ClientConn
+ NoAuth bool
+}
+
+// Validate reports an error if ds is invalid.
+func (ds *DialSettings) Validate() error {
+ hasCreds := ds.APIKey != "" || ds.TokenSource != nil || ds.CredentialsFile != "" || ds.Credentials != nil
+ if ds.NoAuth && hasCreds {
+ return errors.New("options.WithoutAuthentication is incompatible with any option that provides credentials")
+ }
+ // Credentials should not appear with other options.
+ // We currently allow TokenSource and CredentialsFile to coexist.
+ // TODO(jba): make TokenSource & CredentialsFile an error (breaking change).
+ nCreds := 0
+ if ds.Credentials != nil {
+ nCreds++
+ }
+ if ds.CredentialsJSON != nil {
+ nCreds++
+ }
+ if ds.CredentialsFile != "" {
+ nCreds++
+ }
+ if ds.APIKey != "" {
+ nCreds++
+ }
+ if ds.TokenSource != nil {
+ nCreds++
+ }
+ // Accept only one form of credentials, except we allow TokenSource and CredentialsFile for backwards compatibility.
+ if nCreds > 1 && !(nCreds == 2 && ds.TokenSource != nil && ds.CredentialsFile != "") {
+ return errors.New("multiple credential options provided")
+ }
+ if ds.HTTPClient != nil && ds.GRPCConn != nil {
+ return errors.New("WithHTTPClient is incompatible with WithGRPCConn")
+ }
+ if ds.HTTPClient != nil && ds.GRPCDialOpts != nil {
+ return errors.New("WithHTTPClient is incompatible with gRPC dial options")
+ }
+
+ return nil
+}
diff --git a/vendor/google.golang.org/api/iterator/iterator.go b/vendor/google.golang.org/api/iterator/iterator.go
new file mode 100644
index 000000000..3c8ea7732
--- /dev/null
+++ b/vendor/google.golang.org/api/iterator/iterator.go
@@ -0,0 +1,231 @@
+// Copyright 2016 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package iterator provides support for standard Google API iterators.
+// See https://github.com/GoogleCloudPlatform/gcloud-golang/wiki/Iterator-Guidelines.
+package iterator
+
+import (
+ "errors"
+ "fmt"
+ "reflect"
+)
+
+// Done is returned by an iterator's Next method when the iteration is
+// complete; when there are no more items to return.
+var Done = errors.New("no more items in iterator")
+
+// We don't support mixed calls to Next and NextPage because they play
+// with the paging state in incompatible ways.
+var errMixed = errors.New("iterator: Next and NextPage called on same iterator")
+
+// PageInfo contains information about an iterator's paging state.
+type PageInfo struct {
+ // Token is the token used to retrieve the next page of items from the
+ // API. You may set Token immediately after creating an iterator to
+ // begin iteration at a particular point. If Token is the empty string,
+ // the iterator will begin with the first eligible item.
+ //
+ // The result of setting Token after the first call to Next is undefined.
+ //
+ // After the underlying API method is called to retrieve a page of items,
+ // Token is set to the next-page token in the response.
+ Token string
+
+ // MaxSize is the maximum number of items returned by a call to the API.
+ // Set MaxSize as a hint to optimize the buffering behavior of the iterator.
+ // If zero, the page size is determined by the underlying service.
+ //
+ // Use Pager to retrieve a page of a specific, exact size.
+ MaxSize int
+
+ // The error state of the iterator. Manipulated by PageInfo.next and Pager.
+ // This is a latch: it starts as nil, and once set should never change.
+ err error
+
+ // If true, no more calls to fetch should be made. Set to true when fetch
+ // returns an empty page token. The iterator is Done when this is true AND
+ // the buffer is empty.
+ atEnd bool
+
+ // Function that fetches a page from the underlying service. It should pass
+ // the pageSize and pageToken arguments to the service, fill the buffer
+ // with the results from the call, and return the next-page token returned
+ // by the service. The function must not remove any existing items from the
+ // buffer. If the underlying RPC takes an int32 page size, pageSize should
+ // be silently truncated.
+ fetch func(pageSize int, pageToken string) (nextPageToken string, err error)
+
+ // Function that returns the number of currently buffered items.
+ bufLen func() int
+
+ // Function that returns the buffer, after setting the buffer variable to nil.
+ takeBuf func() interface{}
+
+ // Set to true on first call to PageInfo.next or Pager.NextPage. Used to check
+ // for calls to both Next and NextPage with the same iterator.
+ nextCalled, nextPageCalled bool
+}
+
+// NewPageInfo exposes internals for iterator implementations.
+// It is not a stable interface.
+var NewPageInfo = newPageInfo
+
+// If an iterator can support paging, its iterator-creating method should call
+// this (via the NewPageInfo variable above).
+//
+// The fetch, bufLen and takeBuf arguments provide access to the
+// iterator's internal slice of buffered items. They behave as described in
+// PageInfo, above.
+//
+// The return value is the PageInfo.next method bound to the returned PageInfo value.
+// (Returning it avoids exporting PageInfo.next.)
+func newPageInfo(fetch func(int, string) (string, error), bufLen func() int, takeBuf func() interface{}) (*PageInfo, func() error) {
+ pi := &PageInfo{
+ fetch: fetch,
+ bufLen: bufLen,
+ takeBuf: takeBuf,
+ }
+ return pi, pi.next
+}
+
+// Remaining returns the number of items available before the iterator makes another API call.
+func (pi *PageInfo) Remaining() int { return pi.bufLen() }
+
+// next provides support for an iterator's Next function. An iterator's Next
+// should return the error returned by next if non-nil; else it can assume
+// there is at least one item in its buffer, and it should return that item and
+// remove it from the buffer.
+func (pi *PageInfo) next() error {
+ pi.nextCalled = true
+ if pi.err != nil { // Once we get an error, always return it.
+ // TODO(jba): fix so users can retry on transient errors? Probably not worth it.
+ return pi.err
+ }
+ if pi.nextPageCalled {
+ pi.err = errMixed
+ return pi.err
+ }
+ // Loop until we get some items or reach the end.
+ for pi.bufLen() == 0 && !pi.atEnd {
+ if err := pi.fill(pi.MaxSize); err != nil {
+ pi.err = err
+ return pi.err
+ }
+ if pi.Token == "" {
+ pi.atEnd = true
+ }
+ }
+ // Either the buffer is non-empty or pi.atEnd is true (or both).
+ if pi.bufLen() == 0 {
+ // The buffer is empty and pi.atEnd is true, i.e. the service has no
+ // more items.
+ pi.err = Done
+ }
+ return pi.err
+}
+
+// Call the service to fill the buffer, using size and pi.Token. Set pi.Token to the
+// next-page token returned by the call.
+// If fill returns a non-nil error, the buffer will be empty.
+func (pi *PageInfo) fill(size int) error {
+ tok, err := pi.fetch(size, pi.Token)
+ if err != nil {
+ pi.takeBuf() // clear the buffer
+ return err
+ }
+ pi.Token = tok
+ return nil
+}
+
+// Pageable is implemented by iterators that support paging.
+type Pageable interface {
+ // PageInfo returns paging information associated with the iterator.
+ PageInfo() *PageInfo
+}
+
+// Pager supports retrieving iterator items a page at a time.
+type Pager struct {
+ pageInfo *PageInfo
+ pageSize int
+}
+
+// NewPager returns a pager that uses iter. Calls to its NextPage method will
+// obtain exactly pageSize items, unless fewer remain. The pageToken argument
+// indicates where to start the iteration. Pass the empty string to start at
+// the beginning, or pass a token retrieved from a call to Pager.NextPage.
+//
+// If you use an iterator with a Pager, you must not call Next on the iterator.
+func NewPager(iter Pageable, pageSize int, pageToken string) *Pager {
+ p := &Pager{
+ pageInfo: iter.PageInfo(),
+ pageSize: pageSize,
+ }
+ p.pageInfo.Token = pageToken
+ if pageSize <= 0 {
+ p.pageInfo.err = errors.New("iterator: page size must be positive")
+ }
+ return p
+}
+
+// NextPage retrieves a sequence of items from the iterator and appends them
+// to slicep, which must be a pointer to a slice of the iterator's item type.
+// Exactly p.pageSize items will be appended, unless fewer remain.
+//
+// The first return value is the page token to use for the next page of items.
+// If empty, there are no more pages. Aside from checking for the end of the
+// iteration, the returned page token is only needed if the iteration is to be
+// resumed a later time, in another context (possibly another process).
+//
+// The second return value is non-nil if an error occurred. It will never be
+// the special iterator sentinel value Done. To recognize the end of the
+// iteration, compare nextPageToken to the empty string.
+//
+// It is possible for NextPage to return a single zero-length page along with
+// an empty page token when there are no more items in the iteration.
+func (p *Pager) NextPage(slicep interface{}) (nextPageToken string, err error) {
+ p.pageInfo.nextPageCalled = true
+ if p.pageInfo.err != nil {
+ return "", p.pageInfo.err
+ }
+ if p.pageInfo.nextCalled {
+ p.pageInfo.err = errMixed
+ return "", p.pageInfo.err
+ }
+ if p.pageInfo.bufLen() > 0 {
+ return "", errors.New("must call NextPage with an empty buffer")
+ }
+ // The buffer must be empty here, so takeBuf is a no-op. We call it just to get
+ // the buffer's type.
+ wantSliceType := reflect.PtrTo(reflect.ValueOf(p.pageInfo.takeBuf()).Type())
+ if slicep == nil {
+ return "", errors.New("nil passed to Pager.NextPage")
+ }
+ vslicep := reflect.ValueOf(slicep)
+ if vslicep.Type() != wantSliceType {
+ return "", fmt.Errorf("slicep should be of type %s, got %T", wantSliceType, slicep)
+ }
+ for p.pageInfo.bufLen() < p.pageSize {
+ if err := p.pageInfo.fill(p.pageSize - p.pageInfo.bufLen()); err != nil {
+ p.pageInfo.err = err
+ return "", p.pageInfo.err
+ }
+ if p.pageInfo.Token == "" {
+ break
+ }
+ }
+ e := vslicep.Elem()
+ e.Set(reflect.AppendSlice(e, reflect.ValueOf(p.pageInfo.takeBuf())))
+ return p.pageInfo.Token, nil
+}
diff --git a/vendor/google.golang.org/api/option/credentials_go19.go b/vendor/google.golang.org/api/option/credentials_go19.go
new file mode 100644
index 000000000..0636a8294
--- /dev/null
+++ b/vendor/google.golang.org/api/option/credentials_go19.go
@@ -0,0 +1,33 @@
+// Copyright 2018 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// +build go1.9
+
+package option
+
+import (
+ "golang.org/x/oauth2/google"
+ "google.golang.org/api/internal"
+)
+
+type withCreds google.Credentials
+
+func (w *withCreds) Apply(o *internal.DialSettings) {
+ o.Credentials = (*google.Credentials)(w)
+}
+
+// WithCredentials returns a ClientOption that authenticates API calls.
+func WithCredentials(creds *google.Credentials) ClientOption {
+ return (*withCreds)(creds)
+}
diff --git a/vendor/google.golang.org/api/option/credentials_notgo19.go b/vendor/google.golang.org/api/option/credentials_notgo19.go
new file mode 100644
index 000000000..74d3a4b5b
--- /dev/null
+++ b/vendor/google.golang.org/api/option/credentials_notgo19.go
@@ -0,0 +1,32 @@
+// Copyright 2018 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// +build !go1.9
+
+package option
+
+import (
+ "golang.org/x/oauth2/google"
+ "google.golang.org/api/internal"
+)
+
+type withCreds google.DefaultCredentials
+
+func (w *withCreds) Apply(o *internal.DialSettings) {
+ o.Credentials = (*google.DefaultCredentials)(w)
+}
+
+func WithCredentials(creds *google.DefaultCredentials) ClientOption {
+ return (*withCreds)(creds)
+}
diff --git a/vendor/google.golang.org/api/option/option.go b/vendor/google.golang.org/api/option/option.go
new file mode 100644
index 000000000..e7ecfe3c8
--- /dev/null
+++ b/vendor/google.golang.org/api/option/option.go
@@ -0,0 +1,191 @@
+// Copyright 2017 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package option contains options for Google API clients.
+package option
+
+import (
+ "net/http"
+
+ "golang.org/x/oauth2"
+ "google.golang.org/api/internal"
+ "google.golang.org/grpc"
+)
+
+// A ClientOption is an option for a Google API client.
+type ClientOption interface {
+ Apply(*internal.DialSettings)
+}
+
+// WithTokenSource returns a ClientOption that specifies an OAuth2 token
+// source to be used as the basis for authentication.
+func WithTokenSource(s oauth2.TokenSource) ClientOption {
+ return withTokenSource{s}
+}
+
+type withTokenSource struct{ ts oauth2.TokenSource }
+
+func (w withTokenSource) Apply(o *internal.DialSettings) {
+ o.TokenSource = w.ts
+}
+
+type withCredFile string
+
+func (w withCredFile) Apply(o *internal.DialSettings) {
+ o.CredentialsFile = string(w)
+}
+
+// WithCredentialsFile returns a ClientOption that authenticates
+// API calls with the given service account or refresh token JSON
+// credentials file.
+func WithCredentialsFile(filename string) ClientOption {
+ return withCredFile(filename)
+}
+
+// WithServiceAccountFile returns a ClientOption that uses a Google service
+// account credentials file to authenticate.
+//
+// Deprecated: Use WithCredentialsFile instead.
+func WithServiceAccountFile(filename string) ClientOption {
+ return WithCredentialsFile(filename)
+}
+
+// WithCredentialsJSON returns a ClientOption that authenticates
+// API calls with the given service account or refresh token JSON
+// credentials.
+func WithCredentialsJSON(p []byte) ClientOption {
+ return withCredentialsJSON(p)
+}
+
+type withCredentialsJSON []byte
+
+func (w withCredentialsJSON) Apply(o *internal.DialSettings) {
+ o.CredentialsJSON = make([]byte, len(w))
+ copy(o.CredentialsJSON, w)
+}
+
+// WithEndpoint returns a ClientOption that overrides the default endpoint
+// to be used for a service.
+func WithEndpoint(url string) ClientOption {
+ return withEndpoint(url)
+}
+
+type withEndpoint string
+
+func (w withEndpoint) Apply(o *internal.DialSettings) {
+ o.Endpoint = string(w)
+}
+
+// WithScopes returns a ClientOption that overrides the default OAuth2 scopes
+// to be used for a service.
+func WithScopes(scope ...string) ClientOption {
+ return withScopes(scope)
+}
+
+type withScopes []string
+
+func (w withScopes) Apply(o *internal.DialSettings) {
+ o.Scopes = make([]string, len(w))
+ copy(o.Scopes, w)
+}
+
+// WithUserAgent returns a ClientOption that sets the User-Agent.
+func WithUserAgent(ua string) ClientOption {
+ return withUA(ua)
+}
+
+type withUA string
+
+func (w withUA) Apply(o *internal.DialSettings) { o.UserAgent = string(w) }
+
+// WithHTTPClient returns a ClientOption that specifies the HTTP client to use
+// as the basis of communications. This option may only be used with services
+// that support HTTP as their communication transport. When used, the
+// WithHTTPClient option takes precedent over all other supplied options.
+func WithHTTPClient(client *http.Client) ClientOption {
+ return withHTTPClient{client}
+}
+
+type withHTTPClient struct{ client *http.Client }
+
+func (w withHTTPClient) Apply(o *internal.DialSettings) {
+ o.HTTPClient = w.client
+}
+
+// WithGRPCConn returns a ClientOption that specifies the gRPC client
+// connection to use as the basis of communications. This option many only be
+// used with services that support gRPC as their communication transport. When
+// used, the WithGRPCConn option takes precedent over all other supplied
+// options.
+func WithGRPCConn(conn *grpc.ClientConn) ClientOption {
+ return withGRPCConn{conn}
+}
+
+type withGRPCConn struct{ conn *grpc.ClientConn }
+
+func (w withGRPCConn) Apply(o *internal.DialSettings) {
+ o.GRPCConn = w.conn
+}
+
+// WithGRPCDialOption returns a ClientOption that appends a new grpc.DialOption
+// to an underlying gRPC dial. It does not work with WithGRPCConn.
+func WithGRPCDialOption(opt grpc.DialOption) ClientOption {
+ return withGRPCDialOption{opt}
+}
+
+type withGRPCDialOption struct{ opt grpc.DialOption }
+
+func (w withGRPCDialOption) Apply(o *internal.DialSettings) {
+ o.GRPCDialOpts = append(o.GRPCDialOpts, w.opt)
+}
+
+// WithGRPCConnectionPool returns a ClientOption that creates a pool of gRPC
+// connections that requests will be balanced between.
+// This is an EXPERIMENTAL API and may be changed or removed in the future.
+func WithGRPCConnectionPool(size int) ClientOption {
+ return withGRPCConnectionPool(size)
+}
+
+type withGRPCConnectionPool int
+
+func (w withGRPCConnectionPool) Apply(o *internal.DialSettings) {
+ balancer := grpc.RoundRobin(internal.NewPoolResolver(int(w), o))
+ o.GRPCDialOpts = append(o.GRPCDialOpts, grpc.WithBalancer(balancer))
+}
+
+// WithAPIKey returns a ClientOption that specifies an API key to be used
+// as the basis for authentication.
+//
+// API Keys can only be used for JSON-over-HTTP APIs, including those under
+// the import path google.golang.org/api/....
+func WithAPIKey(apiKey string) ClientOption {
+ return withAPIKey(apiKey)
+}
+
+type withAPIKey string
+
+func (w withAPIKey) Apply(o *internal.DialSettings) { o.APIKey = string(w) }
+
+// WithoutAuthentication returns a ClientOption that specifies that no
+// authentication should be used. It is suitable only for testing and for
+// accessing public resources, like public Google Cloud Storage buckets.
+// It is an error to provide both WithoutAuthentication and any of WithAPIKey,
+// WithTokenSource, WithCredentialsFile or WithServiceAccountFile.
+func WithoutAuthentication() ClientOption {
+ return withoutAuthentication{}
+}
+
+type withoutAuthentication struct{}
+
+func (w withoutAuthentication) Apply(o *internal.DialSettings) { o.NoAuth = true }
diff --git a/vendor/google.golang.org/api/storage/v1/storage-api.json b/vendor/google.golang.org/api/storage/v1/storage-api.json
new file mode 100644
index 000000000..49d0a5181
--- /dev/null
+++ b/vendor/google.golang.org/api/storage/v1/storage-api.json
@@ -0,0 +1,3818 @@
+{
+ "auth": {
+ "oauth2": {
+ "scopes": {
+ "https://www.googleapis.com/auth/cloud-platform": {
+ "description": "View and manage your data across Google Cloud Platform services"
+ },
+ "https://www.googleapis.com/auth/cloud-platform.read-only": {
+ "description": "View your data across Google Cloud Platform services"
+ },
+ "https://www.googleapis.com/auth/devstorage.full_control": {
+ "description": "Manage your data and permissions in Google Cloud Storage"
+ },
+ "https://www.googleapis.com/auth/devstorage.read_only": {
+ "description": "View your data in Google Cloud Storage"
+ },
+ "https://www.googleapis.com/auth/devstorage.read_write": {
+ "description": "Manage your data in Google Cloud Storage"
+ }
+ }
+ }
+ },
+ "basePath": "/storage/v1/",
+ "baseUrl": "https://www.googleapis.com/storage/v1/",
+ "batchPath": "batch/storage/v1",
+ "description": "Stores and retrieves potentially large, immutable data objects.",
+ "discoveryVersion": "v1",
+ "documentationLink": "https://developers.google.com/storage/docs/json_api/",
+ "etag": "\"J3WqvAcMk4eQjJXvfSI4Yr8VouA/KPalWULMnQfaqumeaBhBrVfHFNM\"",
+ "icons": {
+ "x16": "https://www.google.com/images/icons/product/cloud_storage-16.png",
+ "x32": "https://www.google.com/images/icons/product/cloud_storage-32.png"
+ },
+ "id": "storage:v1",
+ "kind": "discovery#restDescription",
+ "labels": [
+ "labs"
+ ],
+ "name": "storage",
+ "ownerDomain": "google.com",
+ "ownerName": "Google",
+ "parameters": {
+ "alt": {
+ "default": "json",
+ "description": "Data format for the response.",
+ "enum": [
+ "json"
+ ],
+ "enumDescriptions": [
+ "Responses with Content-Type of application/json"
+ ],
+ "location": "query",
+ "type": "string"
+ },
+ "fields": {
+ "description": "Selector specifying which fields to include in a partial response.",
+ "location": "query",
+ "type": "string"
+ },
+ "key": {
+ "description": "API key. Your API key identifies your project and provides you with API access, quota, and reports. Required unless you provide an OAuth 2.0 token.",
+ "location": "query",
+ "type": "string"
+ },
+ "oauth_token": {
+ "description": "OAuth 2.0 token for the current user.",
+ "location": "query",
+ "type": "string"
+ },
+ "prettyPrint": {
+ "default": "true",
+ "description": "Returns response with indentations and line breaks.",
+ "location": "query",
+ "type": "boolean"
+ },
+ "quotaUser": {
+ "description": "An opaque string that represents a user for quota purposes. Must not exceed 40 characters.",
+ "location": "query",
+ "type": "string"
+ },
+ "userIp": {
+ "description": "Deprecated. Please use quotaUser instead.",
+ "location": "query",
+ "type": "string"
+ }
+ },
+ "protocol": "rest",
+ "resources": {
+ "bucketAccessControls": {
+ "methods": {
+ "delete": {
+ "description": "Permanently deletes the ACL entry for the specified entity on the specified bucket.",
+ "httpMethod": "DELETE",
+ "id": "storage.bucketAccessControls.delete",
+ "parameterOrder": [
+ "bucket",
+ "entity"
+ ],
+ "parameters": {
+ "bucket": {
+ "description": "Name of a bucket.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "entity": {
+ "description": "The entity holding the permission. Can be user-userId, user-emailAddress, group-groupId, group-emailAddress, allUsers, or allAuthenticatedUsers.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "userProject": {
+ "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ "location": "query",
+ "type": "string"
+ }
+ },
+ "path": "b/{bucket}/acl/{entity}",
+ "scopes": [
+ "https://www.googleapis.com/auth/cloud-platform",
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ]
+ },
+ "get": {
+ "description": "Returns the ACL entry for the specified entity on the specified bucket.",
+ "httpMethod": "GET",
+ "id": "storage.bucketAccessControls.get",
+ "parameterOrder": [
+ "bucket",
+ "entity"
+ ],
+ "parameters": {
+ "bucket": {
+ "description": "Name of a bucket.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "entity": {
+ "description": "The entity holding the permission. Can be user-userId, user-emailAddress, group-groupId, group-emailAddress, allUsers, or allAuthenticatedUsers.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "userProject": {
+ "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ "location": "query",
+ "type": "string"
+ }
+ },
+ "path": "b/{bucket}/acl/{entity}",
+ "response": {
+ "$ref": "BucketAccessControl"
+ },
+ "scopes": [
+ "https://www.googleapis.com/auth/cloud-platform",
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ]
+ },
+ "insert": {
+ "description": "Creates a new ACL entry on the specified bucket.",
+ "httpMethod": "POST",
+ "id": "storage.bucketAccessControls.insert",
+ "parameterOrder": [
+ "bucket"
+ ],
+ "parameters": {
+ "bucket": {
+ "description": "Name of a bucket.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "userProject": {
+ "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ "location": "query",
+ "type": "string"
+ }
+ },
+ "path": "b/{bucket}/acl",
+ "request": {
+ "$ref": "BucketAccessControl"
+ },
+ "response": {
+ "$ref": "BucketAccessControl"
+ },
+ "scopes": [
+ "https://www.googleapis.com/auth/cloud-platform",
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ]
+ },
+ "list": {
+ "description": "Retrieves ACL entries on the specified bucket.",
+ "httpMethod": "GET",
+ "id": "storage.bucketAccessControls.list",
+ "parameterOrder": [
+ "bucket"
+ ],
+ "parameters": {
+ "bucket": {
+ "description": "Name of a bucket.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "userProject": {
+ "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ "location": "query",
+ "type": "string"
+ }
+ },
+ "path": "b/{bucket}/acl",
+ "response": {
+ "$ref": "BucketAccessControls"
+ },
+ "scopes": [
+ "https://www.googleapis.com/auth/cloud-platform",
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ]
+ },
+ "patch": {
+ "description": "Patches an ACL entry on the specified bucket.",
+ "httpMethod": "PATCH",
+ "id": "storage.bucketAccessControls.patch",
+ "parameterOrder": [
+ "bucket",
+ "entity"
+ ],
+ "parameters": {
+ "bucket": {
+ "description": "Name of a bucket.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "entity": {
+ "description": "The entity holding the permission. Can be user-userId, user-emailAddress, group-groupId, group-emailAddress, allUsers, or allAuthenticatedUsers.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "userProject": {
+ "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ "location": "query",
+ "type": "string"
+ }
+ },
+ "path": "b/{bucket}/acl/{entity}",
+ "request": {
+ "$ref": "BucketAccessControl"
+ },
+ "response": {
+ "$ref": "BucketAccessControl"
+ },
+ "scopes": [
+ "https://www.googleapis.com/auth/cloud-platform",
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ]
+ },
+ "update": {
+ "description": "Updates an ACL entry on the specified bucket.",
+ "httpMethod": "PUT",
+ "id": "storage.bucketAccessControls.update",
+ "parameterOrder": [
+ "bucket",
+ "entity"
+ ],
+ "parameters": {
+ "bucket": {
+ "description": "Name of a bucket.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "entity": {
+ "description": "The entity holding the permission. Can be user-userId, user-emailAddress, group-groupId, group-emailAddress, allUsers, or allAuthenticatedUsers.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "userProject": {
+ "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ "location": "query",
+ "type": "string"
+ }
+ },
+ "path": "b/{bucket}/acl/{entity}",
+ "request": {
+ "$ref": "BucketAccessControl"
+ },
+ "response": {
+ "$ref": "BucketAccessControl"
+ },
+ "scopes": [
+ "https://www.googleapis.com/auth/cloud-platform",
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ]
+ }
+ }
+ },
+ "buckets": {
+ "methods": {
+ "delete": {
+ "description": "Permanently deletes an empty bucket.",
+ "httpMethod": "DELETE",
+ "id": "storage.buckets.delete",
+ "parameterOrder": [
+ "bucket"
+ ],
+ "parameters": {
+ "bucket": {
+ "description": "Name of a bucket.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "ifMetagenerationMatch": {
+ "description": "If set, only deletes the bucket if its metageneration matches this value.",
+ "format": "int64",
+ "location": "query",
+ "type": "string"
+ },
+ "ifMetagenerationNotMatch": {
+ "description": "If set, only deletes the bucket if its metageneration does not match this value.",
+ "format": "int64",
+ "location": "query",
+ "type": "string"
+ },
+ "userProject": {
+ "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ "location": "query",
+ "type": "string"
+ }
+ },
+ "path": "b/{bucket}",
+ "scopes": [
+ "https://www.googleapis.com/auth/cloud-platform",
+ "https://www.googleapis.com/auth/devstorage.full_control",
+ "https://www.googleapis.com/auth/devstorage.read_write"
+ ]
+ },
+ "get": {
+ "description": "Returns metadata for the specified bucket.",
+ "httpMethod": "GET",
+ "id": "storage.buckets.get",
+ "parameterOrder": [
+ "bucket"
+ ],
+ "parameters": {
+ "bucket": {
+ "description": "Name of a bucket.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "ifMetagenerationMatch": {
+ "description": "Makes the return of the bucket metadata conditional on whether the bucket's current metageneration matches the given value.",
+ "format": "int64",
+ "location": "query",
+ "type": "string"
+ },
+ "ifMetagenerationNotMatch": {
+ "description": "Makes the return of the bucket metadata conditional on whether the bucket's current metageneration does not match the given value.",
+ "format": "int64",
+ "location": "query",
+ "type": "string"
+ },
+ "projection": {
+ "description": "Set of properties to return. Defaults to noAcl.",
+ "enum": [
+ "full",
+ "noAcl"
+ ],
+ "enumDescriptions": [
+ "Include all properties.",
+ "Omit owner, acl and defaultObjectAcl properties."
+ ],
+ "location": "query",
+ "type": "string"
+ },
+ "userProject": {
+ "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ "location": "query",
+ "type": "string"
+ }
+ },
+ "path": "b/{bucket}",
+ "response": {
+ "$ref": "Bucket"
+ },
+ "scopes": [
+ "https://www.googleapis.com/auth/cloud-platform",
+ "https://www.googleapis.com/auth/cloud-platform.read-only",
+ "https://www.googleapis.com/auth/devstorage.full_control",
+ "https://www.googleapis.com/auth/devstorage.read_only",
+ "https://www.googleapis.com/auth/devstorage.read_write"
+ ]
+ },
+ "getIamPolicy": {
+ "description": "Returns an IAM policy for the specified bucket.",
+ "httpMethod": "GET",
+ "id": "storage.buckets.getIamPolicy",
+ "parameterOrder": [
+ "bucket"
+ ],
+ "parameters": {
+ "bucket": {
+ "description": "Name of a bucket.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "userProject": {
+ "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ "location": "query",
+ "type": "string"
+ }
+ },
+ "path": "b/{bucket}/iam",
+ "response": {
+ "$ref": "Policy"
+ },
+ "scopes": [
+ "https://www.googleapis.com/auth/cloud-platform",
+ "https://www.googleapis.com/auth/cloud-platform.read-only",
+ "https://www.googleapis.com/auth/devstorage.full_control",
+ "https://www.googleapis.com/auth/devstorage.read_only",
+ "https://www.googleapis.com/auth/devstorage.read_write"
+ ]
+ },
+ "insert": {
+ "description": "Creates a new bucket.",
+ "httpMethod": "POST",
+ "id": "storage.buckets.insert",
+ "parameterOrder": [
+ "project"
+ ],
+ "parameters": {
+ "predefinedAcl": {
+ "description": "Apply a predefined set of access controls to this bucket.",
+ "enum": [
+ "authenticatedRead",
+ "private",
+ "projectPrivate",
+ "publicRead",
+ "publicReadWrite"
+ ],
+ "enumDescriptions": [
+ "Project team owners get OWNER access, and allAuthenticatedUsers get READER access.",
+ "Project team owners get OWNER access.",
+ "Project team members get access according to their roles.",
+ "Project team owners get OWNER access, and allUsers get READER access.",
+ "Project team owners get OWNER access, and allUsers get WRITER access."
+ ],
+ "location": "query",
+ "type": "string"
+ },
+ "predefinedDefaultObjectAcl": {
+ "description": "Apply a predefined set of default object access controls to this bucket.",
+ "enum": [
+ "authenticatedRead",
+ "bucketOwnerFullControl",
+ "bucketOwnerRead",
+ "private",
+ "projectPrivate",
+ "publicRead"
+ ],
+ "enumDescriptions": [
+ "Object owner gets OWNER access, and allAuthenticatedUsers get READER access.",
+ "Object owner gets OWNER access, and project team owners get OWNER access.",
+ "Object owner gets OWNER access, and project team owners get READER access.",
+ "Object owner gets OWNER access.",
+ "Object owner gets OWNER access, and project team members get access according to their roles.",
+ "Object owner gets OWNER access, and allUsers get READER access."
+ ],
+ "location": "query",
+ "type": "string"
+ },
+ "project": {
+ "description": "A valid API project identifier.",
+ "location": "query",
+ "required": true,
+ "type": "string"
+ },
+ "projection": {
+ "description": "Set of properties to return. Defaults to noAcl, unless the bucket resource specifies acl or defaultObjectAcl properties, when it defaults to full.",
+ "enum": [
+ "full",
+ "noAcl"
+ ],
+ "enumDescriptions": [
+ "Include all properties.",
+ "Omit owner, acl and defaultObjectAcl properties."
+ ],
+ "location": "query",
+ "type": "string"
+ },
+ "userProject": {
+ "description": "The project to be billed for this request.",
+ "location": "query",
+ "type": "string"
+ }
+ },
+ "path": "b",
+ "request": {
+ "$ref": "Bucket"
+ },
+ "response": {
+ "$ref": "Bucket"
+ },
+ "scopes": [
+ "https://www.googleapis.com/auth/cloud-platform",
+ "https://www.googleapis.com/auth/devstorage.full_control",
+ "https://www.googleapis.com/auth/devstorage.read_write"
+ ]
+ },
+ "list": {
+ "description": "Retrieves a list of buckets for a given project.",
+ "httpMethod": "GET",
+ "id": "storage.buckets.list",
+ "parameterOrder": [
+ "project"
+ ],
+ "parameters": {
+ "maxResults": {
+ "default": "1000",
+ "description": "Maximum number of buckets to return in a single response. The service will use this parameter or 1,000 items, whichever is smaller.",
+ "format": "uint32",
+ "location": "query",
+ "minimum": "0",
+ "type": "integer"
+ },
+ "pageToken": {
+ "description": "A previously-returned page token representing part of the larger set of results to view.",
+ "location": "query",
+ "type": "string"
+ },
+ "prefix": {
+ "description": "Filter results to buckets whose names begin with this prefix.",
+ "location": "query",
+ "type": "string"
+ },
+ "project": {
+ "description": "A valid API project identifier.",
+ "location": "query",
+ "required": true,
+ "type": "string"
+ },
+ "projection": {
+ "description": "Set of properties to return. Defaults to noAcl.",
+ "enum": [
+ "full",
+ "noAcl"
+ ],
+ "enumDescriptions": [
+ "Include all properties.",
+ "Omit owner, acl and defaultObjectAcl properties."
+ ],
+ "location": "query",
+ "type": "string"
+ },
+ "userProject": {
+ "description": "The project to be billed for this request.",
+ "location": "query",
+ "type": "string"
+ }
+ },
+ "path": "b",
+ "response": {
+ "$ref": "Buckets"
+ },
+ "scopes": [
+ "https://www.googleapis.com/auth/cloud-platform",
+ "https://www.googleapis.com/auth/cloud-platform.read-only",
+ "https://www.googleapis.com/auth/devstorage.full_control",
+ "https://www.googleapis.com/auth/devstorage.read_only",
+ "https://www.googleapis.com/auth/devstorage.read_write"
+ ]
+ },
+ "lockRetentionPolicy": {
+ "description": "Locks retention policy on a bucket.",
+ "httpMethod": "POST",
+ "id": "storage.buckets.lockRetentionPolicy",
+ "parameterOrder": [
+ "bucket",
+ "ifMetagenerationMatch"
+ ],
+ "parameters": {
+ "bucket": {
+ "description": "Name of a bucket.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "ifMetagenerationMatch": {
+ "description": "Makes the operation conditional on whether bucket's current metageneration matches the given value.",
+ "format": "int64",
+ "location": "query",
+ "required": true,
+ "type": "string"
+ },
+ "userProject": {
+ "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ "location": "query",
+ "type": "string"
+ }
+ },
+ "path": "b/{bucket}/lockRetentionPolicy",
+ "response": {
+ "$ref": "Bucket"
+ },
+ "scopes": [
+ "https://www.googleapis.com/auth/cloud-platform",
+ "https://www.googleapis.com/auth/devstorage.full_control",
+ "https://www.googleapis.com/auth/devstorage.read_write"
+ ]
+ },
+ "patch": {
+ "description": "Patches a bucket. Changes to the bucket will be readable immediately after writing, but configuration changes may take time to propagate.",
+ "httpMethod": "PATCH",
+ "id": "storage.buckets.patch",
+ "parameterOrder": [
+ "bucket"
+ ],
+ "parameters": {
+ "bucket": {
+ "description": "Name of a bucket.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "ifMetagenerationMatch": {
+ "description": "Makes the return of the bucket metadata conditional on whether the bucket's current metageneration matches the given value.",
+ "format": "int64",
+ "location": "query",
+ "type": "string"
+ },
+ "ifMetagenerationNotMatch": {
+ "description": "Makes the return of the bucket metadata conditional on whether the bucket's current metageneration does not match the given value.",
+ "format": "int64",
+ "location": "query",
+ "type": "string"
+ },
+ "predefinedAcl": {
+ "description": "Apply a predefined set of access controls to this bucket.",
+ "enum": [
+ "authenticatedRead",
+ "private",
+ "projectPrivate",
+ "publicRead",
+ "publicReadWrite"
+ ],
+ "enumDescriptions": [
+ "Project team owners get OWNER access, and allAuthenticatedUsers get READER access.",
+ "Project team owners get OWNER access.",
+ "Project team members get access according to their roles.",
+ "Project team owners get OWNER access, and allUsers get READER access.",
+ "Project team owners get OWNER access, and allUsers get WRITER access."
+ ],
+ "location": "query",
+ "type": "string"
+ },
+ "predefinedDefaultObjectAcl": {
+ "description": "Apply a predefined set of default object access controls to this bucket.",
+ "enum": [
+ "authenticatedRead",
+ "bucketOwnerFullControl",
+ "bucketOwnerRead",
+ "private",
+ "projectPrivate",
+ "publicRead"
+ ],
+ "enumDescriptions": [
+ "Object owner gets OWNER access, and allAuthenticatedUsers get READER access.",
+ "Object owner gets OWNER access, and project team owners get OWNER access.",
+ "Object owner gets OWNER access, and project team owners get READER access.",
+ "Object owner gets OWNER access.",
+ "Object owner gets OWNER access, and project team members get access according to their roles.",
+ "Object owner gets OWNER access, and allUsers get READER access."
+ ],
+ "location": "query",
+ "type": "string"
+ },
+ "projection": {
+ "description": "Set of properties to return. Defaults to full.",
+ "enum": [
+ "full",
+ "noAcl"
+ ],
+ "enumDescriptions": [
+ "Include all properties.",
+ "Omit owner, acl and defaultObjectAcl properties."
+ ],
+ "location": "query",
+ "type": "string"
+ },
+ "userProject": {
+ "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ "location": "query",
+ "type": "string"
+ }
+ },
+ "path": "b/{bucket}",
+ "request": {
+ "$ref": "Bucket"
+ },
+ "response": {
+ "$ref": "Bucket"
+ },
+ "scopes": [
+ "https://www.googleapis.com/auth/cloud-platform",
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ]
+ },
+ "setIamPolicy": {
+ "description": "Updates an IAM policy for the specified bucket.",
+ "httpMethod": "PUT",
+ "id": "storage.buckets.setIamPolicy",
+ "parameterOrder": [
+ "bucket"
+ ],
+ "parameters": {
+ "bucket": {
+ "description": "Name of a bucket.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "userProject": {
+ "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ "location": "query",
+ "type": "string"
+ }
+ },
+ "path": "b/{bucket}/iam",
+ "request": {
+ "$ref": "Policy"
+ },
+ "response": {
+ "$ref": "Policy"
+ },
+ "scopes": [
+ "https://www.googleapis.com/auth/cloud-platform",
+ "https://www.googleapis.com/auth/devstorage.full_control",
+ "https://www.googleapis.com/auth/devstorage.read_write"
+ ]
+ },
+ "testIamPermissions": {
+ "description": "Tests a set of permissions on the given bucket to see which, if any, are held by the caller.",
+ "httpMethod": "GET",
+ "id": "storage.buckets.testIamPermissions",
+ "parameterOrder": [
+ "bucket",
+ "permissions"
+ ],
+ "parameters": {
+ "bucket": {
+ "description": "Name of a bucket.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "permissions": {
+ "description": "Permissions to test.",
+ "location": "query",
+ "repeated": true,
+ "required": true,
+ "type": "string"
+ },
+ "userProject": {
+ "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ "location": "query",
+ "type": "string"
+ }
+ },
+ "path": "b/{bucket}/iam/testPermissions",
+ "response": {
+ "$ref": "TestIamPermissionsResponse"
+ },
+ "scopes": [
+ "https://www.googleapis.com/auth/cloud-platform",
+ "https://www.googleapis.com/auth/cloud-platform.read-only",
+ "https://www.googleapis.com/auth/devstorage.full_control",
+ "https://www.googleapis.com/auth/devstorage.read_only",
+ "https://www.googleapis.com/auth/devstorage.read_write"
+ ]
+ },
+ "update": {
+ "description": "Updates a bucket. Changes to the bucket will be readable immediately after writing, but configuration changes may take time to propagate.",
+ "httpMethod": "PUT",
+ "id": "storage.buckets.update",
+ "parameterOrder": [
+ "bucket"
+ ],
+ "parameters": {
+ "bucket": {
+ "description": "Name of a bucket.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "ifMetagenerationMatch": {
+ "description": "Makes the return of the bucket metadata conditional on whether the bucket's current metageneration matches the given value.",
+ "format": "int64",
+ "location": "query",
+ "type": "string"
+ },
+ "ifMetagenerationNotMatch": {
+ "description": "Makes the return of the bucket metadata conditional on whether the bucket's current metageneration does not match the given value.",
+ "format": "int64",
+ "location": "query",
+ "type": "string"
+ },
+ "predefinedAcl": {
+ "description": "Apply a predefined set of access controls to this bucket.",
+ "enum": [
+ "authenticatedRead",
+ "private",
+ "projectPrivate",
+ "publicRead",
+ "publicReadWrite"
+ ],
+ "enumDescriptions": [
+ "Project team owners get OWNER access, and allAuthenticatedUsers get READER access.",
+ "Project team owners get OWNER access.",
+ "Project team members get access according to their roles.",
+ "Project team owners get OWNER access, and allUsers get READER access.",
+ "Project team owners get OWNER access, and allUsers get WRITER access."
+ ],
+ "location": "query",
+ "type": "string"
+ },
+ "predefinedDefaultObjectAcl": {
+ "description": "Apply a predefined set of default object access controls to this bucket.",
+ "enum": [
+ "authenticatedRead",
+ "bucketOwnerFullControl",
+ "bucketOwnerRead",
+ "private",
+ "projectPrivate",
+ "publicRead"
+ ],
+ "enumDescriptions": [
+ "Object owner gets OWNER access, and allAuthenticatedUsers get READER access.",
+ "Object owner gets OWNER access, and project team owners get OWNER access.",
+ "Object owner gets OWNER access, and project team owners get READER access.",
+ "Object owner gets OWNER access.",
+ "Object owner gets OWNER access, and project team members get access according to their roles.",
+ "Object owner gets OWNER access, and allUsers get READER access."
+ ],
+ "location": "query",
+ "type": "string"
+ },
+ "projection": {
+ "description": "Set of properties to return. Defaults to full.",
+ "enum": [
+ "full",
+ "noAcl"
+ ],
+ "enumDescriptions": [
+ "Include all properties.",
+ "Omit owner, acl and defaultObjectAcl properties."
+ ],
+ "location": "query",
+ "type": "string"
+ },
+ "userProject": {
+ "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ "location": "query",
+ "type": "string"
+ }
+ },
+ "path": "b/{bucket}",
+ "request": {
+ "$ref": "Bucket"
+ },
+ "response": {
+ "$ref": "Bucket"
+ },
+ "scopes": [
+ "https://www.googleapis.com/auth/cloud-platform",
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ]
+ }
+ }
+ },
+ "channels": {
+ "methods": {
+ "stop": {
+ "description": "Stop watching resources through this channel",
+ "httpMethod": "POST",
+ "id": "storage.channels.stop",
+ "path": "channels/stop",
+ "request": {
+ "$ref": "Channel",
+ "parameterName": "resource"
+ },
+ "scopes": [
+ "https://www.googleapis.com/auth/cloud-platform",
+ "https://www.googleapis.com/auth/cloud-platform.read-only",
+ "https://www.googleapis.com/auth/devstorage.full_control",
+ "https://www.googleapis.com/auth/devstorage.read_only",
+ "https://www.googleapis.com/auth/devstorage.read_write"
+ ]
+ }
+ }
+ },
+ "defaultObjectAccessControls": {
+ "methods": {
+ "delete": {
+ "description": "Permanently deletes the default object ACL entry for the specified entity on the specified bucket.",
+ "httpMethod": "DELETE",
+ "id": "storage.defaultObjectAccessControls.delete",
+ "parameterOrder": [
+ "bucket",
+ "entity"
+ ],
+ "parameters": {
+ "bucket": {
+ "description": "Name of a bucket.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "entity": {
+ "description": "The entity holding the permission. Can be user-userId, user-emailAddress, group-groupId, group-emailAddress, allUsers, or allAuthenticatedUsers.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "userProject": {
+ "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ "location": "query",
+ "type": "string"
+ }
+ },
+ "path": "b/{bucket}/defaultObjectAcl/{entity}",
+ "scopes": [
+ "https://www.googleapis.com/auth/cloud-platform",
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ]
+ },
+ "get": {
+ "description": "Returns the default object ACL entry for the specified entity on the specified bucket.",
+ "httpMethod": "GET",
+ "id": "storage.defaultObjectAccessControls.get",
+ "parameterOrder": [
+ "bucket",
+ "entity"
+ ],
+ "parameters": {
+ "bucket": {
+ "description": "Name of a bucket.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "entity": {
+ "description": "The entity holding the permission. Can be user-userId, user-emailAddress, group-groupId, group-emailAddress, allUsers, or allAuthenticatedUsers.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "userProject": {
+ "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ "location": "query",
+ "type": "string"
+ }
+ },
+ "path": "b/{bucket}/defaultObjectAcl/{entity}",
+ "response": {
+ "$ref": "ObjectAccessControl"
+ },
+ "scopes": [
+ "https://www.googleapis.com/auth/cloud-platform",
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ]
+ },
+ "insert": {
+ "description": "Creates a new default object ACL entry on the specified bucket.",
+ "httpMethod": "POST",
+ "id": "storage.defaultObjectAccessControls.insert",
+ "parameterOrder": [
+ "bucket"
+ ],
+ "parameters": {
+ "bucket": {
+ "description": "Name of a bucket.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "userProject": {
+ "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ "location": "query",
+ "type": "string"
+ }
+ },
+ "path": "b/{bucket}/defaultObjectAcl",
+ "request": {
+ "$ref": "ObjectAccessControl"
+ },
+ "response": {
+ "$ref": "ObjectAccessControl"
+ },
+ "scopes": [
+ "https://www.googleapis.com/auth/cloud-platform",
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ]
+ },
+ "list": {
+ "description": "Retrieves default object ACL entries on the specified bucket.",
+ "httpMethod": "GET",
+ "id": "storage.defaultObjectAccessControls.list",
+ "parameterOrder": [
+ "bucket"
+ ],
+ "parameters": {
+ "bucket": {
+ "description": "Name of a bucket.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "ifMetagenerationMatch": {
+ "description": "If present, only return default ACL listing if the bucket's current metageneration matches this value.",
+ "format": "int64",
+ "location": "query",
+ "type": "string"
+ },
+ "ifMetagenerationNotMatch": {
+ "description": "If present, only return default ACL listing if the bucket's current metageneration does not match the given value.",
+ "format": "int64",
+ "location": "query",
+ "type": "string"
+ },
+ "userProject": {
+ "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ "location": "query",
+ "type": "string"
+ }
+ },
+ "path": "b/{bucket}/defaultObjectAcl",
+ "response": {
+ "$ref": "ObjectAccessControls"
+ },
+ "scopes": [
+ "https://www.googleapis.com/auth/cloud-platform",
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ]
+ },
+ "patch": {
+ "description": "Patches a default object ACL entry on the specified bucket.",
+ "httpMethod": "PATCH",
+ "id": "storage.defaultObjectAccessControls.patch",
+ "parameterOrder": [
+ "bucket",
+ "entity"
+ ],
+ "parameters": {
+ "bucket": {
+ "description": "Name of a bucket.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "entity": {
+ "description": "The entity holding the permission. Can be user-userId, user-emailAddress, group-groupId, group-emailAddress, allUsers, or allAuthenticatedUsers.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "userProject": {
+ "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ "location": "query",
+ "type": "string"
+ }
+ },
+ "path": "b/{bucket}/defaultObjectAcl/{entity}",
+ "request": {
+ "$ref": "ObjectAccessControl"
+ },
+ "response": {
+ "$ref": "ObjectAccessControl"
+ },
+ "scopes": [
+ "https://www.googleapis.com/auth/cloud-platform",
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ]
+ },
+ "update": {
+ "description": "Updates a default object ACL entry on the specified bucket.",
+ "httpMethod": "PUT",
+ "id": "storage.defaultObjectAccessControls.update",
+ "parameterOrder": [
+ "bucket",
+ "entity"
+ ],
+ "parameters": {
+ "bucket": {
+ "description": "Name of a bucket.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "entity": {
+ "description": "The entity holding the permission. Can be user-userId, user-emailAddress, group-groupId, group-emailAddress, allUsers, or allAuthenticatedUsers.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "userProject": {
+ "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ "location": "query",
+ "type": "string"
+ }
+ },
+ "path": "b/{bucket}/defaultObjectAcl/{entity}",
+ "request": {
+ "$ref": "ObjectAccessControl"
+ },
+ "response": {
+ "$ref": "ObjectAccessControl"
+ },
+ "scopes": [
+ "https://www.googleapis.com/auth/cloud-platform",
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ]
+ }
+ }
+ },
+ "notifications": {
+ "methods": {
+ "delete": {
+ "description": "Permanently deletes a notification subscription.",
+ "httpMethod": "DELETE",
+ "id": "storage.notifications.delete",
+ "parameterOrder": [
+ "bucket",
+ "notification"
+ ],
+ "parameters": {
+ "bucket": {
+ "description": "The parent bucket of the notification.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "notification": {
+ "description": "ID of the notification to delete.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "userProject": {
+ "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ "location": "query",
+ "type": "string"
+ }
+ },
+ "path": "b/{bucket}/notificationConfigs/{notification}",
+ "scopes": [
+ "https://www.googleapis.com/auth/cloud-platform",
+ "https://www.googleapis.com/auth/devstorage.full_control",
+ "https://www.googleapis.com/auth/devstorage.read_write"
+ ]
+ },
+ "get": {
+ "description": "View a notification configuration.",
+ "httpMethod": "GET",
+ "id": "storage.notifications.get",
+ "parameterOrder": [
+ "bucket",
+ "notification"
+ ],
+ "parameters": {
+ "bucket": {
+ "description": "The parent bucket of the notification.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "notification": {
+ "description": "Notification ID",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "userProject": {
+ "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ "location": "query",
+ "type": "string"
+ }
+ },
+ "path": "b/{bucket}/notificationConfigs/{notification}",
+ "response": {
+ "$ref": "Notification"
+ },
+ "scopes": [
+ "https://www.googleapis.com/auth/cloud-platform",
+ "https://www.googleapis.com/auth/cloud-platform.read-only",
+ "https://www.googleapis.com/auth/devstorage.full_control",
+ "https://www.googleapis.com/auth/devstorage.read_only",
+ "https://www.googleapis.com/auth/devstorage.read_write"
+ ]
+ },
+ "insert": {
+ "description": "Creates a notification subscription for a given bucket.",
+ "httpMethod": "POST",
+ "id": "storage.notifications.insert",
+ "parameterOrder": [
+ "bucket"
+ ],
+ "parameters": {
+ "bucket": {
+ "description": "The parent bucket of the notification.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "userProject": {
+ "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ "location": "query",
+ "type": "string"
+ }
+ },
+ "path": "b/{bucket}/notificationConfigs",
+ "request": {
+ "$ref": "Notification"
+ },
+ "response": {
+ "$ref": "Notification"
+ },
+ "scopes": [
+ "https://www.googleapis.com/auth/cloud-platform",
+ "https://www.googleapis.com/auth/devstorage.full_control",
+ "https://www.googleapis.com/auth/devstorage.read_write"
+ ]
+ },
+ "list": {
+ "description": "Retrieves a list of notification subscriptions for a given bucket.",
+ "httpMethod": "GET",
+ "id": "storage.notifications.list",
+ "parameterOrder": [
+ "bucket"
+ ],
+ "parameters": {
+ "bucket": {
+ "description": "Name of a Google Cloud Storage bucket.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "userProject": {
+ "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ "location": "query",
+ "type": "string"
+ }
+ },
+ "path": "b/{bucket}/notificationConfigs",
+ "response": {
+ "$ref": "Notifications"
+ },
+ "scopes": [
+ "https://www.googleapis.com/auth/cloud-platform",
+ "https://www.googleapis.com/auth/cloud-platform.read-only",
+ "https://www.googleapis.com/auth/devstorage.full_control",
+ "https://www.googleapis.com/auth/devstorage.read_only",
+ "https://www.googleapis.com/auth/devstorage.read_write"
+ ]
+ }
+ }
+ },
+ "objectAccessControls": {
+ "methods": {
+ "delete": {
+ "description": "Permanently deletes the ACL entry for the specified entity on the specified object.",
+ "httpMethod": "DELETE",
+ "id": "storage.objectAccessControls.delete",
+ "parameterOrder": [
+ "bucket",
+ "object",
+ "entity"
+ ],
+ "parameters": {
+ "bucket": {
+ "description": "Name of a bucket.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "entity": {
+ "description": "The entity holding the permission. Can be user-userId, user-emailAddress, group-groupId, group-emailAddress, allUsers, or allAuthenticatedUsers.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "generation": {
+ "description": "If present, selects a specific revision of this object (as opposed to the latest version, the default).",
+ "format": "int64",
+ "location": "query",
+ "type": "string"
+ },
+ "object": {
+ "description": "Name of the object. For information about how to URL encode object names to be path safe, see Encoding URI Path Parts.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "userProject": {
+ "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ "location": "query",
+ "type": "string"
+ }
+ },
+ "path": "b/{bucket}/o/{object}/acl/{entity}",
+ "scopes": [
+ "https://www.googleapis.com/auth/cloud-platform",
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ]
+ },
+ "get": {
+ "description": "Returns the ACL entry for the specified entity on the specified object.",
+ "httpMethod": "GET",
+ "id": "storage.objectAccessControls.get",
+ "parameterOrder": [
+ "bucket",
+ "object",
+ "entity"
+ ],
+ "parameters": {
+ "bucket": {
+ "description": "Name of a bucket.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "entity": {
+ "description": "The entity holding the permission. Can be user-userId, user-emailAddress, group-groupId, group-emailAddress, allUsers, or allAuthenticatedUsers.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "generation": {
+ "description": "If present, selects a specific revision of this object (as opposed to the latest version, the default).",
+ "format": "int64",
+ "location": "query",
+ "type": "string"
+ },
+ "object": {
+ "description": "Name of the object. For information about how to URL encode object names to be path safe, see Encoding URI Path Parts.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "userProject": {
+ "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ "location": "query",
+ "type": "string"
+ }
+ },
+ "path": "b/{bucket}/o/{object}/acl/{entity}",
+ "response": {
+ "$ref": "ObjectAccessControl"
+ },
+ "scopes": [
+ "https://www.googleapis.com/auth/cloud-platform",
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ]
+ },
+ "insert": {
+ "description": "Creates a new ACL entry on the specified object.",
+ "httpMethod": "POST",
+ "id": "storage.objectAccessControls.insert",
+ "parameterOrder": [
+ "bucket",
+ "object"
+ ],
+ "parameters": {
+ "bucket": {
+ "description": "Name of a bucket.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "generation": {
+ "description": "If present, selects a specific revision of this object (as opposed to the latest version, the default).",
+ "format": "int64",
+ "location": "query",
+ "type": "string"
+ },
+ "object": {
+ "description": "Name of the object. For information about how to URL encode object names to be path safe, see Encoding URI Path Parts.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "userProject": {
+ "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ "location": "query",
+ "type": "string"
+ }
+ },
+ "path": "b/{bucket}/o/{object}/acl",
+ "request": {
+ "$ref": "ObjectAccessControl"
+ },
+ "response": {
+ "$ref": "ObjectAccessControl"
+ },
+ "scopes": [
+ "https://www.googleapis.com/auth/cloud-platform",
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ]
+ },
+ "list": {
+ "description": "Retrieves ACL entries on the specified object.",
+ "httpMethod": "GET",
+ "id": "storage.objectAccessControls.list",
+ "parameterOrder": [
+ "bucket",
+ "object"
+ ],
+ "parameters": {
+ "bucket": {
+ "description": "Name of a bucket.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "generation": {
+ "description": "If present, selects a specific revision of this object (as opposed to the latest version, the default).",
+ "format": "int64",
+ "location": "query",
+ "type": "string"
+ },
+ "object": {
+ "description": "Name of the object. For information about how to URL encode object names to be path safe, see Encoding URI Path Parts.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "userProject": {
+ "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ "location": "query",
+ "type": "string"
+ }
+ },
+ "path": "b/{bucket}/o/{object}/acl",
+ "response": {
+ "$ref": "ObjectAccessControls"
+ },
+ "scopes": [
+ "https://www.googleapis.com/auth/cloud-platform",
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ]
+ },
+ "patch": {
+ "description": "Patches an ACL entry on the specified object.",
+ "httpMethod": "PATCH",
+ "id": "storage.objectAccessControls.patch",
+ "parameterOrder": [
+ "bucket",
+ "object",
+ "entity"
+ ],
+ "parameters": {
+ "bucket": {
+ "description": "Name of a bucket.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "entity": {
+ "description": "The entity holding the permission. Can be user-userId, user-emailAddress, group-groupId, group-emailAddress, allUsers, or allAuthenticatedUsers.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "generation": {
+ "description": "If present, selects a specific revision of this object (as opposed to the latest version, the default).",
+ "format": "int64",
+ "location": "query",
+ "type": "string"
+ },
+ "object": {
+ "description": "Name of the object. For information about how to URL encode object names to be path safe, see Encoding URI Path Parts.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "userProject": {
+ "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ "location": "query",
+ "type": "string"
+ }
+ },
+ "path": "b/{bucket}/o/{object}/acl/{entity}",
+ "request": {
+ "$ref": "ObjectAccessControl"
+ },
+ "response": {
+ "$ref": "ObjectAccessControl"
+ },
+ "scopes": [
+ "https://www.googleapis.com/auth/cloud-platform",
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ]
+ },
+ "update": {
+ "description": "Updates an ACL entry on the specified object.",
+ "httpMethod": "PUT",
+ "id": "storage.objectAccessControls.update",
+ "parameterOrder": [
+ "bucket",
+ "object",
+ "entity"
+ ],
+ "parameters": {
+ "bucket": {
+ "description": "Name of a bucket.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "entity": {
+ "description": "The entity holding the permission. Can be user-userId, user-emailAddress, group-groupId, group-emailAddress, allUsers, or allAuthenticatedUsers.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "generation": {
+ "description": "If present, selects a specific revision of this object (as opposed to the latest version, the default).",
+ "format": "int64",
+ "location": "query",
+ "type": "string"
+ },
+ "object": {
+ "description": "Name of the object. For information about how to URL encode object names to be path safe, see Encoding URI Path Parts.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "userProject": {
+ "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ "location": "query",
+ "type": "string"
+ }
+ },
+ "path": "b/{bucket}/o/{object}/acl/{entity}",
+ "request": {
+ "$ref": "ObjectAccessControl"
+ },
+ "response": {
+ "$ref": "ObjectAccessControl"
+ },
+ "scopes": [
+ "https://www.googleapis.com/auth/cloud-platform",
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ]
+ }
+ }
+ },
+ "objects": {
+ "methods": {
+ "compose": {
+ "description": "Concatenates a list of existing objects into a new object in the same bucket.",
+ "httpMethod": "POST",
+ "id": "storage.objects.compose",
+ "parameterOrder": [
+ "destinationBucket",
+ "destinationObject"
+ ],
+ "parameters": {
+ "destinationBucket": {
+ "description": "Name of the bucket containing the source objects. The destination object is stored in this bucket.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "destinationObject": {
+ "description": "Name of the new object. For information about how to URL encode object names to be path safe, see Encoding URI Path Parts.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "destinationPredefinedAcl": {
+ "description": "Apply a predefined set of access controls to the destination object.",
+ "enum": [
+ "authenticatedRead",
+ "bucketOwnerFullControl",
+ "bucketOwnerRead",
+ "private",
+ "projectPrivate",
+ "publicRead"
+ ],
+ "enumDescriptions": [
+ "Object owner gets OWNER access, and allAuthenticatedUsers get READER access.",
+ "Object owner gets OWNER access, and project team owners get OWNER access.",
+ "Object owner gets OWNER access, and project team owners get READER access.",
+ "Object owner gets OWNER access.",
+ "Object owner gets OWNER access, and project team members get access according to their roles.",
+ "Object owner gets OWNER access, and allUsers get READER access."
+ ],
+ "location": "query",
+ "type": "string"
+ },
+ "ifGenerationMatch": {
+ "description": "Makes the operation conditional on whether the object's current generation matches the given value. Setting to 0 makes the operation succeed only if there are no live versions of the object.",
+ "format": "int64",
+ "location": "query",
+ "type": "string"
+ },
+ "ifMetagenerationMatch": {
+ "description": "Makes the operation conditional on whether the object's current metageneration matches the given value.",
+ "format": "int64",
+ "location": "query",
+ "type": "string"
+ },
+ "kmsKeyName": {
+ "description": "Resource name of the Cloud KMS key, of the form projects/my-project/locations/global/keyRings/my-kr/cryptoKeys/my-key, that will be used to encrypt the object. Overrides the object metadata's kms_key_name value, if any.",
+ "location": "query",
+ "type": "string"
+ },
+ "userProject": {
+ "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ "location": "query",
+ "type": "string"
+ }
+ },
+ "path": "b/{destinationBucket}/o/{destinationObject}/compose",
+ "request": {
+ "$ref": "ComposeRequest"
+ },
+ "response": {
+ "$ref": "Object"
+ },
+ "scopes": [
+ "https://www.googleapis.com/auth/cloud-platform",
+ "https://www.googleapis.com/auth/devstorage.full_control",
+ "https://www.googleapis.com/auth/devstorage.read_write"
+ ]
+ },
+ "copy": {
+ "description": "Copies a source object to a destination object. Optionally overrides metadata.",
+ "httpMethod": "POST",
+ "id": "storage.objects.copy",
+ "parameterOrder": [
+ "sourceBucket",
+ "sourceObject",
+ "destinationBucket",
+ "destinationObject"
+ ],
+ "parameters": {
+ "destinationBucket": {
+ "description": "Name of the bucket in which to store the new object. Overrides the provided object metadata's bucket value, if any.For information about how to URL encode object names to be path safe, see Encoding URI Path Parts.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "destinationObject": {
+ "description": "Name of the new object. Required when the object metadata is not otherwise provided. Overrides the object metadata's name value, if any.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "destinationPredefinedAcl": {
+ "description": "Apply a predefined set of access controls to the destination object.",
+ "enum": [
+ "authenticatedRead",
+ "bucketOwnerFullControl",
+ "bucketOwnerRead",
+ "private",
+ "projectPrivate",
+ "publicRead"
+ ],
+ "enumDescriptions": [
+ "Object owner gets OWNER access, and allAuthenticatedUsers get READER access.",
+ "Object owner gets OWNER access, and project team owners get OWNER access.",
+ "Object owner gets OWNER access, and project team owners get READER access.",
+ "Object owner gets OWNER access.",
+ "Object owner gets OWNER access, and project team members get access according to their roles.",
+ "Object owner gets OWNER access, and allUsers get READER access."
+ ],
+ "location": "query",
+ "type": "string"
+ },
+ "ifGenerationMatch": {
+ "description": "Makes the operation conditional on whether the destination object's current generation matches the given value. Setting to 0 makes the operation succeed only if there are no live versions of the object.",
+ "format": "int64",
+ "location": "query",
+ "type": "string"
+ },
+ "ifGenerationNotMatch": {
+ "description": "Makes the operation conditional on whether the destination object's current generation does not match the given value. If no live object exists, the precondition fails. Setting to 0 makes the operation succeed only if there is a live version of the object.",
+ "format": "int64",
+ "location": "query",
+ "type": "string"
+ },
+ "ifMetagenerationMatch": {
+ "description": "Makes the operation conditional on whether the destination object's current metageneration matches the given value.",
+ "format": "int64",
+ "location": "query",
+ "type": "string"
+ },
+ "ifMetagenerationNotMatch": {
+ "description": "Makes the operation conditional on whether the destination object's current metageneration does not match the given value.",
+ "format": "int64",
+ "location": "query",
+ "type": "string"
+ },
+ "ifSourceGenerationMatch": {
+ "description": "Makes the operation conditional on whether the source object's current generation matches the given value.",
+ "format": "int64",
+ "location": "query",
+ "type": "string"
+ },
+ "ifSourceGenerationNotMatch": {
+ "description": "Makes the operation conditional on whether the source object's current generation does not match the given value.",
+ "format": "int64",
+ "location": "query",
+ "type": "string"
+ },
+ "ifSourceMetagenerationMatch": {
+ "description": "Makes the operation conditional on whether the source object's current metageneration matches the given value.",
+ "format": "int64",
+ "location": "query",
+ "type": "string"
+ },
+ "ifSourceMetagenerationNotMatch": {
+ "description": "Makes the operation conditional on whether the source object's current metageneration does not match the given value.",
+ "format": "int64",
+ "location": "query",
+ "type": "string"
+ },
+ "projection": {
+ "description": "Set of properties to return. Defaults to noAcl, unless the object resource specifies the acl property, when it defaults to full.",
+ "enum": [
+ "full",
+ "noAcl"
+ ],
+ "enumDescriptions": [
+ "Include all properties.",
+ "Omit the owner, acl property."
+ ],
+ "location": "query",
+ "type": "string"
+ },
+ "sourceBucket": {
+ "description": "Name of the bucket in which to find the source object.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "sourceGeneration": {
+ "description": "If present, selects a specific revision of the source object (as opposed to the latest version, the default).",
+ "format": "int64",
+ "location": "query",
+ "type": "string"
+ },
+ "sourceObject": {
+ "description": "Name of the source object. For information about how to URL encode object names to be path safe, see Encoding URI Path Parts.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "userProject": {
+ "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ "location": "query",
+ "type": "string"
+ }
+ },
+ "path": "b/{sourceBucket}/o/{sourceObject}/copyTo/b/{destinationBucket}/o/{destinationObject}",
+ "request": {
+ "$ref": "Object"
+ },
+ "response": {
+ "$ref": "Object"
+ },
+ "scopes": [
+ "https://www.googleapis.com/auth/cloud-platform",
+ "https://www.googleapis.com/auth/devstorage.full_control",
+ "https://www.googleapis.com/auth/devstorage.read_write"
+ ]
+ },
+ "delete": {
+ "description": "Deletes an object and its metadata. Deletions are permanent if versioning is not enabled for the bucket, or if the generation parameter is used.",
+ "httpMethod": "DELETE",
+ "id": "storage.objects.delete",
+ "parameterOrder": [
+ "bucket",
+ "object"
+ ],
+ "parameters": {
+ "bucket": {
+ "description": "Name of the bucket in which the object resides.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "generation": {
+ "description": "If present, permanently deletes a specific revision of this object (as opposed to the latest version, the default).",
+ "format": "int64",
+ "location": "query",
+ "type": "string"
+ },
+ "ifGenerationMatch": {
+ "description": "Makes the operation conditional on whether the object's current generation matches the given value. Setting to 0 makes the operation succeed only if there are no live versions of the object.",
+ "format": "int64",
+ "location": "query",
+ "type": "string"
+ },
+ "ifGenerationNotMatch": {
+ "description": "Makes the operation conditional on whether the object's current generation does not match the given value. If no live object exists, the precondition fails. Setting to 0 makes the operation succeed only if there is a live version of the object.",
+ "format": "int64",
+ "location": "query",
+ "type": "string"
+ },
+ "ifMetagenerationMatch": {
+ "description": "Makes the operation conditional on whether the object's current metageneration matches the given value.",
+ "format": "int64",
+ "location": "query",
+ "type": "string"
+ },
+ "ifMetagenerationNotMatch": {
+ "description": "Makes the operation conditional on whether the object's current metageneration does not match the given value.",
+ "format": "int64",
+ "location": "query",
+ "type": "string"
+ },
+ "object": {
+ "description": "Name of the object. For information about how to URL encode object names to be path safe, see Encoding URI Path Parts.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "userProject": {
+ "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ "location": "query",
+ "type": "string"
+ }
+ },
+ "path": "b/{bucket}/o/{object}",
+ "scopes": [
+ "https://www.googleapis.com/auth/cloud-platform",
+ "https://www.googleapis.com/auth/devstorage.full_control",
+ "https://www.googleapis.com/auth/devstorage.read_write"
+ ]
+ },
+ "get": {
+ "description": "Retrieves an object or its metadata.",
+ "httpMethod": "GET",
+ "id": "storage.objects.get",
+ "parameterOrder": [
+ "bucket",
+ "object"
+ ],
+ "parameters": {
+ "bucket": {
+ "description": "Name of the bucket in which the object resides.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "generation": {
+ "description": "If present, selects a specific revision of this object (as opposed to the latest version, the default).",
+ "format": "int64",
+ "location": "query",
+ "type": "string"
+ },
+ "ifGenerationMatch": {
+ "description": "Makes the operation conditional on whether the object's current generation matches the given value. Setting to 0 makes the operation succeed only if there are no live versions of the object.",
+ "format": "int64",
+ "location": "query",
+ "type": "string"
+ },
+ "ifGenerationNotMatch": {
+ "description": "Makes the operation conditional on whether the object's current generation does not match the given value. If no live object exists, the precondition fails. Setting to 0 makes the operation succeed only if there is a live version of the object.",
+ "format": "int64",
+ "location": "query",
+ "type": "string"
+ },
+ "ifMetagenerationMatch": {
+ "description": "Makes the operation conditional on whether the object's current metageneration matches the given value.",
+ "format": "int64",
+ "location": "query",
+ "type": "string"
+ },
+ "ifMetagenerationNotMatch": {
+ "description": "Makes the operation conditional on whether the object's current metageneration does not match the given value.",
+ "format": "int64",
+ "location": "query",
+ "type": "string"
+ },
+ "object": {
+ "description": "Name of the object. For information about how to URL encode object names to be path safe, see Encoding URI Path Parts.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "projection": {
+ "description": "Set of properties to return. Defaults to noAcl.",
+ "enum": [
+ "full",
+ "noAcl"
+ ],
+ "enumDescriptions": [
+ "Include all properties.",
+ "Omit the owner, acl property."
+ ],
+ "location": "query",
+ "type": "string"
+ },
+ "userProject": {
+ "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ "location": "query",
+ "type": "string"
+ }
+ },
+ "path": "b/{bucket}/o/{object}",
+ "response": {
+ "$ref": "Object"
+ },
+ "scopes": [
+ "https://www.googleapis.com/auth/cloud-platform",
+ "https://www.googleapis.com/auth/cloud-platform.read-only",
+ "https://www.googleapis.com/auth/devstorage.full_control",
+ "https://www.googleapis.com/auth/devstorage.read_only",
+ "https://www.googleapis.com/auth/devstorage.read_write"
+ ],
+ "supportsMediaDownload": true,
+ "useMediaDownloadService": true
+ },
+ "getIamPolicy": {
+ "description": "Returns an IAM policy for the specified object.",
+ "httpMethod": "GET",
+ "id": "storage.objects.getIamPolicy",
+ "parameterOrder": [
+ "bucket",
+ "object"
+ ],
+ "parameters": {
+ "bucket": {
+ "description": "Name of the bucket in which the object resides.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "generation": {
+ "description": "If present, selects a specific revision of this object (as opposed to the latest version, the default).",
+ "format": "int64",
+ "location": "query",
+ "type": "string"
+ },
+ "object": {
+ "description": "Name of the object. For information about how to URL encode object names to be path safe, see Encoding URI Path Parts.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "userProject": {
+ "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ "location": "query",
+ "type": "string"
+ }
+ },
+ "path": "b/{bucket}/o/{object}/iam",
+ "response": {
+ "$ref": "Policy"
+ },
+ "scopes": [
+ "https://www.googleapis.com/auth/cloud-platform",
+ "https://www.googleapis.com/auth/cloud-platform.read-only",
+ "https://www.googleapis.com/auth/devstorage.full_control",
+ "https://www.googleapis.com/auth/devstorage.read_only",
+ "https://www.googleapis.com/auth/devstorage.read_write"
+ ]
+ },
+ "insert": {
+ "description": "Stores a new object and metadata.",
+ "httpMethod": "POST",
+ "id": "storage.objects.insert",
+ "mediaUpload": {
+ "accept": [
+ "*/*"
+ ],
+ "protocols": {
+ "resumable": {
+ "multipart": true,
+ "path": "/resumable/upload/storage/v1/b/{bucket}/o"
+ },
+ "simple": {
+ "multipart": true,
+ "path": "/upload/storage/v1/b/{bucket}/o"
+ }
+ }
+ },
+ "parameterOrder": [
+ "bucket"
+ ],
+ "parameters": {
+ "bucket": {
+ "description": "Name of the bucket in which to store the new object. Overrides the provided object metadata's bucket value, if any.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "contentEncoding": {
+ "description": "If set, sets the contentEncoding property of the final object to this value. Setting this parameter is equivalent to setting the contentEncoding metadata property. This can be useful when uploading an object with uploadType=media to indicate the encoding of the content being uploaded.",
+ "location": "query",
+ "type": "string"
+ },
+ "ifGenerationMatch": {
+ "description": "Makes the operation conditional on whether the object's current generation matches the given value. Setting to 0 makes the operation succeed only if there are no live versions of the object.",
+ "format": "int64",
+ "location": "query",
+ "type": "string"
+ },
+ "ifGenerationNotMatch": {
+ "description": "Makes the operation conditional on whether the object's current generation does not match the given value. If no live object exists, the precondition fails. Setting to 0 makes the operation succeed only if there is a live version of the object.",
+ "format": "int64",
+ "location": "query",
+ "type": "string"
+ },
+ "ifMetagenerationMatch": {
+ "description": "Makes the operation conditional on whether the object's current metageneration matches the given value.",
+ "format": "int64",
+ "location": "query",
+ "type": "string"
+ },
+ "ifMetagenerationNotMatch": {
+ "description": "Makes the operation conditional on whether the object's current metageneration does not match the given value.",
+ "format": "int64",
+ "location": "query",
+ "type": "string"
+ },
+ "kmsKeyName": {
+ "description": "Resource name of the Cloud KMS key, of the form projects/my-project/locations/global/keyRings/my-kr/cryptoKeys/my-key, that will be used to encrypt the object. Overrides the object metadata's kms_key_name value, if any.",
+ "location": "query",
+ "type": "string"
+ },
+ "name": {
+ "description": "Name of the object. Required when the object metadata is not otherwise provided. Overrides the object metadata's name value, if any. For information about how to URL encode object names to be path safe, see Encoding URI Path Parts.",
+ "location": "query",
+ "type": "string"
+ },
+ "predefinedAcl": {
+ "description": "Apply a predefined set of access controls to this object.",
+ "enum": [
+ "authenticatedRead",
+ "bucketOwnerFullControl",
+ "bucketOwnerRead",
+ "private",
+ "projectPrivate",
+ "publicRead"
+ ],
+ "enumDescriptions": [
+ "Object owner gets OWNER access, and allAuthenticatedUsers get READER access.",
+ "Object owner gets OWNER access, and project team owners get OWNER access.",
+ "Object owner gets OWNER access, and project team owners get READER access.",
+ "Object owner gets OWNER access.",
+ "Object owner gets OWNER access, and project team members get access according to their roles.",
+ "Object owner gets OWNER access, and allUsers get READER access."
+ ],
+ "location": "query",
+ "type": "string"
+ },
+ "projection": {
+ "description": "Set of properties to return. Defaults to noAcl, unless the object resource specifies the acl property, when it defaults to full.",
+ "enum": [
+ "full",
+ "noAcl"
+ ],
+ "enumDescriptions": [
+ "Include all properties.",
+ "Omit the owner, acl property."
+ ],
+ "location": "query",
+ "type": "string"
+ },
+ "userProject": {
+ "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ "location": "query",
+ "type": "string"
+ }
+ },
+ "path": "b/{bucket}/o",
+ "request": {
+ "$ref": "Object"
+ },
+ "response": {
+ "$ref": "Object"
+ },
+ "scopes": [
+ "https://www.googleapis.com/auth/cloud-platform",
+ "https://www.googleapis.com/auth/devstorage.full_control",
+ "https://www.googleapis.com/auth/devstorage.read_write"
+ ],
+ "supportsMediaUpload": true
+ },
+ "list": {
+ "description": "Retrieves a list of objects matching the criteria.",
+ "httpMethod": "GET",
+ "id": "storage.objects.list",
+ "parameterOrder": [
+ "bucket"
+ ],
+ "parameters": {
+ "bucket": {
+ "description": "Name of the bucket in which to look for objects.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "delimiter": {
+ "description": "Returns results in a directory-like mode. items will contain only objects whose names, aside from the prefix, do not contain delimiter. Objects whose names, aside from the prefix, contain delimiter will have their name, truncated after the delimiter, returned in prefixes. Duplicate prefixes are omitted.",
+ "location": "query",
+ "type": "string"
+ },
+ "includeTrailingDelimiter": {
+ "description": "If true, objects that end in exactly one instance of delimiter will have their metadata included in items in addition to prefixes.",
+ "location": "query",
+ "type": "boolean"
+ },
+ "maxResults": {
+ "default": "1000",
+ "description": "Maximum number of items plus prefixes to return in a single page of responses. As duplicate prefixes are omitted, fewer total results may be returned than requested. The service will use this parameter or 1,000 items, whichever is smaller.",
+ "format": "uint32",
+ "location": "query",
+ "minimum": "0",
+ "type": "integer"
+ },
+ "pageToken": {
+ "description": "A previously-returned page token representing part of the larger set of results to view.",
+ "location": "query",
+ "type": "string"
+ },
+ "prefix": {
+ "description": "Filter results to objects whose names begin with this prefix.",
+ "location": "query",
+ "type": "string"
+ },
+ "projection": {
+ "description": "Set of properties to return. Defaults to noAcl.",
+ "enum": [
+ "full",
+ "noAcl"
+ ],
+ "enumDescriptions": [
+ "Include all properties.",
+ "Omit the owner, acl property."
+ ],
+ "location": "query",
+ "type": "string"
+ },
+ "userProject": {
+ "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ "location": "query",
+ "type": "string"
+ },
+ "versions": {
+ "description": "If true, lists all versions of an object as distinct results. The default is false. For more information, see Object Versioning.",
+ "location": "query",
+ "type": "boolean"
+ }
+ },
+ "path": "b/{bucket}/o",
+ "response": {
+ "$ref": "Objects"
+ },
+ "scopes": [
+ "https://www.googleapis.com/auth/cloud-platform",
+ "https://www.googleapis.com/auth/cloud-platform.read-only",
+ "https://www.googleapis.com/auth/devstorage.full_control",
+ "https://www.googleapis.com/auth/devstorage.read_only",
+ "https://www.googleapis.com/auth/devstorage.read_write"
+ ],
+ "supportsSubscription": true
+ },
+ "patch": {
+ "description": "Patches an object's metadata.",
+ "httpMethod": "PATCH",
+ "id": "storage.objects.patch",
+ "parameterOrder": [
+ "bucket",
+ "object"
+ ],
+ "parameters": {
+ "bucket": {
+ "description": "Name of the bucket in which the object resides.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "generation": {
+ "description": "If present, selects a specific revision of this object (as opposed to the latest version, the default).",
+ "format": "int64",
+ "location": "query",
+ "type": "string"
+ },
+ "ifGenerationMatch": {
+ "description": "Makes the operation conditional on whether the object's current generation matches the given value. Setting to 0 makes the operation succeed only if there are no live versions of the object.",
+ "format": "int64",
+ "location": "query",
+ "type": "string"
+ },
+ "ifGenerationNotMatch": {
+ "description": "Makes the operation conditional on whether the object's current generation does not match the given value. If no live object exists, the precondition fails. Setting to 0 makes the operation succeed only if there is a live version of the object.",
+ "format": "int64",
+ "location": "query",
+ "type": "string"
+ },
+ "ifMetagenerationMatch": {
+ "description": "Makes the operation conditional on whether the object's current metageneration matches the given value.",
+ "format": "int64",
+ "location": "query",
+ "type": "string"
+ },
+ "ifMetagenerationNotMatch": {
+ "description": "Makes the operation conditional on whether the object's current metageneration does not match the given value.",
+ "format": "int64",
+ "location": "query",
+ "type": "string"
+ },
+ "object": {
+ "description": "Name of the object. For information about how to URL encode object names to be path safe, see Encoding URI Path Parts.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "predefinedAcl": {
+ "description": "Apply a predefined set of access controls to this object.",
+ "enum": [
+ "authenticatedRead",
+ "bucketOwnerFullControl",
+ "bucketOwnerRead",
+ "private",
+ "projectPrivate",
+ "publicRead"
+ ],
+ "enumDescriptions": [
+ "Object owner gets OWNER access, and allAuthenticatedUsers get READER access.",
+ "Object owner gets OWNER access, and project team owners get OWNER access.",
+ "Object owner gets OWNER access, and project team owners get READER access.",
+ "Object owner gets OWNER access.",
+ "Object owner gets OWNER access, and project team members get access according to their roles.",
+ "Object owner gets OWNER access, and allUsers get READER access."
+ ],
+ "location": "query",
+ "type": "string"
+ },
+ "projection": {
+ "description": "Set of properties to return. Defaults to full.",
+ "enum": [
+ "full",
+ "noAcl"
+ ],
+ "enumDescriptions": [
+ "Include all properties.",
+ "Omit the owner, acl property."
+ ],
+ "location": "query",
+ "type": "string"
+ },
+ "userProject": {
+ "description": "The project to be billed for this request, for Requester Pays buckets.",
+ "location": "query",
+ "type": "string"
+ }
+ },
+ "path": "b/{bucket}/o/{object}",
+ "request": {
+ "$ref": "Object"
+ },
+ "response": {
+ "$ref": "Object"
+ },
+ "scopes": [
+ "https://www.googleapis.com/auth/cloud-platform",
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ]
+ },
+ "rewrite": {
+ "description": "Rewrites a source object to a destination object. Optionally overrides metadata.",
+ "httpMethod": "POST",
+ "id": "storage.objects.rewrite",
+ "parameterOrder": [
+ "sourceBucket",
+ "sourceObject",
+ "destinationBucket",
+ "destinationObject"
+ ],
+ "parameters": {
+ "destinationBucket": {
+ "description": "Name of the bucket in which to store the new object. Overrides the provided object metadata's bucket value, if any.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "destinationKmsKeyName": {
+ "description": "Resource name of the Cloud KMS key, of the form projects/my-project/locations/global/keyRings/my-kr/cryptoKeys/my-key, that will be used to encrypt the object. Overrides the object metadata's kms_key_name value, if any.",
+ "location": "query",
+ "type": "string"
+ },
+ "destinationObject": {
+ "description": "Name of the new object. Required when the object metadata is not otherwise provided. Overrides the object metadata's name value, if any. For information about how to URL encode object names to be path safe, see Encoding URI Path Parts.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "destinationPredefinedAcl": {
+ "description": "Apply a predefined set of access controls to the destination object.",
+ "enum": [
+ "authenticatedRead",
+ "bucketOwnerFullControl",
+ "bucketOwnerRead",
+ "private",
+ "projectPrivate",
+ "publicRead"
+ ],
+ "enumDescriptions": [
+ "Object owner gets OWNER access, and allAuthenticatedUsers get READER access.",
+ "Object owner gets OWNER access, and project team owners get OWNER access.",
+ "Object owner gets OWNER access, and project team owners get READER access.",
+ "Object owner gets OWNER access.",
+ "Object owner gets OWNER access, and project team members get access according to their roles.",
+ "Object owner gets OWNER access, and allUsers get READER access."
+ ],
+ "location": "query",
+ "type": "string"
+ },
+ "ifGenerationMatch": {
+ "description": "Makes the operation conditional on whether the object's current generation matches the given value. Setting to 0 makes the operation succeed only if there are no live versions of the object.",
+ "format": "int64",
+ "location": "query",
+ "type": "string"
+ },
+ "ifGenerationNotMatch": {
+ "description": "Makes the operation conditional on whether the object's current generation does not match the given value. If no live object exists, the precondition fails. Setting to 0 makes the operation succeed only if there is a live version of the object.",
+ "format": "int64",
+ "location": "query",
+ "type": "string"
+ },
+ "ifMetagenerationMatch": {
+ "description": "Makes the operation conditional on whether the destination object's current metageneration matches the given value.",
+ "format": "int64",
+ "location": "query",
+ "type": "string"
+ },
+ "ifMetagenerationNotMatch": {
+ "description": "Makes the operation conditional on whether the destination object's current metageneration does not match the given value.",
+ "format": "int64",
+ "location": "query",
+ "type": "string"
+ },
+ "ifSourceGenerationMatch": {
+ "description": "Makes the operation conditional on whether the source object's current generation matches the given value.",
+ "format": "int64",
+ "location": "query",
+ "type": "string"
+ },
+ "ifSourceGenerationNotMatch": {
+ "description": "Makes the operation conditional on whether the source object's current generation does not match the given value.",
+ "format": "int64",
+ "location": "query",
+ "type": "string"
+ },
+ "ifSourceMetagenerationMatch": {
+ "description": "Makes the operation conditional on whether the source object's current metageneration matches the given value.",
+ "format": "int64",
+ "location": "query",
+ "type": "string"
+ },
+ "ifSourceMetagenerationNotMatch": {
+ "description": "Makes the operation conditional on whether the source object's current metageneration does not match the given value.",
+ "format": "int64",
+ "location": "query",
+ "type": "string"
+ },
+ "maxBytesRewrittenPerCall": {
+ "description": "The maximum number of bytes that will be rewritten per rewrite request. Most callers shouldn't need to specify this parameter - it is primarily in place to support testing. If specified the value must be an integral multiple of 1 MiB (1048576). Also, this only applies to requests where the source and destination span locations and/or storage classes. Finally, this value must not change across rewrite calls else you'll get an error that the rewriteToken is invalid.",
+ "format": "int64",
+ "location": "query",
+ "type": "string"
+ },
+ "projection": {
+ "description": "Set of properties to return. Defaults to noAcl, unless the object resource specifies the acl property, when it defaults to full.",
+ "enum": [
+ "full",
+ "noAcl"
+ ],
+ "enumDescriptions": [
+ "Include all properties.",
+ "Omit the owner, acl property."
+ ],
+ "location": "query",
+ "type": "string"
+ },
+ "rewriteToken": {
+ "description": "Include this field (from the previous rewrite response) on each rewrite request after the first one, until the rewrite response 'done' flag is true. Calls that provide a rewriteToken can omit all other request fields, but if included those fields must match the values provided in the first rewrite request.",
+ "location": "query",
+ "type": "string"
+ },
+ "sourceBucket": {
+ "description": "Name of the bucket in which to find the source object.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "sourceGeneration": {
+ "description": "If present, selects a specific revision of the source object (as opposed to the latest version, the default).",
+ "format": "int64",
+ "location": "query",
+ "type": "string"
+ },
+ "sourceObject": {
+ "description": "Name of the source object. For information about how to URL encode object names to be path safe, see Encoding URI Path Parts.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "userProject": {
+ "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ "location": "query",
+ "type": "string"
+ }
+ },
+ "path": "b/{sourceBucket}/o/{sourceObject}/rewriteTo/b/{destinationBucket}/o/{destinationObject}",
+ "request": {
+ "$ref": "Object"
+ },
+ "response": {
+ "$ref": "RewriteResponse"
+ },
+ "scopes": [
+ "https://www.googleapis.com/auth/cloud-platform",
+ "https://www.googleapis.com/auth/devstorage.full_control",
+ "https://www.googleapis.com/auth/devstorage.read_write"
+ ]
+ },
+ "setIamPolicy": {
+ "description": "Updates an IAM policy for the specified object.",
+ "httpMethod": "PUT",
+ "id": "storage.objects.setIamPolicy",
+ "parameterOrder": [
+ "bucket",
+ "object"
+ ],
+ "parameters": {
+ "bucket": {
+ "description": "Name of the bucket in which the object resides.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "generation": {
+ "description": "If present, selects a specific revision of this object (as opposed to the latest version, the default).",
+ "format": "int64",
+ "location": "query",
+ "type": "string"
+ },
+ "object": {
+ "description": "Name of the object. For information about how to URL encode object names to be path safe, see Encoding URI Path Parts.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "userProject": {
+ "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ "location": "query",
+ "type": "string"
+ }
+ },
+ "path": "b/{bucket}/o/{object}/iam",
+ "request": {
+ "$ref": "Policy"
+ },
+ "response": {
+ "$ref": "Policy"
+ },
+ "scopes": [
+ "https://www.googleapis.com/auth/cloud-platform",
+ "https://www.googleapis.com/auth/devstorage.full_control",
+ "https://www.googleapis.com/auth/devstorage.read_write"
+ ]
+ },
+ "testIamPermissions": {
+ "description": "Tests a set of permissions on the given object to see which, if any, are held by the caller.",
+ "httpMethod": "GET",
+ "id": "storage.objects.testIamPermissions",
+ "parameterOrder": [
+ "bucket",
+ "object",
+ "permissions"
+ ],
+ "parameters": {
+ "bucket": {
+ "description": "Name of the bucket in which the object resides.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "generation": {
+ "description": "If present, selects a specific revision of this object (as opposed to the latest version, the default).",
+ "format": "int64",
+ "location": "query",
+ "type": "string"
+ },
+ "object": {
+ "description": "Name of the object. For information about how to URL encode object names to be path safe, see Encoding URI Path Parts.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "permissions": {
+ "description": "Permissions to test.",
+ "location": "query",
+ "repeated": true,
+ "required": true,
+ "type": "string"
+ },
+ "userProject": {
+ "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ "location": "query",
+ "type": "string"
+ }
+ },
+ "path": "b/{bucket}/o/{object}/iam/testPermissions",
+ "response": {
+ "$ref": "TestIamPermissionsResponse"
+ },
+ "scopes": [
+ "https://www.googleapis.com/auth/cloud-platform",
+ "https://www.googleapis.com/auth/cloud-platform.read-only",
+ "https://www.googleapis.com/auth/devstorage.full_control",
+ "https://www.googleapis.com/auth/devstorage.read_only",
+ "https://www.googleapis.com/auth/devstorage.read_write"
+ ]
+ },
+ "update": {
+ "description": "Updates an object's metadata.",
+ "httpMethod": "PUT",
+ "id": "storage.objects.update",
+ "parameterOrder": [
+ "bucket",
+ "object"
+ ],
+ "parameters": {
+ "bucket": {
+ "description": "Name of the bucket in which the object resides.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "generation": {
+ "description": "If present, selects a specific revision of this object (as opposed to the latest version, the default).",
+ "format": "int64",
+ "location": "query",
+ "type": "string"
+ },
+ "ifGenerationMatch": {
+ "description": "Makes the operation conditional on whether the object's current generation matches the given value. Setting to 0 makes the operation succeed only if there are no live versions of the object.",
+ "format": "int64",
+ "location": "query",
+ "type": "string"
+ },
+ "ifGenerationNotMatch": {
+ "description": "Makes the operation conditional on whether the object's current generation does not match the given value. If no live object exists, the precondition fails. Setting to 0 makes the operation succeed only if there is a live version of the object.",
+ "format": "int64",
+ "location": "query",
+ "type": "string"
+ },
+ "ifMetagenerationMatch": {
+ "description": "Makes the operation conditional on whether the object's current metageneration matches the given value.",
+ "format": "int64",
+ "location": "query",
+ "type": "string"
+ },
+ "ifMetagenerationNotMatch": {
+ "description": "Makes the operation conditional on whether the object's current metageneration does not match the given value.",
+ "format": "int64",
+ "location": "query",
+ "type": "string"
+ },
+ "object": {
+ "description": "Name of the object. For information about how to URL encode object names to be path safe, see Encoding URI Path Parts.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "predefinedAcl": {
+ "description": "Apply a predefined set of access controls to this object.",
+ "enum": [
+ "authenticatedRead",
+ "bucketOwnerFullControl",
+ "bucketOwnerRead",
+ "private",
+ "projectPrivate",
+ "publicRead"
+ ],
+ "enumDescriptions": [
+ "Object owner gets OWNER access, and allAuthenticatedUsers get READER access.",
+ "Object owner gets OWNER access, and project team owners get OWNER access.",
+ "Object owner gets OWNER access, and project team owners get READER access.",
+ "Object owner gets OWNER access.",
+ "Object owner gets OWNER access, and project team members get access according to their roles.",
+ "Object owner gets OWNER access, and allUsers get READER access."
+ ],
+ "location": "query",
+ "type": "string"
+ },
+ "projection": {
+ "description": "Set of properties to return. Defaults to full.",
+ "enum": [
+ "full",
+ "noAcl"
+ ],
+ "enumDescriptions": [
+ "Include all properties.",
+ "Omit the owner, acl property."
+ ],
+ "location": "query",
+ "type": "string"
+ },
+ "userProject": {
+ "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ "location": "query",
+ "type": "string"
+ }
+ },
+ "path": "b/{bucket}/o/{object}",
+ "request": {
+ "$ref": "Object"
+ },
+ "response": {
+ "$ref": "Object"
+ },
+ "scopes": [
+ "https://www.googleapis.com/auth/cloud-platform",
+ "https://www.googleapis.com/auth/devstorage.full_control"
+ ]
+ },
+ "watchAll": {
+ "description": "Watch for changes on all objects in a bucket.",
+ "httpMethod": "POST",
+ "id": "storage.objects.watchAll",
+ "parameterOrder": [
+ "bucket"
+ ],
+ "parameters": {
+ "bucket": {
+ "description": "Name of the bucket in which to look for objects.",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "delimiter": {
+ "description": "Returns results in a directory-like mode. items will contain only objects whose names, aside from the prefix, do not contain delimiter. Objects whose names, aside from the prefix, contain delimiter will have their name, truncated after the delimiter, returned in prefixes. Duplicate prefixes are omitted.",
+ "location": "query",
+ "type": "string"
+ },
+ "includeTrailingDelimiter": {
+ "description": "If true, objects that end in exactly one instance of delimiter will have their metadata included in items in addition to prefixes.",
+ "location": "query",
+ "type": "boolean"
+ },
+ "maxResults": {
+ "default": "1000",
+ "description": "Maximum number of items plus prefixes to return in a single page of responses. As duplicate prefixes are omitted, fewer total results may be returned than requested. The service will use this parameter or 1,000 items, whichever is smaller.",
+ "format": "uint32",
+ "location": "query",
+ "minimum": "0",
+ "type": "integer"
+ },
+ "pageToken": {
+ "description": "A previously-returned page token representing part of the larger set of results to view.",
+ "location": "query",
+ "type": "string"
+ },
+ "prefix": {
+ "description": "Filter results to objects whose names begin with this prefix.",
+ "location": "query",
+ "type": "string"
+ },
+ "projection": {
+ "description": "Set of properties to return. Defaults to noAcl.",
+ "enum": [
+ "full",
+ "noAcl"
+ ],
+ "enumDescriptions": [
+ "Include all properties.",
+ "Omit the owner, acl property."
+ ],
+ "location": "query",
+ "type": "string"
+ },
+ "userProject": {
+ "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ "location": "query",
+ "type": "string"
+ },
+ "versions": {
+ "description": "If true, lists all versions of an object as distinct results. The default is false. For more information, see Object Versioning.",
+ "location": "query",
+ "type": "boolean"
+ }
+ },
+ "path": "b/{bucket}/o/watch",
+ "request": {
+ "$ref": "Channel",
+ "parameterName": "resource"
+ },
+ "response": {
+ "$ref": "Channel"
+ },
+ "scopes": [
+ "https://www.googleapis.com/auth/cloud-platform",
+ "https://www.googleapis.com/auth/cloud-platform.read-only",
+ "https://www.googleapis.com/auth/devstorage.full_control",
+ "https://www.googleapis.com/auth/devstorage.read_only",
+ "https://www.googleapis.com/auth/devstorage.read_write"
+ ],
+ "supportsSubscription": true
+ }
+ }
+ },
+ "projects": {
+ "resources": {
+ "serviceAccount": {
+ "methods": {
+ "get": {
+ "description": "Get the email address of this project's Google Cloud Storage service account.",
+ "httpMethod": "GET",
+ "id": "storage.projects.serviceAccount.get",
+ "parameterOrder": [
+ "projectId"
+ ],
+ "parameters": {
+ "projectId": {
+ "description": "Project ID",
+ "location": "path",
+ "required": true,
+ "type": "string"
+ },
+ "userProject": {
+ "description": "The project to be billed for this request.",
+ "location": "query",
+ "type": "string"
+ }
+ },
+ "path": "projects/{projectId}/serviceAccount",
+ "response": {
+ "$ref": "ServiceAccount"
+ },
+ "scopes": [
+ "https://www.googleapis.com/auth/cloud-platform",
+ "https://www.googleapis.com/auth/cloud-platform.read-only",
+ "https://www.googleapis.com/auth/devstorage.full_control",
+ "https://www.googleapis.com/auth/devstorage.read_only",
+ "https://www.googleapis.com/auth/devstorage.read_write"
+ ]
+ }
+ }
+ }
+ }
+ }
+ },
+ "revision": "20181109",
+ "rootUrl": "https://www.googleapis.com/",
+ "schemas": {
+ "Bucket": {
+ "description": "A bucket.",
+ "id": "Bucket",
+ "properties": {
+ "acl": {
+ "annotations": {
+ "required": [
+ "storage.buckets.update"
+ ]
+ },
+ "description": "Access controls on the bucket.",
+ "items": {
+ "$ref": "BucketAccessControl"
+ },
+ "type": "array"
+ },
+ "billing": {
+ "description": "The bucket's billing configuration.",
+ "properties": {
+ "requesterPays": {
+ "description": "When set to true, Requester Pays is enabled for this bucket.",
+ "type": "boolean"
+ }
+ },
+ "type": "object"
+ },
+ "cors": {
+ "description": "The bucket's Cross-Origin Resource Sharing (CORS) configuration.",
+ "items": {
+ "properties": {
+ "maxAgeSeconds": {
+ "description": "The value, in seconds, to return in the Access-Control-Max-Age header used in preflight responses.",
+ "format": "int32",
+ "type": "integer"
+ },
+ "method": {
+ "description": "The list of HTTP methods on which to include CORS response headers, (GET, OPTIONS, POST, etc) Note: \"*\" is permitted in the list of methods, and means \"any method\".",
+ "items": {
+ "type": "string"
+ },
+ "type": "array"
+ },
+ "origin": {
+ "description": "The list of Origins eligible to receive CORS response headers. Note: \"*\" is permitted in the list of origins, and means \"any Origin\".",
+ "items": {
+ "type": "string"
+ },
+ "type": "array"
+ },
+ "responseHeader": {
+ "description": "The list of HTTP headers other than the simple response headers to give permission for the user-agent to share across domains.",
+ "items": {
+ "type": "string"
+ },
+ "type": "array"
+ }
+ },
+ "type": "object"
+ },
+ "type": "array"
+ },
+ "defaultEventBasedHold": {
+ "description": "The default value for event-based hold on newly created objects in this bucket. Event-based hold is a way to retain objects indefinitely until an event occurs, signified by the hold's release. After being released, such objects will be subject to bucket-level retention (if any). One sample use case of this flag is for banks to hold loan documents for at least 3 years after loan is paid in full. Here, bucket-level retention is 3 years and the event is loan being paid in full. In this example, these objects will be held intact for any number of years until the event has occurred (event-based hold on the object is released) and then 3 more years after that. That means retention duration of the objects begins from the moment event-based hold transitioned from true to false. Objects under event-based hold cannot be deleted, overwritten or archived until the hold is removed.",
+ "type": "boolean"
+ },
+ "defaultObjectAcl": {
+ "description": "Default access controls to apply to new objects when no ACL is provided.",
+ "items": {
+ "$ref": "ObjectAccessControl"
+ },
+ "type": "array"
+ },
+ "encryption": {
+ "description": "Encryption configuration for a bucket.",
+ "properties": {
+ "defaultKmsKeyName": {
+ "description": "A Cloud KMS key that will be used to encrypt objects inserted into this bucket, if no encryption method is specified.",
+ "type": "string"
+ }
+ },
+ "type": "object"
+ },
+ "etag": {
+ "description": "HTTP 1.1 Entity tag for the bucket.",
+ "type": "string"
+ },
+ "iamConfiguration": {
+ "description": "The bucket's IAM configuration.",
+ "properties": {
+ "bucketPolicyOnly": {
+ "properties": {
+ "enabled": {
+ "description": "If set, access checks only use bucket-level IAM policies or above.",
+ "type": "boolean"
+ },
+ "lockedTime": {
+ "description": "The deadline time for changing iamConfiguration.bucketPolicyOnly.enabled from true to false in RFC 3339 format. iamConfiguration.bucketPolicyOnly.enabled may be changed from true to false until the locked time, after which the field is immutable.",
+ "format": "date-time",
+ "type": "string"
+ }
+ },
+ "type": "object"
+ }
+ },
+ "type": "object"
+ },
+ "id": {
+ "description": "The ID of the bucket. For buckets, the id and name properties are the same.",
+ "type": "string"
+ },
+ "kind": {
+ "default": "storage#bucket",
+ "description": "The kind of item this is. For buckets, this is always storage#bucket.",
+ "type": "string"
+ },
+ "labels": {
+ "additionalProperties": {
+ "description": "An individual label entry.",
+ "type": "string"
+ },
+ "description": "User-provided labels, in key/value pairs.",
+ "type": "object"
+ },
+ "lifecycle": {
+ "description": "The bucket's lifecycle configuration. See lifecycle management for more information.",
+ "properties": {
+ "rule": {
+ "description": "A lifecycle management rule, which is made of an action to take and the condition(s) under which the action will be taken.",
+ "items": {
+ "properties": {
+ "action": {
+ "description": "The action to take.",
+ "properties": {
+ "storageClass": {
+ "description": "Target storage class. Required iff the type of the action is SetStorageClass.",
+ "type": "string"
+ },
+ "type": {
+ "description": "Type of the action. Currently, only Delete and SetStorageClass are supported.",
+ "type": "string"
+ }
+ },
+ "type": "object"
+ },
+ "condition": {
+ "description": "The condition(s) under which the action will be taken.",
+ "properties": {
+ "age": {
+ "description": "Age of an object (in days). This condition is satisfied when an object reaches the specified age.",
+ "format": "int32",
+ "type": "integer"
+ },
+ "createdBefore": {
+ "description": "A date in RFC 3339 format with only the date part (for instance, \"2013-01-15\"). This condition is satisfied when an object is created before midnight of the specified date in UTC.",
+ "format": "date",
+ "type": "string"
+ },
+ "isLive": {
+ "description": "Relevant only for versioned objects. If the value is true, this condition matches live objects; if the value is false, it matches archived objects.",
+ "type": "boolean"
+ },
+ "matchesPattern": {
+ "description": "A regular expression that satisfies the RE2 syntax. This condition is satisfied when the name of the object matches the RE2 pattern. Note: This feature is currently in the \"Early Access\" launch stage and is only available to a whitelisted set of users; that means that this feature may be changed in backward-incompatible ways and that it is not guaranteed to be released.",
+ "type": "string"
+ },
+ "matchesStorageClass": {
+ "description": "Objects having any of the storage classes specified by this condition will be matched. Values include MULTI_REGIONAL, REGIONAL, NEARLINE, COLDLINE, STANDARD, and DURABLE_REDUCED_AVAILABILITY.",
+ "items": {
+ "type": "string"
+ },
+ "type": "array"
+ },
+ "numNewerVersions": {
+ "description": "Relevant only for versioned objects. If the value is N, this condition is satisfied when there are at least N versions (including the live version) newer than this version of the object.",
+ "format": "int32",
+ "type": "integer"
+ }
+ },
+ "type": "object"
+ }
+ },
+ "type": "object"
+ },
+ "type": "array"
+ }
+ },
+ "type": "object"
+ },
+ "location": {
+ "description": "The location of the bucket. Object data for objects in the bucket resides in physical storage within this region. Defaults to US. See the developer's guide for the authoritative list.",
+ "type": "string"
+ },
+ "logging": {
+ "description": "The bucket's logging configuration, which defines the destination bucket and optional name prefix for the current bucket's logs.",
+ "properties": {
+ "logBucket": {
+ "description": "The destination bucket where the current bucket's logs should be placed.",
+ "type": "string"
+ },
+ "logObjectPrefix": {
+ "description": "A prefix for log object names.",
+ "type": "string"
+ }
+ },
+ "type": "object"
+ },
+ "metageneration": {
+ "description": "The metadata generation of this bucket.",
+ "format": "int64",
+ "type": "string"
+ },
+ "name": {
+ "annotations": {
+ "required": [
+ "storage.buckets.insert"
+ ]
+ },
+ "description": "The name of the bucket.",
+ "type": "string"
+ },
+ "owner": {
+ "description": "The owner of the bucket. This is always the project team's owner group.",
+ "properties": {
+ "entity": {
+ "description": "The entity, in the form project-owner-projectId.",
+ "type": "string"
+ },
+ "entityId": {
+ "description": "The ID for the entity.",
+ "type": "string"
+ }
+ },
+ "type": "object"
+ },
+ "projectNumber": {
+ "description": "The project number of the project the bucket belongs to.",
+ "format": "uint64",
+ "type": "string"
+ },
+ "retentionPolicy": {
+ "description": "The bucket's retention policy. The retention policy enforces a minimum retention time for all objects contained in the bucket, based on their creation time. Any attempt to overwrite or delete objects younger than the retention period will result in a PERMISSION_DENIED error. An unlocked retention policy can be modified or removed from the bucket via a storage.buckets.update operation. A locked retention policy cannot be removed or shortened in duration for the lifetime of the bucket. Attempting to remove or decrease period of a locked retention policy will result in a PERMISSION_DENIED error.",
+ "properties": {
+ "effectiveTime": {
+ "description": "Server-determined value that indicates the time from which policy was enforced and effective. This value is in RFC 3339 format.",
+ "format": "date-time",
+ "type": "string"
+ },
+ "isLocked": {
+ "description": "Once locked, an object retention policy cannot be modified.",
+ "type": "boolean"
+ },
+ "retentionPeriod": {
+ "description": "The duration in seconds that objects need to be retained. Retention duration must be greater than zero and less than 100 years. Note that enforcement of retention periods less than a day is not guaranteed. Such periods should only be used for testing purposes.",
+ "format": "int64",
+ "type": "string"
+ }
+ },
+ "type": "object"
+ },
+ "selfLink": {
+ "description": "The URI of this bucket.",
+ "type": "string"
+ },
+ "storageClass": {
+ "description": "The bucket's default storage class, used whenever no storageClass is specified for a newly-created object. This defines how objects in the bucket are stored and determines the SLA and the cost of storage. Values include MULTI_REGIONAL, REGIONAL, STANDARD, NEARLINE, COLDLINE, and DURABLE_REDUCED_AVAILABILITY. If this value is not specified when the bucket is created, it will default to STANDARD. For more information, see storage classes.",
+ "type": "string"
+ },
+ "timeCreated": {
+ "description": "The creation time of the bucket in RFC 3339 format.",
+ "format": "date-time",
+ "type": "string"
+ },
+ "updated": {
+ "description": "The modification time of the bucket in RFC 3339 format.",
+ "format": "date-time",
+ "type": "string"
+ },
+ "versioning": {
+ "description": "The bucket's versioning configuration.",
+ "properties": {
+ "enabled": {
+ "description": "While set to true, versioning is fully enabled for this bucket.",
+ "type": "boolean"
+ }
+ },
+ "type": "object"
+ },
+ "website": {
+ "description": "The bucket's website configuration, controlling how the service behaves when accessing bucket contents as a web site. See the Static Website Examples for more information.",
+ "properties": {
+ "mainPageSuffix": {
+ "description": "If the requested object path is missing, the service will ensure the path has a trailing '/', append this suffix, and attempt to retrieve the resulting object. This allows the creation of index.html objects to represent directory pages.",
+ "type": "string"
+ },
+ "notFoundPage": {
+ "description": "If the requested object path is missing, and any mainPageSuffix object is missing, if applicable, the service will return the named object from this bucket as the content for a 404 Not Found result.",
+ "type": "string"
+ }
+ },
+ "type": "object"
+ }
+ },
+ "type": "object"
+ },
+ "BucketAccessControl": {
+ "description": "An access-control entry.",
+ "id": "BucketAccessControl",
+ "properties": {
+ "bucket": {
+ "description": "The name of the bucket.",
+ "type": "string"
+ },
+ "domain": {
+ "description": "The domain associated with the entity, if any.",
+ "type": "string"
+ },
+ "email": {
+ "description": "The email address associated with the entity, if any.",
+ "type": "string"
+ },
+ "entity": {
+ "annotations": {
+ "required": [
+ "storage.bucketAccessControls.insert"
+ ]
+ },
+ "description": "The entity holding the permission, in one of the following forms: \n- user-userId \n- user-email \n- group-groupId \n- group-email \n- domain-domain \n- project-team-projectId \n- allUsers \n- allAuthenticatedUsers Examples: \n- The user liz@example.com would be user-liz@example.com. \n- The group example@googlegroups.com would be group-example@googlegroups.com. \n- To refer to all members of the Google Apps for Business domain example.com, the entity would be domain-example.com.",
+ "type": "string"
+ },
+ "entityId": {
+ "description": "The ID for the entity, if any.",
+ "type": "string"
+ },
+ "etag": {
+ "description": "HTTP 1.1 Entity tag for the access-control entry.",
+ "type": "string"
+ },
+ "id": {
+ "description": "The ID of the access-control entry.",
+ "type": "string"
+ },
+ "kind": {
+ "default": "storage#bucketAccessControl",
+ "description": "The kind of item this is. For bucket access control entries, this is always storage#bucketAccessControl.",
+ "type": "string"
+ },
+ "projectTeam": {
+ "description": "The project team associated with the entity, if any.",
+ "properties": {
+ "projectNumber": {
+ "description": "The project number.",
+ "type": "string"
+ },
+ "team": {
+ "description": "The team.",
+ "type": "string"
+ }
+ },
+ "type": "object"
+ },
+ "role": {
+ "annotations": {
+ "required": [
+ "storage.bucketAccessControls.insert"
+ ]
+ },
+ "description": "The access permission for the entity.",
+ "type": "string"
+ },
+ "selfLink": {
+ "description": "The link to this access-control entry.",
+ "type": "string"
+ }
+ },
+ "type": "object"
+ },
+ "BucketAccessControls": {
+ "description": "An access-control list.",
+ "id": "BucketAccessControls",
+ "properties": {
+ "items": {
+ "description": "The list of items.",
+ "items": {
+ "$ref": "BucketAccessControl"
+ },
+ "type": "array"
+ },
+ "kind": {
+ "default": "storage#bucketAccessControls",
+ "description": "The kind of item this is. For lists of bucket access control entries, this is always storage#bucketAccessControls.",
+ "type": "string"
+ }
+ },
+ "type": "object"
+ },
+ "Buckets": {
+ "description": "A list of buckets.",
+ "id": "Buckets",
+ "properties": {
+ "items": {
+ "description": "The list of items.",
+ "items": {
+ "$ref": "Bucket"
+ },
+ "type": "array"
+ },
+ "kind": {
+ "default": "storage#buckets",
+ "description": "The kind of item this is. For lists of buckets, this is always storage#buckets.",
+ "type": "string"
+ },
+ "nextPageToken": {
+ "description": "The continuation token, used to page through large result sets. Provide this value in a subsequent request to return the next page of results.",
+ "type": "string"
+ }
+ },
+ "type": "object"
+ },
+ "Channel": {
+ "description": "An notification channel used to watch for resource changes.",
+ "id": "Channel",
+ "properties": {
+ "address": {
+ "description": "The address where notifications are delivered for this channel.",
+ "type": "string"
+ },
+ "expiration": {
+ "description": "Date and time of notification channel expiration, expressed as a Unix timestamp, in milliseconds. Optional.",
+ "format": "int64",
+ "type": "string"
+ },
+ "id": {
+ "description": "A UUID or similar unique string that identifies this channel.",
+ "type": "string"
+ },
+ "kind": {
+ "default": "api#channel",
+ "description": "Identifies this as a notification channel used to watch for changes to a resource. Value: the fixed string \"api#channel\".",
+ "type": "string"
+ },
+ "params": {
+ "additionalProperties": {
+ "description": "Declares a new parameter by name.",
+ "type": "string"
+ },
+ "description": "Additional parameters controlling delivery channel behavior. Optional.",
+ "type": "object"
+ },
+ "payload": {
+ "description": "A Boolean value to indicate whether payload is wanted. Optional.",
+ "type": "boolean"
+ },
+ "resourceId": {
+ "description": "An opaque ID that identifies the resource being watched on this channel. Stable across different API versions.",
+ "type": "string"
+ },
+ "resourceUri": {
+ "description": "A version-specific identifier for the watched resource.",
+ "type": "string"
+ },
+ "token": {
+ "description": "An arbitrary string delivered to the target address with each notification delivered over this channel. Optional.",
+ "type": "string"
+ },
+ "type": {
+ "description": "The type of delivery mechanism used for this channel.",
+ "type": "string"
+ }
+ },
+ "type": "object"
+ },
+ "ComposeRequest": {
+ "description": "A Compose request.",
+ "id": "ComposeRequest",
+ "properties": {
+ "destination": {
+ "$ref": "Object",
+ "description": "Properties of the resulting object."
+ },
+ "kind": {
+ "default": "storage#composeRequest",
+ "description": "The kind of item this is.",
+ "type": "string"
+ },
+ "sourceObjects": {
+ "annotations": {
+ "required": [
+ "storage.objects.compose"
+ ]
+ },
+ "description": "The list of source objects that will be concatenated into a single object.",
+ "items": {
+ "properties": {
+ "generation": {
+ "description": "The generation of this object to use as the source.",
+ "format": "int64",
+ "type": "string"
+ },
+ "name": {
+ "annotations": {
+ "required": [
+ "storage.objects.compose"
+ ]
+ },
+ "description": "The source object's name. All source objects must reside in the same bucket.",
+ "type": "string"
+ },
+ "objectPreconditions": {
+ "description": "Conditions that must be met for this operation to execute.",
+ "properties": {
+ "ifGenerationMatch": {
+ "description": "Only perform the composition if the generation of the source object that would be used matches this value. If this value and a generation are both specified, they must be the same value or the call will fail.",
+ "format": "int64",
+ "type": "string"
+ }
+ },
+ "type": "object"
+ }
+ },
+ "type": "object"
+ },
+ "type": "array"
+ }
+ },
+ "type": "object"
+ },
+ "Notification": {
+ "description": "A subscription to receive Google PubSub notifications.",
+ "id": "Notification",
+ "properties": {
+ "custom_attributes": {
+ "additionalProperties": {
+ "type": "string"
+ },
+ "description": "An optional list of additional attributes to attach to each Cloud PubSub message published for this notification subscription.",
+ "type": "object"
+ },
+ "etag": {
+ "description": "HTTP 1.1 Entity tag for this subscription notification.",
+ "type": "string"
+ },
+ "event_types": {
+ "description": "If present, only send notifications about listed event types. If empty, sent notifications for all event types.",
+ "items": {
+ "type": "string"
+ },
+ "type": "array"
+ },
+ "id": {
+ "description": "The ID of the notification.",
+ "type": "string"
+ },
+ "kind": {
+ "default": "storage#notification",
+ "description": "The kind of item this is. For notifications, this is always storage#notification.",
+ "type": "string"
+ },
+ "object_name_prefix": {
+ "description": "If present, only apply this notification configuration to object names that begin with this prefix.",
+ "type": "string"
+ },
+ "payload_format": {
+ "annotations": {
+ "required": [
+ "storage.notifications.insert"
+ ]
+ },
+ "default": "JSON_API_V1",
+ "description": "The desired content of the Payload.",
+ "type": "string"
+ },
+ "selfLink": {
+ "description": "The canonical URL of this notification.",
+ "type": "string"
+ },
+ "topic": {
+ "annotations": {
+ "required": [
+ "storage.notifications.insert"
+ ]
+ },
+ "description": "The Cloud PubSub topic to which this subscription publishes. Formatted as: '//pubsub.googleapis.com/projects/{project-identifier}/topics/{my-topic}'",
+ "type": "string"
+ }
+ },
+ "type": "object"
+ },
+ "Notifications": {
+ "description": "A list of notification subscriptions.",
+ "id": "Notifications",
+ "properties": {
+ "items": {
+ "description": "The list of items.",
+ "items": {
+ "$ref": "Notification"
+ },
+ "type": "array"
+ },
+ "kind": {
+ "default": "storage#notifications",
+ "description": "The kind of item this is. For lists of notifications, this is always storage#notifications.",
+ "type": "string"
+ }
+ },
+ "type": "object"
+ },
+ "Object": {
+ "description": "An object.",
+ "id": "Object",
+ "properties": {
+ "acl": {
+ "annotations": {
+ "required": [
+ "storage.objects.update"
+ ]
+ },
+ "description": "Access controls on the object.",
+ "items": {
+ "$ref": "ObjectAccessControl"
+ },
+ "type": "array"
+ },
+ "bucket": {
+ "description": "The name of the bucket containing this object.",
+ "type": "string"
+ },
+ "cacheControl": {
+ "description": "Cache-Control directive for the object data. If omitted, and the object is accessible to all anonymous users, the default will be public, max-age=3600.",
+ "type": "string"
+ },
+ "componentCount": {
+ "description": "Number of underlying components that make up this object. Components are accumulated by compose operations.",
+ "format": "int32",
+ "type": "integer"
+ },
+ "contentDisposition": {
+ "description": "Content-Disposition of the object data.",
+ "type": "string"
+ },
+ "contentEncoding": {
+ "description": "Content-Encoding of the object data.",
+ "type": "string"
+ },
+ "contentLanguage": {
+ "description": "Content-Language of the object data.",
+ "type": "string"
+ },
+ "contentType": {
+ "description": "Content-Type of the object data. If an object is stored without a Content-Type, it is served as application/octet-stream.",
+ "type": "string"
+ },
+ "crc32c": {
+ "description": "CRC32c checksum, as described in RFC 4960, Appendix B; encoded using base64 in big-endian byte order. For more information about using the CRC32c checksum, see Hashes and ETags: Best Practices.",
+ "type": "string"
+ },
+ "customerEncryption": {
+ "description": "Metadata of customer-supplied encryption key, if the object is encrypted by such a key.",
+ "properties": {
+ "encryptionAlgorithm": {
+ "description": "The encryption algorithm.",
+ "type": "string"
+ },
+ "keySha256": {
+ "description": "SHA256 hash value of the encryption key.",
+ "type": "string"
+ }
+ },
+ "type": "object"
+ },
+ "etag": {
+ "description": "HTTP 1.1 Entity tag for the object.",
+ "type": "string"
+ },
+ "eventBasedHold": {
+ "description": "Whether an object is under event-based hold. Event-based hold is a way to retain objects until an event occurs, which is signified by the hold's release (i.e. this value is set to false). After being released (set to false), such objects will be subject to bucket-level retention (if any). One sample use case of this flag is for banks to hold loan documents for at least 3 years after loan is paid in full. Here, bucket-level retention is 3 years and the event is the loan being paid in full. In this example, these objects will be held intact for any number of years until the event has occurred (event-based hold on the object is released) and then 3 more years after that. That means retention duration of the objects begins from the moment event-based hold transitioned from true to false.",
+ "type": "boolean"
+ },
+ "generation": {
+ "description": "The content generation of this object. Used for object versioning.",
+ "format": "int64",
+ "type": "string"
+ },
+ "id": {
+ "description": "The ID of the object, including the bucket name, object name, and generation number.",
+ "type": "string"
+ },
+ "kind": {
+ "default": "storage#object",
+ "description": "The kind of item this is. For objects, this is always storage#object.",
+ "type": "string"
+ },
+ "kmsKeyName": {
+ "description": "Cloud KMS Key used to encrypt this object, if the object is encrypted by such a key.",
+ "type": "string"
+ },
+ "md5Hash": {
+ "description": "MD5 hash of the data; encoded using base64. For more information about using the MD5 hash, see Hashes and ETags: Best Practices.",
+ "type": "string"
+ },
+ "mediaLink": {
+ "description": "Media download link.",
+ "type": "string"
+ },
+ "metadata": {
+ "additionalProperties": {
+ "description": "An individual metadata entry.",
+ "type": "string"
+ },
+ "description": "User-provided metadata, in key/value pairs.",
+ "type": "object"
+ },
+ "metageneration": {
+ "description": "The version of the metadata for this object at this generation. Used for preconditions and for detecting changes in metadata. A metageneration number is only meaningful in the context of a particular generation of a particular object.",
+ "format": "int64",
+ "type": "string"
+ },
+ "name": {
+ "description": "The name of the object. Required if not specified by URL parameter.",
+ "type": "string"
+ },
+ "owner": {
+ "description": "The owner of the object. This will always be the uploader of the object.",
+ "properties": {
+ "entity": {
+ "description": "The entity, in the form user-userId.",
+ "type": "string"
+ },
+ "entityId": {
+ "description": "The ID for the entity.",
+ "type": "string"
+ }
+ },
+ "type": "object"
+ },
+ "retentionExpirationTime": {
+ "description": "A server-determined value that specifies the earliest time that the object's retention period expires. This value is in RFC 3339 format. Note 1: This field is not provided for objects with an active event-based hold, since retention expiration is unknown until the hold is removed. Note 2: This value can be provided even when temporary hold is set (so that the user can reason about policy without having to first unset the temporary hold).",
+ "format": "date-time",
+ "type": "string"
+ },
+ "selfLink": {
+ "description": "The link to this object.",
+ "type": "string"
+ },
+ "size": {
+ "description": "Content-Length of the data in bytes.",
+ "format": "uint64",
+ "type": "string"
+ },
+ "storageClass": {
+ "description": "Storage class of the object.",
+ "type": "string"
+ },
+ "temporaryHold": {
+ "description": "Whether an object is under temporary hold. While this flag is set to true, the object is protected against deletion and overwrites. A common use case of this flag is regulatory investigations where objects need to be retained while the investigation is ongoing. Note that unlike event-based hold, temporary hold does not impact retention expiration time of an object.",
+ "type": "boolean"
+ },
+ "timeCreated": {
+ "description": "The creation time of the object in RFC 3339 format.",
+ "format": "date-time",
+ "type": "string"
+ },
+ "timeDeleted": {
+ "description": "The deletion time of the object in RFC 3339 format. Will be returned if and only if this version of the object has been deleted.",
+ "format": "date-time",
+ "type": "string"
+ },
+ "timeStorageClassUpdated": {
+ "description": "The time at which the object's storage class was last changed. When the object is initially created, it will be set to timeCreated.",
+ "format": "date-time",
+ "type": "string"
+ },
+ "updated": {
+ "description": "The modification time of the object metadata in RFC 3339 format.",
+ "format": "date-time",
+ "type": "string"
+ }
+ },
+ "type": "object"
+ },
+ "ObjectAccessControl": {
+ "description": "An access-control entry.",
+ "id": "ObjectAccessControl",
+ "properties": {
+ "bucket": {
+ "description": "The name of the bucket.",
+ "type": "string"
+ },
+ "domain": {
+ "description": "The domain associated with the entity, if any.",
+ "type": "string"
+ },
+ "email": {
+ "description": "The email address associated with the entity, if any.",
+ "type": "string"
+ },
+ "entity": {
+ "annotations": {
+ "required": [
+ "storage.defaultObjectAccessControls.insert",
+ "storage.objectAccessControls.insert"
+ ]
+ },
+ "description": "The entity holding the permission, in one of the following forms: \n- user-userId \n- user-email \n- group-groupId \n- group-email \n- domain-domain \n- project-team-projectId \n- allUsers \n- allAuthenticatedUsers Examples: \n- The user liz@example.com would be user-liz@example.com. \n- The group example@googlegroups.com would be group-example@googlegroups.com. \n- To refer to all members of the Google Apps for Business domain example.com, the entity would be domain-example.com.",
+ "type": "string"
+ },
+ "entityId": {
+ "description": "The ID for the entity, if any.",
+ "type": "string"
+ },
+ "etag": {
+ "description": "HTTP 1.1 Entity tag for the access-control entry.",
+ "type": "string"
+ },
+ "generation": {
+ "description": "The content generation of the object, if applied to an object.",
+ "format": "int64",
+ "type": "string"
+ },
+ "id": {
+ "description": "The ID of the access-control entry.",
+ "type": "string"
+ },
+ "kind": {
+ "default": "storage#objectAccessControl",
+ "description": "The kind of item this is. For object access control entries, this is always storage#objectAccessControl.",
+ "type": "string"
+ },
+ "object": {
+ "description": "The name of the object, if applied to an object.",
+ "type": "string"
+ },
+ "projectTeam": {
+ "description": "The project team associated with the entity, if any.",
+ "properties": {
+ "projectNumber": {
+ "description": "The project number.",
+ "type": "string"
+ },
+ "team": {
+ "description": "The team.",
+ "type": "string"
+ }
+ },
+ "type": "object"
+ },
+ "role": {
+ "annotations": {
+ "required": [
+ "storage.defaultObjectAccessControls.insert",
+ "storage.objectAccessControls.insert"
+ ]
+ },
+ "description": "The access permission for the entity.",
+ "type": "string"
+ },
+ "selfLink": {
+ "description": "The link to this access-control entry.",
+ "type": "string"
+ }
+ },
+ "type": "object"
+ },
+ "ObjectAccessControls": {
+ "description": "An access-control list.",
+ "id": "ObjectAccessControls",
+ "properties": {
+ "items": {
+ "description": "The list of items.",
+ "items": {
+ "$ref": "ObjectAccessControl"
+ },
+ "type": "array"
+ },
+ "kind": {
+ "default": "storage#objectAccessControls",
+ "description": "The kind of item this is. For lists of object access control entries, this is always storage#objectAccessControls.",
+ "type": "string"
+ }
+ },
+ "type": "object"
+ },
+ "Objects": {
+ "description": "A list of objects.",
+ "id": "Objects",
+ "properties": {
+ "items": {
+ "description": "The list of items.",
+ "items": {
+ "$ref": "Object"
+ },
+ "type": "array"
+ },
+ "kind": {
+ "default": "storage#objects",
+ "description": "The kind of item this is. For lists of objects, this is always storage#objects.",
+ "type": "string"
+ },
+ "nextPageToken": {
+ "description": "The continuation token, used to page through large result sets. Provide this value in a subsequent request to return the next page of results.",
+ "type": "string"
+ },
+ "prefixes": {
+ "description": "The list of prefixes of objects matching-but-not-listed up to and including the requested delimiter.",
+ "items": {
+ "type": "string"
+ },
+ "type": "array"
+ }
+ },
+ "type": "object"
+ },
+ "Policy": {
+ "description": "A bucket/object IAM policy.",
+ "id": "Policy",
+ "properties": {
+ "bindings": {
+ "annotations": {
+ "required": [
+ "storage.buckets.setIamPolicy",
+ "storage.objects.setIamPolicy"
+ ]
+ },
+ "description": "An association between a role, which comes with a set of permissions, and members who may assume that role.",
+ "items": {
+ "properties": {
+ "condition": {
+ "type": "any"
+ },
+ "members": {
+ "annotations": {
+ "required": [
+ "storage.buckets.setIamPolicy",
+ "storage.objects.setIamPolicy"
+ ]
+ },
+ "description": "A collection of identifiers for members who may assume the provided role. Recognized identifiers are as follows: \n- allUsers — A special identifier that represents anyone on the internet; with or without a Google account. \n- allAuthenticatedUsers — A special identifier that represents anyone who is authenticated with a Google account or a service account. \n- user:emailid — An email address that represents a specific account. For example, user:alice@gmail.com or user:joe@example.com. \n- serviceAccount:emailid — An email address that represents a service account. For example, serviceAccount:my-other-app@appspot.gserviceaccount.com . \n- group:emailid — An email address that represents a Google group. For example, group:admins@example.com. \n- domain:domain — A Google Apps domain name that represents all the users of that domain. For example, domain:google.com or domain:example.com. \n- projectOwner:projectid — Owners of the given project. For example, projectOwner:my-example-project \n- projectEditor:projectid — Editors of the given project. For example, projectEditor:my-example-project \n- projectViewer:projectid — Viewers of the given project. For example, projectViewer:my-example-project",
+ "items": {
+ "type": "string"
+ },
+ "type": "array"
+ },
+ "role": {
+ "annotations": {
+ "required": [
+ "storage.buckets.setIamPolicy",
+ "storage.objects.setIamPolicy"
+ ]
+ },
+ "description": "The role to which members belong. Two types of roles are supported: new IAM roles, which grant permissions that do not map directly to those provided by ACLs, and legacy IAM roles, which do map directly to ACL permissions. All roles are of the format roles/storage.specificRole.\nThe new IAM roles are: \n- roles/storage.admin — Full control of Google Cloud Storage resources. \n- roles/storage.objectViewer — Read-Only access to Google Cloud Storage objects. \n- roles/storage.objectCreator — Access to create objects in Google Cloud Storage. \n- roles/storage.objectAdmin — Full control of Google Cloud Storage objects. The legacy IAM roles are: \n- roles/storage.legacyObjectReader — Read-only access to objects without listing. Equivalent to an ACL entry on an object with the READER role. \n- roles/storage.legacyObjectOwner — Read/write access to existing objects without listing. Equivalent to an ACL entry on an object with the OWNER role. \n- roles/storage.legacyBucketReader — Read access to buckets with object listing. Equivalent to an ACL entry on a bucket with the READER role. \n- roles/storage.legacyBucketWriter — Read access to buckets with object listing/creation/deletion. Equivalent to an ACL entry on a bucket with the WRITER role. \n- roles/storage.legacyBucketOwner — Read and write access to existing buckets with object listing/creation/deletion. Equivalent to an ACL entry on a bucket with the OWNER role.",
+ "type": "string"
+ }
+ },
+ "type": "object"
+ },
+ "type": "array"
+ },
+ "etag": {
+ "description": "HTTP 1.1 Entity tag for the policy.",
+ "format": "byte",
+ "type": "string"
+ },
+ "kind": {
+ "default": "storage#policy",
+ "description": "The kind of item this is. For policies, this is always storage#policy. This field is ignored on input.",
+ "type": "string"
+ },
+ "resourceId": {
+ "description": "The ID of the resource to which this policy belongs. Will be of the form projects/_/buckets/bucket for buckets, and projects/_/buckets/bucket/objects/object for objects. A specific generation may be specified by appending #generationNumber to the end of the object name, e.g. projects/_/buckets/my-bucket/objects/data.txt#17. The current generation can be denoted with #0. This field is ignored on input.",
+ "type": "string"
+ }
+ },
+ "type": "object"
+ },
+ "RewriteResponse": {
+ "description": "A rewrite response.",
+ "id": "RewriteResponse",
+ "properties": {
+ "done": {
+ "description": "true if the copy is finished; otherwise, false if the copy is in progress. This property is always present in the response.",
+ "type": "boolean"
+ },
+ "kind": {
+ "default": "storage#rewriteResponse",
+ "description": "The kind of item this is.",
+ "type": "string"
+ },
+ "objectSize": {
+ "description": "The total size of the object being copied in bytes. This property is always present in the response.",
+ "format": "int64",
+ "type": "string"
+ },
+ "resource": {
+ "$ref": "Object",
+ "description": "A resource containing the metadata for the copied-to object. This property is present in the response only when copying completes."
+ },
+ "rewriteToken": {
+ "description": "A token to use in subsequent requests to continue copying data. This token is present in the response only when there is more data to copy.",
+ "type": "string"
+ },
+ "totalBytesRewritten": {
+ "description": "The total bytes written so far, which can be used to provide a waiting user with a progress indicator. This property is always present in the response.",
+ "format": "int64",
+ "type": "string"
+ }
+ },
+ "type": "object"
+ },
+ "ServiceAccount": {
+ "description": "A subscription to receive Google PubSub notifications.",
+ "id": "ServiceAccount",
+ "properties": {
+ "email_address": {
+ "description": "The ID of the notification.",
+ "type": "string"
+ },
+ "kind": {
+ "default": "storage#serviceAccount",
+ "description": "The kind of item this is. For notifications, this is always storage#notification.",
+ "type": "string"
+ }
+ },
+ "type": "object"
+ },
+ "TestIamPermissionsResponse": {
+ "description": "A storage.(buckets|objects).testIamPermissions response.",
+ "id": "TestIamPermissionsResponse",
+ "properties": {
+ "kind": {
+ "default": "storage#testIamPermissionsResponse",
+ "description": "The kind of item this is.",
+ "type": "string"
+ },
+ "permissions": {
+ "description": "The permissions held by the caller. Permissions are always of the format storage.resource.capability, where resource is one of buckets or objects. The supported permissions are as follows: \n- storage.buckets.delete — Delete bucket. \n- storage.buckets.get — Read bucket metadata. \n- storage.buckets.getIamPolicy — Read bucket IAM policy. \n- storage.buckets.create — Create bucket. \n- storage.buckets.list — List buckets. \n- storage.buckets.setIamPolicy — Update bucket IAM policy. \n- storage.buckets.update — Update bucket metadata. \n- storage.objects.delete — Delete object. \n- storage.objects.get — Read object data and metadata. \n- storage.objects.getIamPolicy — Read object IAM policy. \n- storage.objects.create — Create object. \n- storage.objects.list — List objects. \n- storage.objects.setIamPolicy — Update object IAM policy. \n- storage.objects.update — Update object metadata.",
+ "items": {
+ "type": "string"
+ },
+ "type": "array"
+ }
+ },
+ "type": "object"
+ }
+ },
+ "servicePath": "storage/v1/",
+ "title": "Cloud Storage JSON API",
+ "version": "v1"
+} \ No newline at end of file
diff --git a/vendor/google.golang.org/api/storage/v1/storage-gen.go b/vendor/google.golang.org/api/storage/v1/storage-gen.go
new file mode 100644
index 000000000..606686f87
--- /dev/null
+++ b/vendor/google.golang.org/api/storage/v1/storage-gen.go
@@ -0,0 +1,11472 @@
+// Copyright 2018 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Code generated file. DO NOT EDIT.
+
+// Package storage provides access to the Cloud Storage JSON API.
+//
+// This package is DEPRECATED. Use package cloud.google.com/go/storage instead.
+//
+// See https://developers.google.com/storage/docs/json_api/
+//
+// Usage example:
+//
+// import "google.golang.org/api/storage/v1"
+// ...
+// storageService, err := storage.New(oauthHttpClient)
+package storage // import "google.golang.org/api/storage/v1"
+
+import (
+ "bytes"
+ "context"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "io"
+ "net/http"
+ "net/url"
+ "strconv"
+ "strings"
+
+ gensupport "google.golang.org/api/gensupport"
+ googleapi "google.golang.org/api/googleapi"
+)
+
+// Always reference these packages, just in case the auto-generated code
+// below doesn't.
+var _ = bytes.NewBuffer
+var _ = strconv.Itoa
+var _ = fmt.Sprintf
+var _ = json.NewDecoder
+var _ = io.Copy
+var _ = url.Parse
+var _ = gensupport.MarshalJSON
+var _ = googleapi.Version
+var _ = errors.New
+var _ = strings.Replace
+var _ = context.Canceled
+
+const apiId = "storage:v1"
+const apiName = "storage"
+const apiVersion = "v1"
+const basePath = "https://www.googleapis.com/storage/v1/"
+
+// OAuth2 scopes used by this API.
+const (
+ // View and manage your data across Google Cloud Platform services
+ CloudPlatformScope = "https://www.googleapis.com/auth/cloud-platform"
+
+ // View your data across Google Cloud Platform services
+ CloudPlatformReadOnlyScope = "https://www.googleapis.com/auth/cloud-platform.read-only"
+
+ // Manage your data and permissions in Google Cloud Storage
+ DevstorageFullControlScope = "https://www.googleapis.com/auth/devstorage.full_control"
+
+ // View your data in Google Cloud Storage
+ DevstorageReadOnlyScope = "https://www.googleapis.com/auth/devstorage.read_only"
+
+ // Manage your data in Google Cloud Storage
+ DevstorageReadWriteScope = "https://www.googleapis.com/auth/devstorage.read_write"
+)
+
+func New(client *http.Client) (*Service, error) {
+ if client == nil {
+ return nil, errors.New("client is nil")
+ }
+ s := &Service{client: client, BasePath: basePath}
+ s.BucketAccessControls = NewBucketAccessControlsService(s)
+ s.Buckets = NewBucketsService(s)
+ s.Channels = NewChannelsService(s)
+ s.DefaultObjectAccessControls = NewDefaultObjectAccessControlsService(s)
+ s.Notifications = NewNotificationsService(s)
+ s.ObjectAccessControls = NewObjectAccessControlsService(s)
+ s.Objects = NewObjectsService(s)
+ s.Projects = NewProjectsService(s)
+ return s, nil
+}
+
+type Service struct {
+ client *http.Client
+ BasePath string // API endpoint base URL
+ UserAgent string // optional additional User-Agent fragment
+
+ BucketAccessControls *BucketAccessControlsService
+
+ Buckets *BucketsService
+
+ Channels *ChannelsService
+
+ DefaultObjectAccessControls *DefaultObjectAccessControlsService
+
+ Notifications *NotificationsService
+
+ ObjectAccessControls *ObjectAccessControlsService
+
+ Objects *ObjectsService
+
+ Projects *ProjectsService
+}
+
+func (s *Service) userAgent() string {
+ if s.UserAgent == "" {
+ return googleapi.UserAgent
+ }
+ return googleapi.UserAgent + " " + s.UserAgent
+}
+
+func NewBucketAccessControlsService(s *Service) *BucketAccessControlsService {
+ rs := &BucketAccessControlsService{s: s}
+ return rs
+}
+
+type BucketAccessControlsService struct {
+ s *Service
+}
+
+func NewBucketsService(s *Service) *BucketsService {
+ rs := &BucketsService{s: s}
+ return rs
+}
+
+type BucketsService struct {
+ s *Service
+}
+
+func NewChannelsService(s *Service) *ChannelsService {
+ rs := &ChannelsService{s: s}
+ return rs
+}
+
+type ChannelsService struct {
+ s *Service
+}
+
+func NewDefaultObjectAccessControlsService(s *Service) *DefaultObjectAccessControlsService {
+ rs := &DefaultObjectAccessControlsService{s: s}
+ return rs
+}
+
+type DefaultObjectAccessControlsService struct {
+ s *Service
+}
+
+func NewNotificationsService(s *Service) *NotificationsService {
+ rs := &NotificationsService{s: s}
+ return rs
+}
+
+type NotificationsService struct {
+ s *Service
+}
+
+func NewObjectAccessControlsService(s *Service) *ObjectAccessControlsService {
+ rs := &ObjectAccessControlsService{s: s}
+ return rs
+}
+
+type ObjectAccessControlsService struct {
+ s *Service
+}
+
+func NewObjectsService(s *Service) *ObjectsService {
+ rs := &ObjectsService{s: s}
+ return rs
+}
+
+type ObjectsService struct {
+ s *Service
+}
+
+func NewProjectsService(s *Service) *ProjectsService {
+ rs := &ProjectsService{s: s}
+ rs.ServiceAccount = NewProjectsServiceAccountService(s)
+ return rs
+}
+
+type ProjectsService struct {
+ s *Service
+
+ ServiceAccount *ProjectsServiceAccountService
+}
+
+func NewProjectsServiceAccountService(s *Service) *ProjectsServiceAccountService {
+ rs := &ProjectsServiceAccountService{s: s}
+ return rs
+}
+
+type ProjectsServiceAccountService struct {
+ s *Service
+}
+
+// Bucket: A bucket.
+type Bucket struct {
+ // Acl: Access controls on the bucket.
+ Acl []*BucketAccessControl `json:"acl,omitempty"`
+
+ // Billing: The bucket's billing configuration.
+ Billing *BucketBilling `json:"billing,omitempty"`
+
+ // Cors: The bucket's Cross-Origin Resource Sharing (CORS)
+ // configuration.
+ Cors []*BucketCors `json:"cors,omitempty"`
+
+ // DefaultEventBasedHold: The default value for event-based hold on
+ // newly created objects in this bucket. Event-based hold is a way to
+ // retain objects indefinitely until an event occurs, signified by the
+ // hold's release. After being released, such objects will be subject to
+ // bucket-level retention (if any). One sample use case of this flag is
+ // for banks to hold loan documents for at least 3 years after loan is
+ // paid in full. Here, bucket-level retention is 3 years and the event
+ // is loan being paid in full. In this example, these objects will be
+ // held intact for any number of years until the event has occurred
+ // (event-based hold on the object is released) and then 3 more years
+ // after that. That means retention duration of the objects begins from
+ // the moment event-based hold transitioned from true to false. Objects
+ // under event-based hold cannot be deleted, overwritten or archived
+ // until the hold is removed.
+ DefaultEventBasedHold bool `json:"defaultEventBasedHold,omitempty"`
+
+ // DefaultObjectAcl: Default access controls to apply to new objects
+ // when no ACL is provided.
+ DefaultObjectAcl []*ObjectAccessControl `json:"defaultObjectAcl,omitempty"`
+
+ // Encryption: Encryption configuration for a bucket.
+ Encryption *BucketEncryption `json:"encryption,omitempty"`
+
+ // Etag: HTTP 1.1 Entity tag for the bucket.
+ Etag string `json:"etag,omitempty"`
+
+ // IamConfiguration: The bucket's IAM configuration.
+ IamConfiguration *BucketIamConfiguration `json:"iamConfiguration,omitempty"`
+
+ // Id: The ID of the bucket. For buckets, the id and name properties are
+ // the same.
+ Id string `json:"id,omitempty"`
+
+ // Kind: The kind of item this is. For buckets, this is always
+ // storage#bucket.
+ Kind string `json:"kind,omitempty"`
+
+ // Labels: User-provided labels, in key/value pairs.
+ Labels map[string]string `json:"labels,omitempty"`
+
+ // Lifecycle: The bucket's lifecycle configuration. See lifecycle
+ // management for more information.
+ Lifecycle *BucketLifecycle `json:"lifecycle,omitempty"`
+
+ // Location: The location of the bucket. Object data for objects in the
+ // bucket resides in physical storage within this region. Defaults to
+ // US. See the developer's guide for the authoritative list.
+ Location string `json:"location,omitempty"`
+
+ // Logging: The bucket's logging configuration, which defines the
+ // destination bucket and optional name prefix for the current bucket's
+ // logs.
+ Logging *BucketLogging `json:"logging,omitempty"`
+
+ // Metageneration: The metadata generation of this bucket.
+ Metageneration int64 `json:"metageneration,omitempty,string"`
+
+ // Name: The name of the bucket.
+ Name string `json:"name,omitempty"`
+
+ // Owner: The owner of the bucket. This is always the project team's
+ // owner group.
+ Owner *BucketOwner `json:"owner,omitempty"`
+
+ // ProjectNumber: The project number of the project the bucket belongs
+ // to.
+ ProjectNumber uint64 `json:"projectNumber,omitempty,string"`
+
+ // RetentionPolicy: The bucket's retention policy. The retention policy
+ // enforces a minimum retention time for all objects contained in the
+ // bucket, based on their creation time. Any attempt to overwrite or
+ // delete objects younger than the retention period will result in a
+ // PERMISSION_DENIED error. An unlocked retention policy can be modified
+ // or removed from the bucket via a storage.buckets.update operation. A
+ // locked retention policy cannot be removed or shortened in duration
+ // for the lifetime of the bucket. Attempting to remove or decrease
+ // period of a locked retention policy will result in a
+ // PERMISSION_DENIED error.
+ RetentionPolicy *BucketRetentionPolicy `json:"retentionPolicy,omitempty"`
+
+ // SelfLink: The URI of this bucket.
+ SelfLink string `json:"selfLink,omitempty"`
+
+ // StorageClass: The bucket's default storage class, used whenever no
+ // storageClass is specified for a newly-created object. This defines
+ // how objects in the bucket are stored and determines the SLA and the
+ // cost of storage. Values include MULTI_REGIONAL, REGIONAL, STANDARD,
+ // NEARLINE, COLDLINE, and DURABLE_REDUCED_AVAILABILITY. If this value
+ // is not specified when the bucket is created, it will default to
+ // STANDARD. For more information, see storage classes.
+ StorageClass string `json:"storageClass,omitempty"`
+
+ // TimeCreated: The creation time of the bucket in RFC 3339 format.
+ TimeCreated string `json:"timeCreated,omitempty"`
+
+ // Updated: The modification time of the bucket in RFC 3339 format.
+ Updated string `json:"updated,omitempty"`
+
+ // Versioning: The bucket's versioning configuration.
+ Versioning *BucketVersioning `json:"versioning,omitempty"`
+
+ // Website: The bucket's website configuration, controlling how the
+ // service behaves when accessing bucket contents as a web site. See the
+ // Static Website Examples for more information.
+ Website *BucketWebsite `json:"website,omitempty"`
+
+ // ServerResponse contains the HTTP response code and headers from the
+ // server.
+ googleapi.ServerResponse `json:"-"`
+
+ // ForceSendFields is a list of field names (e.g. "Acl") to
+ // unconditionally include in API requests. By default, fields with
+ // empty values are omitted from API requests. However, any non-pointer,
+ // non-interface field appearing in ForceSendFields will be sent to the
+ // server regardless of whether the field is empty or not. This may be
+ // used to include empty fields in Patch requests.
+ ForceSendFields []string `json:"-"`
+
+ // NullFields is a list of field names (e.g. "Acl") to include in API
+ // requests with the JSON null value. By default, fields with empty
+ // values are omitted from API requests. However, any field with an
+ // empty value appearing in NullFields will be sent to the server as
+ // null. It is an error if a field in this list has a non-empty value.
+ // This may be used to include null fields in Patch requests.
+ NullFields []string `json:"-"`
+}
+
+func (s *Bucket) MarshalJSON() ([]byte, error) {
+ type NoMethod Bucket
+ raw := NoMethod(*s)
+ return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
+}
+
+// BucketBilling: The bucket's billing configuration.
+type BucketBilling struct {
+ // RequesterPays: When set to true, Requester Pays is enabled for this
+ // bucket.
+ RequesterPays bool `json:"requesterPays,omitempty"`
+
+ // ForceSendFields is a list of field names (e.g. "RequesterPays") to
+ // unconditionally include in API requests. By default, fields with
+ // empty values are omitted from API requests. However, any non-pointer,
+ // non-interface field appearing in ForceSendFields will be sent to the
+ // server regardless of whether the field is empty or not. This may be
+ // used to include empty fields in Patch requests.
+ ForceSendFields []string `json:"-"`
+
+ // NullFields is a list of field names (e.g. "RequesterPays") to include
+ // in API requests with the JSON null value. By default, fields with
+ // empty values are omitted from API requests. However, any field with
+ // an empty value appearing in NullFields will be sent to the server as
+ // null. It is an error if a field in this list has a non-empty value.
+ // This may be used to include null fields in Patch requests.
+ NullFields []string `json:"-"`
+}
+
+func (s *BucketBilling) MarshalJSON() ([]byte, error) {
+ type NoMethod BucketBilling
+ raw := NoMethod(*s)
+ return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
+}
+
+type BucketCors struct {
+ // MaxAgeSeconds: The value, in seconds, to return in the
+ // Access-Control-Max-Age header used in preflight responses.
+ MaxAgeSeconds int64 `json:"maxAgeSeconds,omitempty"`
+
+ // Method: The list of HTTP methods on which to include CORS response
+ // headers, (GET, OPTIONS, POST, etc) Note: "*" is permitted in the list
+ // of methods, and means "any method".
+ Method []string `json:"method,omitempty"`
+
+ // Origin: The list of Origins eligible to receive CORS response
+ // headers. Note: "*" is permitted in the list of origins, and means
+ // "any Origin".
+ Origin []string `json:"origin,omitempty"`
+
+ // ResponseHeader: The list of HTTP headers other than the simple
+ // response headers to give permission for the user-agent to share
+ // across domains.
+ ResponseHeader []string `json:"responseHeader,omitempty"`
+
+ // ForceSendFields is a list of field names (e.g. "MaxAgeSeconds") to
+ // unconditionally include in API requests. By default, fields with
+ // empty values are omitted from API requests. However, any non-pointer,
+ // non-interface field appearing in ForceSendFields will be sent to the
+ // server regardless of whether the field is empty or not. This may be
+ // used to include empty fields in Patch requests.
+ ForceSendFields []string `json:"-"`
+
+ // NullFields is a list of field names (e.g. "MaxAgeSeconds") to include
+ // in API requests with the JSON null value. By default, fields with
+ // empty values are omitted from API requests. However, any field with
+ // an empty value appearing in NullFields will be sent to the server as
+ // null. It is an error if a field in this list has a non-empty value.
+ // This may be used to include null fields in Patch requests.
+ NullFields []string `json:"-"`
+}
+
+func (s *BucketCors) MarshalJSON() ([]byte, error) {
+ type NoMethod BucketCors
+ raw := NoMethod(*s)
+ return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
+}
+
+// BucketEncryption: Encryption configuration for a bucket.
+type BucketEncryption struct {
+ // DefaultKmsKeyName: A Cloud KMS key that will be used to encrypt
+ // objects inserted into this bucket, if no encryption method is
+ // specified.
+ DefaultKmsKeyName string `json:"defaultKmsKeyName,omitempty"`
+
+ // ForceSendFields is a list of field names (e.g. "DefaultKmsKeyName")
+ // to unconditionally include in API requests. By default, fields with
+ // empty values are omitted from API requests. However, any non-pointer,
+ // non-interface field appearing in ForceSendFields will be sent to the
+ // server regardless of whether the field is empty or not. This may be
+ // used to include empty fields in Patch requests.
+ ForceSendFields []string `json:"-"`
+
+ // NullFields is a list of field names (e.g. "DefaultKmsKeyName") to
+ // include in API requests with the JSON null value. By default, fields
+ // with empty values are omitted from API requests. However, any field
+ // with an empty value appearing in NullFields will be sent to the
+ // server as null. It is an error if a field in this list has a
+ // non-empty value. This may be used to include null fields in Patch
+ // requests.
+ NullFields []string `json:"-"`
+}
+
+func (s *BucketEncryption) MarshalJSON() ([]byte, error) {
+ type NoMethod BucketEncryption
+ raw := NoMethod(*s)
+ return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
+}
+
+// BucketIamConfiguration: The bucket's IAM configuration.
+type BucketIamConfiguration struct {
+ BucketPolicyOnly *BucketIamConfigurationBucketPolicyOnly `json:"bucketPolicyOnly,omitempty"`
+
+ // ForceSendFields is a list of field names (e.g. "BucketPolicyOnly") to
+ // unconditionally include in API requests. By default, fields with
+ // empty values are omitted from API requests. However, any non-pointer,
+ // non-interface field appearing in ForceSendFields will be sent to the
+ // server regardless of whether the field is empty or not. This may be
+ // used to include empty fields in Patch requests.
+ ForceSendFields []string `json:"-"`
+
+ // NullFields is a list of field names (e.g. "BucketPolicyOnly") to
+ // include in API requests with the JSON null value. By default, fields
+ // with empty values are omitted from API requests. However, any field
+ // with an empty value appearing in NullFields will be sent to the
+ // server as null. It is an error if a field in this list has a
+ // non-empty value. This may be used to include null fields in Patch
+ // requests.
+ NullFields []string `json:"-"`
+}
+
+func (s *BucketIamConfiguration) MarshalJSON() ([]byte, error) {
+ type NoMethod BucketIamConfiguration
+ raw := NoMethod(*s)
+ return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
+}
+
+type BucketIamConfigurationBucketPolicyOnly struct {
+ // Enabled: If set, access checks only use bucket-level IAM policies or
+ // above.
+ Enabled bool `json:"enabled,omitempty"`
+
+ // LockedTime: The deadline time for changing
+ // iamConfiguration.bucketPolicyOnly.enabled from true to false in RFC
+ // 3339 format. iamConfiguration.bucketPolicyOnly.enabled may be changed
+ // from true to false until the locked time, after which the field is
+ // immutable.
+ LockedTime string `json:"lockedTime,omitempty"`
+
+ // ForceSendFields is a list of field names (e.g. "Enabled") to
+ // unconditionally include in API requests. By default, fields with
+ // empty values are omitted from API requests. However, any non-pointer,
+ // non-interface field appearing in ForceSendFields will be sent to the
+ // server regardless of whether the field is empty or not. This may be
+ // used to include empty fields in Patch requests.
+ ForceSendFields []string `json:"-"`
+
+ // NullFields is a list of field names (e.g. "Enabled") to include in
+ // API requests with the JSON null value. By default, fields with empty
+ // values are omitted from API requests. However, any field with an
+ // empty value appearing in NullFields will be sent to the server as
+ // null. It is an error if a field in this list has a non-empty value.
+ // This may be used to include null fields in Patch requests.
+ NullFields []string `json:"-"`
+}
+
+func (s *BucketIamConfigurationBucketPolicyOnly) MarshalJSON() ([]byte, error) {
+ type NoMethod BucketIamConfigurationBucketPolicyOnly
+ raw := NoMethod(*s)
+ return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
+}
+
+// BucketLifecycle: The bucket's lifecycle configuration. See lifecycle
+// management for more information.
+type BucketLifecycle struct {
+ // Rule: A lifecycle management rule, which is made of an action to take
+ // and the condition(s) under which the action will be taken.
+ Rule []*BucketLifecycleRule `json:"rule,omitempty"`
+
+ // ForceSendFields is a list of field names (e.g. "Rule") to
+ // unconditionally include in API requests. By default, fields with
+ // empty values are omitted from API requests. However, any non-pointer,
+ // non-interface field appearing in ForceSendFields will be sent to the
+ // server regardless of whether the field is empty or not. This may be
+ // used to include empty fields in Patch requests.
+ ForceSendFields []string `json:"-"`
+
+ // NullFields is a list of field names (e.g. "Rule") to include in API
+ // requests with the JSON null value. By default, fields with empty
+ // values are omitted from API requests. However, any field with an
+ // empty value appearing in NullFields will be sent to the server as
+ // null. It is an error if a field in this list has a non-empty value.
+ // This may be used to include null fields in Patch requests.
+ NullFields []string `json:"-"`
+}
+
+func (s *BucketLifecycle) MarshalJSON() ([]byte, error) {
+ type NoMethod BucketLifecycle
+ raw := NoMethod(*s)
+ return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
+}
+
+type BucketLifecycleRule struct {
+ // Action: The action to take.
+ Action *BucketLifecycleRuleAction `json:"action,omitempty"`
+
+ // Condition: The condition(s) under which the action will be taken.
+ Condition *BucketLifecycleRuleCondition `json:"condition,omitempty"`
+
+ // ForceSendFields is a list of field names (e.g. "Action") to
+ // unconditionally include in API requests. By default, fields with
+ // empty values are omitted from API requests. However, any non-pointer,
+ // non-interface field appearing in ForceSendFields will be sent to the
+ // server regardless of whether the field is empty or not. This may be
+ // used to include empty fields in Patch requests.
+ ForceSendFields []string `json:"-"`
+
+ // NullFields is a list of field names (e.g. "Action") to include in API
+ // requests with the JSON null value. By default, fields with empty
+ // values are omitted from API requests. However, any field with an
+ // empty value appearing in NullFields will be sent to the server as
+ // null. It is an error if a field in this list has a non-empty value.
+ // This may be used to include null fields in Patch requests.
+ NullFields []string `json:"-"`
+}
+
+func (s *BucketLifecycleRule) MarshalJSON() ([]byte, error) {
+ type NoMethod BucketLifecycleRule
+ raw := NoMethod(*s)
+ return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
+}
+
+// BucketLifecycleRuleAction: The action to take.
+type BucketLifecycleRuleAction struct {
+ // StorageClass: Target storage class. Required iff the type of the
+ // action is SetStorageClass.
+ StorageClass string `json:"storageClass,omitempty"`
+
+ // Type: Type of the action. Currently, only Delete and SetStorageClass
+ // are supported.
+ Type string `json:"type,omitempty"`
+
+ // ForceSendFields is a list of field names (e.g. "StorageClass") to
+ // unconditionally include in API requests. By default, fields with
+ // empty values are omitted from API requests. However, any non-pointer,
+ // non-interface field appearing in ForceSendFields will be sent to the
+ // server regardless of whether the field is empty or not. This may be
+ // used to include empty fields in Patch requests.
+ ForceSendFields []string `json:"-"`
+
+ // NullFields is a list of field names (e.g. "StorageClass") to include
+ // in API requests with the JSON null value. By default, fields with
+ // empty values are omitted from API requests. However, any field with
+ // an empty value appearing in NullFields will be sent to the server as
+ // null. It is an error if a field in this list has a non-empty value.
+ // This may be used to include null fields in Patch requests.
+ NullFields []string `json:"-"`
+}
+
+func (s *BucketLifecycleRuleAction) MarshalJSON() ([]byte, error) {
+ type NoMethod BucketLifecycleRuleAction
+ raw := NoMethod(*s)
+ return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
+}
+
+// BucketLifecycleRuleCondition: The condition(s) under which the action
+// will be taken.
+type BucketLifecycleRuleCondition struct {
+ // Age: Age of an object (in days). This condition is satisfied when an
+ // object reaches the specified age.
+ Age int64 `json:"age,omitempty"`
+
+ // CreatedBefore: A date in RFC 3339 format with only the date part (for
+ // instance, "2013-01-15"). This condition is satisfied when an object
+ // is created before midnight of the specified date in UTC.
+ CreatedBefore string `json:"createdBefore,omitempty"`
+
+ // IsLive: Relevant only for versioned objects. If the value is true,
+ // this condition matches live objects; if the value is false, it
+ // matches archived objects.
+ IsLive *bool `json:"isLive,omitempty"`
+
+ // MatchesPattern: A regular expression that satisfies the RE2 syntax.
+ // This condition is satisfied when the name of the object matches the
+ // RE2 pattern. Note: This feature is currently in the "Early Access"
+ // launch stage and is only available to a whitelisted set of users;
+ // that means that this feature may be changed in backward-incompatible
+ // ways and that it is not guaranteed to be released.
+ MatchesPattern string `json:"matchesPattern,omitempty"`
+
+ // MatchesStorageClass: Objects having any of the storage classes
+ // specified by this condition will be matched. Values include
+ // MULTI_REGIONAL, REGIONAL, NEARLINE, COLDLINE, STANDARD, and
+ // DURABLE_REDUCED_AVAILABILITY.
+ MatchesStorageClass []string `json:"matchesStorageClass,omitempty"`
+
+ // NumNewerVersions: Relevant only for versioned objects. If the value
+ // is N, this condition is satisfied when there are at least N versions
+ // (including the live version) newer than this version of the object.
+ NumNewerVersions int64 `json:"numNewerVersions,omitempty"`
+
+ // ForceSendFields is a list of field names (e.g. "Age") to
+ // unconditionally include in API requests. By default, fields with
+ // empty values are omitted from API requests. However, any non-pointer,
+ // non-interface field appearing in ForceSendFields will be sent to the
+ // server regardless of whether the field is empty or not. This may be
+ // used to include empty fields in Patch requests.
+ ForceSendFields []string `json:"-"`
+
+ // NullFields is a list of field names (e.g. "Age") to include in API
+ // requests with the JSON null value. By default, fields with empty
+ // values are omitted from API requests. However, any field with an
+ // empty value appearing in NullFields will be sent to the server as
+ // null. It is an error if a field in this list has a non-empty value.
+ // This may be used to include null fields in Patch requests.
+ NullFields []string `json:"-"`
+}
+
+func (s *BucketLifecycleRuleCondition) MarshalJSON() ([]byte, error) {
+ type NoMethod BucketLifecycleRuleCondition
+ raw := NoMethod(*s)
+ return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
+}
+
+// BucketLogging: The bucket's logging configuration, which defines the
+// destination bucket and optional name prefix for the current bucket's
+// logs.
+type BucketLogging struct {
+ // LogBucket: The destination bucket where the current bucket's logs
+ // should be placed.
+ LogBucket string `json:"logBucket,omitempty"`
+
+ // LogObjectPrefix: A prefix for log object names.
+ LogObjectPrefix string `json:"logObjectPrefix,omitempty"`
+
+ // ForceSendFields is a list of field names (e.g. "LogBucket") to
+ // unconditionally include in API requests. By default, fields with
+ // empty values are omitted from API requests. However, any non-pointer,
+ // non-interface field appearing in ForceSendFields will be sent to the
+ // server regardless of whether the field is empty or not. This may be
+ // used to include empty fields in Patch requests.
+ ForceSendFields []string `json:"-"`
+
+ // NullFields is a list of field names (e.g. "LogBucket") to include in
+ // API requests with the JSON null value. By default, fields with empty
+ // values are omitted from API requests. However, any field with an
+ // empty value appearing in NullFields will be sent to the server as
+ // null. It is an error if a field in this list has a non-empty value.
+ // This may be used to include null fields in Patch requests.
+ NullFields []string `json:"-"`
+}
+
+func (s *BucketLogging) MarshalJSON() ([]byte, error) {
+ type NoMethod BucketLogging
+ raw := NoMethod(*s)
+ return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
+}
+
+// BucketOwner: The owner of the bucket. This is always the project
+// team's owner group.
+type BucketOwner struct {
+ // Entity: The entity, in the form project-owner-projectId.
+ Entity string `json:"entity,omitempty"`
+
+ // EntityId: The ID for the entity.
+ EntityId string `json:"entityId,omitempty"`
+
+ // ForceSendFields is a list of field names (e.g. "Entity") to
+ // unconditionally include in API requests. By default, fields with
+ // empty values are omitted from API requests. However, any non-pointer,
+ // non-interface field appearing in ForceSendFields will be sent to the
+ // server regardless of whether the field is empty or not. This may be
+ // used to include empty fields in Patch requests.
+ ForceSendFields []string `json:"-"`
+
+ // NullFields is a list of field names (e.g. "Entity") to include in API
+ // requests with the JSON null value. By default, fields with empty
+ // values are omitted from API requests. However, any field with an
+ // empty value appearing in NullFields will be sent to the server as
+ // null. It is an error if a field in this list has a non-empty value.
+ // This may be used to include null fields in Patch requests.
+ NullFields []string `json:"-"`
+}
+
+func (s *BucketOwner) MarshalJSON() ([]byte, error) {
+ type NoMethod BucketOwner
+ raw := NoMethod(*s)
+ return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
+}
+
+// BucketRetentionPolicy: The bucket's retention policy. The retention
+// policy enforces a minimum retention time for all objects contained in
+// the bucket, based on their creation time. Any attempt to overwrite or
+// delete objects younger than the retention period will result in a
+// PERMISSION_DENIED error. An unlocked retention policy can be modified
+// or removed from the bucket via a storage.buckets.update operation. A
+// locked retention policy cannot be removed or shortened in duration
+// for the lifetime of the bucket. Attempting to remove or decrease
+// period of a locked retention policy will result in a
+// PERMISSION_DENIED error.
+type BucketRetentionPolicy struct {
+ // EffectiveTime: Server-determined value that indicates the time from
+ // which policy was enforced and effective. This value is in RFC 3339
+ // format.
+ EffectiveTime string `json:"effectiveTime,omitempty"`
+
+ // IsLocked: Once locked, an object retention policy cannot be modified.
+ IsLocked bool `json:"isLocked,omitempty"`
+
+ // RetentionPeriod: The duration in seconds that objects need to be
+ // retained. Retention duration must be greater than zero and less than
+ // 100 years. Note that enforcement of retention periods less than a day
+ // is not guaranteed. Such periods should only be used for testing
+ // purposes.
+ RetentionPeriod int64 `json:"retentionPeriod,omitempty,string"`
+
+ // ForceSendFields is a list of field names (e.g. "EffectiveTime") to
+ // unconditionally include in API requests. By default, fields with
+ // empty values are omitted from API requests. However, any non-pointer,
+ // non-interface field appearing in ForceSendFields will be sent to the
+ // server regardless of whether the field is empty or not. This may be
+ // used to include empty fields in Patch requests.
+ ForceSendFields []string `json:"-"`
+
+ // NullFields is a list of field names (e.g. "EffectiveTime") to include
+ // in API requests with the JSON null value. By default, fields with
+ // empty values are omitted from API requests. However, any field with
+ // an empty value appearing in NullFields will be sent to the server as
+ // null. It is an error if a field in this list has a non-empty value.
+ // This may be used to include null fields in Patch requests.
+ NullFields []string `json:"-"`
+}
+
+func (s *BucketRetentionPolicy) MarshalJSON() ([]byte, error) {
+ type NoMethod BucketRetentionPolicy
+ raw := NoMethod(*s)
+ return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
+}
+
+// BucketVersioning: The bucket's versioning configuration.
+type BucketVersioning struct {
+ // Enabled: While set to true, versioning is fully enabled for this
+ // bucket.
+ Enabled bool `json:"enabled,omitempty"`
+
+ // ForceSendFields is a list of field names (e.g. "Enabled") to
+ // unconditionally include in API requests. By default, fields with
+ // empty values are omitted from API requests. However, any non-pointer,
+ // non-interface field appearing in ForceSendFields will be sent to the
+ // server regardless of whether the field is empty or not. This may be
+ // used to include empty fields in Patch requests.
+ ForceSendFields []string `json:"-"`
+
+ // NullFields is a list of field names (e.g. "Enabled") to include in
+ // API requests with the JSON null value. By default, fields with empty
+ // values are omitted from API requests. However, any field with an
+ // empty value appearing in NullFields will be sent to the server as
+ // null. It is an error if a field in this list has a non-empty value.
+ // This may be used to include null fields in Patch requests.
+ NullFields []string `json:"-"`
+}
+
+func (s *BucketVersioning) MarshalJSON() ([]byte, error) {
+ type NoMethod BucketVersioning
+ raw := NoMethod(*s)
+ return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
+}
+
+// BucketWebsite: The bucket's website configuration, controlling how
+// the service behaves when accessing bucket contents as a web site. See
+// the Static Website Examples for more information.
+type BucketWebsite struct {
+ // MainPageSuffix: If the requested object path is missing, the service
+ // will ensure the path has a trailing '/', append this suffix, and
+ // attempt to retrieve the resulting object. This allows the creation of
+ // index.html objects to represent directory pages.
+ MainPageSuffix string `json:"mainPageSuffix,omitempty"`
+
+ // NotFoundPage: If the requested object path is missing, and any
+ // mainPageSuffix object is missing, if applicable, the service will
+ // return the named object from this bucket as the content for a 404 Not
+ // Found result.
+ NotFoundPage string `json:"notFoundPage,omitempty"`
+
+ // ForceSendFields is a list of field names (e.g. "MainPageSuffix") to
+ // unconditionally include in API requests. By default, fields with
+ // empty values are omitted from API requests. However, any non-pointer,
+ // non-interface field appearing in ForceSendFields will be sent to the
+ // server regardless of whether the field is empty or not. This may be
+ // used to include empty fields in Patch requests.
+ ForceSendFields []string `json:"-"`
+
+ // NullFields is a list of field names (e.g. "MainPageSuffix") to
+ // include in API requests with the JSON null value. By default, fields
+ // with empty values are omitted from API requests. However, any field
+ // with an empty value appearing in NullFields will be sent to the
+ // server as null. It is an error if a field in this list has a
+ // non-empty value. This may be used to include null fields in Patch
+ // requests.
+ NullFields []string `json:"-"`
+}
+
+func (s *BucketWebsite) MarshalJSON() ([]byte, error) {
+ type NoMethod BucketWebsite
+ raw := NoMethod(*s)
+ return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
+}
+
+// BucketAccessControl: An access-control entry.
+type BucketAccessControl struct {
+ // Bucket: The name of the bucket.
+ Bucket string `json:"bucket,omitempty"`
+
+ // Domain: The domain associated with the entity, if any.
+ Domain string `json:"domain,omitempty"`
+
+ // Email: The email address associated with the entity, if any.
+ Email string `json:"email,omitempty"`
+
+ // Entity: The entity holding the permission, in one of the following
+ // forms:
+ // - user-userId
+ // - user-email
+ // - group-groupId
+ // - group-email
+ // - domain-domain
+ // - project-team-projectId
+ // - allUsers
+ // - allAuthenticatedUsers Examples:
+ // - The user liz@example.com would be user-liz@example.com.
+ // - The group example@googlegroups.com would be
+ // group-example@googlegroups.com.
+ // - To refer to all members of the Google Apps for Business domain
+ // example.com, the entity would be domain-example.com.
+ Entity string `json:"entity,omitempty"`
+
+ // EntityId: The ID for the entity, if any.
+ EntityId string `json:"entityId,omitempty"`
+
+ // Etag: HTTP 1.1 Entity tag for the access-control entry.
+ Etag string `json:"etag,omitempty"`
+
+ // Id: The ID of the access-control entry.
+ Id string `json:"id,omitempty"`
+
+ // Kind: The kind of item this is. For bucket access control entries,
+ // this is always storage#bucketAccessControl.
+ Kind string `json:"kind,omitempty"`
+
+ // ProjectTeam: The project team associated with the entity, if any.
+ ProjectTeam *BucketAccessControlProjectTeam `json:"projectTeam,omitempty"`
+
+ // Role: The access permission for the entity.
+ Role string `json:"role,omitempty"`
+
+ // SelfLink: The link to this access-control entry.
+ SelfLink string `json:"selfLink,omitempty"`
+
+ // ServerResponse contains the HTTP response code and headers from the
+ // server.
+ googleapi.ServerResponse `json:"-"`
+
+ // ForceSendFields is a list of field names (e.g. "Bucket") to
+ // unconditionally include in API requests. By default, fields with
+ // empty values are omitted from API requests. However, any non-pointer,
+ // non-interface field appearing in ForceSendFields will be sent to the
+ // server regardless of whether the field is empty or not. This may be
+ // used to include empty fields in Patch requests.
+ ForceSendFields []string `json:"-"`
+
+ // NullFields is a list of field names (e.g. "Bucket") to include in API
+ // requests with the JSON null value. By default, fields with empty
+ // values are omitted from API requests. However, any field with an
+ // empty value appearing in NullFields will be sent to the server as
+ // null. It is an error if a field in this list has a non-empty value.
+ // This may be used to include null fields in Patch requests.
+ NullFields []string `json:"-"`
+}
+
+func (s *BucketAccessControl) MarshalJSON() ([]byte, error) {
+ type NoMethod BucketAccessControl
+ raw := NoMethod(*s)
+ return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
+}
+
+// BucketAccessControlProjectTeam: The project team associated with the
+// entity, if any.
+type BucketAccessControlProjectTeam struct {
+ // ProjectNumber: The project number.
+ ProjectNumber string `json:"projectNumber,omitempty"`
+
+ // Team: The team.
+ Team string `json:"team,omitempty"`
+
+ // ForceSendFields is a list of field names (e.g. "ProjectNumber") to
+ // unconditionally include in API requests. By default, fields with
+ // empty values are omitted from API requests. However, any non-pointer,
+ // non-interface field appearing in ForceSendFields will be sent to the
+ // server regardless of whether the field is empty or not. This may be
+ // used to include empty fields in Patch requests.
+ ForceSendFields []string `json:"-"`
+
+ // NullFields is a list of field names (e.g. "ProjectNumber") to include
+ // in API requests with the JSON null value. By default, fields with
+ // empty values are omitted from API requests. However, any field with
+ // an empty value appearing in NullFields will be sent to the server as
+ // null. It is an error if a field in this list has a non-empty value.
+ // This may be used to include null fields in Patch requests.
+ NullFields []string `json:"-"`
+}
+
+func (s *BucketAccessControlProjectTeam) MarshalJSON() ([]byte, error) {
+ type NoMethod BucketAccessControlProjectTeam
+ raw := NoMethod(*s)
+ return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
+}
+
+// BucketAccessControls: An access-control list.
+type BucketAccessControls struct {
+ // Items: The list of items.
+ Items []*BucketAccessControl `json:"items,omitempty"`
+
+ // Kind: The kind of item this is. For lists of bucket access control
+ // entries, this is always storage#bucketAccessControls.
+ Kind string `json:"kind,omitempty"`
+
+ // ServerResponse contains the HTTP response code and headers from the
+ // server.
+ googleapi.ServerResponse `json:"-"`
+
+ // ForceSendFields is a list of field names (e.g. "Items") to
+ // unconditionally include in API requests. By default, fields with
+ // empty values are omitted from API requests. However, any non-pointer,
+ // non-interface field appearing in ForceSendFields will be sent to the
+ // server regardless of whether the field is empty or not. This may be
+ // used to include empty fields in Patch requests.
+ ForceSendFields []string `json:"-"`
+
+ // NullFields is a list of field names (e.g. "Items") to include in API
+ // requests with the JSON null value. By default, fields with empty
+ // values are omitted from API requests. However, any field with an
+ // empty value appearing in NullFields will be sent to the server as
+ // null. It is an error if a field in this list has a non-empty value.
+ // This may be used to include null fields in Patch requests.
+ NullFields []string `json:"-"`
+}
+
+func (s *BucketAccessControls) MarshalJSON() ([]byte, error) {
+ type NoMethod BucketAccessControls
+ raw := NoMethod(*s)
+ return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
+}
+
+// Buckets: A list of buckets.
+type Buckets struct {
+ // Items: The list of items.
+ Items []*Bucket `json:"items,omitempty"`
+
+ // Kind: The kind of item this is. For lists of buckets, this is always
+ // storage#buckets.
+ Kind string `json:"kind,omitempty"`
+
+ // NextPageToken: The continuation token, used to page through large
+ // result sets. Provide this value in a subsequent request to return the
+ // next page of results.
+ NextPageToken string `json:"nextPageToken,omitempty"`
+
+ // ServerResponse contains the HTTP response code and headers from the
+ // server.
+ googleapi.ServerResponse `json:"-"`
+
+ // ForceSendFields is a list of field names (e.g. "Items") to
+ // unconditionally include in API requests. By default, fields with
+ // empty values are omitted from API requests. However, any non-pointer,
+ // non-interface field appearing in ForceSendFields will be sent to the
+ // server regardless of whether the field is empty or not. This may be
+ // used to include empty fields in Patch requests.
+ ForceSendFields []string `json:"-"`
+
+ // NullFields is a list of field names (e.g. "Items") to include in API
+ // requests with the JSON null value. By default, fields with empty
+ // values are omitted from API requests. However, any field with an
+ // empty value appearing in NullFields will be sent to the server as
+ // null. It is an error if a field in this list has a non-empty value.
+ // This may be used to include null fields in Patch requests.
+ NullFields []string `json:"-"`
+}
+
+func (s *Buckets) MarshalJSON() ([]byte, error) {
+ type NoMethod Buckets
+ raw := NoMethod(*s)
+ return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
+}
+
+// Channel: An notification channel used to watch for resource changes.
+type Channel struct {
+ // Address: The address where notifications are delivered for this
+ // channel.
+ Address string `json:"address,omitempty"`
+
+ // Expiration: Date and time of notification channel expiration,
+ // expressed as a Unix timestamp, in milliseconds. Optional.
+ Expiration int64 `json:"expiration,omitempty,string"`
+
+ // Id: A UUID or similar unique string that identifies this channel.
+ Id string `json:"id,omitempty"`
+
+ // Kind: Identifies this as a notification channel used to watch for
+ // changes to a resource. Value: the fixed string "api#channel".
+ Kind string `json:"kind,omitempty"`
+
+ // Params: Additional parameters controlling delivery channel behavior.
+ // Optional.
+ Params map[string]string `json:"params,omitempty"`
+
+ // Payload: A Boolean value to indicate whether payload is wanted.
+ // Optional.
+ Payload bool `json:"payload,omitempty"`
+
+ // ResourceId: An opaque ID that identifies the resource being watched
+ // on this channel. Stable across different API versions.
+ ResourceId string `json:"resourceId,omitempty"`
+
+ // ResourceUri: A version-specific identifier for the watched resource.
+ ResourceUri string `json:"resourceUri,omitempty"`
+
+ // Token: An arbitrary string delivered to the target address with each
+ // notification delivered over this channel. Optional.
+ Token string `json:"token,omitempty"`
+
+ // Type: The type of delivery mechanism used for this channel.
+ Type string `json:"type,omitempty"`
+
+ // ServerResponse contains the HTTP response code and headers from the
+ // server.
+ googleapi.ServerResponse `json:"-"`
+
+ // ForceSendFields is a list of field names (e.g. "Address") to
+ // unconditionally include in API requests. By default, fields with
+ // empty values are omitted from API requests. However, any non-pointer,
+ // non-interface field appearing in ForceSendFields will be sent to the
+ // server regardless of whether the field is empty or not. This may be
+ // used to include empty fields in Patch requests.
+ ForceSendFields []string `json:"-"`
+
+ // NullFields is a list of field names (e.g. "Address") to include in
+ // API requests with the JSON null value. By default, fields with empty
+ // values are omitted from API requests. However, any field with an
+ // empty value appearing in NullFields will be sent to the server as
+ // null. It is an error if a field in this list has a non-empty value.
+ // This may be used to include null fields in Patch requests.
+ NullFields []string `json:"-"`
+}
+
+func (s *Channel) MarshalJSON() ([]byte, error) {
+ type NoMethod Channel
+ raw := NoMethod(*s)
+ return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
+}
+
+// ComposeRequest: A Compose request.
+type ComposeRequest struct {
+ // Destination: Properties of the resulting object.
+ Destination *Object `json:"destination,omitempty"`
+
+ // Kind: The kind of item this is.
+ Kind string `json:"kind,omitempty"`
+
+ // SourceObjects: The list of source objects that will be concatenated
+ // into a single object.
+ SourceObjects []*ComposeRequestSourceObjects `json:"sourceObjects,omitempty"`
+
+ // ForceSendFields is a list of field names (e.g. "Destination") to
+ // unconditionally include in API requests. By default, fields with
+ // empty values are omitted from API requests. However, any non-pointer,
+ // non-interface field appearing in ForceSendFields will be sent to the
+ // server regardless of whether the field is empty or not. This may be
+ // used to include empty fields in Patch requests.
+ ForceSendFields []string `json:"-"`
+
+ // NullFields is a list of field names (e.g. "Destination") to include
+ // in API requests with the JSON null value. By default, fields with
+ // empty values are omitted from API requests. However, any field with
+ // an empty value appearing in NullFields will be sent to the server as
+ // null. It is an error if a field in this list has a non-empty value.
+ // This may be used to include null fields in Patch requests.
+ NullFields []string `json:"-"`
+}
+
+func (s *ComposeRequest) MarshalJSON() ([]byte, error) {
+ type NoMethod ComposeRequest
+ raw := NoMethod(*s)
+ return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
+}
+
+type ComposeRequestSourceObjects struct {
+ // Generation: The generation of this object to use as the source.
+ Generation int64 `json:"generation,omitempty,string"`
+
+ // Name: The source object's name. All source objects must reside in the
+ // same bucket.
+ Name string `json:"name,omitempty"`
+
+ // ObjectPreconditions: Conditions that must be met for this operation
+ // to execute.
+ ObjectPreconditions *ComposeRequestSourceObjectsObjectPreconditions `json:"objectPreconditions,omitempty"`
+
+ // ForceSendFields is a list of field names (e.g. "Generation") to
+ // unconditionally include in API requests. By default, fields with
+ // empty values are omitted from API requests. However, any non-pointer,
+ // non-interface field appearing in ForceSendFields will be sent to the
+ // server regardless of whether the field is empty or not. This may be
+ // used to include empty fields in Patch requests.
+ ForceSendFields []string `json:"-"`
+
+ // NullFields is a list of field names (e.g. "Generation") to include in
+ // API requests with the JSON null value. By default, fields with empty
+ // values are omitted from API requests. However, any field with an
+ // empty value appearing in NullFields will be sent to the server as
+ // null. It is an error if a field in this list has a non-empty value.
+ // This may be used to include null fields in Patch requests.
+ NullFields []string `json:"-"`
+}
+
+func (s *ComposeRequestSourceObjects) MarshalJSON() ([]byte, error) {
+ type NoMethod ComposeRequestSourceObjects
+ raw := NoMethod(*s)
+ return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
+}
+
+// ComposeRequestSourceObjectsObjectPreconditions: Conditions that must
+// be met for this operation to execute.
+type ComposeRequestSourceObjectsObjectPreconditions struct {
+ // IfGenerationMatch: Only perform the composition if the generation of
+ // the source object that would be used matches this value. If this
+ // value and a generation are both specified, they must be the same
+ // value or the call will fail.
+ IfGenerationMatch int64 `json:"ifGenerationMatch,omitempty,string"`
+
+ // ForceSendFields is a list of field names (e.g. "IfGenerationMatch")
+ // to unconditionally include in API requests. By default, fields with
+ // empty values are omitted from API requests. However, any non-pointer,
+ // non-interface field appearing in ForceSendFields will be sent to the
+ // server regardless of whether the field is empty or not. This may be
+ // used to include empty fields in Patch requests.
+ ForceSendFields []string `json:"-"`
+
+ // NullFields is a list of field names (e.g. "IfGenerationMatch") to
+ // include in API requests with the JSON null value. By default, fields
+ // with empty values are omitted from API requests. However, any field
+ // with an empty value appearing in NullFields will be sent to the
+ // server as null. It is an error if a field in this list has a
+ // non-empty value. This may be used to include null fields in Patch
+ // requests.
+ NullFields []string `json:"-"`
+}
+
+func (s *ComposeRequestSourceObjectsObjectPreconditions) MarshalJSON() ([]byte, error) {
+ type NoMethod ComposeRequestSourceObjectsObjectPreconditions
+ raw := NoMethod(*s)
+ return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
+}
+
+// Notification: A subscription to receive Google PubSub notifications.
+type Notification struct {
+ // CustomAttributes: An optional list of additional attributes to attach
+ // to each Cloud PubSub message published for this notification
+ // subscription.
+ CustomAttributes map[string]string `json:"custom_attributes,omitempty"`
+
+ // Etag: HTTP 1.1 Entity tag for this subscription notification.
+ Etag string `json:"etag,omitempty"`
+
+ // EventTypes: If present, only send notifications about listed event
+ // types. If empty, sent notifications for all event types.
+ EventTypes []string `json:"event_types,omitempty"`
+
+ // Id: The ID of the notification.
+ Id string `json:"id,omitempty"`
+
+ // Kind: The kind of item this is. For notifications, this is always
+ // storage#notification.
+ Kind string `json:"kind,omitempty"`
+
+ // ObjectNamePrefix: If present, only apply this notification
+ // configuration to object names that begin with this prefix.
+ ObjectNamePrefix string `json:"object_name_prefix,omitempty"`
+
+ // PayloadFormat: The desired content of the Payload.
+ PayloadFormat string `json:"payload_format,omitempty"`
+
+ // SelfLink: The canonical URL of this notification.
+ SelfLink string `json:"selfLink,omitempty"`
+
+ // Topic: The Cloud PubSub topic to which this subscription publishes.
+ // Formatted as:
+ // '//pubsub.googleapis.com/projects/{project-identifier}/topics/{my-topi
+ // c}'
+ Topic string `json:"topic,omitempty"`
+
+ // ServerResponse contains the HTTP response code and headers from the
+ // server.
+ googleapi.ServerResponse `json:"-"`
+
+ // ForceSendFields is a list of field names (e.g. "CustomAttributes") to
+ // unconditionally include in API requests. By default, fields with
+ // empty values are omitted from API requests. However, any non-pointer,
+ // non-interface field appearing in ForceSendFields will be sent to the
+ // server regardless of whether the field is empty or not. This may be
+ // used to include empty fields in Patch requests.
+ ForceSendFields []string `json:"-"`
+
+ // NullFields is a list of field names (e.g. "CustomAttributes") to
+ // include in API requests with the JSON null value. By default, fields
+ // with empty values are omitted from API requests. However, any field
+ // with an empty value appearing in NullFields will be sent to the
+ // server as null. It is an error if a field in this list has a
+ // non-empty value. This may be used to include null fields in Patch
+ // requests.
+ NullFields []string `json:"-"`
+}
+
+func (s *Notification) MarshalJSON() ([]byte, error) {
+ type NoMethod Notification
+ raw := NoMethod(*s)
+ return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
+}
+
+// Notifications: A list of notification subscriptions.
+type Notifications struct {
+ // Items: The list of items.
+ Items []*Notification `json:"items,omitempty"`
+
+ // Kind: The kind of item this is. For lists of notifications, this is
+ // always storage#notifications.
+ Kind string `json:"kind,omitempty"`
+
+ // ServerResponse contains the HTTP response code and headers from the
+ // server.
+ googleapi.ServerResponse `json:"-"`
+
+ // ForceSendFields is a list of field names (e.g. "Items") to
+ // unconditionally include in API requests. By default, fields with
+ // empty values are omitted from API requests. However, any non-pointer,
+ // non-interface field appearing in ForceSendFields will be sent to the
+ // server regardless of whether the field is empty or not. This may be
+ // used to include empty fields in Patch requests.
+ ForceSendFields []string `json:"-"`
+
+ // NullFields is a list of field names (e.g. "Items") to include in API
+ // requests with the JSON null value. By default, fields with empty
+ // values are omitted from API requests. However, any field with an
+ // empty value appearing in NullFields will be sent to the server as
+ // null. It is an error if a field in this list has a non-empty value.
+ // This may be used to include null fields in Patch requests.
+ NullFields []string `json:"-"`
+}
+
+func (s *Notifications) MarshalJSON() ([]byte, error) {
+ type NoMethod Notifications
+ raw := NoMethod(*s)
+ return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
+}
+
+// Object: An object.
+type Object struct {
+ // Acl: Access controls on the object.
+ Acl []*ObjectAccessControl `json:"acl,omitempty"`
+
+ // Bucket: The name of the bucket containing this object.
+ Bucket string `json:"bucket,omitempty"`
+
+ // CacheControl: Cache-Control directive for the object data. If
+ // omitted, and the object is accessible to all anonymous users, the
+ // default will be public, max-age=3600.
+ CacheControl string `json:"cacheControl,omitempty"`
+
+ // ComponentCount: Number of underlying components that make up this
+ // object. Components are accumulated by compose operations.
+ ComponentCount int64 `json:"componentCount,omitempty"`
+
+ // ContentDisposition: Content-Disposition of the object data.
+ ContentDisposition string `json:"contentDisposition,omitempty"`
+
+ // ContentEncoding: Content-Encoding of the object data.
+ ContentEncoding string `json:"contentEncoding,omitempty"`
+
+ // ContentLanguage: Content-Language of the object data.
+ ContentLanguage string `json:"contentLanguage,omitempty"`
+
+ // ContentType: Content-Type of the object data. If an object is stored
+ // without a Content-Type, it is served as application/octet-stream.
+ ContentType string `json:"contentType,omitempty"`
+
+ // Crc32c: CRC32c checksum, as described in RFC 4960, Appendix B;
+ // encoded using base64 in big-endian byte order. For more information
+ // about using the CRC32c checksum, see Hashes and ETags: Best
+ // Practices.
+ Crc32c string `json:"crc32c,omitempty"`
+
+ // CustomerEncryption: Metadata of customer-supplied encryption key, if
+ // the object is encrypted by such a key.
+ CustomerEncryption *ObjectCustomerEncryption `json:"customerEncryption,omitempty"`
+
+ // Etag: HTTP 1.1 Entity tag for the object.
+ Etag string `json:"etag,omitempty"`
+
+ // EventBasedHold: Whether an object is under event-based hold.
+ // Event-based hold is a way to retain objects until an event occurs,
+ // which is signified by the hold's release (i.e. this value is set to
+ // false). After being released (set to false), such objects will be
+ // subject to bucket-level retention (if any). One sample use case of
+ // this flag is for banks to hold loan documents for at least 3 years
+ // after loan is paid in full. Here, bucket-level retention is 3 years
+ // and the event is the loan being paid in full. In this example, these
+ // objects will be held intact for any number of years until the event
+ // has occurred (event-based hold on the object is released) and then 3
+ // more years after that. That means retention duration of the objects
+ // begins from the moment event-based hold transitioned from true to
+ // false.
+ EventBasedHold bool `json:"eventBasedHold,omitempty"`
+
+ // Generation: The content generation of this object. Used for object
+ // versioning.
+ Generation int64 `json:"generation,omitempty,string"`
+
+ // Id: The ID of the object, including the bucket name, object name, and
+ // generation number.
+ Id string `json:"id,omitempty"`
+
+ // Kind: The kind of item this is. For objects, this is always
+ // storage#object.
+ Kind string `json:"kind,omitempty"`
+
+ // KmsKeyName: Cloud KMS Key used to encrypt this object, if the object
+ // is encrypted by such a key.
+ KmsKeyName string `json:"kmsKeyName,omitempty"`
+
+ // Md5Hash: MD5 hash of the data; encoded using base64. For more
+ // information about using the MD5 hash, see Hashes and ETags: Best
+ // Practices.
+ Md5Hash string `json:"md5Hash,omitempty"`
+
+ // MediaLink: Media download link.
+ MediaLink string `json:"mediaLink,omitempty"`
+
+ // Metadata: User-provided metadata, in key/value pairs.
+ Metadata map[string]string `json:"metadata,omitempty"`
+
+ // Metageneration: The version of the metadata for this object at this
+ // generation. Used for preconditions and for detecting changes in
+ // metadata. A metageneration number is only meaningful in the context
+ // of a particular generation of a particular object.
+ Metageneration int64 `json:"metageneration,omitempty,string"`
+
+ // Name: The name of the object. Required if not specified by URL
+ // parameter.
+ Name string `json:"name,omitempty"`
+
+ // Owner: The owner of the object. This will always be the uploader of
+ // the object.
+ Owner *ObjectOwner `json:"owner,omitempty"`
+
+ // RetentionExpirationTime: A server-determined value that specifies the
+ // earliest time that the object's retention period expires. This value
+ // is in RFC 3339 format. Note 1: This field is not provided for objects
+ // with an active event-based hold, since retention expiration is
+ // unknown until the hold is removed. Note 2: This value can be provided
+ // even when temporary hold is set (so that the user can reason about
+ // policy without having to first unset the temporary hold).
+ RetentionExpirationTime string `json:"retentionExpirationTime,omitempty"`
+
+ // SelfLink: The link to this object.
+ SelfLink string `json:"selfLink,omitempty"`
+
+ // Size: Content-Length of the data in bytes.
+ Size uint64 `json:"size,omitempty,string"`
+
+ // StorageClass: Storage class of the object.
+ StorageClass string `json:"storageClass,omitempty"`
+
+ // TemporaryHold: Whether an object is under temporary hold. While this
+ // flag is set to true, the object is protected against deletion and
+ // overwrites. A common use case of this flag is regulatory
+ // investigations where objects need to be retained while the
+ // investigation is ongoing. Note that unlike event-based hold,
+ // temporary hold does not impact retention expiration time of an
+ // object.
+ TemporaryHold bool `json:"temporaryHold,omitempty"`
+
+ // TimeCreated: The creation time of the object in RFC 3339 format.
+ TimeCreated string `json:"timeCreated,omitempty"`
+
+ // TimeDeleted: The deletion time of the object in RFC 3339 format. Will
+ // be returned if and only if this version of the object has been
+ // deleted.
+ TimeDeleted string `json:"timeDeleted,omitempty"`
+
+ // TimeStorageClassUpdated: The time at which the object's storage class
+ // was last changed. When the object is initially created, it will be
+ // set to timeCreated.
+ TimeStorageClassUpdated string `json:"timeStorageClassUpdated,omitempty"`
+
+ // Updated: The modification time of the object metadata in RFC 3339
+ // format.
+ Updated string `json:"updated,omitempty"`
+
+ // ServerResponse contains the HTTP response code and headers from the
+ // server.
+ googleapi.ServerResponse `json:"-"`
+
+ // ForceSendFields is a list of field names (e.g. "Acl") to
+ // unconditionally include in API requests. By default, fields with
+ // empty values are omitted from API requests. However, any non-pointer,
+ // non-interface field appearing in ForceSendFields will be sent to the
+ // server regardless of whether the field is empty or not. This may be
+ // used to include empty fields in Patch requests.
+ ForceSendFields []string `json:"-"`
+
+ // NullFields is a list of field names (e.g. "Acl") to include in API
+ // requests with the JSON null value. By default, fields with empty
+ // values are omitted from API requests. However, any field with an
+ // empty value appearing in NullFields will be sent to the server as
+ // null. It is an error if a field in this list has a non-empty value.
+ // This may be used to include null fields in Patch requests.
+ NullFields []string `json:"-"`
+}
+
+func (s *Object) MarshalJSON() ([]byte, error) {
+ type NoMethod Object
+ raw := NoMethod(*s)
+ return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
+}
+
+// ObjectCustomerEncryption: Metadata of customer-supplied encryption
+// key, if the object is encrypted by such a key.
+type ObjectCustomerEncryption struct {
+ // EncryptionAlgorithm: The encryption algorithm.
+ EncryptionAlgorithm string `json:"encryptionAlgorithm,omitempty"`
+
+ // KeySha256: SHA256 hash value of the encryption key.
+ KeySha256 string `json:"keySha256,omitempty"`
+
+ // ForceSendFields is a list of field names (e.g. "EncryptionAlgorithm")
+ // to unconditionally include in API requests. By default, fields with
+ // empty values are omitted from API requests. However, any non-pointer,
+ // non-interface field appearing in ForceSendFields will be sent to the
+ // server regardless of whether the field is empty or not. This may be
+ // used to include empty fields in Patch requests.
+ ForceSendFields []string `json:"-"`
+
+ // NullFields is a list of field names (e.g. "EncryptionAlgorithm") to
+ // include in API requests with the JSON null value. By default, fields
+ // with empty values are omitted from API requests. However, any field
+ // with an empty value appearing in NullFields will be sent to the
+ // server as null. It is an error if a field in this list has a
+ // non-empty value. This may be used to include null fields in Patch
+ // requests.
+ NullFields []string `json:"-"`
+}
+
+func (s *ObjectCustomerEncryption) MarshalJSON() ([]byte, error) {
+ type NoMethod ObjectCustomerEncryption
+ raw := NoMethod(*s)
+ return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
+}
+
+// ObjectOwner: The owner of the object. This will always be the
+// uploader of the object.
+type ObjectOwner struct {
+ // Entity: The entity, in the form user-userId.
+ Entity string `json:"entity,omitempty"`
+
+ // EntityId: The ID for the entity.
+ EntityId string `json:"entityId,omitempty"`
+
+ // ForceSendFields is a list of field names (e.g. "Entity") to
+ // unconditionally include in API requests. By default, fields with
+ // empty values are omitted from API requests. However, any non-pointer,
+ // non-interface field appearing in ForceSendFields will be sent to the
+ // server regardless of whether the field is empty or not. This may be
+ // used to include empty fields in Patch requests.
+ ForceSendFields []string `json:"-"`
+
+ // NullFields is a list of field names (e.g. "Entity") to include in API
+ // requests with the JSON null value. By default, fields with empty
+ // values are omitted from API requests. However, any field with an
+ // empty value appearing in NullFields will be sent to the server as
+ // null. It is an error if a field in this list has a non-empty value.
+ // This may be used to include null fields in Patch requests.
+ NullFields []string `json:"-"`
+}
+
+func (s *ObjectOwner) MarshalJSON() ([]byte, error) {
+ type NoMethod ObjectOwner
+ raw := NoMethod(*s)
+ return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
+}
+
+// ObjectAccessControl: An access-control entry.
+type ObjectAccessControl struct {
+ // Bucket: The name of the bucket.
+ Bucket string `json:"bucket,omitempty"`
+
+ // Domain: The domain associated with the entity, if any.
+ Domain string `json:"domain,omitempty"`
+
+ // Email: The email address associated with the entity, if any.
+ Email string `json:"email,omitempty"`
+
+ // Entity: The entity holding the permission, in one of the following
+ // forms:
+ // - user-userId
+ // - user-email
+ // - group-groupId
+ // - group-email
+ // - domain-domain
+ // - project-team-projectId
+ // - allUsers
+ // - allAuthenticatedUsers Examples:
+ // - The user liz@example.com would be user-liz@example.com.
+ // - The group example@googlegroups.com would be
+ // group-example@googlegroups.com.
+ // - To refer to all members of the Google Apps for Business domain
+ // example.com, the entity would be domain-example.com.
+ Entity string `json:"entity,omitempty"`
+
+ // EntityId: The ID for the entity, if any.
+ EntityId string `json:"entityId,omitempty"`
+
+ // Etag: HTTP 1.1 Entity tag for the access-control entry.
+ Etag string `json:"etag,omitempty"`
+
+ // Generation: The content generation of the object, if applied to an
+ // object.
+ Generation int64 `json:"generation,omitempty,string"`
+
+ // Id: The ID of the access-control entry.
+ Id string `json:"id,omitempty"`
+
+ // Kind: The kind of item this is. For object access control entries,
+ // this is always storage#objectAccessControl.
+ Kind string `json:"kind,omitempty"`
+
+ // Object: The name of the object, if applied to an object.
+ Object string `json:"object,omitempty"`
+
+ // ProjectTeam: The project team associated with the entity, if any.
+ ProjectTeam *ObjectAccessControlProjectTeam `json:"projectTeam,omitempty"`
+
+ // Role: The access permission for the entity.
+ Role string `json:"role,omitempty"`
+
+ // SelfLink: The link to this access-control entry.
+ SelfLink string `json:"selfLink,omitempty"`
+
+ // ServerResponse contains the HTTP response code and headers from the
+ // server.
+ googleapi.ServerResponse `json:"-"`
+
+ // ForceSendFields is a list of field names (e.g. "Bucket") to
+ // unconditionally include in API requests. By default, fields with
+ // empty values are omitted from API requests. However, any non-pointer,
+ // non-interface field appearing in ForceSendFields will be sent to the
+ // server regardless of whether the field is empty or not. This may be
+ // used to include empty fields in Patch requests.
+ ForceSendFields []string `json:"-"`
+
+ // NullFields is a list of field names (e.g. "Bucket") to include in API
+ // requests with the JSON null value. By default, fields with empty
+ // values are omitted from API requests. However, any field with an
+ // empty value appearing in NullFields will be sent to the server as
+ // null. It is an error if a field in this list has a non-empty value.
+ // This may be used to include null fields in Patch requests.
+ NullFields []string `json:"-"`
+}
+
+func (s *ObjectAccessControl) MarshalJSON() ([]byte, error) {
+ type NoMethod ObjectAccessControl
+ raw := NoMethod(*s)
+ return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
+}
+
+// ObjectAccessControlProjectTeam: The project team associated with the
+// entity, if any.
+type ObjectAccessControlProjectTeam struct {
+ // ProjectNumber: The project number.
+ ProjectNumber string `json:"projectNumber,omitempty"`
+
+ // Team: The team.
+ Team string `json:"team,omitempty"`
+
+ // ForceSendFields is a list of field names (e.g. "ProjectNumber") to
+ // unconditionally include in API requests. By default, fields with
+ // empty values are omitted from API requests. However, any non-pointer,
+ // non-interface field appearing in ForceSendFields will be sent to the
+ // server regardless of whether the field is empty or not. This may be
+ // used to include empty fields in Patch requests.
+ ForceSendFields []string `json:"-"`
+
+ // NullFields is a list of field names (e.g. "ProjectNumber") to include
+ // in API requests with the JSON null value. By default, fields with
+ // empty values are omitted from API requests. However, any field with
+ // an empty value appearing in NullFields will be sent to the server as
+ // null. It is an error if a field in this list has a non-empty value.
+ // This may be used to include null fields in Patch requests.
+ NullFields []string `json:"-"`
+}
+
+func (s *ObjectAccessControlProjectTeam) MarshalJSON() ([]byte, error) {
+ type NoMethod ObjectAccessControlProjectTeam
+ raw := NoMethod(*s)
+ return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
+}
+
+// ObjectAccessControls: An access-control list.
+type ObjectAccessControls struct {
+ // Items: The list of items.
+ Items []*ObjectAccessControl `json:"items,omitempty"`
+
+ // Kind: The kind of item this is. For lists of object access control
+ // entries, this is always storage#objectAccessControls.
+ Kind string `json:"kind,omitempty"`
+
+ // ServerResponse contains the HTTP response code and headers from the
+ // server.
+ googleapi.ServerResponse `json:"-"`
+
+ // ForceSendFields is a list of field names (e.g. "Items") to
+ // unconditionally include in API requests. By default, fields with
+ // empty values are omitted from API requests. However, any non-pointer,
+ // non-interface field appearing in ForceSendFields will be sent to the
+ // server regardless of whether the field is empty or not. This may be
+ // used to include empty fields in Patch requests.
+ ForceSendFields []string `json:"-"`
+
+ // NullFields is a list of field names (e.g. "Items") to include in API
+ // requests with the JSON null value. By default, fields with empty
+ // values are omitted from API requests. However, any field with an
+ // empty value appearing in NullFields will be sent to the server as
+ // null. It is an error if a field in this list has a non-empty value.
+ // This may be used to include null fields in Patch requests.
+ NullFields []string `json:"-"`
+}
+
+func (s *ObjectAccessControls) MarshalJSON() ([]byte, error) {
+ type NoMethod ObjectAccessControls
+ raw := NoMethod(*s)
+ return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
+}
+
+// Objects: A list of objects.
+type Objects struct {
+ // Items: The list of items.
+ Items []*Object `json:"items,omitempty"`
+
+ // Kind: The kind of item this is. For lists of objects, this is always
+ // storage#objects.
+ Kind string `json:"kind,omitempty"`
+
+ // NextPageToken: The continuation token, used to page through large
+ // result sets. Provide this value in a subsequent request to return the
+ // next page of results.
+ NextPageToken string `json:"nextPageToken,omitempty"`
+
+ // Prefixes: The list of prefixes of objects matching-but-not-listed up
+ // to and including the requested delimiter.
+ Prefixes []string `json:"prefixes,omitempty"`
+
+ // ServerResponse contains the HTTP response code and headers from the
+ // server.
+ googleapi.ServerResponse `json:"-"`
+
+ // ForceSendFields is a list of field names (e.g. "Items") to
+ // unconditionally include in API requests. By default, fields with
+ // empty values are omitted from API requests. However, any non-pointer,
+ // non-interface field appearing in ForceSendFields will be sent to the
+ // server regardless of whether the field is empty or not. This may be
+ // used to include empty fields in Patch requests.
+ ForceSendFields []string `json:"-"`
+
+ // NullFields is a list of field names (e.g. "Items") to include in API
+ // requests with the JSON null value. By default, fields with empty
+ // values are omitted from API requests. However, any field with an
+ // empty value appearing in NullFields will be sent to the server as
+ // null. It is an error if a field in this list has a non-empty value.
+ // This may be used to include null fields in Patch requests.
+ NullFields []string `json:"-"`
+}
+
+func (s *Objects) MarshalJSON() ([]byte, error) {
+ type NoMethod Objects
+ raw := NoMethod(*s)
+ return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
+}
+
+// Policy: A bucket/object IAM policy.
+type Policy struct {
+ // Bindings: An association between a role, which comes with a set of
+ // permissions, and members who may assume that role.
+ Bindings []*PolicyBindings `json:"bindings,omitempty"`
+
+ // Etag: HTTP 1.1 Entity tag for the policy.
+ Etag string `json:"etag,omitempty"`
+
+ // Kind: The kind of item this is. For policies, this is always
+ // storage#policy. This field is ignored on input.
+ Kind string `json:"kind,omitempty"`
+
+ // ResourceId: The ID of the resource to which this policy belongs. Will
+ // be of the form projects/_/buckets/bucket for buckets, and
+ // projects/_/buckets/bucket/objects/object for objects. A specific
+ // generation may be specified by appending #generationNumber to the end
+ // of the object name, e.g.
+ // projects/_/buckets/my-bucket/objects/data.txt#17. The current
+ // generation can be denoted with #0. This field is ignored on input.
+ ResourceId string `json:"resourceId,omitempty"`
+
+ // ServerResponse contains the HTTP response code and headers from the
+ // server.
+ googleapi.ServerResponse `json:"-"`
+
+ // ForceSendFields is a list of field names (e.g. "Bindings") to
+ // unconditionally include in API requests. By default, fields with
+ // empty values are omitted from API requests. However, any non-pointer,
+ // non-interface field appearing in ForceSendFields will be sent to the
+ // server regardless of whether the field is empty or not. This may be
+ // used to include empty fields in Patch requests.
+ ForceSendFields []string `json:"-"`
+
+ // NullFields is a list of field names (e.g. "Bindings") to include in
+ // API requests with the JSON null value. By default, fields with empty
+ // values are omitted from API requests. However, any field with an
+ // empty value appearing in NullFields will be sent to the server as
+ // null. It is an error if a field in this list has a non-empty value.
+ // This may be used to include null fields in Patch requests.
+ NullFields []string `json:"-"`
+}
+
+func (s *Policy) MarshalJSON() ([]byte, error) {
+ type NoMethod Policy
+ raw := NoMethod(*s)
+ return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
+}
+
+type PolicyBindings struct {
+ Condition interface{} `json:"condition,omitempty"`
+
+ // Members: A collection of identifiers for members who may assume the
+ // provided role. Recognized identifiers are as follows:
+ // - allUsers — A special identifier that represents anyone on the
+ // internet; with or without a Google account.
+ // - allAuthenticatedUsers — A special identifier that represents
+ // anyone who is authenticated with a Google account or a service
+ // account.
+ // - user:emailid — An email address that represents a specific
+ // account. For example, user:alice@gmail.com or user:joe@example.com.
+ //
+ // - serviceAccount:emailid — An email address that represents a
+ // service account. For example,
+ // serviceAccount:my-other-app@appspot.gserviceaccount.com .
+ // - group:emailid — An email address that represents a Google group.
+ // For example, group:admins@example.com.
+ // - domain:domain — A Google Apps domain name that represents all the
+ // users of that domain. For example, domain:google.com or
+ // domain:example.com.
+ // - projectOwner:projectid — Owners of the given project. For
+ // example, projectOwner:my-example-project
+ // - projectEditor:projectid — Editors of the given project. For
+ // example, projectEditor:my-example-project
+ // - projectViewer:projectid — Viewers of the given project. For
+ // example, projectViewer:my-example-project
+ Members []string `json:"members,omitempty"`
+
+ // Role: The role to which members belong. Two types of roles are
+ // supported: new IAM roles, which grant permissions that do not map
+ // directly to those provided by ACLs, and legacy IAM roles, which do
+ // map directly to ACL permissions. All roles are of the format
+ // roles/storage.specificRole.
+ // The new IAM roles are:
+ // - roles/storage.admin — Full control of Google Cloud Storage
+ // resources.
+ // - roles/storage.objectViewer — Read-Only access to Google Cloud
+ // Storage objects.
+ // - roles/storage.objectCreator — Access to create objects in Google
+ // Cloud Storage.
+ // - roles/storage.objectAdmin — Full control of Google Cloud Storage
+ // objects. The legacy IAM roles are:
+ // - roles/storage.legacyObjectReader — Read-only access to objects
+ // without listing. Equivalent to an ACL entry on an object with the
+ // READER role.
+ // - roles/storage.legacyObjectOwner — Read/write access to existing
+ // objects without listing. Equivalent to an ACL entry on an object with
+ // the OWNER role.
+ // - roles/storage.legacyBucketReader — Read access to buckets with
+ // object listing. Equivalent to an ACL entry on a bucket with the
+ // READER role.
+ // - roles/storage.legacyBucketWriter — Read access to buckets with
+ // object listing/creation/deletion. Equivalent to an ACL entry on a
+ // bucket with the WRITER role.
+ // - roles/storage.legacyBucketOwner — Read and write access to
+ // existing buckets with object listing/creation/deletion. Equivalent to
+ // an ACL entry on a bucket with the OWNER role.
+ Role string `json:"role,omitempty"`
+
+ // ForceSendFields is a list of field names (e.g. "Condition") to
+ // unconditionally include in API requests. By default, fields with
+ // empty values are omitted from API requests. However, any non-pointer,
+ // non-interface field appearing in ForceSendFields will be sent to the
+ // server regardless of whether the field is empty or not. This may be
+ // used to include empty fields in Patch requests.
+ ForceSendFields []string `json:"-"`
+
+ // NullFields is a list of field names (e.g. "Condition") to include in
+ // API requests with the JSON null value. By default, fields with empty
+ // values are omitted from API requests. However, any field with an
+ // empty value appearing in NullFields will be sent to the server as
+ // null. It is an error if a field in this list has a non-empty value.
+ // This may be used to include null fields in Patch requests.
+ NullFields []string `json:"-"`
+}
+
+func (s *PolicyBindings) MarshalJSON() ([]byte, error) {
+ type NoMethod PolicyBindings
+ raw := NoMethod(*s)
+ return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
+}
+
+// RewriteResponse: A rewrite response.
+type RewriteResponse struct {
+ // Done: true if the copy is finished; otherwise, false if the copy is
+ // in progress. This property is always present in the response.
+ Done bool `json:"done,omitempty"`
+
+ // Kind: The kind of item this is.
+ Kind string `json:"kind,omitempty"`
+
+ // ObjectSize: The total size of the object being copied in bytes. This
+ // property is always present in the response.
+ ObjectSize int64 `json:"objectSize,omitempty,string"`
+
+ // Resource: A resource containing the metadata for the copied-to
+ // object. This property is present in the response only when copying
+ // completes.
+ Resource *Object `json:"resource,omitempty"`
+
+ // RewriteToken: A token to use in subsequent requests to continue
+ // copying data. This token is present in the response only when there
+ // is more data to copy.
+ RewriteToken string `json:"rewriteToken,omitempty"`
+
+ // TotalBytesRewritten: The total bytes written so far, which can be
+ // used to provide a waiting user with a progress indicator. This
+ // property is always present in the response.
+ TotalBytesRewritten int64 `json:"totalBytesRewritten,omitempty,string"`
+
+ // ServerResponse contains the HTTP response code and headers from the
+ // server.
+ googleapi.ServerResponse `json:"-"`
+
+ // ForceSendFields is a list of field names (e.g. "Done") to
+ // unconditionally include in API requests. By default, fields with
+ // empty values are omitted from API requests. However, any non-pointer,
+ // non-interface field appearing in ForceSendFields will be sent to the
+ // server regardless of whether the field is empty or not. This may be
+ // used to include empty fields in Patch requests.
+ ForceSendFields []string `json:"-"`
+
+ // NullFields is a list of field names (e.g. "Done") to include in API
+ // requests with the JSON null value. By default, fields with empty
+ // values are omitted from API requests. However, any field with an
+ // empty value appearing in NullFields will be sent to the server as
+ // null. It is an error if a field in this list has a non-empty value.
+ // This may be used to include null fields in Patch requests.
+ NullFields []string `json:"-"`
+}
+
+func (s *RewriteResponse) MarshalJSON() ([]byte, error) {
+ type NoMethod RewriteResponse
+ raw := NoMethod(*s)
+ return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
+}
+
+// ServiceAccount: A subscription to receive Google PubSub
+// notifications.
+type ServiceAccount struct {
+ // EmailAddress: The ID of the notification.
+ EmailAddress string `json:"email_address,omitempty"`
+
+ // Kind: The kind of item this is. For notifications, this is always
+ // storage#notification.
+ Kind string `json:"kind,omitempty"`
+
+ // ServerResponse contains the HTTP response code and headers from the
+ // server.
+ googleapi.ServerResponse `json:"-"`
+
+ // ForceSendFields is a list of field names (e.g. "EmailAddress") to
+ // unconditionally include in API requests. By default, fields with
+ // empty values are omitted from API requests. However, any non-pointer,
+ // non-interface field appearing in ForceSendFields will be sent to the
+ // server regardless of whether the field is empty or not. This may be
+ // used to include empty fields in Patch requests.
+ ForceSendFields []string `json:"-"`
+
+ // NullFields is a list of field names (e.g. "EmailAddress") to include
+ // in API requests with the JSON null value. By default, fields with
+ // empty values are omitted from API requests. However, any field with
+ // an empty value appearing in NullFields will be sent to the server as
+ // null. It is an error if a field in this list has a non-empty value.
+ // This may be used to include null fields in Patch requests.
+ NullFields []string `json:"-"`
+}
+
+func (s *ServiceAccount) MarshalJSON() ([]byte, error) {
+ type NoMethod ServiceAccount
+ raw := NoMethod(*s)
+ return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
+}
+
+// TestIamPermissionsResponse: A
+// storage.(buckets|objects).testIamPermissions response.
+type TestIamPermissionsResponse struct {
+ // Kind: The kind of item this is.
+ Kind string `json:"kind,omitempty"`
+
+ // Permissions: The permissions held by the caller. Permissions are
+ // always of the format storage.resource.capability, where resource is
+ // one of buckets or objects. The supported permissions are as follows:
+ //
+ // - storage.buckets.delete — Delete bucket.
+ // - storage.buckets.get — Read bucket metadata.
+ // - storage.buckets.getIamPolicy — Read bucket IAM policy.
+ // - storage.buckets.create — Create bucket.
+ // - storage.buckets.list — List buckets.
+ // - storage.buckets.setIamPolicy — Update bucket IAM policy.
+ // - storage.buckets.update — Update bucket metadata.
+ // - storage.objects.delete — Delete object.
+ // - storage.objects.get — Read object data and metadata.
+ // - storage.objects.getIamPolicy — Read object IAM policy.
+ // - storage.objects.create — Create object.
+ // - storage.objects.list — List objects.
+ // - storage.objects.setIamPolicy — Update object IAM policy.
+ // - storage.objects.update — Update object metadata.
+ Permissions []string `json:"permissions,omitempty"`
+
+ // ServerResponse contains the HTTP response code and headers from the
+ // server.
+ googleapi.ServerResponse `json:"-"`
+
+ // ForceSendFields is a list of field names (e.g. "Kind") to
+ // unconditionally include in API requests. By default, fields with
+ // empty values are omitted from API requests. However, any non-pointer,
+ // non-interface field appearing in ForceSendFields will be sent to the
+ // server regardless of whether the field is empty or not. This may be
+ // used to include empty fields in Patch requests.
+ ForceSendFields []string `json:"-"`
+
+ // NullFields is a list of field names (e.g. "Kind") to include in API
+ // requests with the JSON null value. By default, fields with empty
+ // values are omitted from API requests. However, any field with an
+ // empty value appearing in NullFields will be sent to the server as
+ // null. It is an error if a field in this list has a non-empty value.
+ // This may be used to include null fields in Patch requests.
+ NullFields []string `json:"-"`
+}
+
+func (s *TestIamPermissionsResponse) MarshalJSON() ([]byte, error) {
+ type NoMethod TestIamPermissionsResponse
+ raw := NoMethod(*s)
+ return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields)
+}
+
+// method id "storage.bucketAccessControls.delete":
+
+type BucketAccessControlsDeleteCall struct {
+ s *Service
+ bucket string
+ entity string
+ urlParams_ gensupport.URLParams
+ ctx_ context.Context
+ header_ http.Header
+}
+
+// Delete: Permanently deletes the ACL entry for the specified entity on
+// the specified bucket.
+func (r *BucketAccessControlsService) Delete(bucket string, entity string) *BucketAccessControlsDeleteCall {
+ c := &BucketAccessControlsDeleteCall{s: r.s, urlParams_: make(gensupport.URLParams)}
+ c.bucket = bucket
+ c.entity = entity
+ return c
+}
+
+// UserProject sets the optional parameter "userProject": The project to
+// be billed for this request. Required for Requester Pays buckets.
+func (c *BucketAccessControlsDeleteCall) UserProject(userProject string) *BucketAccessControlsDeleteCall {
+ c.urlParams_.Set("userProject", userProject)
+ return c
+}
+
+// Fields allows partial responses to be retrieved. See
+// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
+// for more information.
+func (c *BucketAccessControlsDeleteCall) Fields(s ...googleapi.Field) *BucketAccessControlsDeleteCall {
+ c.urlParams_.Set("fields", googleapi.CombineFields(s))
+ return c
+}
+
+// Context sets the context to be used in this call's Do method. Any
+// pending HTTP request will be aborted if the provided context is
+// canceled.
+func (c *BucketAccessControlsDeleteCall) Context(ctx context.Context) *BucketAccessControlsDeleteCall {
+ c.ctx_ = ctx
+ return c
+}
+
+// Header returns an http.Header that can be modified by the caller to
+// add HTTP headers to the request.
+func (c *BucketAccessControlsDeleteCall) Header() http.Header {
+ if c.header_ == nil {
+ c.header_ = make(http.Header)
+ }
+ return c.header_
+}
+
+func (c *BucketAccessControlsDeleteCall) doRequest(alt string) (*http.Response, error) {
+ reqHeaders := make(http.Header)
+ for k, v := range c.header_ {
+ reqHeaders[k] = v
+ }
+ reqHeaders.Set("User-Agent", c.s.userAgent())
+ var body io.Reader = nil
+ c.urlParams_.Set("alt", alt)
+ c.urlParams_.Set("prettyPrint", "false")
+ urls := googleapi.ResolveRelative(c.s.BasePath, "b/{bucket}/acl/{entity}")
+ urls += "?" + c.urlParams_.Encode()
+ req, err := http.NewRequest("DELETE", urls, body)
+ if err != nil {
+ return nil, err
+ }
+ req.Header = reqHeaders
+ googleapi.Expand(req.URL, map[string]string{
+ "bucket": c.bucket,
+ "entity": c.entity,
+ })
+ return gensupport.SendRequest(c.ctx_, c.s.client, req)
+}
+
+// Do executes the "storage.bucketAccessControls.delete" call.
+func (c *BucketAccessControlsDeleteCall) Do(opts ...googleapi.CallOption) error {
+ gensupport.SetOptions(c.urlParams_, opts...)
+ res, err := c.doRequest("json")
+ if err != nil {
+ return err
+ }
+ defer googleapi.CloseBody(res)
+ if err := googleapi.CheckResponse(res); err != nil {
+ return err
+ }
+ return nil
+ // {
+ // "description": "Permanently deletes the ACL entry for the specified entity on the specified bucket.",
+ // "httpMethod": "DELETE",
+ // "id": "storage.bucketAccessControls.delete",
+ // "parameterOrder": [
+ // "bucket",
+ // "entity"
+ // ],
+ // "parameters": {
+ // "bucket": {
+ // "description": "Name of a bucket.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "entity": {
+ // "description": "The entity holding the permission. Can be user-userId, user-emailAddress, group-groupId, group-emailAddress, allUsers, or allAuthenticatedUsers.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "userProject": {
+ // "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ // "location": "query",
+ // "type": "string"
+ // }
+ // },
+ // "path": "b/{bucket}/acl/{entity}",
+ // "scopes": [
+ // "https://www.googleapis.com/auth/cloud-platform",
+ // "https://www.googleapis.com/auth/devstorage.full_control"
+ // ]
+ // }
+
+}
+
+// method id "storage.bucketAccessControls.get":
+
+type BucketAccessControlsGetCall struct {
+ s *Service
+ bucket string
+ entity string
+ urlParams_ gensupport.URLParams
+ ifNoneMatch_ string
+ ctx_ context.Context
+ header_ http.Header
+}
+
+// Get: Returns the ACL entry for the specified entity on the specified
+// bucket.
+func (r *BucketAccessControlsService) Get(bucket string, entity string) *BucketAccessControlsGetCall {
+ c := &BucketAccessControlsGetCall{s: r.s, urlParams_: make(gensupport.URLParams)}
+ c.bucket = bucket
+ c.entity = entity
+ return c
+}
+
+// UserProject sets the optional parameter "userProject": The project to
+// be billed for this request. Required for Requester Pays buckets.
+func (c *BucketAccessControlsGetCall) UserProject(userProject string) *BucketAccessControlsGetCall {
+ c.urlParams_.Set("userProject", userProject)
+ return c
+}
+
+// Fields allows partial responses to be retrieved. See
+// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
+// for more information.
+func (c *BucketAccessControlsGetCall) Fields(s ...googleapi.Field) *BucketAccessControlsGetCall {
+ c.urlParams_.Set("fields", googleapi.CombineFields(s))
+ return c
+}
+
+// IfNoneMatch sets the optional parameter which makes the operation
+// fail if the object's ETag matches the given value. This is useful for
+// getting updates only after the object has changed since the last
+// request. Use googleapi.IsNotModified to check whether the response
+// error from Do is the result of In-None-Match.
+func (c *BucketAccessControlsGetCall) IfNoneMatch(entityTag string) *BucketAccessControlsGetCall {
+ c.ifNoneMatch_ = entityTag
+ return c
+}
+
+// Context sets the context to be used in this call's Do method. Any
+// pending HTTP request will be aborted if the provided context is
+// canceled.
+func (c *BucketAccessControlsGetCall) Context(ctx context.Context) *BucketAccessControlsGetCall {
+ c.ctx_ = ctx
+ return c
+}
+
+// Header returns an http.Header that can be modified by the caller to
+// add HTTP headers to the request.
+func (c *BucketAccessControlsGetCall) Header() http.Header {
+ if c.header_ == nil {
+ c.header_ = make(http.Header)
+ }
+ return c.header_
+}
+
+func (c *BucketAccessControlsGetCall) doRequest(alt string) (*http.Response, error) {
+ reqHeaders := make(http.Header)
+ for k, v := range c.header_ {
+ reqHeaders[k] = v
+ }
+ reqHeaders.Set("User-Agent", c.s.userAgent())
+ if c.ifNoneMatch_ != "" {
+ reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
+ }
+ var body io.Reader = nil
+ c.urlParams_.Set("alt", alt)
+ c.urlParams_.Set("prettyPrint", "false")
+ urls := googleapi.ResolveRelative(c.s.BasePath, "b/{bucket}/acl/{entity}")
+ urls += "?" + c.urlParams_.Encode()
+ req, err := http.NewRequest("GET", urls, body)
+ if err != nil {
+ return nil, err
+ }
+ req.Header = reqHeaders
+ googleapi.Expand(req.URL, map[string]string{
+ "bucket": c.bucket,
+ "entity": c.entity,
+ })
+ return gensupport.SendRequest(c.ctx_, c.s.client, req)
+}
+
+// Do executes the "storage.bucketAccessControls.get" call.
+// Exactly one of *BucketAccessControl or error will be non-nil. Any
+// non-2xx status code is an error. Response headers are in either
+// *BucketAccessControl.ServerResponse.Header or (if a response was
+// returned at all) in error.(*googleapi.Error).Header. Use
+// googleapi.IsNotModified to check whether the returned error was
+// because http.StatusNotModified was returned.
+func (c *BucketAccessControlsGetCall) Do(opts ...googleapi.CallOption) (*BucketAccessControl, error) {
+ gensupport.SetOptions(c.urlParams_, opts...)
+ res, err := c.doRequest("json")
+ if res != nil && res.StatusCode == http.StatusNotModified {
+ if res.Body != nil {
+ res.Body.Close()
+ }
+ return nil, &googleapi.Error{
+ Code: res.StatusCode,
+ Header: res.Header,
+ }
+ }
+ if err != nil {
+ return nil, err
+ }
+ defer googleapi.CloseBody(res)
+ if err := googleapi.CheckResponse(res); err != nil {
+ return nil, err
+ }
+ ret := &BucketAccessControl{
+ ServerResponse: googleapi.ServerResponse{
+ Header: res.Header,
+ HTTPStatusCode: res.StatusCode,
+ },
+ }
+ target := &ret
+ if err := gensupport.DecodeResponse(target, res); err != nil {
+ return nil, err
+ }
+ return ret, nil
+ // {
+ // "description": "Returns the ACL entry for the specified entity on the specified bucket.",
+ // "httpMethod": "GET",
+ // "id": "storage.bucketAccessControls.get",
+ // "parameterOrder": [
+ // "bucket",
+ // "entity"
+ // ],
+ // "parameters": {
+ // "bucket": {
+ // "description": "Name of a bucket.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "entity": {
+ // "description": "The entity holding the permission. Can be user-userId, user-emailAddress, group-groupId, group-emailAddress, allUsers, or allAuthenticatedUsers.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "userProject": {
+ // "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ // "location": "query",
+ // "type": "string"
+ // }
+ // },
+ // "path": "b/{bucket}/acl/{entity}",
+ // "response": {
+ // "$ref": "BucketAccessControl"
+ // },
+ // "scopes": [
+ // "https://www.googleapis.com/auth/cloud-platform",
+ // "https://www.googleapis.com/auth/devstorage.full_control"
+ // ]
+ // }
+
+}
+
+// method id "storage.bucketAccessControls.insert":
+
+type BucketAccessControlsInsertCall struct {
+ s *Service
+ bucket string
+ bucketaccesscontrol *BucketAccessControl
+ urlParams_ gensupport.URLParams
+ ctx_ context.Context
+ header_ http.Header
+}
+
+// Insert: Creates a new ACL entry on the specified bucket.
+func (r *BucketAccessControlsService) Insert(bucket string, bucketaccesscontrol *BucketAccessControl) *BucketAccessControlsInsertCall {
+ c := &BucketAccessControlsInsertCall{s: r.s, urlParams_: make(gensupport.URLParams)}
+ c.bucket = bucket
+ c.bucketaccesscontrol = bucketaccesscontrol
+ return c
+}
+
+// UserProject sets the optional parameter "userProject": The project to
+// be billed for this request. Required for Requester Pays buckets.
+func (c *BucketAccessControlsInsertCall) UserProject(userProject string) *BucketAccessControlsInsertCall {
+ c.urlParams_.Set("userProject", userProject)
+ return c
+}
+
+// Fields allows partial responses to be retrieved. See
+// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
+// for more information.
+func (c *BucketAccessControlsInsertCall) Fields(s ...googleapi.Field) *BucketAccessControlsInsertCall {
+ c.urlParams_.Set("fields", googleapi.CombineFields(s))
+ return c
+}
+
+// Context sets the context to be used in this call's Do method. Any
+// pending HTTP request will be aborted if the provided context is
+// canceled.
+func (c *BucketAccessControlsInsertCall) Context(ctx context.Context) *BucketAccessControlsInsertCall {
+ c.ctx_ = ctx
+ return c
+}
+
+// Header returns an http.Header that can be modified by the caller to
+// add HTTP headers to the request.
+func (c *BucketAccessControlsInsertCall) Header() http.Header {
+ if c.header_ == nil {
+ c.header_ = make(http.Header)
+ }
+ return c.header_
+}
+
+func (c *BucketAccessControlsInsertCall) doRequest(alt string) (*http.Response, error) {
+ reqHeaders := make(http.Header)
+ for k, v := range c.header_ {
+ reqHeaders[k] = v
+ }
+ reqHeaders.Set("User-Agent", c.s.userAgent())
+ var body io.Reader = nil
+ body, err := googleapi.WithoutDataWrapper.JSONReader(c.bucketaccesscontrol)
+ if err != nil {
+ return nil, err
+ }
+ reqHeaders.Set("Content-Type", "application/json")
+ c.urlParams_.Set("alt", alt)
+ c.urlParams_.Set("prettyPrint", "false")
+ urls := googleapi.ResolveRelative(c.s.BasePath, "b/{bucket}/acl")
+ urls += "?" + c.urlParams_.Encode()
+ req, err := http.NewRequest("POST", urls, body)
+ if err != nil {
+ return nil, err
+ }
+ req.Header = reqHeaders
+ googleapi.Expand(req.URL, map[string]string{
+ "bucket": c.bucket,
+ })
+ return gensupport.SendRequest(c.ctx_, c.s.client, req)
+}
+
+// Do executes the "storage.bucketAccessControls.insert" call.
+// Exactly one of *BucketAccessControl or error will be non-nil. Any
+// non-2xx status code is an error. Response headers are in either
+// *BucketAccessControl.ServerResponse.Header or (if a response was
+// returned at all) in error.(*googleapi.Error).Header. Use
+// googleapi.IsNotModified to check whether the returned error was
+// because http.StatusNotModified was returned.
+func (c *BucketAccessControlsInsertCall) Do(opts ...googleapi.CallOption) (*BucketAccessControl, error) {
+ gensupport.SetOptions(c.urlParams_, opts...)
+ res, err := c.doRequest("json")
+ if res != nil && res.StatusCode == http.StatusNotModified {
+ if res.Body != nil {
+ res.Body.Close()
+ }
+ return nil, &googleapi.Error{
+ Code: res.StatusCode,
+ Header: res.Header,
+ }
+ }
+ if err != nil {
+ return nil, err
+ }
+ defer googleapi.CloseBody(res)
+ if err := googleapi.CheckResponse(res); err != nil {
+ return nil, err
+ }
+ ret := &BucketAccessControl{
+ ServerResponse: googleapi.ServerResponse{
+ Header: res.Header,
+ HTTPStatusCode: res.StatusCode,
+ },
+ }
+ target := &ret
+ if err := gensupport.DecodeResponse(target, res); err != nil {
+ return nil, err
+ }
+ return ret, nil
+ // {
+ // "description": "Creates a new ACL entry on the specified bucket.",
+ // "httpMethod": "POST",
+ // "id": "storage.bucketAccessControls.insert",
+ // "parameterOrder": [
+ // "bucket"
+ // ],
+ // "parameters": {
+ // "bucket": {
+ // "description": "Name of a bucket.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "userProject": {
+ // "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ // "location": "query",
+ // "type": "string"
+ // }
+ // },
+ // "path": "b/{bucket}/acl",
+ // "request": {
+ // "$ref": "BucketAccessControl"
+ // },
+ // "response": {
+ // "$ref": "BucketAccessControl"
+ // },
+ // "scopes": [
+ // "https://www.googleapis.com/auth/cloud-platform",
+ // "https://www.googleapis.com/auth/devstorage.full_control"
+ // ]
+ // }
+
+}
+
+// method id "storage.bucketAccessControls.list":
+
+type BucketAccessControlsListCall struct {
+ s *Service
+ bucket string
+ urlParams_ gensupport.URLParams
+ ifNoneMatch_ string
+ ctx_ context.Context
+ header_ http.Header
+}
+
+// List: Retrieves ACL entries on the specified bucket.
+func (r *BucketAccessControlsService) List(bucket string) *BucketAccessControlsListCall {
+ c := &BucketAccessControlsListCall{s: r.s, urlParams_: make(gensupport.URLParams)}
+ c.bucket = bucket
+ return c
+}
+
+// UserProject sets the optional parameter "userProject": The project to
+// be billed for this request. Required for Requester Pays buckets.
+func (c *BucketAccessControlsListCall) UserProject(userProject string) *BucketAccessControlsListCall {
+ c.urlParams_.Set("userProject", userProject)
+ return c
+}
+
+// Fields allows partial responses to be retrieved. See
+// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
+// for more information.
+func (c *BucketAccessControlsListCall) Fields(s ...googleapi.Field) *BucketAccessControlsListCall {
+ c.urlParams_.Set("fields", googleapi.CombineFields(s))
+ return c
+}
+
+// IfNoneMatch sets the optional parameter which makes the operation
+// fail if the object's ETag matches the given value. This is useful for
+// getting updates only after the object has changed since the last
+// request. Use googleapi.IsNotModified to check whether the response
+// error from Do is the result of In-None-Match.
+func (c *BucketAccessControlsListCall) IfNoneMatch(entityTag string) *BucketAccessControlsListCall {
+ c.ifNoneMatch_ = entityTag
+ return c
+}
+
+// Context sets the context to be used in this call's Do method. Any
+// pending HTTP request will be aborted if the provided context is
+// canceled.
+func (c *BucketAccessControlsListCall) Context(ctx context.Context) *BucketAccessControlsListCall {
+ c.ctx_ = ctx
+ return c
+}
+
+// Header returns an http.Header that can be modified by the caller to
+// add HTTP headers to the request.
+func (c *BucketAccessControlsListCall) Header() http.Header {
+ if c.header_ == nil {
+ c.header_ = make(http.Header)
+ }
+ return c.header_
+}
+
+func (c *BucketAccessControlsListCall) doRequest(alt string) (*http.Response, error) {
+ reqHeaders := make(http.Header)
+ for k, v := range c.header_ {
+ reqHeaders[k] = v
+ }
+ reqHeaders.Set("User-Agent", c.s.userAgent())
+ if c.ifNoneMatch_ != "" {
+ reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
+ }
+ var body io.Reader = nil
+ c.urlParams_.Set("alt", alt)
+ c.urlParams_.Set("prettyPrint", "false")
+ urls := googleapi.ResolveRelative(c.s.BasePath, "b/{bucket}/acl")
+ urls += "?" + c.urlParams_.Encode()
+ req, err := http.NewRequest("GET", urls, body)
+ if err != nil {
+ return nil, err
+ }
+ req.Header = reqHeaders
+ googleapi.Expand(req.URL, map[string]string{
+ "bucket": c.bucket,
+ })
+ return gensupport.SendRequest(c.ctx_, c.s.client, req)
+}
+
+// Do executes the "storage.bucketAccessControls.list" call.
+// Exactly one of *BucketAccessControls or error will be non-nil. Any
+// non-2xx status code is an error. Response headers are in either
+// *BucketAccessControls.ServerResponse.Header or (if a response was
+// returned at all) in error.(*googleapi.Error).Header. Use
+// googleapi.IsNotModified to check whether the returned error was
+// because http.StatusNotModified was returned.
+func (c *BucketAccessControlsListCall) Do(opts ...googleapi.CallOption) (*BucketAccessControls, error) {
+ gensupport.SetOptions(c.urlParams_, opts...)
+ res, err := c.doRequest("json")
+ if res != nil && res.StatusCode == http.StatusNotModified {
+ if res.Body != nil {
+ res.Body.Close()
+ }
+ return nil, &googleapi.Error{
+ Code: res.StatusCode,
+ Header: res.Header,
+ }
+ }
+ if err != nil {
+ return nil, err
+ }
+ defer googleapi.CloseBody(res)
+ if err := googleapi.CheckResponse(res); err != nil {
+ return nil, err
+ }
+ ret := &BucketAccessControls{
+ ServerResponse: googleapi.ServerResponse{
+ Header: res.Header,
+ HTTPStatusCode: res.StatusCode,
+ },
+ }
+ target := &ret
+ if err := gensupport.DecodeResponse(target, res); err != nil {
+ return nil, err
+ }
+ return ret, nil
+ // {
+ // "description": "Retrieves ACL entries on the specified bucket.",
+ // "httpMethod": "GET",
+ // "id": "storage.bucketAccessControls.list",
+ // "parameterOrder": [
+ // "bucket"
+ // ],
+ // "parameters": {
+ // "bucket": {
+ // "description": "Name of a bucket.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "userProject": {
+ // "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ // "location": "query",
+ // "type": "string"
+ // }
+ // },
+ // "path": "b/{bucket}/acl",
+ // "response": {
+ // "$ref": "BucketAccessControls"
+ // },
+ // "scopes": [
+ // "https://www.googleapis.com/auth/cloud-platform",
+ // "https://www.googleapis.com/auth/devstorage.full_control"
+ // ]
+ // }
+
+}
+
+// method id "storage.bucketAccessControls.patch":
+
+type BucketAccessControlsPatchCall struct {
+ s *Service
+ bucket string
+ entity string
+ bucketaccesscontrol *BucketAccessControl
+ urlParams_ gensupport.URLParams
+ ctx_ context.Context
+ header_ http.Header
+}
+
+// Patch: Patches an ACL entry on the specified bucket.
+func (r *BucketAccessControlsService) Patch(bucket string, entity string, bucketaccesscontrol *BucketAccessControl) *BucketAccessControlsPatchCall {
+ c := &BucketAccessControlsPatchCall{s: r.s, urlParams_: make(gensupport.URLParams)}
+ c.bucket = bucket
+ c.entity = entity
+ c.bucketaccesscontrol = bucketaccesscontrol
+ return c
+}
+
+// UserProject sets the optional parameter "userProject": The project to
+// be billed for this request. Required for Requester Pays buckets.
+func (c *BucketAccessControlsPatchCall) UserProject(userProject string) *BucketAccessControlsPatchCall {
+ c.urlParams_.Set("userProject", userProject)
+ return c
+}
+
+// Fields allows partial responses to be retrieved. See
+// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
+// for more information.
+func (c *BucketAccessControlsPatchCall) Fields(s ...googleapi.Field) *BucketAccessControlsPatchCall {
+ c.urlParams_.Set("fields", googleapi.CombineFields(s))
+ return c
+}
+
+// Context sets the context to be used in this call's Do method. Any
+// pending HTTP request will be aborted if the provided context is
+// canceled.
+func (c *BucketAccessControlsPatchCall) Context(ctx context.Context) *BucketAccessControlsPatchCall {
+ c.ctx_ = ctx
+ return c
+}
+
+// Header returns an http.Header that can be modified by the caller to
+// add HTTP headers to the request.
+func (c *BucketAccessControlsPatchCall) Header() http.Header {
+ if c.header_ == nil {
+ c.header_ = make(http.Header)
+ }
+ return c.header_
+}
+
+func (c *BucketAccessControlsPatchCall) doRequest(alt string) (*http.Response, error) {
+ reqHeaders := make(http.Header)
+ for k, v := range c.header_ {
+ reqHeaders[k] = v
+ }
+ reqHeaders.Set("User-Agent", c.s.userAgent())
+ var body io.Reader = nil
+ body, err := googleapi.WithoutDataWrapper.JSONReader(c.bucketaccesscontrol)
+ if err != nil {
+ return nil, err
+ }
+ reqHeaders.Set("Content-Type", "application/json")
+ c.urlParams_.Set("alt", alt)
+ c.urlParams_.Set("prettyPrint", "false")
+ urls := googleapi.ResolveRelative(c.s.BasePath, "b/{bucket}/acl/{entity}")
+ urls += "?" + c.urlParams_.Encode()
+ req, err := http.NewRequest("PATCH", urls, body)
+ if err != nil {
+ return nil, err
+ }
+ req.Header = reqHeaders
+ googleapi.Expand(req.URL, map[string]string{
+ "bucket": c.bucket,
+ "entity": c.entity,
+ })
+ return gensupport.SendRequest(c.ctx_, c.s.client, req)
+}
+
+// Do executes the "storage.bucketAccessControls.patch" call.
+// Exactly one of *BucketAccessControl or error will be non-nil. Any
+// non-2xx status code is an error. Response headers are in either
+// *BucketAccessControl.ServerResponse.Header or (if a response was
+// returned at all) in error.(*googleapi.Error).Header. Use
+// googleapi.IsNotModified to check whether the returned error was
+// because http.StatusNotModified was returned.
+func (c *BucketAccessControlsPatchCall) Do(opts ...googleapi.CallOption) (*BucketAccessControl, error) {
+ gensupport.SetOptions(c.urlParams_, opts...)
+ res, err := c.doRequest("json")
+ if res != nil && res.StatusCode == http.StatusNotModified {
+ if res.Body != nil {
+ res.Body.Close()
+ }
+ return nil, &googleapi.Error{
+ Code: res.StatusCode,
+ Header: res.Header,
+ }
+ }
+ if err != nil {
+ return nil, err
+ }
+ defer googleapi.CloseBody(res)
+ if err := googleapi.CheckResponse(res); err != nil {
+ return nil, err
+ }
+ ret := &BucketAccessControl{
+ ServerResponse: googleapi.ServerResponse{
+ Header: res.Header,
+ HTTPStatusCode: res.StatusCode,
+ },
+ }
+ target := &ret
+ if err := gensupport.DecodeResponse(target, res); err != nil {
+ return nil, err
+ }
+ return ret, nil
+ // {
+ // "description": "Patches an ACL entry on the specified bucket.",
+ // "httpMethod": "PATCH",
+ // "id": "storage.bucketAccessControls.patch",
+ // "parameterOrder": [
+ // "bucket",
+ // "entity"
+ // ],
+ // "parameters": {
+ // "bucket": {
+ // "description": "Name of a bucket.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "entity": {
+ // "description": "The entity holding the permission. Can be user-userId, user-emailAddress, group-groupId, group-emailAddress, allUsers, or allAuthenticatedUsers.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "userProject": {
+ // "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ // "location": "query",
+ // "type": "string"
+ // }
+ // },
+ // "path": "b/{bucket}/acl/{entity}",
+ // "request": {
+ // "$ref": "BucketAccessControl"
+ // },
+ // "response": {
+ // "$ref": "BucketAccessControl"
+ // },
+ // "scopes": [
+ // "https://www.googleapis.com/auth/cloud-platform",
+ // "https://www.googleapis.com/auth/devstorage.full_control"
+ // ]
+ // }
+
+}
+
+// method id "storage.bucketAccessControls.update":
+
+type BucketAccessControlsUpdateCall struct {
+ s *Service
+ bucket string
+ entity string
+ bucketaccesscontrol *BucketAccessControl
+ urlParams_ gensupport.URLParams
+ ctx_ context.Context
+ header_ http.Header
+}
+
+// Update: Updates an ACL entry on the specified bucket.
+func (r *BucketAccessControlsService) Update(bucket string, entity string, bucketaccesscontrol *BucketAccessControl) *BucketAccessControlsUpdateCall {
+ c := &BucketAccessControlsUpdateCall{s: r.s, urlParams_: make(gensupport.URLParams)}
+ c.bucket = bucket
+ c.entity = entity
+ c.bucketaccesscontrol = bucketaccesscontrol
+ return c
+}
+
+// UserProject sets the optional parameter "userProject": The project to
+// be billed for this request. Required for Requester Pays buckets.
+func (c *BucketAccessControlsUpdateCall) UserProject(userProject string) *BucketAccessControlsUpdateCall {
+ c.urlParams_.Set("userProject", userProject)
+ return c
+}
+
+// Fields allows partial responses to be retrieved. See
+// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
+// for more information.
+func (c *BucketAccessControlsUpdateCall) Fields(s ...googleapi.Field) *BucketAccessControlsUpdateCall {
+ c.urlParams_.Set("fields", googleapi.CombineFields(s))
+ return c
+}
+
+// Context sets the context to be used in this call's Do method. Any
+// pending HTTP request will be aborted if the provided context is
+// canceled.
+func (c *BucketAccessControlsUpdateCall) Context(ctx context.Context) *BucketAccessControlsUpdateCall {
+ c.ctx_ = ctx
+ return c
+}
+
+// Header returns an http.Header that can be modified by the caller to
+// add HTTP headers to the request.
+func (c *BucketAccessControlsUpdateCall) Header() http.Header {
+ if c.header_ == nil {
+ c.header_ = make(http.Header)
+ }
+ return c.header_
+}
+
+func (c *BucketAccessControlsUpdateCall) doRequest(alt string) (*http.Response, error) {
+ reqHeaders := make(http.Header)
+ for k, v := range c.header_ {
+ reqHeaders[k] = v
+ }
+ reqHeaders.Set("User-Agent", c.s.userAgent())
+ var body io.Reader = nil
+ body, err := googleapi.WithoutDataWrapper.JSONReader(c.bucketaccesscontrol)
+ if err != nil {
+ return nil, err
+ }
+ reqHeaders.Set("Content-Type", "application/json")
+ c.urlParams_.Set("alt", alt)
+ c.urlParams_.Set("prettyPrint", "false")
+ urls := googleapi.ResolveRelative(c.s.BasePath, "b/{bucket}/acl/{entity}")
+ urls += "?" + c.urlParams_.Encode()
+ req, err := http.NewRequest("PUT", urls, body)
+ if err != nil {
+ return nil, err
+ }
+ req.Header = reqHeaders
+ googleapi.Expand(req.URL, map[string]string{
+ "bucket": c.bucket,
+ "entity": c.entity,
+ })
+ return gensupport.SendRequest(c.ctx_, c.s.client, req)
+}
+
+// Do executes the "storage.bucketAccessControls.update" call.
+// Exactly one of *BucketAccessControl or error will be non-nil. Any
+// non-2xx status code is an error. Response headers are in either
+// *BucketAccessControl.ServerResponse.Header or (if a response was
+// returned at all) in error.(*googleapi.Error).Header. Use
+// googleapi.IsNotModified to check whether the returned error was
+// because http.StatusNotModified was returned.
+func (c *BucketAccessControlsUpdateCall) Do(opts ...googleapi.CallOption) (*BucketAccessControl, error) {
+ gensupport.SetOptions(c.urlParams_, opts...)
+ res, err := c.doRequest("json")
+ if res != nil && res.StatusCode == http.StatusNotModified {
+ if res.Body != nil {
+ res.Body.Close()
+ }
+ return nil, &googleapi.Error{
+ Code: res.StatusCode,
+ Header: res.Header,
+ }
+ }
+ if err != nil {
+ return nil, err
+ }
+ defer googleapi.CloseBody(res)
+ if err := googleapi.CheckResponse(res); err != nil {
+ return nil, err
+ }
+ ret := &BucketAccessControl{
+ ServerResponse: googleapi.ServerResponse{
+ Header: res.Header,
+ HTTPStatusCode: res.StatusCode,
+ },
+ }
+ target := &ret
+ if err := gensupport.DecodeResponse(target, res); err != nil {
+ return nil, err
+ }
+ return ret, nil
+ // {
+ // "description": "Updates an ACL entry on the specified bucket.",
+ // "httpMethod": "PUT",
+ // "id": "storage.bucketAccessControls.update",
+ // "parameterOrder": [
+ // "bucket",
+ // "entity"
+ // ],
+ // "parameters": {
+ // "bucket": {
+ // "description": "Name of a bucket.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "entity": {
+ // "description": "The entity holding the permission. Can be user-userId, user-emailAddress, group-groupId, group-emailAddress, allUsers, or allAuthenticatedUsers.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "userProject": {
+ // "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ // "location": "query",
+ // "type": "string"
+ // }
+ // },
+ // "path": "b/{bucket}/acl/{entity}",
+ // "request": {
+ // "$ref": "BucketAccessControl"
+ // },
+ // "response": {
+ // "$ref": "BucketAccessControl"
+ // },
+ // "scopes": [
+ // "https://www.googleapis.com/auth/cloud-platform",
+ // "https://www.googleapis.com/auth/devstorage.full_control"
+ // ]
+ // }
+
+}
+
+// method id "storage.buckets.delete":
+
+type BucketsDeleteCall struct {
+ s *Service
+ bucket string
+ urlParams_ gensupport.URLParams
+ ctx_ context.Context
+ header_ http.Header
+}
+
+// Delete: Permanently deletes an empty bucket.
+func (r *BucketsService) Delete(bucket string) *BucketsDeleteCall {
+ c := &BucketsDeleteCall{s: r.s, urlParams_: make(gensupport.URLParams)}
+ c.bucket = bucket
+ return c
+}
+
+// IfMetagenerationMatch sets the optional parameter
+// "ifMetagenerationMatch": If set, only deletes the bucket if its
+// metageneration matches this value.
+func (c *BucketsDeleteCall) IfMetagenerationMatch(ifMetagenerationMatch int64) *BucketsDeleteCall {
+ c.urlParams_.Set("ifMetagenerationMatch", fmt.Sprint(ifMetagenerationMatch))
+ return c
+}
+
+// IfMetagenerationNotMatch sets the optional parameter
+// "ifMetagenerationNotMatch": If set, only deletes the bucket if its
+// metageneration does not match this value.
+func (c *BucketsDeleteCall) IfMetagenerationNotMatch(ifMetagenerationNotMatch int64) *BucketsDeleteCall {
+ c.urlParams_.Set("ifMetagenerationNotMatch", fmt.Sprint(ifMetagenerationNotMatch))
+ return c
+}
+
+// UserProject sets the optional parameter "userProject": The project to
+// be billed for this request. Required for Requester Pays buckets.
+func (c *BucketsDeleteCall) UserProject(userProject string) *BucketsDeleteCall {
+ c.urlParams_.Set("userProject", userProject)
+ return c
+}
+
+// Fields allows partial responses to be retrieved. See
+// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
+// for more information.
+func (c *BucketsDeleteCall) Fields(s ...googleapi.Field) *BucketsDeleteCall {
+ c.urlParams_.Set("fields", googleapi.CombineFields(s))
+ return c
+}
+
+// Context sets the context to be used in this call's Do method. Any
+// pending HTTP request will be aborted if the provided context is
+// canceled.
+func (c *BucketsDeleteCall) Context(ctx context.Context) *BucketsDeleteCall {
+ c.ctx_ = ctx
+ return c
+}
+
+// Header returns an http.Header that can be modified by the caller to
+// add HTTP headers to the request.
+func (c *BucketsDeleteCall) Header() http.Header {
+ if c.header_ == nil {
+ c.header_ = make(http.Header)
+ }
+ return c.header_
+}
+
+func (c *BucketsDeleteCall) doRequest(alt string) (*http.Response, error) {
+ reqHeaders := make(http.Header)
+ for k, v := range c.header_ {
+ reqHeaders[k] = v
+ }
+ reqHeaders.Set("User-Agent", c.s.userAgent())
+ var body io.Reader = nil
+ c.urlParams_.Set("alt", alt)
+ c.urlParams_.Set("prettyPrint", "false")
+ urls := googleapi.ResolveRelative(c.s.BasePath, "b/{bucket}")
+ urls += "?" + c.urlParams_.Encode()
+ req, err := http.NewRequest("DELETE", urls, body)
+ if err != nil {
+ return nil, err
+ }
+ req.Header = reqHeaders
+ googleapi.Expand(req.URL, map[string]string{
+ "bucket": c.bucket,
+ })
+ return gensupport.SendRequest(c.ctx_, c.s.client, req)
+}
+
+// Do executes the "storage.buckets.delete" call.
+func (c *BucketsDeleteCall) Do(opts ...googleapi.CallOption) error {
+ gensupport.SetOptions(c.urlParams_, opts...)
+ res, err := c.doRequest("json")
+ if err != nil {
+ return err
+ }
+ defer googleapi.CloseBody(res)
+ if err := googleapi.CheckResponse(res); err != nil {
+ return err
+ }
+ return nil
+ // {
+ // "description": "Permanently deletes an empty bucket.",
+ // "httpMethod": "DELETE",
+ // "id": "storage.buckets.delete",
+ // "parameterOrder": [
+ // "bucket"
+ // ],
+ // "parameters": {
+ // "bucket": {
+ // "description": "Name of a bucket.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "ifMetagenerationMatch": {
+ // "description": "If set, only deletes the bucket if its metageneration matches this value.",
+ // "format": "int64",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "ifMetagenerationNotMatch": {
+ // "description": "If set, only deletes the bucket if its metageneration does not match this value.",
+ // "format": "int64",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "userProject": {
+ // "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ // "location": "query",
+ // "type": "string"
+ // }
+ // },
+ // "path": "b/{bucket}",
+ // "scopes": [
+ // "https://www.googleapis.com/auth/cloud-platform",
+ // "https://www.googleapis.com/auth/devstorage.full_control",
+ // "https://www.googleapis.com/auth/devstorage.read_write"
+ // ]
+ // }
+
+}
+
+// method id "storage.buckets.get":
+
+type BucketsGetCall struct {
+ s *Service
+ bucket string
+ urlParams_ gensupport.URLParams
+ ifNoneMatch_ string
+ ctx_ context.Context
+ header_ http.Header
+}
+
+// Get: Returns metadata for the specified bucket.
+func (r *BucketsService) Get(bucket string) *BucketsGetCall {
+ c := &BucketsGetCall{s: r.s, urlParams_: make(gensupport.URLParams)}
+ c.bucket = bucket
+ return c
+}
+
+// IfMetagenerationMatch sets the optional parameter
+// "ifMetagenerationMatch": Makes the return of the bucket metadata
+// conditional on whether the bucket's current metageneration matches
+// the given value.
+func (c *BucketsGetCall) IfMetagenerationMatch(ifMetagenerationMatch int64) *BucketsGetCall {
+ c.urlParams_.Set("ifMetagenerationMatch", fmt.Sprint(ifMetagenerationMatch))
+ return c
+}
+
+// IfMetagenerationNotMatch sets the optional parameter
+// "ifMetagenerationNotMatch": Makes the return of the bucket metadata
+// conditional on whether the bucket's current metageneration does not
+// match the given value.
+func (c *BucketsGetCall) IfMetagenerationNotMatch(ifMetagenerationNotMatch int64) *BucketsGetCall {
+ c.urlParams_.Set("ifMetagenerationNotMatch", fmt.Sprint(ifMetagenerationNotMatch))
+ return c
+}
+
+// Projection sets the optional parameter "projection": Set of
+// properties to return. Defaults to noAcl.
+//
+// Possible values:
+// "full" - Include all properties.
+// "noAcl" - Omit owner, acl and defaultObjectAcl properties.
+func (c *BucketsGetCall) Projection(projection string) *BucketsGetCall {
+ c.urlParams_.Set("projection", projection)
+ return c
+}
+
+// UserProject sets the optional parameter "userProject": The project to
+// be billed for this request. Required for Requester Pays buckets.
+func (c *BucketsGetCall) UserProject(userProject string) *BucketsGetCall {
+ c.urlParams_.Set("userProject", userProject)
+ return c
+}
+
+// Fields allows partial responses to be retrieved. See
+// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
+// for more information.
+func (c *BucketsGetCall) Fields(s ...googleapi.Field) *BucketsGetCall {
+ c.urlParams_.Set("fields", googleapi.CombineFields(s))
+ return c
+}
+
+// IfNoneMatch sets the optional parameter which makes the operation
+// fail if the object's ETag matches the given value. This is useful for
+// getting updates only after the object has changed since the last
+// request. Use googleapi.IsNotModified to check whether the response
+// error from Do is the result of In-None-Match.
+func (c *BucketsGetCall) IfNoneMatch(entityTag string) *BucketsGetCall {
+ c.ifNoneMatch_ = entityTag
+ return c
+}
+
+// Context sets the context to be used in this call's Do method. Any
+// pending HTTP request will be aborted if the provided context is
+// canceled.
+func (c *BucketsGetCall) Context(ctx context.Context) *BucketsGetCall {
+ c.ctx_ = ctx
+ return c
+}
+
+// Header returns an http.Header that can be modified by the caller to
+// add HTTP headers to the request.
+func (c *BucketsGetCall) Header() http.Header {
+ if c.header_ == nil {
+ c.header_ = make(http.Header)
+ }
+ return c.header_
+}
+
+func (c *BucketsGetCall) doRequest(alt string) (*http.Response, error) {
+ reqHeaders := make(http.Header)
+ for k, v := range c.header_ {
+ reqHeaders[k] = v
+ }
+ reqHeaders.Set("User-Agent", c.s.userAgent())
+ if c.ifNoneMatch_ != "" {
+ reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
+ }
+ var body io.Reader = nil
+ c.urlParams_.Set("alt", alt)
+ c.urlParams_.Set("prettyPrint", "false")
+ urls := googleapi.ResolveRelative(c.s.BasePath, "b/{bucket}")
+ urls += "?" + c.urlParams_.Encode()
+ req, err := http.NewRequest("GET", urls, body)
+ if err != nil {
+ return nil, err
+ }
+ req.Header = reqHeaders
+ googleapi.Expand(req.URL, map[string]string{
+ "bucket": c.bucket,
+ })
+ return gensupport.SendRequest(c.ctx_, c.s.client, req)
+}
+
+// Do executes the "storage.buckets.get" call.
+// Exactly one of *Bucket or error will be non-nil. Any non-2xx status
+// code is an error. Response headers are in either
+// *Bucket.ServerResponse.Header or (if a response was returned at all)
+// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to
+// check whether the returned error was because http.StatusNotModified
+// was returned.
+func (c *BucketsGetCall) Do(opts ...googleapi.CallOption) (*Bucket, error) {
+ gensupport.SetOptions(c.urlParams_, opts...)
+ res, err := c.doRequest("json")
+ if res != nil && res.StatusCode == http.StatusNotModified {
+ if res.Body != nil {
+ res.Body.Close()
+ }
+ return nil, &googleapi.Error{
+ Code: res.StatusCode,
+ Header: res.Header,
+ }
+ }
+ if err != nil {
+ return nil, err
+ }
+ defer googleapi.CloseBody(res)
+ if err := googleapi.CheckResponse(res); err != nil {
+ return nil, err
+ }
+ ret := &Bucket{
+ ServerResponse: googleapi.ServerResponse{
+ Header: res.Header,
+ HTTPStatusCode: res.StatusCode,
+ },
+ }
+ target := &ret
+ if err := gensupport.DecodeResponse(target, res); err != nil {
+ return nil, err
+ }
+ return ret, nil
+ // {
+ // "description": "Returns metadata for the specified bucket.",
+ // "httpMethod": "GET",
+ // "id": "storage.buckets.get",
+ // "parameterOrder": [
+ // "bucket"
+ // ],
+ // "parameters": {
+ // "bucket": {
+ // "description": "Name of a bucket.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "ifMetagenerationMatch": {
+ // "description": "Makes the return of the bucket metadata conditional on whether the bucket's current metageneration matches the given value.",
+ // "format": "int64",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "ifMetagenerationNotMatch": {
+ // "description": "Makes the return of the bucket metadata conditional on whether the bucket's current metageneration does not match the given value.",
+ // "format": "int64",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "projection": {
+ // "description": "Set of properties to return. Defaults to noAcl.",
+ // "enum": [
+ // "full",
+ // "noAcl"
+ // ],
+ // "enumDescriptions": [
+ // "Include all properties.",
+ // "Omit owner, acl and defaultObjectAcl properties."
+ // ],
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "userProject": {
+ // "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ // "location": "query",
+ // "type": "string"
+ // }
+ // },
+ // "path": "b/{bucket}",
+ // "response": {
+ // "$ref": "Bucket"
+ // },
+ // "scopes": [
+ // "https://www.googleapis.com/auth/cloud-platform",
+ // "https://www.googleapis.com/auth/cloud-platform.read-only",
+ // "https://www.googleapis.com/auth/devstorage.full_control",
+ // "https://www.googleapis.com/auth/devstorage.read_only",
+ // "https://www.googleapis.com/auth/devstorage.read_write"
+ // ]
+ // }
+
+}
+
+// method id "storage.buckets.getIamPolicy":
+
+type BucketsGetIamPolicyCall struct {
+ s *Service
+ bucket string
+ urlParams_ gensupport.URLParams
+ ifNoneMatch_ string
+ ctx_ context.Context
+ header_ http.Header
+}
+
+// GetIamPolicy: Returns an IAM policy for the specified bucket.
+func (r *BucketsService) GetIamPolicy(bucket string) *BucketsGetIamPolicyCall {
+ c := &BucketsGetIamPolicyCall{s: r.s, urlParams_: make(gensupport.URLParams)}
+ c.bucket = bucket
+ return c
+}
+
+// UserProject sets the optional parameter "userProject": The project to
+// be billed for this request. Required for Requester Pays buckets.
+func (c *BucketsGetIamPolicyCall) UserProject(userProject string) *BucketsGetIamPolicyCall {
+ c.urlParams_.Set("userProject", userProject)
+ return c
+}
+
+// Fields allows partial responses to be retrieved. See
+// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
+// for more information.
+func (c *BucketsGetIamPolicyCall) Fields(s ...googleapi.Field) *BucketsGetIamPolicyCall {
+ c.urlParams_.Set("fields", googleapi.CombineFields(s))
+ return c
+}
+
+// IfNoneMatch sets the optional parameter which makes the operation
+// fail if the object's ETag matches the given value. This is useful for
+// getting updates only after the object has changed since the last
+// request. Use googleapi.IsNotModified to check whether the response
+// error from Do is the result of In-None-Match.
+func (c *BucketsGetIamPolicyCall) IfNoneMatch(entityTag string) *BucketsGetIamPolicyCall {
+ c.ifNoneMatch_ = entityTag
+ return c
+}
+
+// Context sets the context to be used in this call's Do method. Any
+// pending HTTP request will be aborted if the provided context is
+// canceled.
+func (c *BucketsGetIamPolicyCall) Context(ctx context.Context) *BucketsGetIamPolicyCall {
+ c.ctx_ = ctx
+ return c
+}
+
+// Header returns an http.Header that can be modified by the caller to
+// add HTTP headers to the request.
+func (c *BucketsGetIamPolicyCall) Header() http.Header {
+ if c.header_ == nil {
+ c.header_ = make(http.Header)
+ }
+ return c.header_
+}
+
+func (c *BucketsGetIamPolicyCall) doRequest(alt string) (*http.Response, error) {
+ reqHeaders := make(http.Header)
+ for k, v := range c.header_ {
+ reqHeaders[k] = v
+ }
+ reqHeaders.Set("User-Agent", c.s.userAgent())
+ if c.ifNoneMatch_ != "" {
+ reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
+ }
+ var body io.Reader = nil
+ c.urlParams_.Set("alt", alt)
+ c.urlParams_.Set("prettyPrint", "false")
+ urls := googleapi.ResolveRelative(c.s.BasePath, "b/{bucket}/iam")
+ urls += "?" + c.urlParams_.Encode()
+ req, err := http.NewRequest("GET", urls, body)
+ if err != nil {
+ return nil, err
+ }
+ req.Header = reqHeaders
+ googleapi.Expand(req.URL, map[string]string{
+ "bucket": c.bucket,
+ })
+ return gensupport.SendRequest(c.ctx_, c.s.client, req)
+}
+
+// Do executes the "storage.buckets.getIamPolicy" call.
+// Exactly one of *Policy or error will be non-nil. Any non-2xx status
+// code is an error. Response headers are in either
+// *Policy.ServerResponse.Header or (if a response was returned at all)
+// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to
+// check whether the returned error was because http.StatusNotModified
+// was returned.
+func (c *BucketsGetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, error) {
+ gensupport.SetOptions(c.urlParams_, opts...)
+ res, err := c.doRequest("json")
+ if res != nil && res.StatusCode == http.StatusNotModified {
+ if res.Body != nil {
+ res.Body.Close()
+ }
+ return nil, &googleapi.Error{
+ Code: res.StatusCode,
+ Header: res.Header,
+ }
+ }
+ if err != nil {
+ return nil, err
+ }
+ defer googleapi.CloseBody(res)
+ if err := googleapi.CheckResponse(res); err != nil {
+ return nil, err
+ }
+ ret := &Policy{
+ ServerResponse: googleapi.ServerResponse{
+ Header: res.Header,
+ HTTPStatusCode: res.StatusCode,
+ },
+ }
+ target := &ret
+ if err := gensupport.DecodeResponse(target, res); err != nil {
+ return nil, err
+ }
+ return ret, nil
+ // {
+ // "description": "Returns an IAM policy for the specified bucket.",
+ // "httpMethod": "GET",
+ // "id": "storage.buckets.getIamPolicy",
+ // "parameterOrder": [
+ // "bucket"
+ // ],
+ // "parameters": {
+ // "bucket": {
+ // "description": "Name of a bucket.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "userProject": {
+ // "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ // "location": "query",
+ // "type": "string"
+ // }
+ // },
+ // "path": "b/{bucket}/iam",
+ // "response": {
+ // "$ref": "Policy"
+ // },
+ // "scopes": [
+ // "https://www.googleapis.com/auth/cloud-platform",
+ // "https://www.googleapis.com/auth/cloud-platform.read-only",
+ // "https://www.googleapis.com/auth/devstorage.full_control",
+ // "https://www.googleapis.com/auth/devstorage.read_only",
+ // "https://www.googleapis.com/auth/devstorage.read_write"
+ // ]
+ // }
+
+}
+
+// method id "storage.buckets.insert":
+
+type BucketsInsertCall struct {
+ s *Service
+ bucket *Bucket
+ urlParams_ gensupport.URLParams
+ ctx_ context.Context
+ header_ http.Header
+}
+
+// Insert: Creates a new bucket.
+func (r *BucketsService) Insert(projectid string, bucket *Bucket) *BucketsInsertCall {
+ c := &BucketsInsertCall{s: r.s, urlParams_: make(gensupport.URLParams)}
+ c.urlParams_.Set("project", projectid)
+ c.bucket = bucket
+ return c
+}
+
+// PredefinedAcl sets the optional parameter "predefinedAcl": Apply a
+// predefined set of access controls to this bucket.
+//
+// Possible values:
+// "authenticatedRead" - Project team owners get OWNER access, and
+// allAuthenticatedUsers get READER access.
+// "private" - Project team owners get OWNER access.
+// "projectPrivate" - Project team members get access according to
+// their roles.
+// "publicRead" - Project team owners get OWNER access, and allUsers
+// get READER access.
+// "publicReadWrite" - Project team owners get OWNER access, and
+// allUsers get WRITER access.
+func (c *BucketsInsertCall) PredefinedAcl(predefinedAcl string) *BucketsInsertCall {
+ c.urlParams_.Set("predefinedAcl", predefinedAcl)
+ return c
+}
+
+// PredefinedDefaultObjectAcl sets the optional parameter
+// "predefinedDefaultObjectAcl": Apply a predefined set of default
+// object access controls to this bucket.
+//
+// Possible values:
+// "authenticatedRead" - Object owner gets OWNER access, and
+// allAuthenticatedUsers get READER access.
+// "bucketOwnerFullControl" - Object owner gets OWNER access, and
+// project team owners get OWNER access.
+// "bucketOwnerRead" - Object owner gets OWNER access, and project
+// team owners get READER access.
+// "private" - Object owner gets OWNER access.
+// "projectPrivate" - Object owner gets OWNER access, and project team
+// members get access according to their roles.
+// "publicRead" - Object owner gets OWNER access, and allUsers get
+// READER access.
+func (c *BucketsInsertCall) PredefinedDefaultObjectAcl(predefinedDefaultObjectAcl string) *BucketsInsertCall {
+ c.urlParams_.Set("predefinedDefaultObjectAcl", predefinedDefaultObjectAcl)
+ return c
+}
+
+// Projection sets the optional parameter "projection": Set of
+// properties to return. Defaults to noAcl, unless the bucket resource
+// specifies acl or defaultObjectAcl properties, when it defaults to
+// full.
+//
+// Possible values:
+// "full" - Include all properties.
+// "noAcl" - Omit owner, acl and defaultObjectAcl properties.
+func (c *BucketsInsertCall) Projection(projection string) *BucketsInsertCall {
+ c.urlParams_.Set("projection", projection)
+ return c
+}
+
+// UserProject sets the optional parameter "userProject": The project to
+// be billed for this request.
+func (c *BucketsInsertCall) UserProject(userProject string) *BucketsInsertCall {
+ c.urlParams_.Set("userProject", userProject)
+ return c
+}
+
+// Fields allows partial responses to be retrieved. See
+// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
+// for more information.
+func (c *BucketsInsertCall) Fields(s ...googleapi.Field) *BucketsInsertCall {
+ c.urlParams_.Set("fields", googleapi.CombineFields(s))
+ return c
+}
+
+// Context sets the context to be used in this call's Do method. Any
+// pending HTTP request will be aborted if the provided context is
+// canceled.
+func (c *BucketsInsertCall) Context(ctx context.Context) *BucketsInsertCall {
+ c.ctx_ = ctx
+ return c
+}
+
+// Header returns an http.Header that can be modified by the caller to
+// add HTTP headers to the request.
+func (c *BucketsInsertCall) Header() http.Header {
+ if c.header_ == nil {
+ c.header_ = make(http.Header)
+ }
+ return c.header_
+}
+
+func (c *BucketsInsertCall) doRequest(alt string) (*http.Response, error) {
+ reqHeaders := make(http.Header)
+ for k, v := range c.header_ {
+ reqHeaders[k] = v
+ }
+ reqHeaders.Set("User-Agent", c.s.userAgent())
+ var body io.Reader = nil
+ body, err := googleapi.WithoutDataWrapper.JSONReader(c.bucket)
+ if err != nil {
+ return nil, err
+ }
+ reqHeaders.Set("Content-Type", "application/json")
+ c.urlParams_.Set("alt", alt)
+ c.urlParams_.Set("prettyPrint", "false")
+ urls := googleapi.ResolveRelative(c.s.BasePath, "b")
+ urls += "?" + c.urlParams_.Encode()
+ req, err := http.NewRequest("POST", urls, body)
+ if err != nil {
+ return nil, err
+ }
+ req.Header = reqHeaders
+ return gensupport.SendRequest(c.ctx_, c.s.client, req)
+}
+
+// Do executes the "storage.buckets.insert" call.
+// Exactly one of *Bucket or error will be non-nil. Any non-2xx status
+// code is an error. Response headers are in either
+// *Bucket.ServerResponse.Header or (if a response was returned at all)
+// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to
+// check whether the returned error was because http.StatusNotModified
+// was returned.
+func (c *BucketsInsertCall) Do(opts ...googleapi.CallOption) (*Bucket, error) {
+ gensupport.SetOptions(c.urlParams_, opts...)
+ res, err := c.doRequest("json")
+ if res != nil && res.StatusCode == http.StatusNotModified {
+ if res.Body != nil {
+ res.Body.Close()
+ }
+ return nil, &googleapi.Error{
+ Code: res.StatusCode,
+ Header: res.Header,
+ }
+ }
+ if err != nil {
+ return nil, err
+ }
+ defer googleapi.CloseBody(res)
+ if err := googleapi.CheckResponse(res); err != nil {
+ return nil, err
+ }
+ ret := &Bucket{
+ ServerResponse: googleapi.ServerResponse{
+ Header: res.Header,
+ HTTPStatusCode: res.StatusCode,
+ },
+ }
+ target := &ret
+ if err := gensupport.DecodeResponse(target, res); err != nil {
+ return nil, err
+ }
+ return ret, nil
+ // {
+ // "description": "Creates a new bucket.",
+ // "httpMethod": "POST",
+ // "id": "storage.buckets.insert",
+ // "parameterOrder": [
+ // "project"
+ // ],
+ // "parameters": {
+ // "predefinedAcl": {
+ // "description": "Apply a predefined set of access controls to this bucket.",
+ // "enum": [
+ // "authenticatedRead",
+ // "private",
+ // "projectPrivate",
+ // "publicRead",
+ // "publicReadWrite"
+ // ],
+ // "enumDescriptions": [
+ // "Project team owners get OWNER access, and allAuthenticatedUsers get READER access.",
+ // "Project team owners get OWNER access.",
+ // "Project team members get access according to their roles.",
+ // "Project team owners get OWNER access, and allUsers get READER access.",
+ // "Project team owners get OWNER access, and allUsers get WRITER access."
+ // ],
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "predefinedDefaultObjectAcl": {
+ // "description": "Apply a predefined set of default object access controls to this bucket.",
+ // "enum": [
+ // "authenticatedRead",
+ // "bucketOwnerFullControl",
+ // "bucketOwnerRead",
+ // "private",
+ // "projectPrivate",
+ // "publicRead"
+ // ],
+ // "enumDescriptions": [
+ // "Object owner gets OWNER access, and allAuthenticatedUsers get READER access.",
+ // "Object owner gets OWNER access, and project team owners get OWNER access.",
+ // "Object owner gets OWNER access, and project team owners get READER access.",
+ // "Object owner gets OWNER access.",
+ // "Object owner gets OWNER access, and project team members get access according to their roles.",
+ // "Object owner gets OWNER access, and allUsers get READER access."
+ // ],
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "project": {
+ // "description": "A valid API project identifier.",
+ // "location": "query",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "projection": {
+ // "description": "Set of properties to return. Defaults to noAcl, unless the bucket resource specifies acl or defaultObjectAcl properties, when it defaults to full.",
+ // "enum": [
+ // "full",
+ // "noAcl"
+ // ],
+ // "enumDescriptions": [
+ // "Include all properties.",
+ // "Omit owner, acl and defaultObjectAcl properties."
+ // ],
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "userProject": {
+ // "description": "The project to be billed for this request.",
+ // "location": "query",
+ // "type": "string"
+ // }
+ // },
+ // "path": "b",
+ // "request": {
+ // "$ref": "Bucket"
+ // },
+ // "response": {
+ // "$ref": "Bucket"
+ // },
+ // "scopes": [
+ // "https://www.googleapis.com/auth/cloud-platform",
+ // "https://www.googleapis.com/auth/devstorage.full_control",
+ // "https://www.googleapis.com/auth/devstorage.read_write"
+ // ]
+ // }
+
+}
+
+// method id "storage.buckets.list":
+
+type BucketsListCall struct {
+ s *Service
+ urlParams_ gensupport.URLParams
+ ifNoneMatch_ string
+ ctx_ context.Context
+ header_ http.Header
+}
+
+// List: Retrieves a list of buckets for a given project.
+func (r *BucketsService) List(projectid string) *BucketsListCall {
+ c := &BucketsListCall{s: r.s, urlParams_: make(gensupport.URLParams)}
+ c.urlParams_.Set("project", projectid)
+ return c
+}
+
+// MaxResults sets the optional parameter "maxResults": Maximum number
+// of buckets to return in a single response. The service will use this
+// parameter or 1,000 items, whichever is smaller.
+func (c *BucketsListCall) MaxResults(maxResults int64) *BucketsListCall {
+ c.urlParams_.Set("maxResults", fmt.Sprint(maxResults))
+ return c
+}
+
+// PageToken sets the optional parameter "pageToken": A
+// previously-returned page token representing part of the larger set of
+// results to view.
+func (c *BucketsListCall) PageToken(pageToken string) *BucketsListCall {
+ c.urlParams_.Set("pageToken", pageToken)
+ return c
+}
+
+// Prefix sets the optional parameter "prefix": Filter results to
+// buckets whose names begin with this prefix.
+func (c *BucketsListCall) Prefix(prefix string) *BucketsListCall {
+ c.urlParams_.Set("prefix", prefix)
+ return c
+}
+
+// Projection sets the optional parameter "projection": Set of
+// properties to return. Defaults to noAcl.
+//
+// Possible values:
+// "full" - Include all properties.
+// "noAcl" - Omit owner, acl and defaultObjectAcl properties.
+func (c *BucketsListCall) Projection(projection string) *BucketsListCall {
+ c.urlParams_.Set("projection", projection)
+ return c
+}
+
+// UserProject sets the optional parameter "userProject": The project to
+// be billed for this request.
+func (c *BucketsListCall) UserProject(userProject string) *BucketsListCall {
+ c.urlParams_.Set("userProject", userProject)
+ return c
+}
+
+// Fields allows partial responses to be retrieved. See
+// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
+// for more information.
+func (c *BucketsListCall) Fields(s ...googleapi.Field) *BucketsListCall {
+ c.urlParams_.Set("fields", googleapi.CombineFields(s))
+ return c
+}
+
+// IfNoneMatch sets the optional parameter which makes the operation
+// fail if the object's ETag matches the given value. This is useful for
+// getting updates only after the object has changed since the last
+// request. Use googleapi.IsNotModified to check whether the response
+// error from Do is the result of In-None-Match.
+func (c *BucketsListCall) IfNoneMatch(entityTag string) *BucketsListCall {
+ c.ifNoneMatch_ = entityTag
+ return c
+}
+
+// Context sets the context to be used in this call's Do method. Any
+// pending HTTP request will be aborted if the provided context is
+// canceled.
+func (c *BucketsListCall) Context(ctx context.Context) *BucketsListCall {
+ c.ctx_ = ctx
+ return c
+}
+
+// Header returns an http.Header that can be modified by the caller to
+// add HTTP headers to the request.
+func (c *BucketsListCall) Header() http.Header {
+ if c.header_ == nil {
+ c.header_ = make(http.Header)
+ }
+ return c.header_
+}
+
+func (c *BucketsListCall) doRequest(alt string) (*http.Response, error) {
+ reqHeaders := make(http.Header)
+ for k, v := range c.header_ {
+ reqHeaders[k] = v
+ }
+ reqHeaders.Set("User-Agent", c.s.userAgent())
+ if c.ifNoneMatch_ != "" {
+ reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
+ }
+ var body io.Reader = nil
+ c.urlParams_.Set("alt", alt)
+ c.urlParams_.Set("prettyPrint", "false")
+ urls := googleapi.ResolveRelative(c.s.BasePath, "b")
+ urls += "?" + c.urlParams_.Encode()
+ req, err := http.NewRequest("GET", urls, body)
+ if err != nil {
+ return nil, err
+ }
+ req.Header = reqHeaders
+ return gensupport.SendRequest(c.ctx_, c.s.client, req)
+}
+
+// Do executes the "storage.buckets.list" call.
+// Exactly one of *Buckets or error will be non-nil. Any non-2xx status
+// code is an error. Response headers are in either
+// *Buckets.ServerResponse.Header or (if a response was returned at all)
+// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to
+// check whether the returned error was because http.StatusNotModified
+// was returned.
+func (c *BucketsListCall) Do(opts ...googleapi.CallOption) (*Buckets, error) {
+ gensupport.SetOptions(c.urlParams_, opts...)
+ res, err := c.doRequest("json")
+ if res != nil && res.StatusCode == http.StatusNotModified {
+ if res.Body != nil {
+ res.Body.Close()
+ }
+ return nil, &googleapi.Error{
+ Code: res.StatusCode,
+ Header: res.Header,
+ }
+ }
+ if err != nil {
+ return nil, err
+ }
+ defer googleapi.CloseBody(res)
+ if err := googleapi.CheckResponse(res); err != nil {
+ return nil, err
+ }
+ ret := &Buckets{
+ ServerResponse: googleapi.ServerResponse{
+ Header: res.Header,
+ HTTPStatusCode: res.StatusCode,
+ },
+ }
+ target := &ret
+ if err := gensupport.DecodeResponse(target, res); err != nil {
+ return nil, err
+ }
+ return ret, nil
+ // {
+ // "description": "Retrieves a list of buckets for a given project.",
+ // "httpMethod": "GET",
+ // "id": "storage.buckets.list",
+ // "parameterOrder": [
+ // "project"
+ // ],
+ // "parameters": {
+ // "maxResults": {
+ // "default": "1000",
+ // "description": "Maximum number of buckets to return in a single response. The service will use this parameter or 1,000 items, whichever is smaller.",
+ // "format": "uint32",
+ // "location": "query",
+ // "minimum": "0",
+ // "type": "integer"
+ // },
+ // "pageToken": {
+ // "description": "A previously-returned page token representing part of the larger set of results to view.",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "prefix": {
+ // "description": "Filter results to buckets whose names begin with this prefix.",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "project": {
+ // "description": "A valid API project identifier.",
+ // "location": "query",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "projection": {
+ // "description": "Set of properties to return. Defaults to noAcl.",
+ // "enum": [
+ // "full",
+ // "noAcl"
+ // ],
+ // "enumDescriptions": [
+ // "Include all properties.",
+ // "Omit owner, acl and defaultObjectAcl properties."
+ // ],
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "userProject": {
+ // "description": "The project to be billed for this request.",
+ // "location": "query",
+ // "type": "string"
+ // }
+ // },
+ // "path": "b",
+ // "response": {
+ // "$ref": "Buckets"
+ // },
+ // "scopes": [
+ // "https://www.googleapis.com/auth/cloud-platform",
+ // "https://www.googleapis.com/auth/cloud-platform.read-only",
+ // "https://www.googleapis.com/auth/devstorage.full_control",
+ // "https://www.googleapis.com/auth/devstorage.read_only",
+ // "https://www.googleapis.com/auth/devstorage.read_write"
+ // ]
+ // }
+
+}
+
+// Pages invokes f for each page of results.
+// A non-nil error returned from f will halt the iteration.
+// The provided context supersedes any context provided to the Context method.
+func (c *BucketsListCall) Pages(ctx context.Context, f func(*Buckets) error) error {
+ c.ctx_ = ctx
+ defer c.PageToken(c.urlParams_.Get("pageToken")) // reset paging to original point
+ for {
+ x, err := c.Do()
+ if err != nil {
+ return err
+ }
+ if err := f(x); err != nil {
+ return err
+ }
+ if x.NextPageToken == "" {
+ return nil
+ }
+ c.PageToken(x.NextPageToken)
+ }
+}
+
+// method id "storage.buckets.lockRetentionPolicy":
+
+type BucketsLockRetentionPolicyCall struct {
+ s *Service
+ bucket string
+ urlParams_ gensupport.URLParams
+ ctx_ context.Context
+ header_ http.Header
+}
+
+// LockRetentionPolicy: Locks retention policy on a bucket.
+func (r *BucketsService) LockRetentionPolicy(bucket string, ifMetagenerationMatch int64) *BucketsLockRetentionPolicyCall {
+ c := &BucketsLockRetentionPolicyCall{s: r.s, urlParams_: make(gensupport.URLParams)}
+ c.bucket = bucket
+ c.urlParams_.Set("ifMetagenerationMatch", fmt.Sprint(ifMetagenerationMatch))
+ return c
+}
+
+// UserProject sets the optional parameter "userProject": The project to
+// be billed for this request. Required for Requester Pays buckets.
+func (c *BucketsLockRetentionPolicyCall) UserProject(userProject string) *BucketsLockRetentionPolicyCall {
+ c.urlParams_.Set("userProject", userProject)
+ return c
+}
+
+// Fields allows partial responses to be retrieved. See
+// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
+// for more information.
+func (c *BucketsLockRetentionPolicyCall) Fields(s ...googleapi.Field) *BucketsLockRetentionPolicyCall {
+ c.urlParams_.Set("fields", googleapi.CombineFields(s))
+ return c
+}
+
+// Context sets the context to be used in this call's Do method. Any
+// pending HTTP request will be aborted if the provided context is
+// canceled.
+func (c *BucketsLockRetentionPolicyCall) Context(ctx context.Context) *BucketsLockRetentionPolicyCall {
+ c.ctx_ = ctx
+ return c
+}
+
+// Header returns an http.Header that can be modified by the caller to
+// add HTTP headers to the request.
+func (c *BucketsLockRetentionPolicyCall) Header() http.Header {
+ if c.header_ == nil {
+ c.header_ = make(http.Header)
+ }
+ return c.header_
+}
+
+func (c *BucketsLockRetentionPolicyCall) doRequest(alt string) (*http.Response, error) {
+ reqHeaders := make(http.Header)
+ for k, v := range c.header_ {
+ reqHeaders[k] = v
+ }
+ reqHeaders.Set("User-Agent", c.s.userAgent())
+ var body io.Reader = nil
+ c.urlParams_.Set("alt", alt)
+ c.urlParams_.Set("prettyPrint", "false")
+ urls := googleapi.ResolveRelative(c.s.BasePath, "b/{bucket}/lockRetentionPolicy")
+ urls += "?" + c.urlParams_.Encode()
+ req, err := http.NewRequest("POST", urls, body)
+ if err != nil {
+ return nil, err
+ }
+ req.Header = reqHeaders
+ googleapi.Expand(req.URL, map[string]string{
+ "bucket": c.bucket,
+ })
+ return gensupport.SendRequest(c.ctx_, c.s.client, req)
+}
+
+// Do executes the "storage.buckets.lockRetentionPolicy" call.
+// Exactly one of *Bucket or error will be non-nil. Any non-2xx status
+// code is an error. Response headers are in either
+// *Bucket.ServerResponse.Header or (if a response was returned at all)
+// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to
+// check whether the returned error was because http.StatusNotModified
+// was returned.
+func (c *BucketsLockRetentionPolicyCall) Do(opts ...googleapi.CallOption) (*Bucket, error) {
+ gensupport.SetOptions(c.urlParams_, opts...)
+ res, err := c.doRequest("json")
+ if res != nil && res.StatusCode == http.StatusNotModified {
+ if res.Body != nil {
+ res.Body.Close()
+ }
+ return nil, &googleapi.Error{
+ Code: res.StatusCode,
+ Header: res.Header,
+ }
+ }
+ if err != nil {
+ return nil, err
+ }
+ defer googleapi.CloseBody(res)
+ if err := googleapi.CheckResponse(res); err != nil {
+ return nil, err
+ }
+ ret := &Bucket{
+ ServerResponse: googleapi.ServerResponse{
+ Header: res.Header,
+ HTTPStatusCode: res.StatusCode,
+ },
+ }
+ target := &ret
+ if err := gensupport.DecodeResponse(target, res); err != nil {
+ return nil, err
+ }
+ return ret, nil
+ // {
+ // "description": "Locks retention policy on a bucket.",
+ // "httpMethod": "POST",
+ // "id": "storage.buckets.lockRetentionPolicy",
+ // "parameterOrder": [
+ // "bucket",
+ // "ifMetagenerationMatch"
+ // ],
+ // "parameters": {
+ // "bucket": {
+ // "description": "Name of a bucket.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "ifMetagenerationMatch": {
+ // "description": "Makes the operation conditional on whether bucket's current metageneration matches the given value.",
+ // "format": "int64",
+ // "location": "query",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "userProject": {
+ // "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ // "location": "query",
+ // "type": "string"
+ // }
+ // },
+ // "path": "b/{bucket}/lockRetentionPolicy",
+ // "response": {
+ // "$ref": "Bucket"
+ // },
+ // "scopes": [
+ // "https://www.googleapis.com/auth/cloud-platform",
+ // "https://www.googleapis.com/auth/devstorage.full_control",
+ // "https://www.googleapis.com/auth/devstorage.read_write"
+ // ]
+ // }
+
+}
+
+// method id "storage.buckets.patch":
+
+type BucketsPatchCall struct {
+ s *Service
+ bucket string
+ bucket2 *Bucket
+ urlParams_ gensupport.URLParams
+ ctx_ context.Context
+ header_ http.Header
+}
+
+// Patch: Patches a bucket. Changes to the bucket will be readable
+// immediately after writing, but configuration changes may take time to
+// propagate.
+func (r *BucketsService) Patch(bucket string, bucket2 *Bucket) *BucketsPatchCall {
+ c := &BucketsPatchCall{s: r.s, urlParams_: make(gensupport.URLParams)}
+ c.bucket = bucket
+ c.bucket2 = bucket2
+ return c
+}
+
+// IfMetagenerationMatch sets the optional parameter
+// "ifMetagenerationMatch": Makes the return of the bucket metadata
+// conditional on whether the bucket's current metageneration matches
+// the given value.
+func (c *BucketsPatchCall) IfMetagenerationMatch(ifMetagenerationMatch int64) *BucketsPatchCall {
+ c.urlParams_.Set("ifMetagenerationMatch", fmt.Sprint(ifMetagenerationMatch))
+ return c
+}
+
+// IfMetagenerationNotMatch sets the optional parameter
+// "ifMetagenerationNotMatch": Makes the return of the bucket metadata
+// conditional on whether the bucket's current metageneration does not
+// match the given value.
+func (c *BucketsPatchCall) IfMetagenerationNotMatch(ifMetagenerationNotMatch int64) *BucketsPatchCall {
+ c.urlParams_.Set("ifMetagenerationNotMatch", fmt.Sprint(ifMetagenerationNotMatch))
+ return c
+}
+
+// PredefinedAcl sets the optional parameter "predefinedAcl": Apply a
+// predefined set of access controls to this bucket.
+//
+// Possible values:
+// "authenticatedRead" - Project team owners get OWNER access, and
+// allAuthenticatedUsers get READER access.
+// "private" - Project team owners get OWNER access.
+// "projectPrivate" - Project team members get access according to
+// their roles.
+// "publicRead" - Project team owners get OWNER access, and allUsers
+// get READER access.
+// "publicReadWrite" - Project team owners get OWNER access, and
+// allUsers get WRITER access.
+func (c *BucketsPatchCall) PredefinedAcl(predefinedAcl string) *BucketsPatchCall {
+ c.urlParams_.Set("predefinedAcl", predefinedAcl)
+ return c
+}
+
+// PredefinedDefaultObjectAcl sets the optional parameter
+// "predefinedDefaultObjectAcl": Apply a predefined set of default
+// object access controls to this bucket.
+//
+// Possible values:
+// "authenticatedRead" - Object owner gets OWNER access, and
+// allAuthenticatedUsers get READER access.
+// "bucketOwnerFullControl" - Object owner gets OWNER access, and
+// project team owners get OWNER access.
+// "bucketOwnerRead" - Object owner gets OWNER access, and project
+// team owners get READER access.
+// "private" - Object owner gets OWNER access.
+// "projectPrivate" - Object owner gets OWNER access, and project team
+// members get access according to their roles.
+// "publicRead" - Object owner gets OWNER access, and allUsers get
+// READER access.
+func (c *BucketsPatchCall) PredefinedDefaultObjectAcl(predefinedDefaultObjectAcl string) *BucketsPatchCall {
+ c.urlParams_.Set("predefinedDefaultObjectAcl", predefinedDefaultObjectAcl)
+ return c
+}
+
+// Projection sets the optional parameter "projection": Set of
+// properties to return. Defaults to full.
+//
+// Possible values:
+// "full" - Include all properties.
+// "noAcl" - Omit owner, acl and defaultObjectAcl properties.
+func (c *BucketsPatchCall) Projection(projection string) *BucketsPatchCall {
+ c.urlParams_.Set("projection", projection)
+ return c
+}
+
+// UserProject sets the optional parameter "userProject": The project to
+// be billed for this request. Required for Requester Pays buckets.
+func (c *BucketsPatchCall) UserProject(userProject string) *BucketsPatchCall {
+ c.urlParams_.Set("userProject", userProject)
+ return c
+}
+
+// Fields allows partial responses to be retrieved. See
+// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
+// for more information.
+func (c *BucketsPatchCall) Fields(s ...googleapi.Field) *BucketsPatchCall {
+ c.urlParams_.Set("fields", googleapi.CombineFields(s))
+ return c
+}
+
+// Context sets the context to be used in this call's Do method. Any
+// pending HTTP request will be aborted if the provided context is
+// canceled.
+func (c *BucketsPatchCall) Context(ctx context.Context) *BucketsPatchCall {
+ c.ctx_ = ctx
+ return c
+}
+
+// Header returns an http.Header that can be modified by the caller to
+// add HTTP headers to the request.
+func (c *BucketsPatchCall) Header() http.Header {
+ if c.header_ == nil {
+ c.header_ = make(http.Header)
+ }
+ return c.header_
+}
+
+func (c *BucketsPatchCall) doRequest(alt string) (*http.Response, error) {
+ reqHeaders := make(http.Header)
+ for k, v := range c.header_ {
+ reqHeaders[k] = v
+ }
+ reqHeaders.Set("User-Agent", c.s.userAgent())
+ var body io.Reader = nil
+ body, err := googleapi.WithoutDataWrapper.JSONReader(c.bucket2)
+ if err != nil {
+ return nil, err
+ }
+ reqHeaders.Set("Content-Type", "application/json")
+ c.urlParams_.Set("alt", alt)
+ c.urlParams_.Set("prettyPrint", "false")
+ urls := googleapi.ResolveRelative(c.s.BasePath, "b/{bucket}")
+ urls += "?" + c.urlParams_.Encode()
+ req, err := http.NewRequest("PATCH", urls, body)
+ if err != nil {
+ return nil, err
+ }
+ req.Header = reqHeaders
+ googleapi.Expand(req.URL, map[string]string{
+ "bucket": c.bucket,
+ })
+ return gensupport.SendRequest(c.ctx_, c.s.client, req)
+}
+
+// Do executes the "storage.buckets.patch" call.
+// Exactly one of *Bucket or error will be non-nil. Any non-2xx status
+// code is an error. Response headers are in either
+// *Bucket.ServerResponse.Header or (if a response was returned at all)
+// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to
+// check whether the returned error was because http.StatusNotModified
+// was returned.
+func (c *BucketsPatchCall) Do(opts ...googleapi.CallOption) (*Bucket, error) {
+ gensupport.SetOptions(c.urlParams_, opts...)
+ res, err := c.doRequest("json")
+ if res != nil && res.StatusCode == http.StatusNotModified {
+ if res.Body != nil {
+ res.Body.Close()
+ }
+ return nil, &googleapi.Error{
+ Code: res.StatusCode,
+ Header: res.Header,
+ }
+ }
+ if err != nil {
+ return nil, err
+ }
+ defer googleapi.CloseBody(res)
+ if err := googleapi.CheckResponse(res); err != nil {
+ return nil, err
+ }
+ ret := &Bucket{
+ ServerResponse: googleapi.ServerResponse{
+ Header: res.Header,
+ HTTPStatusCode: res.StatusCode,
+ },
+ }
+ target := &ret
+ if err := gensupport.DecodeResponse(target, res); err != nil {
+ return nil, err
+ }
+ return ret, nil
+ // {
+ // "description": "Patches a bucket. Changes to the bucket will be readable immediately after writing, but configuration changes may take time to propagate.",
+ // "httpMethod": "PATCH",
+ // "id": "storage.buckets.patch",
+ // "parameterOrder": [
+ // "bucket"
+ // ],
+ // "parameters": {
+ // "bucket": {
+ // "description": "Name of a bucket.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "ifMetagenerationMatch": {
+ // "description": "Makes the return of the bucket metadata conditional on whether the bucket's current metageneration matches the given value.",
+ // "format": "int64",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "ifMetagenerationNotMatch": {
+ // "description": "Makes the return of the bucket metadata conditional on whether the bucket's current metageneration does not match the given value.",
+ // "format": "int64",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "predefinedAcl": {
+ // "description": "Apply a predefined set of access controls to this bucket.",
+ // "enum": [
+ // "authenticatedRead",
+ // "private",
+ // "projectPrivate",
+ // "publicRead",
+ // "publicReadWrite"
+ // ],
+ // "enumDescriptions": [
+ // "Project team owners get OWNER access, and allAuthenticatedUsers get READER access.",
+ // "Project team owners get OWNER access.",
+ // "Project team members get access according to their roles.",
+ // "Project team owners get OWNER access, and allUsers get READER access.",
+ // "Project team owners get OWNER access, and allUsers get WRITER access."
+ // ],
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "predefinedDefaultObjectAcl": {
+ // "description": "Apply a predefined set of default object access controls to this bucket.",
+ // "enum": [
+ // "authenticatedRead",
+ // "bucketOwnerFullControl",
+ // "bucketOwnerRead",
+ // "private",
+ // "projectPrivate",
+ // "publicRead"
+ // ],
+ // "enumDescriptions": [
+ // "Object owner gets OWNER access, and allAuthenticatedUsers get READER access.",
+ // "Object owner gets OWNER access, and project team owners get OWNER access.",
+ // "Object owner gets OWNER access, and project team owners get READER access.",
+ // "Object owner gets OWNER access.",
+ // "Object owner gets OWNER access, and project team members get access according to their roles.",
+ // "Object owner gets OWNER access, and allUsers get READER access."
+ // ],
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "projection": {
+ // "description": "Set of properties to return. Defaults to full.",
+ // "enum": [
+ // "full",
+ // "noAcl"
+ // ],
+ // "enumDescriptions": [
+ // "Include all properties.",
+ // "Omit owner, acl and defaultObjectAcl properties."
+ // ],
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "userProject": {
+ // "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ // "location": "query",
+ // "type": "string"
+ // }
+ // },
+ // "path": "b/{bucket}",
+ // "request": {
+ // "$ref": "Bucket"
+ // },
+ // "response": {
+ // "$ref": "Bucket"
+ // },
+ // "scopes": [
+ // "https://www.googleapis.com/auth/cloud-platform",
+ // "https://www.googleapis.com/auth/devstorage.full_control"
+ // ]
+ // }
+
+}
+
+// method id "storage.buckets.setIamPolicy":
+
+type BucketsSetIamPolicyCall struct {
+ s *Service
+ bucket string
+ policy *Policy
+ urlParams_ gensupport.URLParams
+ ctx_ context.Context
+ header_ http.Header
+}
+
+// SetIamPolicy: Updates an IAM policy for the specified bucket.
+func (r *BucketsService) SetIamPolicy(bucket string, policy *Policy) *BucketsSetIamPolicyCall {
+ c := &BucketsSetIamPolicyCall{s: r.s, urlParams_: make(gensupport.URLParams)}
+ c.bucket = bucket
+ c.policy = policy
+ return c
+}
+
+// UserProject sets the optional parameter "userProject": The project to
+// be billed for this request. Required for Requester Pays buckets.
+func (c *BucketsSetIamPolicyCall) UserProject(userProject string) *BucketsSetIamPolicyCall {
+ c.urlParams_.Set("userProject", userProject)
+ return c
+}
+
+// Fields allows partial responses to be retrieved. See
+// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
+// for more information.
+func (c *BucketsSetIamPolicyCall) Fields(s ...googleapi.Field) *BucketsSetIamPolicyCall {
+ c.urlParams_.Set("fields", googleapi.CombineFields(s))
+ return c
+}
+
+// Context sets the context to be used in this call's Do method. Any
+// pending HTTP request will be aborted if the provided context is
+// canceled.
+func (c *BucketsSetIamPolicyCall) Context(ctx context.Context) *BucketsSetIamPolicyCall {
+ c.ctx_ = ctx
+ return c
+}
+
+// Header returns an http.Header that can be modified by the caller to
+// add HTTP headers to the request.
+func (c *BucketsSetIamPolicyCall) Header() http.Header {
+ if c.header_ == nil {
+ c.header_ = make(http.Header)
+ }
+ return c.header_
+}
+
+func (c *BucketsSetIamPolicyCall) doRequest(alt string) (*http.Response, error) {
+ reqHeaders := make(http.Header)
+ for k, v := range c.header_ {
+ reqHeaders[k] = v
+ }
+ reqHeaders.Set("User-Agent", c.s.userAgent())
+ var body io.Reader = nil
+ body, err := googleapi.WithoutDataWrapper.JSONReader(c.policy)
+ if err != nil {
+ return nil, err
+ }
+ reqHeaders.Set("Content-Type", "application/json")
+ c.urlParams_.Set("alt", alt)
+ c.urlParams_.Set("prettyPrint", "false")
+ urls := googleapi.ResolveRelative(c.s.BasePath, "b/{bucket}/iam")
+ urls += "?" + c.urlParams_.Encode()
+ req, err := http.NewRequest("PUT", urls, body)
+ if err != nil {
+ return nil, err
+ }
+ req.Header = reqHeaders
+ googleapi.Expand(req.URL, map[string]string{
+ "bucket": c.bucket,
+ })
+ return gensupport.SendRequest(c.ctx_, c.s.client, req)
+}
+
+// Do executes the "storage.buckets.setIamPolicy" call.
+// Exactly one of *Policy or error will be non-nil. Any non-2xx status
+// code is an error. Response headers are in either
+// *Policy.ServerResponse.Header or (if a response was returned at all)
+// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to
+// check whether the returned error was because http.StatusNotModified
+// was returned.
+func (c *BucketsSetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, error) {
+ gensupport.SetOptions(c.urlParams_, opts...)
+ res, err := c.doRequest("json")
+ if res != nil && res.StatusCode == http.StatusNotModified {
+ if res.Body != nil {
+ res.Body.Close()
+ }
+ return nil, &googleapi.Error{
+ Code: res.StatusCode,
+ Header: res.Header,
+ }
+ }
+ if err != nil {
+ return nil, err
+ }
+ defer googleapi.CloseBody(res)
+ if err := googleapi.CheckResponse(res); err != nil {
+ return nil, err
+ }
+ ret := &Policy{
+ ServerResponse: googleapi.ServerResponse{
+ Header: res.Header,
+ HTTPStatusCode: res.StatusCode,
+ },
+ }
+ target := &ret
+ if err := gensupport.DecodeResponse(target, res); err != nil {
+ return nil, err
+ }
+ return ret, nil
+ // {
+ // "description": "Updates an IAM policy for the specified bucket.",
+ // "httpMethod": "PUT",
+ // "id": "storage.buckets.setIamPolicy",
+ // "parameterOrder": [
+ // "bucket"
+ // ],
+ // "parameters": {
+ // "bucket": {
+ // "description": "Name of a bucket.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "userProject": {
+ // "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ // "location": "query",
+ // "type": "string"
+ // }
+ // },
+ // "path": "b/{bucket}/iam",
+ // "request": {
+ // "$ref": "Policy"
+ // },
+ // "response": {
+ // "$ref": "Policy"
+ // },
+ // "scopes": [
+ // "https://www.googleapis.com/auth/cloud-platform",
+ // "https://www.googleapis.com/auth/devstorage.full_control",
+ // "https://www.googleapis.com/auth/devstorage.read_write"
+ // ]
+ // }
+
+}
+
+// method id "storage.buckets.testIamPermissions":
+
+type BucketsTestIamPermissionsCall struct {
+ s *Service
+ bucket string
+ urlParams_ gensupport.URLParams
+ ifNoneMatch_ string
+ ctx_ context.Context
+ header_ http.Header
+}
+
+// TestIamPermissions: Tests a set of permissions on the given bucket to
+// see which, if any, are held by the caller.
+func (r *BucketsService) TestIamPermissions(bucket string, permissions []string) *BucketsTestIamPermissionsCall {
+ c := &BucketsTestIamPermissionsCall{s: r.s, urlParams_: make(gensupport.URLParams)}
+ c.bucket = bucket
+ c.urlParams_.SetMulti("permissions", append([]string{}, permissions...))
+ return c
+}
+
+// UserProject sets the optional parameter "userProject": The project to
+// be billed for this request. Required for Requester Pays buckets.
+func (c *BucketsTestIamPermissionsCall) UserProject(userProject string) *BucketsTestIamPermissionsCall {
+ c.urlParams_.Set("userProject", userProject)
+ return c
+}
+
+// Fields allows partial responses to be retrieved. See
+// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
+// for more information.
+func (c *BucketsTestIamPermissionsCall) Fields(s ...googleapi.Field) *BucketsTestIamPermissionsCall {
+ c.urlParams_.Set("fields", googleapi.CombineFields(s))
+ return c
+}
+
+// IfNoneMatch sets the optional parameter which makes the operation
+// fail if the object's ETag matches the given value. This is useful for
+// getting updates only after the object has changed since the last
+// request. Use googleapi.IsNotModified to check whether the response
+// error from Do is the result of In-None-Match.
+func (c *BucketsTestIamPermissionsCall) IfNoneMatch(entityTag string) *BucketsTestIamPermissionsCall {
+ c.ifNoneMatch_ = entityTag
+ return c
+}
+
+// Context sets the context to be used in this call's Do method. Any
+// pending HTTP request will be aborted if the provided context is
+// canceled.
+func (c *BucketsTestIamPermissionsCall) Context(ctx context.Context) *BucketsTestIamPermissionsCall {
+ c.ctx_ = ctx
+ return c
+}
+
+// Header returns an http.Header that can be modified by the caller to
+// add HTTP headers to the request.
+func (c *BucketsTestIamPermissionsCall) Header() http.Header {
+ if c.header_ == nil {
+ c.header_ = make(http.Header)
+ }
+ return c.header_
+}
+
+func (c *BucketsTestIamPermissionsCall) doRequest(alt string) (*http.Response, error) {
+ reqHeaders := make(http.Header)
+ for k, v := range c.header_ {
+ reqHeaders[k] = v
+ }
+ reqHeaders.Set("User-Agent", c.s.userAgent())
+ if c.ifNoneMatch_ != "" {
+ reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
+ }
+ var body io.Reader = nil
+ c.urlParams_.Set("alt", alt)
+ c.urlParams_.Set("prettyPrint", "false")
+ urls := googleapi.ResolveRelative(c.s.BasePath, "b/{bucket}/iam/testPermissions")
+ urls += "?" + c.urlParams_.Encode()
+ req, err := http.NewRequest("GET", urls, body)
+ if err != nil {
+ return nil, err
+ }
+ req.Header = reqHeaders
+ googleapi.Expand(req.URL, map[string]string{
+ "bucket": c.bucket,
+ })
+ return gensupport.SendRequest(c.ctx_, c.s.client, req)
+}
+
+// Do executes the "storage.buckets.testIamPermissions" call.
+// Exactly one of *TestIamPermissionsResponse or error will be non-nil.
+// Any non-2xx status code is an error. Response headers are in either
+// *TestIamPermissionsResponse.ServerResponse.Header or (if a response
+// was returned at all) in error.(*googleapi.Error).Header. Use
+// googleapi.IsNotModified to check whether the returned error was
+// because http.StatusNotModified was returned.
+func (c *BucketsTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (*TestIamPermissionsResponse, error) {
+ gensupport.SetOptions(c.urlParams_, opts...)
+ res, err := c.doRequest("json")
+ if res != nil && res.StatusCode == http.StatusNotModified {
+ if res.Body != nil {
+ res.Body.Close()
+ }
+ return nil, &googleapi.Error{
+ Code: res.StatusCode,
+ Header: res.Header,
+ }
+ }
+ if err != nil {
+ return nil, err
+ }
+ defer googleapi.CloseBody(res)
+ if err := googleapi.CheckResponse(res); err != nil {
+ return nil, err
+ }
+ ret := &TestIamPermissionsResponse{
+ ServerResponse: googleapi.ServerResponse{
+ Header: res.Header,
+ HTTPStatusCode: res.StatusCode,
+ },
+ }
+ target := &ret
+ if err := gensupport.DecodeResponse(target, res); err != nil {
+ return nil, err
+ }
+ return ret, nil
+ // {
+ // "description": "Tests a set of permissions on the given bucket to see which, if any, are held by the caller.",
+ // "httpMethod": "GET",
+ // "id": "storage.buckets.testIamPermissions",
+ // "parameterOrder": [
+ // "bucket",
+ // "permissions"
+ // ],
+ // "parameters": {
+ // "bucket": {
+ // "description": "Name of a bucket.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "permissions": {
+ // "description": "Permissions to test.",
+ // "location": "query",
+ // "repeated": true,
+ // "required": true,
+ // "type": "string"
+ // },
+ // "userProject": {
+ // "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ // "location": "query",
+ // "type": "string"
+ // }
+ // },
+ // "path": "b/{bucket}/iam/testPermissions",
+ // "response": {
+ // "$ref": "TestIamPermissionsResponse"
+ // },
+ // "scopes": [
+ // "https://www.googleapis.com/auth/cloud-platform",
+ // "https://www.googleapis.com/auth/cloud-platform.read-only",
+ // "https://www.googleapis.com/auth/devstorage.full_control",
+ // "https://www.googleapis.com/auth/devstorage.read_only",
+ // "https://www.googleapis.com/auth/devstorage.read_write"
+ // ]
+ // }
+
+}
+
+// method id "storage.buckets.update":
+
+type BucketsUpdateCall struct {
+ s *Service
+ bucket string
+ bucket2 *Bucket
+ urlParams_ gensupport.URLParams
+ ctx_ context.Context
+ header_ http.Header
+}
+
+// Update: Updates a bucket. Changes to the bucket will be readable
+// immediately after writing, but configuration changes may take time to
+// propagate.
+func (r *BucketsService) Update(bucket string, bucket2 *Bucket) *BucketsUpdateCall {
+ c := &BucketsUpdateCall{s: r.s, urlParams_: make(gensupport.URLParams)}
+ c.bucket = bucket
+ c.bucket2 = bucket2
+ return c
+}
+
+// IfMetagenerationMatch sets the optional parameter
+// "ifMetagenerationMatch": Makes the return of the bucket metadata
+// conditional on whether the bucket's current metageneration matches
+// the given value.
+func (c *BucketsUpdateCall) IfMetagenerationMatch(ifMetagenerationMatch int64) *BucketsUpdateCall {
+ c.urlParams_.Set("ifMetagenerationMatch", fmt.Sprint(ifMetagenerationMatch))
+ return c
+}
+
+// IfMetagenerationNotMatch sets the optional parameter
+// "ifMetagenerationNotMatch": Makes the return of the bucket metadata
+// conditional on whether the bucket's current metageneration does not
+// match the given value.
+func (c *BucketsUpdateCall) IfMetagenerationNotMatch(ifMetagenerationNotMatch int64) *BucketsUpdateCall {
+ c.urlParams_.Set("ifMetagenerationNotMatch", fmt.Sprint(ifMetagenerationNotMatch))
+ return c
+}
+
+// PredefinedAcl sets the optional parameter "predefinedAcl": Apply a
+// predefined set of access controls to this bucket.
+//
+// Possible values:
+// "authenticatedRead" - Project team owners get OWNER access, and
+// allAuthenticatedUsers get READER access.
+// "private" - Project team owners get OWNER access.
+// "projectPrivate" - Project team members get access according to
+// their roles.
+// "publicRead" - Project team owners get OWNER access, and allUsers
+// get READER access.
+// "publicReadWrite" - Project team owners get OWNER access, and
+// allUsers get WRITER access.
+func (c *BucketsUpdateCall) PredefinedAcl(predefinedAcl string) *BucketsUpdateCall {
+ c.urlParams_.Set("predefinedAcl", predefinedAcl)
+ return c
+}
+
+// PredefinedDefaultObjectAcl sets the optional parameter
+// "predefinedDefaultObjectAcl": Apply a predefined set of default
+// object access controls to this bucket.
+//
+// Possible values:
+// "authenticatedRead" - Object owner gets OWNER access, and
+// allAuthenticatedUsers get READER access.
+// "bucketOwnerFullControl" - Object owner gets OWNER access, and
+// project team owners get OWNER access.
+// "bucketOwnerRead" - Object owner gets OWNER access, and project
+// team owners get READER access.
+// "private" - Object owner gets OWNER access.
+// "projectPrivate" - Object owner gets OWNER access, and project team
+// members get access according to their roles.
+// "publicRead" - Object owner gets OWNER access, and allUsers get
+// READER access.
+func (c *BucketsUpdateCall) PredefinedDefaultObjectAcl(predefinedDefaultObjectAcl string) *BucketsUpdateCall {
+ c.urlParams_.Set("predefinedDefaultObjectAcl", predefinedDefaultObjectAcl)
+ return c
+}
+
+// Projection sets the optional parameter "projection": Set of
+// properties to return. Defaults to full.
+//
+// Possible values:
+// "full" - Include all properties.
+// "noAcl" - Omit owner, acl and defaultObjectAcl properties.
+func (c *BucketsUpdateCall) Projection(projection string) *BucketsUpdateCall {
+ c.urlParams_.Set("projection", projection)
+ return c
+}
+
+// UserProject sets the optional parameter "userProject": The project to
+// be billed for this request. Required for Requester Pays buckets.
+func (c *BucketsUpdateCall) UserProject(userProject string) *BucketsUpdateCall {
+ c.urlParams_.Set("userProject", userProject)
+ return c
+}
+
+// Fields allows partial responses to be retrieved. See
+// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
+// for more information.
+func (c *BucketsUpdateCall) Fields(s ...googleapi.Field) *BucketsUpdateCall {
+ c.urlParams_.Set("fields", googleapi.CombineFields(s))
+ return c
+}
+
+// Context sets the context to be used in this call's Do method. Any
+// pending HTTP request will be aborted if the provided context is
+// canceled.
+func (c *BucketsUpdateCall) Context(ctx context.Context) *BucketsUpdateCall {
+ c.ctx_ = ctx
+ return c
+}
+
+// Header returns an http.Header that can be modified by the caller to
+// add HTTP headers to the request.
+func (c *BucketsUpdateCall) Header() http.Header {
+ if c.header_ == nil {
+ c.header_ = make(http.Header)
+ }
+ return c.header_
+}
+
+func (c *BucketsUpdateCall) doRequest(alt string) (*http.Response, error) {
+ reqHeaders := make(http.Header)
+ for k, v := range c.header_ {
+ reqHeaders[k] = v
+ }
+ reqHeaders.Set("User-Agent", c.s.userAgent())
+ var body io.Reader = nil
+ body, err := googleapi.WithoutDataWrapper.JSONReader(c.bucket2)
+ if err != nil {
+ return nil, err
+ }
+ reqHeaders.Set("Content-Type", "application/json")
+ c.urlParams_.Set("alt", alt)
+ c.urlParams_.Set("prettyPrint", "false")
+ urls := googleapi.ResolveRelative(c.s.BasePath, "b/{bucket}")
+ urls += "?" + c.urlParams_.Encode()
+ req, err := http.NewRequest("PUT", urls, body)
+ if err != nil {
+ return nil, err
+ }
+ req.Header = reqHeaders
+ googleapi.Expand(req.URL, map[string]string{
+ "bucket": c.bucket,
+ })
+ return gensupport.SendRequest(c.ctx_, c.s.client, req)
+}
+
+// Do executes the "storage.buckets.update" call.
+// Exactly one of *Bucket or error will be non-nil. Any non-2xx status
+// code is an error. Response headers are in either
+// *Bucket.ServerResponse.Header or (if a response was returned at all)
+// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to
+// check whether the returned error was because http.StatusNotModified
+// was returned.
+func (c *BucketsUpdateCall) Do(opts ...googleapi.CallOption) (*Bucket, error) {
+ gensupport.SetOptions(c.urlParams_, opts...)
+ res, err := c.doRequest("json")
+ if res != nil && res.StatusCode == http.StatusNotModified {
+ if res.Body != nil {
+ res.Body.Close()
+ }
+ return nil, &googleapi.Error{
+ Code: res.StatusCode,
+ Header: res.Header,
+ }
+ }
+ if err != nil {
+ return nil, err
+ }
+ defer googleapi.CloseBody(res)
+ if err := googleapi.CheckResponse(res); err != nil {
+ return nil, err
+ }
+ ret := &Bucket{
+ ServerResponse: googleapi.ServerResponse{
+ Header: res.Header,
+ HTTPStatusCode: res.StatusCode,
+ },
+ }
+ target := &ret
+ if err := gensupport.DecodeResponse(target, res); err != nil {
+ return nil, err
+ }
+ return ret, nil
+ // {
+ // "description": "Updates a bucket. Changes to the bucket will be readable immediately after writing, but configuration changes may take time to propagate.",
+ // "httpMethod": "PUT",
+ // "id": "storage.buckets.update",
+ // "parameterOrder": [
+ // "bucket"
+ // ],
+ // "parameters": {
+ // "bucket": {
+ // "description": "Name of a bucket.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "ifMetagenerationMatch": {
+ // "description": "Makes the return of the bucket metadata conditional on whether the bucket's current metageneration matches the given value.",
+ // "format": "int64",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "ifMetagenerationNotMatch": {
+ // "description": "Makes the return of the bucket metadata conditional on whether the bucket's current metageneration does not match the given value.",
+ // "format": "int64",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "predefinedAcl": {
+ // "description": "Apply a predefined set of access controls to this bucket.",
+ // "enum": [
+ // "authenticatedRead",
+ // "private",
+ // "projectPrivate",
+ // "publicRead",
+ // "publicReadWrite"
+ // ],
+ // "enumDescriptions": [
+ // "Project team owners get OWNER access, and allAuthenticatedUsers get READER access.",
+ // "Project team owners get OWNER access.",
+ // "Project team members get access according to their roles.",
+ // "Project team owners get OWNER access, and allUsers get READER access.",
+ // "Project team owners get OWNER access, and allUsers get WRITER access."
+ // ],
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "predefinedDefaultObjectAcl": {
+ // "description": "Apply a predefined set of default object access controls to this bucket.",
+ // "enum": [
+ // "authenticatedRead",
+ // "bucketOwnerFullControl",
+ // "bucketOwnerRead",
+ // "private",
+ // "projectPrivate",
+ // "publicRead"
+ // ],
+ // "enumDescriptions": [
+ // "Object owner gets OWNER access, and allAuthenticatedUsers get READER access.",
+ // "Object owner gets OWNER access, and project team owners get OWNER access.",
+ // "Object owner gets OWNER access, and project team owners get READER access.",
+ // "Object owner gets OWNER access.",
+ // "Object owner gets OWNER access, and project team members get access according to their roles.",
+ // "Object owner gets OWNER access, and allUsers get READER access."
+ // ],
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "projection": {
+ // "description": "Set of properties to return. Defaults to full.",
+ // "enum": [
+ // "full",
+ // "noAcl"
+ // ],
+ // "enumDescriptions": [
+ // "Include all properties.",
+ // "Omit owner, acl and defaultObjectAcl properties."
+ // ],
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "userProject": {
+ // "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ // "location": "query",
+ // "type": "string"
+ // }
+ // },
+ // "path": "b/{bucket}",
+ // "request": {
+ // "$ref": "Bucket"
+ // },
+ // "response": {
+ // "$ref": "Bucket"
+ // },
+ // "scopes": [
+ // "https://www.googleapis.com/auth/cloud-platform",
+ // "https://www.googleapis.com/auth/devstorage.full_control"
+ // ]
+ // }
+
+}
+
+// method id "storage.channels.stop":
+
+type ChannelsStopCall struct {
+ s *Service
+ channel *Channel
+ urlParams_ gensupport.URLParams
+ ctx_ context.Context
+ header_ http.Header
+}
+
+// Stop: Stop watching resources through this channel
+func (r *ChannelsService) Stop(channel *Channel) *ChannelsStopCall {
+ c := &ChannelsStopCall{s: r.s, urlParams_: make(gensupport.URLParams)}
+ c.channel = channel
+ return c
+}
+
+// Fields allows partial responses to be retrieved. See
+// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
+// for more information.
+func (c *ChannelsStopCall) Fields(s ...googleapi.Field) *ChannelsStopCall {
+ c.urlParams_.Set("fields", googleapi.CombineFields(s))
+ return c
+}
+
+// Context sets the context to be used in this call's Do method. Any
+// pending HTTP request will be aborted if the provided context is
+// canceled.
+func (c *ChannelsStopCall) Context(ctx context.Context) *ChannelsStopCall {
+ c.ctx_ = ctx
+ return c
+}
+
+// Header returns an http.Header that can be modified by the caller to
+// add HTTP headers to the request.
+func (c *ChannelsStopCall) Header() http.Header {
+ if c.header_ == nil {
+ c.header_ = make(http.Header)
+ }
+ return c.header_
+}
+
+func (c *ChannelsStopCall) doRequest(alt string) (*http.Response, error) {
+ reqHeaders := make(http.Header)
+ for k, v := range c.header_ {
+ reqHeaders[k] = v
+ }
+ reqHeaders.Set("User-Agent", c.s.userAgent())
+ var body io.Reader = nil
+ body, err := googleapi.WithoutDataWrapper.JSONReader(c.channel)
+ if err != nil {
+ return nil, err
+ }
+ reqHeaders.Set("Content-Type", "application/json")
+ c.urlParams_.Set("alt", alt)
+ c.urlParams_.Set("prettyPrint", "false")
+ urls := googleapi.ResolveRelative(c.s.BasePath, "channels/stop")
+ urls += "?" + c.urlParams_.Encode()
+ req, err := http.NewRequest("POST", urls, body)
+ if err != nil {
+ return nil, err
+ }
+ req.Header = reqHeaders
+ return gensupport.SendRequest(c.ctx_, c.s.client, req)
+}
+
+// Do executes the "storage.channels.stop" call.
+func (c *ChannelsStopCall) Do(opts ...googleapi.CallOption) error {
+ gensupport.SetOptions(c.urlParams_, opts...)
+ res, err := c.doRequest("json")
+ if err != nil {
+ return err
+ }
+ defer googleapi.CloseBody(res)
+ if err := googleapi.CheckResponse(res); err != nil {
+ return err
+ }
+ return nil
+ // {
+ // "description": "Stop watching resources through this channel",
+ // "httpMethod": "POST",
+ // "id": "storage.channels.stop",
+ // "path": "channels/stop",
+ // "request": {
+ // "$ref": "Channel",
+ // "parameterName": "resource"
+ // },
+ // "scopes": [
+ // "https://www.googleapis.com/auth/cloud-platform",
+ // "https://www.googleapis.com/auth/cloud-platform.read-only",
+ // "https://www.googleapis.com/auth/devstorage.full_control",
+ // "https://www.googleapis.com/auth/devstorage.read_only",
+ // "https://www.googleapis.com/auth/devstorage.read_write"
+ // ]
+ // }
+
+}
+
+// method id "storage.defaultObjectAccessControls.delete":
+
+type DefaultObjectAccessControlsDeleteCall struct {
+ s *Service
+ bucket string
+ entity string
+ urlParams_ gensupport.URLParams
+ ctx_ context.Context
+ header_ http.Header
+}
+
+// Delete: Permanently deletes the default object ACL entry for the
+// specified entity on the specified bucket.
+func (r *DefaultObjectAccessControlsService) Delete(bucket string, entity string) *DefaultObjectAccessControlsDeleteCall {
+ c := &DefaultObjectAccessControlsDeleteCall{s: r.s, urlParams_: make(gensupport.URLParams)}
+ c.bucket = bucket
+ c.entity = entity
+ return c
+}
+
+// UserProject sets the optional parameter "userProject": The project to
+// be billed for this request. Required for Requester Pays buckets.
+func (c *DefaultObjectAccessControlsDeleteCall) UserProject(userProject string) *DefaultObjectAccessControlsDeleteCall {
+ c.urlParams_.Set("userProject", userProject)
+ return c
+}
+
+// Fields allows partial responses to be retrieved. See
+// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
+// for more information.
+func (c *DefaultObjectAccessControlsDeleteCall) Fields(s ...googleapi.Field) *DefaultObjectAccessControlsDeleteCall {
+ c.urlParams_.Set("fields", googleapi.CombineFields(s))
+ return c
+}
+
+// Context sets the context to be used in this call's Do method. Any
+// pending HTTP request will be aborted if the provided context is
+// canceled.
+func (c *DefaultObjectAccessControlsDeleteCall) Context(ctx context.Context) *DefaultObjectAccessControlsDeleteCall {
+ c.ctx_ = ctx
+ return c
+}
+
+// Header returns an http.Header that can be modified by the caller to
+// add HTTP headers to the request.
+func (c *DefaultObjectAccessControlsDeleteCall) Header() http.Header {
+ if c.header_ == nil {
+ c.header_ = make(http.Header)
+ }
+ return c.header_
+}
+
+func (c *DefaultObjectAccessControlsDeleteCall) doRequest(alt string) (*http.Response, error) {
+ reqHeaders := make(http.Header)
+ for k, v := range c.header_ {
+ reqHeaders[k] = v
+ }
+ reqHeaders.Set("User-Agent", c.s.userAgent())
+ var body io.Reader = nil
+ c.urlParams_.Set("alt", alt)
+ c.urlParams_.Set("prettyPrint", "false")
+ urls := googleapi.ResolveRelative(c.s.BasePath, "b/{bucket}/defaultObjectAcl/{entity}")
+ urls += "?" + c.urlParams_.Encode()
+ req, err := http.NewRequest("DELETE", urls, body)
+ if err != nil {
+ return nil, err
+ }
+ req.Header = reqHeaders
+ googleapi.Expand(req.URL, map[string]string{
+ "bucket": c.bucket,
+ "entity": c.entity,
+ })
+ return gensupport.SendRequest(c.ctx_, c.s.client, req)
+}
+
+// Do executes the "storage.defaultObjectAccessControls.delete" call.
+func (c *DefaultObjectAccessControlsDeleteCall) Do(opts ...googleapi.CallOption) error {
+ gensupport.SetOptions(c.urlParams_, opts...)
+ res, err := c.doRequest("json")
+ if err != nil {
+ return err
+ }
+ defer googleapi.CloseBody(res)
+ if err := googleapi.CheckResponse(res); err != nil {
+ return err
+ }
+ return nil
+ // {
+ // "description": "Permanently deletes the default object ACL entry for the specified entity on the specified bucket.",
+ // "httpMethod": "DELETE",
+ // "id": "storage.defaultObjectAccessControls.delete",
+ // "parameterOrder": [
+ // "bucket",
+ // "entity"
+ // ],
+ // "parameters": {
+ // "bucket": {
+ // "description": "Name of a bucket.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "entity": {
+ // "description": "The entity holding the permission. Can be user-userId, user-emailAddress, group-groupId, group-emailAddress, allUsers, or allAuthenticatedUsers.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "userProject": {
+ // "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ // "location": "query",
+ // "type": "string"
+ // }
+ // },
+ // "path": "b/{bucket}/defaultObjectAcl/{entity}",
+ // "scopes": [
+ // "https://www.googleapis.com/auth/cloud-platform",
+ // "https://www.googleapis.com/auth/devstorage.full_control"
+ // ]
+ // }
+
+}
+
+// method id "storage.defaultObjectAccessControls.get":
+
+type DefaultObjectAccessControlsGetCall struct {
+ s *Service
+ bucket string
+ entity string
+ urlParams_ gensupport.URLParams
+ ifNoneMatch_ string
+ ctx_ context.Context
+ header_ http.Header
+}
+
+// Get: Returns the default object ACL entry for the specified entity on
+// the specified bucket.
+func (r *DefaultObjectAccessControlsService) Get(bucket string, entity string) *DefaultObjectAccessControlsGetCall {
+ c := &DefaultObjectAccessControlsGetCall{s: r.s, urlParams_: make(gensupport.URLParams)}
+ c.bucket = bucket
+ c.entity = entity
+ return c
+}
+
+// UserProject sets the optional parameter "userProject": The project to
+// be billed for this request. Required for Requester Pays buckets.
+func (c *DefaultObjectAccessControlsGetCall) UserProject(userProject string) *DefaultObjectAccessControlsGetCall {
+ c.urlParams_.Set("userProject", userProject)
+ return c
+}
+
+// Fields allows partial responses to be retrieved. See
+// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
+// for more information.
+func (c *DefaultObjectAccessControlsGetCall) Fields(s ...googleapi.Field) *DefaultObjectAccessControlsGetCall {
+ c.urlParams_.Set("fields", googleapi.CombineFields(s))
+ return c
+}
+
+// IfNoneMatch sets the optional parameter which makes the operation
+// fail if the object's ETag matches the given value. This is useful for
+// getting updates only after the object has changed since the last
+// request. Use googleapi.IsNotModified to check whether the response
+// error from Do is the result of In-None-Match.
+func (c *DefaultObjectAccessControlsGetCall) IfNoneMatch(entityTag string) *DefaultObjectAccessControlsGetCall {
+ c.ifNoneMatch_ = entityTag
+ return c
+}
+
+// Context sets the context to be used in this call's Do method. Any
+// pending HTTP request will be aborted if the provided context is
+// canceled.
+func (c *DefaultObjectAccessControlsGetCall) Context(ctx context.Context) *DefaultObjectAccessControlsGetCall {
+ c.ctx_ = ctx
+ return c
+}
+
+// Header returns an http.Header that can be modified by the caller to
+// add HTTP headers to the request.
+func (c *DefaultObjectAccessControlsGetCall) Header() http.Header {
+ if c.header_ == nil {
+ c.header_ = make(http.Header)
+ }
+ return c.header_
+}
+
+func (c *DefaultObjectAccessControlsGetCall) doRequest(alt string) (*http.Response, error) {
+ reqHeaders := make(http.Header)
+ for k, v := range c.header_ {
+ reqHeaders[k] = v
+ }
+ reqHeaders.Set("User-Agent", c.s.userAgent())
+ if c.ifNoneMatch_ != "" {
+ reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
+ }
+ var body io.Reader = nil
+ c.urlParams_.Set("alt", alt)
+ c.urlParams_.Set("prettyPrint", "false")
+ urls := googleapi.ResolveRelative(c.s.BasePath, "b/{bucket}/defaultObjectAcl/{entity}")
+ urls += "?" + c.urlParams_.Encode()
+ req, err := http.NewRequest("GET", urls, body)
+ if err != nil {
+ return nil, err
+ }
+ req.Header = reqHeaders
+ googleapi.Expand(req.URL, map[string]string{
+ "bucket": c.bucket,
+ "entity": c.entity,
+ })
+ return gensupport.SendRequest(c.ctx_, c.s.client, req)
+}
+
+// Do executes the "storage.defaultObjectAccessControls.get" call.
+// Exactly one of *ObjectAccessControl or error will be non-nil. Any
+// non-2xx status code is an error. Response headers are in either
+// *ObjectAccessControl.ServerResponse.Header or (if a response was
+// returned at all) in error.(*googleapi.Error).Header. Use
+// googleapi.IsNotModified to check whether the returned error was
+// because http.StatusNotModified was returned.
+func (c *DefaultObjectAccessControlsGetCall) Do(opts ...googleapi.CallOption) (*ObjectAccessControl, error) {
+ gensupport.SetOptions(c.urlParams_, opts...)
+ res, err := c.doRequest("json")
+ if res != nil && res.StatusCode == http.StatusNotModified {
+ if res.Body != nil {
+ res.Body.Close()
+ }
+ return nil, &googleapi.Error{
+ Code: res.StatusCode,
+ Header: res.Header,
+ }
+ }
+ if err != nil {
+ return nil, err
+ }
+ defer googleapi.CloseBody(res)
+ if err := googleapi.CheckResponse(res); err != nil {
+ return nil, err
+ }
+ ret := &ObjectAccessControl{
+ ServerResponse: googleapi.ServerResponse{
+ Header: res.Header,
+ HTTPStatusCode: res.StatusCode,
+ },
+ }
+ target := &ret
+ if err := gensupport.DecodeResponse(target, res); err != nil {
+ return nil, err
+ }
+ return ret, nil
+ // {
+ // "description": "Returns the default object ACL entry for the specified entity on the specified bucket.",
+ // "httpMethod": "GET",
+ // "id": "storage.defaultObjectAccessControls.get",
+ // "parameterOrder": [
+ // "bucket",
+ // "entity"
+ // ],
+ // "parameters": {
+ // "bucket": {
+ // "description": "Name of a bucket.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "entity": {
+ // "description": "The entity holding the permission. Can be user-userId, user-emailAddress, group-groupId, group-emailAddress, allUsers, or allAuthenticatedUsers.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "userProject": {
+ // "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ // "location": "query",
+ // "type": "string"
+ // }
+ // },
+ // "path": "b/{bucket}/defaultObjectAcl/{entity}",
+ // "response": {
+ // "$ref": "ObjectAccessControl"
+ // },
+ // "scopes": [
+ // "https://www.googleapis.com/auth/cloud-platform",
+ // "https://www.googleapis.com/auth/devstorage.full_control"
+ // ]
+ // }
+
+}
+
+// method id "storage.defaultObjectAccessControls.insert":
+
+type DefaultObjectAccessControlsInsertCall struct {
+ s *Service
+ bucket string
+ objectaccesscontrol *ObjectAccessControl
+ urlParams_ gensupport.URLParams
+ ctx_ context.Context
+ header_ http.Header
+}
+
+// Insert: Creates a new default object ACL entry on the specified
+// bucket.
+func (r *DefaultObjectAccessControlsService) Insert(bucket string, objectaccesscontrol *ObjectAccessControl) *DefaultObjectAccessControlsInsertCall {
+ c := &DefaultObjectAccessControlsInsertCall{s: r.s, urlParams_: make(gensupport.URLParams)}
+ c.bucket = bucket
+ c.objectaccesscontrol = objectaccesscontrol
+ return c
+}
+
+// UserProject sets the optional parameter "userProject": The project to
+// be billed for this request. Required for Requester Pays buckets.
+func (c *DefaultObjectAccessControlsInsertCall) UserProject(userProject string) *DefaultObjectAccessControlsInsertCall {
+ c.urlParams_.Set("userProject", userProject)
+ return c
+}
+
+// Fields allows partial responses to be retrieved. See
+// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
+// for more information.
+func (c *DefaultObjectAccessControlsInsertCall) Fields(s ...googleapi.Field) *DefaultObjectAccessControlsInsertCall {
+ c.urlParams_.Set("fields", googleapi.CombineFields(s))
+ return c
+}
+
+// Context sets the context to be used in this call's Do method. Any
+// pending HTTP request will be aborted if the provided context is
+// canceled.
+func (c *DefaultObjectAccessControlsInsertCall) Context(ctx context.Context) *DefaultObjectAccessControlsInsertCall {
+ c.ctx_ = ctx
+ return c
+}
+
+// Header returns an http.Header that can be modified by the caller to
+// add HTTP headers to the request.
+func (c *DefaultObjectAccessControlsInsertCall) Header() http.Header {
+ if c.header_ == nil {
+ c.header_ = make(http.Header)
+ }
+ return c.header_
+}
+
+func (c *DefaultObjectAccessControlsInsertCall) doRequest(alt string) (*http.Response, error) {
+ reqHeaders := make(http.Header)
+ for k, v := range c.header_ {
+ reqHeaders[k] = v
+ }
+ reqHeaders.Set("User-Agent", c.s.userAgent())
+ var body io.Reader = nil
+ body, err := googleapi.WithoutDataWrapper.JSONReader(c.objectaccesscontrol)
+ if err != nil {
+ return nil, err
+ }
+ reqHeaders.Set("Content-Type", "application/json")
+ c.urlParams_.Set("alt", alt)
+ c.urlParams_.Set("prettyPrint", "false")
+ urls := googleapi.ResolveRelative(c.s.BasePath, "b/{bucket}/defaultObjectAcl")
+ urls += "?" + c.urlParams_.Encode()
+ req, err := http.NewRequest("POST", urls, body)
+ if err != nil {
+ return nil, err
+ }
+ req.Header = reqHeaders
+ googleapi.Expand(req.URL, map[string]string{
+ "bucket": c.bucket,
+ })
+ return gensupport.SendRequest(c.ctx_, c.s.client, req)
+}
+
+// Do executes the "storage.defaultObjectAccessControls.insert" call.
+// Exactly one of *ObjectAccessControl or error will be non-nil. Any
+// non-2xx status code is an error. Response headers are in either
+// *ObjectAccessControl.ServerResponse.Header or (if a response was
+// returned at all) in error.(*googleapi.Error).Header. Use
+// googleapi.IsNotModified to check whether the returned error was
+// because http.StatusNotModified was returned.
+func (c *DefaultObjectAccessControlsInsertCall) Do(opts ...googleapi.CallOption) (*ObjectAccessControl, error) {
+ gensupport.SetOptions(c.urlParams_, opts...)
+ res, err := c.doRequest("json")
+ if res != nil && res.StatusCode == http.StatusNotModified {
+ if res.Body != nil {
+ res.Body.Close()
+ }
+ return nil, &googleapi.Error{
+ Code: res.StatusCode,
+ Header: res.Header,
+ }
+ }
+ if err != nil {
+ return nil, err
+ }
+ defer googleapi.CloseBody(res)
+ if err := googleapi.CheckResponse(res); err != nil {
+ return nil, err
+ }
+ ret := &ObjectAccessControl{
+ ServerResponse: googleapi.ServerResponse{
+ Header: res.Header,
+ HTTPStatusCode: res.StatusCode,
+ },
+ }
+ target := &ret
+ if err := gensupport.DecodeResponse(target, res); err != nil {
+ return nil, err
+ }
+ return ret, nil
+ // {
+ // "description": "Creates a new default object ACL entry on the specified bucket.",
+ // "httpMethod": "POST",
+ // "id": "storage.defaultObjectAccessControls.insert",
+ // "parameterOrder": [
+ // "bucket"
+ // ],
+ // "parameters": {
+ // "bucket": {
+ // "description": "Name of a bucket.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "userProject": {
+ // "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ // "location": "query",
+ // "type": "string"
+ // }
+ // },
+ // "path": "b/{bucket}/defaultObjectAcl",
+ // "request": {
+ // "$ref": "ObjectAccessControl"
+ // },
+ // "response": {
+ // "$ref": "ObjectAccessControl"
+ // },
+ // "scopes": [
+ // "https://www.googleapis.com/auth/cloud-platform",
+ // "https://www.googleapis.com/auth/devstorage.full_control"
+ // ]
+ // }
+
+}
+
+// method id "storage.defaultObjectAccessControls.list":
+
+type DefaultObjectAccessControlsListCall struct {
+ s *Service
+ bucket string
+ urlParams_ gensupport.URLParams
+ ifNoneMatch_ string
+ ctx_ context.Context
+ header_ http.Header
+}
+
+// List: Retrieves default object ACL entries on the specified bucket.
+func (r *DefaultObjectAccessControlsService) List(bucket string) *DefaultObjectAccessControlsListCall {
+ c := &DefaultObjectAccessControlsListCall{s: r.s, urlParams_: make(gensupport.URLParams)}
+ c.bucket = bucket
+ return c
+}
+
+// IfMetagenerationMatch sets the optional parameter
+// "ifMetagenerationMatch": If present, only return default ACL listing
+// if the bucket's current metageneration matches this value.
+func (c *DefaultObjectAccessControlsListCall) IfMetagenerationMatch(ifMetagenerationMatch int64) *DefaultObjectAccessControlsListCall {
+ c.urlParams_.Set("ifMetagenerationMatch", fmt.Sprint(ifMetagenerationMatch))
+ return c
+}
+
+// IfMetagenerationNotMatch sets the optional parameter
+// "ifMetagenerationNotMatch": If present, only return default ACL
+// listing if the bucket's current metageneration does not match the
+// given value.
+func (c *DefaultObjectAccessControlsListCall) IfMetagenerationNotMatch(ifMetagenerationNotMatch int64) *DefaultObjectAccessControlsListCall {
+ c.urlParams_.Set("ifMetagenerationNotMatch", fmt.Sprint(ifMetagenerationNotMatch))
+ return c
+}
+
+// UserProject sets the optional parameter "userProject": The project to
+// be billed for this request. Required for Requester Pays buckets.
+func (c *DefaultObjectAccessControlsListCall) UserProject(userProject string) *DefaultObjectAccessControlsListCall {
+ c.urlParams_.Set("userProject", userProject)
+ return c
+}
+
+// Fields allows partial responses to be retrieved. See
+// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
+// for more information.
+func (c *DefaultObjectAccessControlsListCall) Fields(s ...googleapi.Field) *DefaultObjectAccessControlsListCall {
+ c.urlParams_.Set("fields", googleapi.CombineFields(s))
+ return c
+}
+
+// IfNoneMatch sets the optional parameter which makes the operation
+// fail if the object's ETag matches the given value. This is useful for
+// getting updates only after the object has changed since the last
+// request. Use googleapi.IsNotModified to check whether the response
+// error from Do is the result of In-None-Match.
+func (c *DefaultObjectAccessControlsListCall) IfNoneMatch(entityTag string) *DefaultObjectAccessControlsListCall {
+ c.ifNoneMatch_ = entityTag
+ return c
+}
+
+// Context sets the context to be used in this call's Do method. Any
+// pending HTTP request will be aborted if the provided context is
+// canceled.
+func (c *DefaultObjectAccessControlsListCall) Context(ctx context.Context) *DefaultObjectAccessControlsListCall {
+ c.ctx_ = ctx
+ return c
+}
+
+// Header returns an http.Header that can be modified by the caller to
+// add HTTP headers to the request.
+func (c *DefaultObjectAccessControlsListCall) Header() http.Header {
+ if c.header_ == nil {
+ c.header_ = make(http.Header)
+ }
+ return c.header_
+}
+
+func (c *DefaultObjectAccessControlsListCall) doRequest(alt string) (*http.Response, error) {
+ reqHeaders := make(http.Header)
+ for k, v := range c.header_ {
+ reqHeaders[k] = v
+ }
+ reqHeaders.Set("User-Agent", c.s.userAgent())
+ if c.ifNoneMatch_ != "" {
+ reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
+ }
+ var body io.Reader = nil
+ c.urlParams_.Set("alt", alt)
+ c.urlParams_.Set("prettyPrint", "false")
+ urls := googleapi.ResolveRelative(c.s.BasePath, "b/{bucket}/defaultObjectAcl")
+ urls += "?" + c.urlParams_.Encode()
+ req, err := http.NewRequest("GET", urls, body)
+ if err != nil {
+ return nil, err
+ }
+ req.Header = reqHeaders
+ googleapi.Expand(req.URL, map[string]string{
+ "bucket": c.bucket,
+ })
+ return gensupport.SendRequest(c.ctx_, c.s.client, req)
+}
+
+// Do executes the "storage.defaultObjectAccessControls.list" call.
+// Exactly one of *ObjectAccessControls or error will be non-nil. Any
+// non-2xx status code is an error. Response headers are in either
+// *ObjectAccessControls.ServerResponse.Header or (if a response was
+// returned at all) in error.(*googleapi.Error).Header. Use
+// googleapi.IsNotModified to check whether the returned error was
+// because http.StatusNotModified was returned.
+func (c *DefaultObjectAccessControlsListCall) Do(opts ...googleapi.CallOption) (*ObjectAccessControls, error) {
+ gensupport.SetOptions(c.urlParams_, opts...)
+ res, err := c.doRequest("json")
+ if res != nil && res.StatusCode == http.StatusNotModified {
+ if res.Body != nil {
+ res.Body.Close()
+ }
+ return nil, &googleapi.Error{
+ Code: res.StatusCode,
+ Header: res.Header,
+ }
+ }
+ if err != nil {
+ return nil, err
+ }
+ defer googleapi.CloseBody(res)
+ if err := googleapi.CheckResponse(res); err != nil {
+ return nil, err
+ }
+ ret := &ObjectAccessControls{
+ ServerResponse: googleapi.ServerResponse{
+ Header: res.Header,
+ HTTPStatusCode: res.StatusCode,
+ },
+ }
+ target := &ret
+ if err := gensupport.DecodeResponse(target, res); err != nil {
+ return nil, err
+ }
+ return ret, nil
+ // {
+ // "description": "Retrieves default object ACL entries on the specified bucket.",
+ // "httpMethod": "GET",
+ // "id": "storage.defaultObjectAccessControls.list",
+ // "parameterOrder": [
+ // "bucket"
+ // ],
+ // "parameters": {
+ // "bucket": {
+ // "description": "Name of a bucket.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "ifMetagenerationMatch": {
+ // "description": "If present, only return default ACL listing if the bucket's current metageneration matches this value.",
+ // "format": "int64",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "ifMetagenerationNotMatch": {
+ // "description": "If present, only return default ACL listing if the bucket's current metageneration does not match the given value.",
+ // "format": "int64",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "userProject": {
+ // "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ // "location": "query",
+ // "type": "string"
+ // }
+ // },
+ // "path": "b/{bucket}/defaultObjectAcl",
+ // "response": {
+ // "$ref": "ObjectAccessControls"
+ // },
+ // "scopes": [
+ // "https://www.googleapis.com/auth/cloud-platform",
+ // "https://www.googleapis.com/auth/devstorage.full_control"
+ // ]
+ // }
+
+}
+
+// method id "storage.defaultObjectAccessControls.patch":
+
+type DefaultObjectAccessControlsPatchCall struct {
+ s *Service
+ bucket string
+ entity string
+ objectaccesscontrol *ObjectAccessControl
+ urlParams_ gensupport.URLParams
+ ctx_ context.Context
+ header_ http.Header
+}
+
+// Patch: Patches a default object ACL entry on the specified bucket.
+func (r *DefaultObjectAccessControlsService) Patch(bucket string, entity string, objectaccesscontrol *ObjectAccessControl) *DefaultObjectAccessControlsPatchCall {
+ c := &DefaultObjectAccessControlsPatchCall{s: r.s, urlParams_: make(gensupport.URLParams)}
+ c.bucket = bucket
+ c.entity = entity
+ c.objectaccesscontrol = objectaccesscontrol
+ return c
+}
+
+// UserProject sets the optional parameter "userProject": The project to
+// be billed for this request. Required for Requester Pays buckets.
+func (c *DefaultObjectAccessControlsPatchCall) UserProject(userProject string) *DefaultObjectAccessControlsPatchCall {
+ c.urlParams_.Set("userProject", userProject)
+ return c
+}
+
+// Fields allows partial responses to be retrieved. See
+// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
+// for more information.
+func (c *DefaultObjectAccessControlsPatchCall) Fields(s ...googleapi.Field) *DefaultObjectAccessControlsPatchCall {
+ c.urlParams_.Set("fields", googleapi.CombineFields(s))
+ return c
+}
+
+// Context sets the context to be used in this call's Do method. Any
+// pending HTTP request will be aborted if the provided context is
+// canceled.
+func (c *DefaultObjectAccessControlsPatchCall) Context(ctx context.Context) *DefaultObjectAccessControlsPatchCall {
+ c.ctx_ = ctx
+ return c
+}
+
+// Header returns an http.Header that can be modified by the caller to
+// add HTTP headers to the request.
+func (c *DefaultObjectAccessControlsPatchCall) Header() http.Header {
+ if c.header_ == nil {
+ c.header_ = make(http.Header)
+ }
+ return c.header_
+}
+
+func (c *DefaultObjectAccessControlsPatchCall) doRequest(alt string) (*http.Response, error) {
+ reqHeaders := make(http.Header)
+ for k, v := range c.header_ {
+ reqHeaders[k] = v
+ }
+ reqHeaders.Set("User-Agent", c.s.userAgent())
+ var body io.Reader = nil
+ body, err := googleapi.WithoutDataWrapper.JSONReader(c.objectaccesscontrol)
+ if err != nil {
+ return nil, err
+ }
+ reqHeaders.Set("Content-Type", "application/json")
+ c.urlParams_.Set("alt", alt)
+ c.urlParams_.Set("prettyPrint", "false")
+ urls := googleapi.ResolveRelative(c.s.BasePath, "b/{bucket}/defaultObjectAcl/{entity}")
+ urls += "?" + c.urlParams_.Encode()
+ req, err := http.NewRequest("PATCH", urls, body)
+ if err != nil {
+ return nil, err
+ }
+ req.Header = reqHeaders
+ googleapi.Expand(req.URL, map[string]string{
+ "bucket": c.bucket,
+ "entity": c.entity,
+ })
+ return gensupport.SendRequest(c.ctx_, c.s.client, req)
+}
+
+// Do executes the "storage.defaultObjectAccessControls.patch" call.
+// Exactly one of *ObjectAccessControl or error will be non-nil. Any
+// non-2xx status code is an error. Response headers are in either
+// *ObjectAccessControl.ServerResponse.Header or (if a response was
+// returned at all) in error.(*googleapi.Error).Header. Use
+// googleapi.IsNotModified to check whether the returned error was
+// because http.StatusNotModified was returned.
+func (c *DefaultObjectAccessControlsPatchCall) Do(opts ...googleapi.CallOption) (*ObjectAccessControl, error) {
+ gensupport.SetOptions(c.urlParams_, opts...)
+ res, err := c.doRequest("json")
+ if res != nil && res.StatusCode == http.StatusNotModified {
+ if res.Body != nil {
+ res.Body.Close()
+ }
+ return nil, &googleapi.Error{
+ Code: res.StatusCode,
+ Header: res.Header,
+ }
+ }
+ if err != nil {
+ return nil, err
+ }
+ defer googleapi.CloseBody(res)
+ if err := googleapi.CheckResponse(res); err != nil {
+ return nil, err
+ }
+ ret := &ObjectAccessControl{
+ ServerResponse: googleapi.ServerResponse{
+ Header: res.Header,
+ HTTPStatusCode: res.StatusCode,
+ },
+ }
+ target := &ret
+ if err := gensupport.DecodeResponse(target, res); err != nil {
+ return nil, err
+ }
+ return ret, nil
+ // {
+ // "description": "Patches a default object ACL entry on the specified bucket.",
+ // "httpMethod": "PATCH",
+ // "id": "storage.defaultObjectAccessControls.patch",
+ // "parameterOrder": [
+ // "bucket",
+ // "entity"
+ // ],
+ // "parameters": {
+ // "bucket": {
+ // "description": "Name of a bucket.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "entity": {
+ // "description": "The entity holding the permission. Can be user-userId, user-emailAddress, group-groupId, group-emailAddress, allUsers, or allAuthenticatedUsers.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "userProject": {
+ // "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ // "location": "query",
+ // "type": "string"
+ // }
+ // },
+ // "path": "b/{bucket}/defaultObjectAcl/{entity}",
+ // "request": {
+ // "$ref": "ObjectAccessControl"
+ // },
+ // "response": {
+ // "$ref": "ObjectAccessControl"
+ // },
+ // "scopes": [
+ // "https://www.googleapis.com/auth/cloud-platform",
+ // "https://www.googleapis.com/auth/devstorage.full_control"
+ // ]
+ // }
+
+}
+
+// method id "storage.defaultObjectAccessControls.update":
+
+type DefaultObjectAccessControlsUpdateCall struct {
+ s *Service
+ bucket string
+ entity string
+ objectaccesscontrol *ObjectAccessControl
+ urlParams_ gensupport.URLParams
+ ctx_ context.Context
+ header_ http.Header
+}
+
+// Update: Updates a default object ACL entry on the specified bucket.
+func (r *DefaultObjectAccessControlsService) Update(bucket string, entity string, objectaccesscontrol *ObjectAccessControl) *DefaultObjectAccessControlsUpdateCall {
+ c := &DefaultObjectAccessControlsUpdateCall{s: r.s, urlParams_: make(gensupport.URLParams)}
+ c.bucket = bucket
+ c.entity = entity
+ c.objectaccesscontrol = objectaccesscontrol
+ return c
+}
+
+// UserProject sets the optional parameter "userProject": The project to
+// be billed for this request. Required for Requester Pays buckets.
+func (c *DefaultObjectAccessControlsUpdateCall) UserProject(userProject string) *DefaultObjectAccessControlsUpdateCall {
+ c.urlParams_.Set("userProject", userProject)
+ return c
+}
+
+// Fields allows partial responses to be retrieved. See
+// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
+// for more information.
+func (c *DefaultObjectAccessControlsUpdateCall) Fields(s ...googleapi.Field) *DefaultObjectAccessControlsUpdateCall {
+ c.urlParams_.Set("fields", googleapi.CombineFields(s))
+ return c
+}
+
+// Context sets the context to be used in this call's Do method. Any
+// pending HTTP request will be aborted if the provided context is
+// canceled.
+func (c *DefaultObjectAccessControlsUpdateCall) Context(ctx context.Context) *DefaultObjectAccessControlsUpdateCall {
+ c.ctx_ = ctx
+ return c
+}
+
+// Header returns an http.Header that can be modified by the caller to
+// add HTTP headers to the request.
+func (c *DefaultObjectAccessControlsUpdateCall) Header() http.Header {
+ if c.header_ == nil {
+ c.header_ = make(http.Header)
+ }
+ return c.header_
+}
+
+func (c *DefaultObjectAccessControlsUpdateCall) doRequest(alt string) (*http.Response, error) {
+ reqHeaders := make(http.Header)
+ for k, v := range c.header_ {
+ reqHeaders[k] = v
+ }
+ reqHeaders.Set("User-Agent", c.s.userAgent())
+ var body io.Reader = nil
+ body, err := googleapi.WithoutDataWrapper.JSONReader(c.objectaccesscontrol)
+ if err != nil {
+ return nil, err
+ }
+ reqHeaders.Set("Content-Type", "application/json")
+ c.urlParams_.Set("alt", alt)
+ c.urlParams_.Set("prettyPrint", "false")
+ urls := googleapi.ResolveRelative(c.s.BasePath, "b/{bucket}/defaultObjectAcl/{entity}")
+ urls += "?" + c.urlParams_.Encode()
+ req, err := http.NewRequest("PUT", urls, body)
+ if err != nil {
+ return nil, err
+ }
+ req.Header = reqHeaders
+ googleapi.Expand(req.URL, map[string]string{
+ "bucket": c.bucket,
+ "entity": c.entity,
+ })
+ return gensupport.SendRequest(c.ctx_, c.s.client, req)
+}
+
+// Do executes the "storage.defaultObjectAccessControls.update" call.
+// Exactly one of *ObjectAccessControl or error will be non-nil. Any
+// non-2xx status code is an error. Response headers are in either
+// *ObjectAccessControl.ServerResponse.Header or (if a response was
+// returned at all) in error.(*googleapi.Error).Header. Use
+// googleapi.IsNotModified to check whether the returned error was
+// because http.StatusNotModified was returned.
+func (c *DefaultObjectAccessControlsUpdateCall) Do(opts ...googleapi.CallOption) (*ObjectAccessControl, error) {
+ gensupport.SetOptions(c.urlParams_, opts...)
+ res, err := c.doRequest("json")
+ if res != nil && res.StatusCode == http.StatusNotModified {
+ if res.Body != nil {
+ res.Body.Close()
+ }
+ return nil, &googleapi.Error{
+ Code: res.StatusCode,
+ Header: res.Header,
+ }
+ }
+ if err != nil {
+ return nil, err
+ }
+ defer googleapi.CloseBody(res)
+ if err := googleapi.CheckResponse(res); err != nil {
+ return nil, err
+ }
+ ret := &ObjectAccessControl{
+ ServerResponse: googleapi.ServerResponse{
+ Header: res.Header,
+ HTTPStatusCode: res.StatusCode,
+ },
+ }
+ target := &ret
+ if err := gensupport.DecodeResponse(target, res); err != nil {
+ return nil, err
+ }
+ return ret, nil
+ // {
+ // "description": "Updates a default object ACL entry on the specified bucket.",
+ // "httpMethod": "PUT",
+ // "id": "storage.defaultObjectAccessControls.update",
+ // "parameterOrder": [
+ // "bucket",
+ // "entity"
+ // ],
+ // "parameters": {
+ // "bucket": {
+ // "description": "Name of a bucket.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "entity": {
+ // "description": "The entity holding the permission. Can be user-userId, user-emailAddress, group-groupId, group-emailAddress, allUsers, or allAuthenticatedUsers.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "userProject": {
+ // "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ // "location": "query",
+ // "type": "string"
+ // }
+ // },
+ // "path": "b/{bucket}/defaultObjectAcl/{entity}",
+ // "request": {
+ // "$ref": "ObjectAccessControl"
+ // },
+ // "response": {
+ // "$ref": "ObjectAccessControl"
+ // },
+ // "scopes": [
+ // "https://www.googleapis.com/auth/cloud-platform",
+ // "https://www.googleapis.com/auth/devstorage.full_control"
+ // ]
+ // }
+
+}
+
+// method id "storage.notifications.delete":
+
+type NotificationsDeleteCall struct {
+ s *Service
+ bucket string
+ notification string
+ urlParams_ gensupport.URLParams
+ ctx_ context.Context
+ header_ http.Header
+}
+
+// Delete: Permanently deletes a notification subscription.
+func (r *NotificationsService) Delete(bucket string, notification string) *NotificationsDeleteCall {
+ c := &NotificationsDeleteCall{s: r.s, urlParams_: make(gensupport.URLParams)}
+ c.bucket = bucket
+ c.notification = notification
+ return c
+}
+
+// UserProject sets the optional parameter "userProject": The project to
+// be billed for this request. Required for Requester Pays buckets.
+func (c *NotificationsDeleteCall) UserProject(userProject string) *NotificationsDeleteCall {
+ c.urlParams_.Set("userProject", userProject)
+ return c
+}
+
+// Fields allows partial responses to be retrieved. See
+// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
+// for more information.
+func (c *NotificationsDeleteCall) Fields(s ...googleapi.Field) *NotificationsDeleteCall {
+ c.urlParams_.Set("fields", googleapi.CombineFields(s))
+ return c
+}
+
+// Context sets the context to be used in this call's Do method. Any
+// pending HTTP request will be aborted if the provided context is
+// canceled.
+func (c *NotificationsDeleteCall) Context(ctx context.Context) *NotificationsDeleteCall {
+ c.ctx_ = ctx
+ return c
+}
+
+// Header returns an http.Header that can be modified by the caller to
+// add HTTP headers to the request.
+func (c *NotificationsDeleteCall) Header() http.Header {
+ if c.header_ == nil {
+ c.header_ = make(http.Header)
+ }
+ return c.header_
+}
+
+func (c *NotificationsDeleteCall) doRequest(alt string) (*http.Response, error) {
+ reqHeaders := make(http.Header)
+ for k, v := range c.header_ {
+ reqHeaders[k] = v
+ }
+ reqHeaders.Set("User-Agent", c.s.userAgent())
+ var body io.Reader = nil
+ c.urlParams_.Set("alt", alt)
+ c.urlParams_.Set("prettyPrint", "false")
+ urls := googleapi.ResolveRelative(c.s.BasePath, "b/{bucket}/notificationConfigs/{notification}")
+ urls += "?" + c.urlParams_.Encode()
+ req, err := http.NewRequest("DELETE", urls, body)
+ if err != nil {
+ return nil, err
+ }
+ req.Header = reqHeaders
+ googleapi.Expand(req.URL, map[string]string{
+ "bucket": c.bucket,
+ "notification": c.notification,
+ })
+ return gensupport.SendRequest(c.ctx_, c.s.client, req)
+}
+
+// Do executes the "storage.notifications.delete" call.
+func (c *NotificationsDeleteCall) Do(opts ...googleapi.CallOption) error {
+ gensupport.SetOptions(c.urlParams_, opts...)
+ res, err := c.doRequest("json")
+ if err != nil {
+ return err
+ }
+ defer googleapi.CloseBody(res)
+ if err := googleapi.CheckResponse(res); err != nil {
+ return err
+ }
+ return nil
+ // {
+ // "description": "Permanently deletes a notification subscription.",
+ // "httpMethod": "DELETE",
+ // "id": "storage.notifications.delete",
+ // "parameterOrder": [
+ // "bucket",
+ // "notification"
+ // ],
+ // "parameters": {
+ // "bucket": {
+ // "description": "The parent bucket of the notification.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "notification": {
+ // "description": "ID of the notification to delete.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "userProject": {
+ // "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ // "location": "query",
+ // "type": "string"
+ // }
+ // },
+ // "path": "b/{bucket}/notificationConfigs/{notification}",
+ // "scopes": [
+ // "https://www.googleapis.com/auth/cloud-platform",
+ // "https://www.googleapis.com/auth/devstorage.full_control",
+ // "https://www.googleapis.com/auth/devstorage.read_write"
+ // ]
+ // }
+
+}
+
+// method id "storage.notifications.get":
+
+type NotificationsGetCall struct {
+ s *Service
+ bucket string
+ notification string
+ urlParams_ gensupport.URLParams
+ ifNoneMatch_ string
+ ctx_ context.Context
+ header_ http.Header
+}
+
+// Get: View a notification configuration.
+func (r *NotificationsService) Get(bucket string, notification string) *NotificationsGetCall {
+ c := &NotificationsGetCall{s: r.s, urlParams_: make(gensupport.URLParams)}
+ c.bucket = bucket
+ c.notification = notification
+ return c
+}
+
+// UserProject sets the optional parameter "userProject": The project to
+// be billed for this request. Required for Requester Pays buckets.
+func (c *NotificationsGetCall) UserProject(userProject string) *NotificationsGetCall {
+ c.urlParams_.Set("userProject", userProject)
+ return c
+}
+
+// Fields allows partial responses to be retrieved. See
+// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
+// for more information.
+func (c *NotificationsGetCall) Fields(s ...googleapi.Field) *NotificationsGetCall {
+ c.urlParams_.Set("fields", googleapi.CombineFields(s))
+ return c
+}
+
+// IfNoneMatch sets the optional parameter which makes the operation
+// fail if the object's ETag matches the given value. This is useful for
+// getting updates only after the object has changed since the last
+// request. Use googleapi.IsNotModified to check whether the response
+// error from Do is the result of In-None-Match.
+func (c *NotificationsGetCall) IfNoneMatch(entityTag string) *NotificationsGetCall {
+ c.ifNoneMatch_ = entityTag
+ return c
+}
+
+// Context sets the context to be used in this call's Do method. Any
+// pending HTTP request will be aborted if the provided context is
+// canceled.
+func (c *NotificationsGetCall) Context(ctx context.Context) *NotificationsGetCall {
+ c.ctx_ = ctx
+ return c
+}
+
+// Header returns an http.Header that can be modified by the caller to
+// add HTTP headers to the request.
+func (c *NotificationsGetCall) Header() http.Header {
+ if c.header_ == nil {
+ c.header_ = make(http.Header)
+ }
+ return c.header_
+}
+
+func (c *NotificationsGetCall) doRequest(alt string) (*http.Response, error) {
+ reqHeaders := make(http.Header)
+ for k, v := range c.header_ {
+ reqHeaders[k] = v
+ }
+ reqHeaders.Set("User-Agent", c.s.userAgent())
+ if c.ifNoneMatch_ != "" {
+ reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
+ }
+ var body io.Reader = nil
+ c.urlParams_.Set("alt", alt)
+ c.urlParams_.Set("prettyPrint", "false")
+ urls := googleapi.ResolveRelative(c.s.BasePath, "b/{bucket}/notificationConfigs/{notification}")
+ urls += "?" + c.urlParams_.Encode()
+ req, err := http.NewRequest("GET", urls, body)
+ if err != nil {
+ return nil, err
+ }
+ req.Header = reqHeaders
+ googleapi.Expand(req.URL, map[string]string{
+ "bucket": c.bucket,
+ "notification": c.notification,
+ })
+ return gensupport.SendRequest(c.ctx_, c.s.client, req)
+}
+
+// Do executes the "storage.notifications.get" call.
+// Exactly one of *Notification or error will be non-nil. Any non-2xx
+// status code is an error. Response headers are in either
+// *Notification.ServerResponse.Header or (if a response was returned at
+// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified
+// to check whether the returned error was because
+// http.StatusNotModified was returned.
+func (c *NotificationsGetCall) Do(opts ...googleapi.CallOption) (*Notification, error) {
+ gensupport.SetOptions(c.urlParams_, opts...)
+ res, err := c.doRequest("json")
+ if res != nil && res.StatusCode == http.StatusNotModified {
+ if res.Body != nil {
+ res.Body.Close()
+ }
+ return nil, &googleapi.Error{
+ Code: res.StatusCode,
+ Header: res.Header,
+ }
+ }
+ if err != nil {
+ return nil, err
+ }
+ defer googleapi.CloseBody(res)
+ if err := googleapi.CheckResponse(res); err != nil {
+ return nil, err
+ }
+ ret := &Notification{
+ ServerResponse: googleapi.ServerResponse{
+ Header: res.Header,
+ HTTPStatusCode: res.StatusCode,
+ },
+ }
+ target := &ret
+ if err := gensupport.DecodeResponse(target, res); err != nil {
+ return nil, err
+ }
+ return ret, nil
+ // {
+ // "description": "View a notification configuration.",
+ // "httpMethod": "GET",
+ // "id": "storage.notifications.get",
+ // "parameterOrder": [
+ // "bucket",
+ // "notification"
+ // ],
+ // "parameters": {
+ // "bucket": {
+ // "description": "The parent bucket of the notification.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "notification": {
+ // "description": "Notification ID",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "userProject": {
+ // "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ // "location": "query",
+ // "type": "string"
+ // }
+ // },
+ // "path": "b/{bucket}/notificationConfigs/{notification}",
+ // "response": {
+ // "$ref": "Notification"
+ // },
+ // "scopes": [
+ // "https://www.googleapis.com/auth/cloud-platform",
+ // "https://www.googleapis.com/auth/cloud-platform.read-only",
+ // "https://www.googleapis.com/auth/devstorage.full_control",
+ // "https://www.googleapis.com/auth/devstorage.read_only",
+ // "https://www.googleapis.com/auth/devstorage.read_write"
+ // ]
+ // }
+
+}
+
+// method id "storage.notifications.insert":
+
+type NotificationsInsertCall struct {
+ s *Service
+ bucket string
+ notification *Notification
+ urlParams_ gensupport.URLParams
+ ctx_ context.Context
+ header_ http.Header
+}
+
+// Insert: Creates a notification subscription for a given bucket.
+func (r *NotificationsService) Insert(bucket string, notification *Notification) *NotificationsInsertCall {
+ c := &NotificationsInsertCall{s: r.s, urlParams_: make(gensupport.URLParams)}
+ c.bucket = bucket
+ c.notification = notification
+ return c
+}
+
+// UserProject sets the optional parameter "userProject": The project to
+// be billed for this request. Required for Requester Pays buckets.
+func (c *NotificationsInsertCall) UserProject(userProject string) *NotificationsInsertCall {
+ c.urlParams_.Set("userProject", userProject)
+ return c
+}
+
+// Fields allows partial responses to be retrieved. See
+// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
+// for more information.
+func (c *NotificationsInsertCall) Fields(s ...googleapi.Field) *NotificationsInsertCall {
+ c.urlParams_.Set("fields", googleapi.CombineFields(s))
+ return c
+}
+
+// Context sets the context to be used in this call's Do method. Any
+// pending HTTP request will be aborted if the provided context is
+// canceled.
+func (c *NotificationsInsertCall) Context(ctx context.Context) *NotificationsInsertCall {
+ c.ctx_ = ctx
+ return c
+}
+
+// Header returns an http.Header that can be modified by the caller to
+// add HTTP headers to the request.
+func (c *NotificationsInsertCall) Header() http.Header {
+ if c.header_ == nil {
+ c.header_ = make(http.Header)
+ }
+ return c.header_
+}
+
+func (c *NotificationsInsertCall) doRequest(alt string) (*http.Response, error) {
+ reqHeaders := make(http.Header)
+ for k, v := range c.header_ {
+ reqHeaders[k] = v
+ }
+ reqHeaders.Set("User-Agent", c.s.userAgent())
+ var body io.Reader = nil
+ body, err := googleapi.WithoutDataWrapper.JSONReader(c.notification)
+ if err != nil {
+ return nil, err
+ }
+ reqHeaders.Set("Content-Type", "application/json")
+ c.urlParams_.Set("alt", alt)
+ c.urlParams_.Set("prettyPrint", "false")
+ urls := googleapi.ResolveRelative(c.s.BasePath, "b/{bucket}/notificationConfigs")
+ urls += "?" + c.urlParams_.Encode()
+ req, err := http.NewRequest("POST", urls, body)
+ if err != nil {
+ return nil, err
+ }
+ req.Header = reqHeaders
+ googleapi.Expand(req.URL, map[string]string{
+ "bucket": c.bucket,
+ })
+ return gensupport.SendRequest(c.ctx_, c.s.client, req)
+}
+
+// Do executes the "storage.notifications.insert" call.
+// Exactly one of *Notification or error will be non-nil. Any non-2xx
+// status code is an error. Response headers are in either
+// *Notification.ServerResponse.Header or (if a response was returned at
+// all) in error.(*googleapi.Error).Header. Use googleapi.IsNotModified
+// to check whether the returned error was because
+// http.StatusNotModified was returned.
+func (c *NotificationsInsertCall) Do(opts ...googleapi.CallOption) (*Notification, error) {
+ gensupport.SetOptions(c.urlParams_, opts...)
+ res, err := c.doRequest("json")
+ if res != nil && res.StatusCode == http.StatusNotModified {
+ if res.Body != nil {
+ res.Body.Close()
+ }
+ return nil, &googleapi.Error{
+ Code: res.StatusCode,
+ Header: res.Header,
+ }
+ }
+ if err != nil {
+ return nil, err
+ }
+ defer googleapi.CloseBody(res)
+ if err := googleapi.CheckResponse(res); err != nil {
+ return nil, err
+ }
+ ret := &Notification{
+ ServerResponse: googleapi.ServerResponse{
+ Header: res.Header,
+ HTTPStatusCode: res.StatusCode,
+ },
+ }
+ target := &ret
+ if err := gensupport.DecodeResponse(target, res); err != nil {
+ return nil, err
+ }
+ return ret, nil
+ // {
+ // "description": "Creates a notification subscription for a given bucket.",
+ // "httpMethod": "POST",
+ // "id": "storage.notifications.insert",
+ // "parameterOrder": [
+ // "bucket"
+ // ],
+ // "parameters": {
+ // "bucket": {
+ // "description": "The parent bucket of the notification.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "userProject": {
+ // "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ // "location": "query",
+ // "type": "string"
+ // }
+ // },
+ // "path": "b/{bucket}/notificationConfigs",
+ // "request": {
+ // "$ref": "Notification"
+ // },
+ // "response": {
+ // "$ref": "Notification"
+ // },
+ // "scopes": [
+ // "https://www.googleapis.com/auth/cloud-platform",
+ // "https://www.googleapis.com/auth/devstorage.full_control",
+ // "https://www.googleapis.com/auth/devstorage.read_write"
+ // ]
+ // }
+
+}
+
+// method id "storage.notifications.list":
+
+type NotificationsListCall struct {
+ s *Service
+ bucket string
+ urlParams_ gensupport.URLParams
+ ifNoneMatch_ string
+ ctx_ context.Context
+ header_ http.Header
+}
+
+// List: Retrieves a list of notification subscriptions for a given
+// bucket.
+func (r *NotificationsService) List(bucket string) *NotificationsListCall {
+ c := &NotificationsListCall{s: r.s, urlParams_: make(gensupport.URLParams)}
+ c.bucket = bucket
+ return c
+}
+
+// UserProject sets the optional parameter "userProject": The project to
+// be billed for this request. Required for Requester Pays buckets.
+func (c *NotificationsListCall) UserProject(userProject string) *NotificationsListCall {
+ c.urlParams_.Set("userProject", userProject)
+ return c
+}
+
+// Fields allows partial responses to be retrieved. See
+// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
+// for more information.
+func (c *NotificationsListCall) Fields(s ...googleapi.Field) *NotificationsListCall {
+ c.urlParams_.Set("fields", googleapi.CombineFields(s))
+ return c
+}
+
+// IfNoneMatch sets the optional parameter which makes the operation
+// fail if the object's ETag matches the given value. This is useful for
+// getting updates only after the object has changed since the last
+// request. Use googleapi.IsNotModified to check whether the response
+// error from Do is the result of In-None-Match.
+func (c *NotificationsListCall) IfNoneMatch(entityTag string) *NotificationsListCall {
+ c.ifNoneMatch_ = entityTag
+ return c
+}
+
+// Context sets the context to be used in this call's Do method. Any
+// pending HTTP request will be aborted if the provided context is
+// canceled.
+func (c *NotificationsListCall) Context(ctx context.Context) *NotificationsListCall {
+ c.ctx_ = ctx
+ return c
+}
+
+// Header returns an http.Header that can be modified by the caller to
+// add HTTP headers to the request.
+func (c *NotificationsListCall) Header() http.Header {
+ if c.header_ == nil {
+ c.header_ = make(http.Header)
+ }
+ return c.header_
+}
+
+func (c *NotificationsListCall) doRequest(alt string) (*http.Response, error) {
+ reqHeaders := make(http.Header)
+ for k, v := range c.header_ {
+ reqHeaders[k] = v
+ }
+ reqHeaders.Set("User-Agent", c.s.userAgent())
+ if c.ifNoneMatch_ != "" {
+ reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
+ }
+ var body io.Reader = nil
+ c.urlParams_.Set("alt", alt)
+ c.urlParams_.Set("prettyPrint", "false")
+ urls := googleapi.ResolveRelative(c.s.BasePath, "b/{bucket}/notificationConfigs")
+ urls += "?" + c.urlParams_.Encode()
+ req, err := http.NewRequest("GET", urls, body)
+ if err != nil {
+ return nil, err
+ }
+ req.Header = reqHeaders
+ googleapi.Expand(req.URL, map[string]string{
+ "bucket": c.bucket,
+ })
+ return gensupport.SendRequest(c.ctx_, c.s.client, req)
+}
+
+// Do executes the "storage.notifications.list" call.
+// Exactly one of *Notifications or error will be non-nil. Any non-2xx
+// status code is an error. Response headers are in either
+// *Notifications.ServerResponse.Header or (if a response was returned
+// at all) in error.(*googleapi.Error).Header. Use
+// googleapi.IsNotModified to check whether the returned error was
+// because http.StatusNotModified was returned.
+func (c *NotificationsListCall) Do(opts ...googleapi.CallOption) (*Notifications, error) {
+ gensupport.SetOptions(c.urlParams_, opts...)
+ res, err := c.doRequest("json")
+ if res != nil && res.StatusCode == http.StatusNotModified {
+ if res.Body != nil {
+ res.Body.Close()
+ }
+ return nil, &googleapi.Error{
+ Code: res.StatusCode,
+ Header: res.Header,
+ }
+ }
+ if err != nil {
+ return nil, err
+ }
+ defer googleapi.CloseBody(res)
+ if err := googleapi.CheckResponse(res); err != nil {
+ return nil, err
+ }
+ ret := &Notifications{
+ ServerResponse: googleapi.ServerResponse{
+ Header: res.Header,
+ HTTPStatusCode: res.StatusCode,
+ },
+ }
+ target := &ret
+ if err := gensupport.DecodeResponse(target, res); err != nil {
+ return nil, err
+ }
+ return ret, nil
+ // {
+ // "description": "Retrieves a list of notification subscriptions for a given bucket.",
+ // "httpMethod": "GET",
+ // "id": "storage.notifications.list",
+ // "parameterOrder": [
+ // "bucket"
+ // ],
+ // "parameters": {
+ // "bucket": {
+ // "description": "Name of a Google Cloud Storage bucket.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "userProject": {
+ // "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ // "location": "query",
+ // "type": "string"
+ // }
+ // },
+ // "path": "b/{bucket}/notificationConfigs",
+ // "response": {
+ // "$ref": "Notifications"
+ // },
+ // "scopes": [
+ // "https://www.googleapis.com/auth/cloud-platform",
+ // "https://www.googleapis.com/auth/cloud-platform.read-only",
+ // "https://www.googleapis.com/auth/devstorage.full_control",
+ // "https://www.googleapis.com/auth/devstorage.read_only",
+ // "https://www.googleapis.com/auth/devstorage.read_write"
+ // ]
+ // }
+
+}
+
+// method id "storage.objectAccessControls.delete":
+
+type ObjectAccessControlsDeleteCall struct {
+ s *Service
+ bucket string
+ object string
+ entity string
+ urlParams_ gensupport.URLParams
+ ctx_ context.Context
+ header_ http.Header
+}
+
+// Delete: Permanently deletes the ACL entry for the specified entity on
+// the specified object.
+func (r *ObjectAccessControlsService) Delete(bucket string, object string, entity string) *ObjectAccessControlsDeleteCall {
+ c := &ObjectAccessControlsDeleteCall{s: r.s, urlParams_: make(gensupport.URLParams)}
+ c.bucket = bucket
+ c.object = object
+ c.entity = entity
+ return c
+}
+
+// Generation sets the optional parameter "generation": If present,
+// selects a specific revision of this object (as opposed to the latest
+// version, the default).
+func (c *ObjectAccessControlsDeleteCall) Generation(generation int64) *ObjectAccessControlsDeleteCall {
+ c.urlParams_.Set("generation", fmt.Sprint(generation))
+ return c
+}
+
+// UserProject sets the optional parameter "userProject": The project to
+// be billed for this request. Required for Requester Pays buckets.
+func (c *ObjectAccessControlsDeleteCall) UserProject(userProject string) *ObjectAccessControlsDeleteCall {
+ c.urlParams_.Set("userProject", userProject)
+ return c
+}
+
+// Fields allows partial responses to be retrieved. See
+// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
+// for more information.
+func (c *ObjectAccessControlsDeleteCall) Fields(s ...googleapi.Field) *ObjectAccessControlsDeleteCall {
+ c.urlParams_.Set("fields", googleapi.CombineFields(s))
+ return c
+}
+
+// Context sets the context to be used in this call's Do method. Any
+// pending HTTP request will be aborted if the provided context is
+// canceled.
+func (c *ObjectAccessControlsDeleteCall) Context(ctx context.Context) *ObjectAccessControlsDeleteCall {
+ c.ctx_ = ctx
+ return c
+}
+
+// Header returns an http.Header that can be modified by the caller to
+// add HTTP headers to the request.
+func (c *ObjectAccessControlsDeleteCall) Header() http.Header {
+ if c.header_ == nil {
+ c.header_ = make(http.Header)
+ }
+ return c.header_
+}
+
+func (c *ObjectAccessControlsDeleteCall) doRequest(alt string) (*http.Response, error) {
+ reqHeaders := make(http.Header)
+ for k, v := range c.header_ {
+ reqHeaders[k] = v
+ }
+ reqHeaders.Set("User-Agent", c.s.userAgent())
+ var body io.Reader = nil
+ c.urlParams_.Set("alt", alt)
+ c.urlParams_.Set("prettyPrint", "false")
+ urls := googleapi.ResolveRelative(c.s.BasePath, "b/{bucket}/o/{object}/acl/{entity}")
+ urls += "?" + c.urlParams_.Encode()
+ req, err := http.NewRequest("DELETE", urls, body)
+ if err != nil {
+ return nil, err
+ }
+ req.Header = reqHeaders
+ googleapi.Expand(req.URL, map[string]string{
+ "bucket": c.bucket,
+ "object": c.object,
+ "entity": c.entity,
+ })
+ return gensupport.SendRequest(c.ctx_, c.s.client, req)
+}
+
+// Do executes the "storage.objectAccessControls.delete" call.
+func (c *ObjectAccessControlsDeleteCall) Do(opts ...googleapi.CallOption) error {
+ gensupport.SetOptions(c.urlParams_, opts...)
+ res, err := c.doRequest("json")
+ if err != nil {
+ return err
+ }
+ defer googleapi.CloseBody(res)
+ if err := googleapi.CheckResponse(res); err != nil {
+ return err
+ }
+ return nil
+ // {
+ // "description": "Permanently deletes the ACL entry for the specified entity on the specified object.",
+ // "httpMethod": "DELETE",
+ // "id": "storage.objectAccessControls.delete",
+ // "parameterOrder": [
+ // "bucket",
+ // "object",
+ // "entity"
+ // ],
+ // "parameters": {
+ // "bucket": {
+ // "description": "Name of a bucket.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "entity": {
+ // "description": "The entity holding the permission. Can be user-userId, user-emailAddress, group-groupId, group-emailAddress, allUsers, or allAuthenticatedUsers.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "generation": {
+ // "description": "If present, selects a specific revision of this object (as opposed to the latest version, the default).",
+ // "format": "int64",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "object": {
+ // "description": "Name of the object. For information about how to URL encode object names to be path safe, see Encoding URI Path Parts.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "userProject": {
+ // "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ // "location": "query",
+ // "type": "string"
+ // }
+ // },
+ // "path": "b/{bucket}/o/{object}/acl/{entity}",
+ // "scopes": [
+ // "https://www.googleapis.com/auth/cloud-platform",
+ // "https://www.googleapis.com/auth/devstorage.full_control"
+ // ]
+ // }
+
+}
+
+// method id "storage.objectAccessControls.get":
+
+type ObjectAccessControlsGetCall struct {
+ s *Service
+ bucket string
+ object string
+ entity string
+ urlParams_ gensupport.URLParams
+ ifNoneMatch_ string
+ ctx_ context.Context
+ header_ http.Header
+}
+
+// Get: Returns the ACL entry for the specified entity on the specified
+// object.
+func (r *ObjectAccessControlsService) Get(bucket string, object string, entity string) *ObjectAccessControlsGetCall {
+ c := &ObjectAccessControlsGetCall{s: r.s, urlParams_: make(gensupport.URLParams)}
+ c.bucket = bucket
+ c.object = object
+ c.entity = entity
+ return c
+}
+
+// Generation sets the optional parameter "generation": If present,
+// selects a specific revision of this object (as opposed to the latest
+// version, the default).
+func (c *ObjectAccessControlsGetCall) Generation(generation int64) *ObjectAccessControlsGetCall {
+ c.urlParams_.Set("generation", fmt.Sprint(generation))
+ return c
+}
+
+// UserProject sets the optional parameter "userProject": The project to
+// be billed for this request. Required for Requester Pays buckets.
+func (c *ObjectAccessControlsGetCall) UserProject(userProject string) *ObjectAccessControlsGetCall {
+ c.urlParams_.Set("userProject", userProject)
+ return c
+}
+
+// Fields allows partial responses to be retrieved. See
+// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
+// for more information.
+func (c *ObjectAccessControlsGetCall) Fields(s ...googleapi.Field) *ObjectAccessControlsGetCall {
+ c.urlParams_.Set("fields", googleapi.CombineFields(s))
+ return c
+}
+
+// IfNoneMatch sets the optional parameter which makes the operation
+// fail if the object's ETag matches the given value. This is useful for
+// getting updates only after the object has changed since the last
+// request. Use googleapi.IsNotModified to check whether the response
+// error from Do is the result of In-None-Match.
+func (c *ObjectAccessControlsGetCall) IfNoneMatch(entityTag string) *ObjectAccessControlsGetCall {
+ c.ifNoneMatch_ = entityTag
+ return c
+}
+
+// Context sets the context to be used in this call's Do method. Any
+// pending HTTP request will be aborted if the provided context is
+// canceled.
+func (c *ObjectAccessControlsGetCall) Context(ctx context.Context) *ObjectAccessControlsGetCall {
+ c.ctx_ = ctx
+ return c
+}
+
+// Header returns an http.Header that can be modified by the caller to
+// add HTTP headers to the request.
+func (c *ObjectAccessControlsGetCall) Header() http.Header {
+ if c.header_ == nil {
+ c.header_ = make(http.Header)
+ }
+ return c.header_
+}
+
+func (c *ObjectAccessControlsGetCall) doRequest(alt string) (*http.Response, error) {
+ reqHeaders := make(http.Header)
+ for k, v := range c.header_ {
+ reqHeaders[k] = v
+ }
+ reqHeaders.Set("User-Agent", c.s.userAgent())
+ if c.ifNoneMatch_ != "" {
+ reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
+ }
+ var body io.Reader = nil
+ c.urlParams_.Set("alt", alt)
+ c.urlParams_.Set("prettyPrint", "false")
+ urls := googleapi.ResolveRelative(c.s.BasePath, "b/{bucket}/o/{object}/acl/{entity}")
+ urls += "?" + c.urlParams_.Encode()
+ req, err := http.NewRequest("GET", urls, body)
+ if err != nil {
+ return nil, err
+ }
+ req.Header = reqHeaders
+ googleapi.Expand(req.URL, map[string]string{
+ "bucket": c.bucket,
+ "object": c.object,
+ "entity": c.entity,
+ })
+ return gensupport.SendRequest(c.ctx_, c.s.client, req)
+}
+
+// Do executes the "storage.objectAccessControls.get" call.
+// Exactly one of *ObjectAccessControl or error will be non-nil. Any
+// non-2xx status code is an error. Response headers are in either
+// *ObjectAccessControl.ServerResponse.Header or (if a response was
+// returned at all) in error.(*googleapi.Error).Header. Use
+// googleapi.IsNotModified to check whether the returned error was
+// because http.StatusNotModified was returned.
+func (c *ObjectAccessControlsGetCall) Do(opts ...googleapi.CallOption) (*ObjectAccessControl, error) {
+ gensupport.SetOptions(c.urlParams_, opts...)
+ res, err := c.doRequest("json")
+ if res != nil && res.StatusCode == http.StatusNotModified {
+ if res.Body != nil {
+ res.Body.Close()
+ }
+ return nil, &googleapi.Error{
+ Code: res.StatusCode,
+ Header: res.Header,
+ }
+ }
+ if err != nil {
+ return nil, err
+ }
+ defer googleapi.CloseBody(res)
+ if err := googleapi.CheckResponse(res); err != nil {
+ return nil, err
+ }
+ ret := &ObjectAccessControl{
+ ServerResponse: googleapi.ServerResponse{
+ Header: res.Header,
+ HTTPStatusCode: res.StatusCode,
+ },
+ }
+ target := &ret
+ if err := gensupport.DecodeResponse(target, res); err != nil {
+ return nil, err
+ }
+ return ret, nil
+ // {
+ // "description": "Returns the ACL entry for the specified entity on the specified object.",
+ // "httpMethod": "GET",
+ // "id": "storage.objectAccessControls.get",
+ // "parameterOrder": [
+ // "bucket",
+ // "object",
+ // "entity"
+ // ],
+ // "parameters": {
+ // "bucket": {
+ // "description": "Name of a bucket.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "entity": {
+ // "description": "The entity holding the permission. Can be user-userId, user-emailAddress, group-groupId, group-emailAddress, allUsers, or allAuthenticatedUsers.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "generation": {
+ // "description": "If present, selects a specific revision of this object (as opposed to the latest version, the default).",
+ // "format": "int64",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "object": {
+ // "description": "Name of the object. For information about how to URL encode object names to be path safe, see Encoding URI Path Parts.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "userProject": {
+ // "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ // "location": "query",
+ // "type": "string"
+ // }
+ // },
+ // "path": "b/{bucket}/o/{object}/acl/{entity}",
+ // "response": {
+ // "$ref": "ObjectAccessControl"
+ // },
+ // "scopes": [
+ // "https://www.googleapis.com/auth/cloud-platform",
+ // "https://www.googleapis.com/auth/devstorage.full_control"
+ // ]
+ // }
+
+}
+
+// method id "storage.objectAccessControls.insert":
+
+type ObjectAccessControlsInsertCall struct {
+ s *Service
+ bucket string
+ object string
+ objectaccesscontrol *ObjectAccessControl
+ urlParams_ gensupport.URLParams
+ ctx_ context.Context
+ header_ http.Header
+}
+
+// Insert: Creates a new ACL entry on the specified object.
+func (r *ObjectAccessControlsService) Insert(bucket string, object string, objectaccesscontrol *ObjectAccessControl) *ObjectAccessControlsInsertCall {
+ c := &ObjectAccessControlsInsertCall{s: r.s, urlParams_: make(gensupport.URLParams)}
+ c.bucket = bucket
+ c.object = object
+ c.objectaccesscontrol = objectaccesscontrol
+ return c
+}
+
+// Generation sets the optional parameter "generation": If present,
+// selects a specific revision of this object (as opposed to the latest
+// version, the default).
+func (c *ObjectAccessControlsInsertCall) Generation(generation int64) *ObjectAccessControlsInsertCall {
+ c.urlParams_.Set("generation", fmt.Sprint(generation))
+ return c
+}
+
+// UserProject sets the optional parameter "userProject": The project to
+// be billed for this request. Required for Requester Pays buckets.
+func (c *ObjectAccessControlsInsertCall) UserProject(userProject string) *ObjectAccessControlsInsertCall {
+ c.urlParams_.Set("userProject", userProject)
+ return c
+}
+
+// Fields allows partial responses to be retrieved. See
+// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
+// for more information.
+func (c *ObjectAccessControlsInsertCall) Fields(s ...googleapi.Field) *ObjectAccessControlsInsertCall {
+ c.urlParams_.Set("fields", googleapi.CombineFields(s))
+ return c
+}
+
+// Context sets the context to be used in this call's Do method. Any
+// pending HTTP request will be aborted if the provided context is
+// canceled.
+func (c *ObjectAccessControlsInsertCall) Context(ctx context.Context) *ObjectAccessControlsInsertCall {
+ c.ctx_ = ctx
+ return c
+}
+
+// Header returns an http.Header that can be modified by the caller to
+// add HTTP headers to the request.
+func (c *ObjectAccessControlsInsertCall) Header() http.Header {
+ if c.header_ == nil {
+ c.header_ = make(http.Header)
+ }
+ return c.header_
+}
+
+func (c *ObjectAccessControlsInsertCall) doRequest(alt string) (*http.Response, error) {
+ reqHeaders := make(http.Header)
+ for k, v := range c.header_ {
+ reqHeaders[k] = v
+ }
+ reqHeaders.Set("User-Agent", c.s.userAgent())
+ var body io.Reader = nil
+ body, err := googleapi.WithoutDataWrapper.JSONReader(c.objectaccesscontrol)
+ if err != nil {
+ return nil, err
+ }
+ reqHeaders.Set("Content-Type", "application/json")
+ c.urlParams_.Set("alt", alt)
+ c.urlParams_.Set("prettyPrint", "false")
+ urls := googleapi.ResolveRelative(c.s.BasePath, "b/{bucket}/o/{object}/acl")
+ urls += "?" + c.urlParams_.Encode()
+ req, err := http.NewRequest("POST", urls, body)
+ if err != nil {
+ return nil, err
+ }
+ req.Header = reqHeaders
+ googleapi.Expand(req.URL, map[string]string{
+ "bucket": c.bucket,
+ "object": c.object,
+ })
+ return gensupport.SendRequest(c.ctx_, c.s.client, req)
+}
+
+// Do executes the "storage.objectAccessControls.insert" call.
+// Exactly one of *ObjectAccessControl or error will be non-nil. Any
+// non-2xx status code is an error. Response headers are in either
+// *ObjectAccessControl.ServerResponse.Header or (if a response was
+// returned at all) in error.(*googleapi.Error).Header. Use
+// googleapi.IsNotModified to check whether the returned error was
+// because http.StatusNotModified was returned.
+func (c *ObjectAccessControlsInsertCall) Do(opts ...googleapi.CallOption) (*ObjectAccessControl, error) {
+ gensupport.SetOptions(c.urlParams_, opts...)
+ res, err := c.doRequest("json")
+ if res != nil && res.StatusCode == http.StatusNotModified {
+ if res.Body != nil {
+ res.Body.Close()
+ }
+ return nil, &googleapi.Error{
+ Code: res.StatusCode,
+ Header: res.Header,
+ }
+ }
+ if err != nil {
+ return nil, err
+ }
+ defer googleapi.CloseBody(res)
+ if err := googleapi.CheckResponse(res); err != nil {
+ return nil, err
+ }
+ ret := &ObjectAccessControl{
+ ServerResponse: googleapi.ServerResponse{
+ Header: res.Header,
+ HTTPStatusCode: res.StatusCode,
+ },
+ }
+ target := &ret
+ if err := gensupport.DecodeResponse(target, res); err != nil {
+ return nil, err
+ }
+ return ret, nil
+ // {
+ // "description": "Creates a new ACL entry on the specified object.",
+ // "httpMethod": "POST",
+ // "id": "storage.objectAccessControls.insert",
+ // "parameterOrder": [
+ // "bucket",
+ // "object"
+ // ],
+ // "parameters": {
+ // "bucket": {
+ // "description": "Name of a bucket.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "generation": {
+ // "description": "If present, selects a specific revision of this object (as opposed to the latest version, the default).",
+ // "format": "int64",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "object": {
+ // "description": "Name of the object. For information about how to URL encode object names to be path safe, see Encoding URI Path Parts.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "userProject": {
+ // "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ // "location": "query",
+ // "type": "string"
+ // }
+ // },
+ // "path": "b/{bucket}/o/{object}/acl",
+ // "request": {
+ // "$ref": "ObjectAccessControl"
+ // },
+ // "response": {
+ // "$ref": "ObjectAccessControl"
+ // },
+ // "scopes": [
+ // "https://www.googleapis.com/auth/cloud-platform",
+ // "https://www.googleapis.com/auth/devstorage.full_control"
+ // ]
+ // }
+
+}
+
+// method id "storage.objectAccessControls.list":
+
+type ObjectAccessControlsListCall struct {
+ s *Service
+ bucket string
+ object string
+ urlParams_ gensupport.URLParams
+ ifNoneMatch_ string
+ ctx_ context.Context
+ header_ http.Header
+}
+
+// List: Retrieves ACL entries on the specified object.
+func (r *ObjectAccessControlsService) List(bucket string, object string) *ObjectAccessControlsListCall {
+ c := &ObjectAccessControlsListCall{s: r.s, urlParams_: make(gensupport.URLParams)}
+ c.bucket = bucket
+ c.object = object
+ return c
+}
+
+// Generation sets the optional parameter "generation": If present,
+// selects a specific revision of this object (as opposed to the latest
+// version, the default).
+func (c *ObjectAccessControlsListCall) Generation(generation int64) *ObjectAccessControlsListCall {
+ c.urlParams_.Set("generation", fmt.Sprint(generation))
+ return c
+}
+
+// UserProject sets the optional parameter "userProject": The project to
+// be billed for this request. Required for Requester Pays buckets.
+func (c *ObjectAccessControlsListCall) UserProject(userProject string) *ObjectAccessControlsListCall {
+ c.urlParams_.Set("userProject", userProject)
+ return c
+}
+
+// Fields allows partial responses to be retrieved. See
+// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
+// for more information.
+func (c *ObjectAccessControlsListCall) Fields(s ...googleapi.Field) *ObjectAccessControlsListCall {
+ c.urlParams_.Set("fields", googleapi.CombineFields(s))
+ return c
+}
+
+// IfNoneMatch sets the optional parameter which makes the operation
+// fail if the object's ETag matches the given value. This is useful for
+// getting updates only after the object has changed since the last
+// request. Use googleapi.IsNotModified to check whether the response
+// error from Do is the result of In-None-Match.
+func (c *ObjectAccessControlsListCall) IfNoneMatch(entityTag string) *ObjectAccessControlsListCall {
+ c.ifNoneMatch_ = entityTag
+ return c
+}
+
+// Context sets the context to be used in this call's Do method. Any
+// pending HTTP request will be aborted if the provided context is
+// canceled.
+func (c *ObjectAccessControlsListCall) Context(ctx context.Context) *ObjectAccessControlsListCall {
+ c.ctx_ = ctx
+ return c
+}
+
+// Header returns an http.Header that can be modified by the caller to
+// add HTTP headers to the request.
+func (c *ObjectAccessControlsListCall) Header() http.Header {
+ if c.header_ == nil {
+ c.header_ = make(http.Header)
+ }
+ return c.header_
+}
+
+func (c *ObjectAccessControlsListCall) doRequest(alt string) (*http.Response, error) {
+ reqHeaders := make(http.Header)
+ for k, v := range c.header_ {
+ reqHeaders[k] = v
+ }
+ reqHeaders.Set("User-Agent", c.s.userAgent())
+ if c.ifNoneMatch_ != "" {
+ reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
+ }
+ var body io.Reader = nil
+ c.urlParams_.Set("alt", alt)
+ c.urlParams_.Set("prettyPrint", "false")
+ urls := googleapi.ResolveRelative(c.s.BasePath, "b/{bucket}/o/{object}/acl")
+ urls += "?" + c.urlParams_.Encode()
+ req, err := http.NewRequest("GET", urls, body)
+ if err != nil {
+ return nil, err
+ }
+ req.Header = reqHeaders
+ googleapi.Expand(req.URL, map[string]string{
+ "bucket": c.bucket,
+ "object": c.object,
+ })
+ return gensupport.SendRequest(c.ctx_, c.s.client, req)
+}
+
+// Do executes the "storage.objectAccessControls.list" call.
+// Exactly one of *ObjectAccessControls or error will be non-nil. Any
+// non-2xx status code is an error. Response headers are in either
+// *ObjectAccessControls.ServerResponse.Header or (if a response was
+// returned at all) in error.(*googleapi.Error).Header. Use
+// googleapi.IsNotModified to check whether the returned error was
+// because http.StatusNotModified was returned.
+func (c *ObjectAccessControlsListCall) Do(opts ...googleapi.CallOption) (*ObjectAccessControls, error) {
+ gensupport.SetOptions(c.urlParams_, opts...)
+ res, err := c.doRequest("json")
+ if res != nil && res.StatusCode == http.StatusNotModified {
+ if res.Body != nil {
+ res.Body.Close()
+ }
+ return nil, &googleapi.Error{
+ Code: res.StatusCode,
+ Header: res.Header,
+ }
+ }
+ if err != nil {
+ return nil, err
+ }
+ defer googleapi.CloseBody(res)
+ if err := googleapi.CheckResponse(res); err != nil {
+ return nil, err
+ }
+ ret := &ObjectAccessControls{
+ ServerResponse: googleapi.ServerResponse{
+ Header: res.Header,
+ HTTPStatusCode: res.StatusCode,
+ },
+ }
+ target := &ret
+ if err := gensupport.DecodeResponse(target, res); err != nil {
+ return nil, err
+ }
+ return ret, nil
+ // {
+ // "description": "Retrieves ACL entries on the specified object.",
+ // "httpMethod": "GET",
+ // "id": "storage.objectAccessControls.list",
+ // "parameterOrder": [
+ // "bucket",
+ // "object"
+ // ],
+ // "parameters": {
+ // "bucket": {
+ // "description": "Name of a bucket.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "generation": {
+ // "description": "If present, selects a specific revision of this object (as opposed to the latest version, the default).",
+ // "format": "int64",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "object": {
+ // "description": "Name of the object. For information about how to URL encode object names to be path safe, see Encoding URI Path Parts.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "userProject": {
+ // "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ // "location": "query",
+ // "type": "string"
+ // }
+ // },
+ // "path": "b/{bucket}/o/{object}/acl",
+ // "response": {
+ // "$ref": "ObjectAccessControls"
+ // },
+ // "scopes": [
+ // "https://www.googleapis.com/auth/cloud-platform",
+ // "https://www.googleapis.com/auth/devstorage.full_control"
+ // ]
+ // }
+
+}
+
+// method id "storage.objectAccessControls.patch":
+
+type ObjectAccessControlsPatchCall struct {
+ s *Service
+ bucket string
+ object string
+ entity string
+ objectaccesscontrol *ObjectAccessControl
+ urlParams_ gensupport.URLParams
+ ctx_ context.Context
+ header_ http.Header
+}
+
+// Patch: Patches an ACL entry on the specified object.
+func (r *ObjectAccessControlsService) Patch(bucket string, object string, entity string, objectaccesscontrol *ObjectAccessControl) *ObjectAccessControlsPatchCall {
+ c := &ObjectAccessControlsPatchCall{s: r.s, urlParams_: make(gensupport.URLParams)}
+ c.bucket = bucket
+ c.object = object
+ c.entity = entity
+ c.objectaccesscontrol = objectaccesscontrol
+ return c
+}
+
+// Generation sets the optional parameter "generation": If present,
+// selects a specific revision of this object (as opposed to the latest
+// version, the default).
+func (c *ObjectAccessControlsPatchCall) Generation(generation int64) *ObjectAccessControlsPatchCall {
+ c.urlParams_.Set("generation", fmt.Sprint(generation))
+ return c
+}
+
+// UserProject sets the optional parameter "userProject": The project to
+// be billed for this request. Required for Requester Pays buckets.
+func (c *ObjectAccessControlsPatchCall) UserProject(userProject string) *ObjectAccessControlsPatchCall {
+ c.urlParams_.Set("userProject", userProject)
+ return c
+}
+
+// Fields allows partial responses to be retrieved. See
+// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
+// for more information.
+func (c *ObjectAccessControlsPatchCall) Fields(s ...googleapi.Field) *ObjectAccessControlsPatchCall {
+ c.urlParams_.Set("fields", googleapi.CombineFields(s))
+ return c
+}
+
+// Context sets the context to be used in this call's Do method. Any
+// pending HTTP request will be aborted if the provided context is
+// canceled.
+func (c *ObjectAccessControlsPatchCall) Context(ctx context.Context) *ObjectAccessControlsPatchCall {
+ c.ctx_ = ctx
+ return c
+}
+
+// Header returns an http.Header that can be modified by the caller to
+// add HTTP headers to the request.
+func (c *ObjectAccessControlsPatchCall) Header() http.Header {
+ if c.header_ == nil {
+ c.header_ = make(http.Header)
+ }
+ return c.header_
+}
+
+func (c *ObjectAccessControlsPatchCall) doRequest(alt string) (*http.Response, error) {
+ reqHeaders := make(http.Header)
+ for k, v := range c.header_ {
+ reqHeaders[k] = v
+ }
+ reqHeaders.Set("User-Agent", c.s.userAgent())
+ var body io.Reader = nil
+ body, err := googleapi.WithoutDataWrapper.JSONReader(c.objectaccesscontrol)
+ if err != nil {
+ return nil, err
+ }
+ reqHeaders.Set("Content-Type", "application/json")
+ c.urlParams_.Set("alt", alt)
+ c.urlParams_.Set("prettyPrint", "false")
+ urls := googleapi.ResolveRelative(c.s.BasePath, "b/{bucket}/o/{object}/acl/{entity}")
+ urls += "?" + c.urlParams_.Encode()
+ req, err := http.NewRequest("PATCH", urls, body)
+ if err != nil {
+ return nil, err
+ }
+ req.Header = reqHeaders
+ googleapi.Expand(req.URL, map[string]string{
+ "bucket": c.bucket,
+ "object": c.object,
+ "entity": c.entity,
+ })
+ return gensupport.SendRequest(c.ctx_, c.s.client, req)
+}
+
+// Do executes the "storage.objectAccessControls.patch" call.
+// Exactly one of *ObjectAccessControl or error will be non-nil. Any
+// non-2xx status code is an error. Response headers are in either
+// *ObjectAccessControl.ServerResponse.Header or (if a response was
+// returned at all) in error.(*googleapi.Error).Header. Use
+// googleapi.IsNotModified to check whether the returned error was
+// because http.StatusNotModified was returned.
+func (c *ObjectAccessControlsPatchCall) Do(opts ...googleapi.CallOption) (*ObjectAccessControl, error) {
+ gensupport.SetOptions(c.urlParams_, opts...)
+ res, err := c.doRequest("json")
+ if res != nil && res.StatusCode == http.StatusNotModified {
+ if res.Body != nil {
+ res.Body.Close()
+ }
+ return nil, &googleapi.Error{
+ Code: res.StatusCode,
+ Header: res.Header,
+ }
+ }
+ if err != nil {
+ return nil, err
+ }
+ defer googleapi.CloseBody(res)
+ if err := googleapi.CheckResponse(res); err != nil {
+ return nil, err
+ }
+ ret := &ObjectAccessControl{
+ ServerResponse: googleapi.ServerResponse{
+ Header: res.Header,
+ HTTPStatusCode: res.StatusCode,
+ },
+ }
+ target := &ret
+ if err := gensupport.DecodeResponse(target, res); err != nil {
+ return nil, err
+ }
+ return ret, nil
+ // {
+ // "description": "Patches an ACL entry on the specified object.",
+ // "httpMethod": "PATCH",
+ // "id": "storage.objectAccessControls.patch",
+ // "parameterOrder": [
+ // "bucket",
+ // "object",
+ // "entity"
+ // ],
+ // "parameters": {
+ // "bucket": {
+ // "description": "Name of a bucket.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "entity": {
+ // "description": "The entity holding the permission. Can be user-userId, user-emailAddress, group-groupId, group-emailAddress, allUsers, or allAuthenticatedUsers.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "generation": {
+ // "description": "If present, selects a specific revision of this object (as opposed to the latest version, the default).",
+ // "format": "int64",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "object": {
+ // "description": "Name of the object. For information about how to URL encode object names to be path safe, see Encoding URI Path Parts.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "userProject": {
+ // "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ // "location": "query",
+ // "type": "string"
+ // }
+ // },
+ // "path": "b/{bucket}/o/{object}/acl/{entity}",
+ // "request": {
+ // "$ref": "ObjectAccessControl"
+ // },
+ // "response": {
+ // "$ref": "ObjectAccessControl"
+ // },
+ // "scopes": [
+ // "https://www.googleapis.com/auth/cloud-platform",
+ // "https://www.googleapis.com/auth/devstorage.full_control"
+ // ]
+ // }
+
+}
+
+// method id "storage.objectAccessControls.update":
+
+type ObjectAccessControlsUpdateCall struct {
+ s *Service
+ bucket string
+ object string
+ entity string
+ objectaccesscontrol *ObjectAccessControl
+ urlParams_ gensupport.URLParams
+ ctx_ context.Context
+ header_ http.Header
+}
+
+// Update: Updates an ACL entry on the specified object.
+func (r *ObjectAccessControlsService) Update(bucket string, object string, entity string, objectaccesscontrol *ObjectAccessControl) *ObjectAccessControlsUpdateCall {
+ c := &ObjectAccessControlsUpdateCall{s: r.s, urlParams_: make(gensupport.URLParams)}
+ c.bucket = bucket
+ c.object = object
+ c.entity = entity
+ c.objectaccesscontrol = objectaccesscontrol
+ return c
+}
+
+// Generation sets the optional parameter "generation": If present,
+// selects a specific revision of this object (as opposed to the latest
+// version, the default).
+func (c *ObjectAccessControlsUpdateCall) Generation(generation int64) *ObjectAccessControlsUpdateCall {
+ c.urlParams_.Set("generation", fmt.Sprint(generation))
+ return c
+}
+
+// UserProject sets the optional parameter "userProject": The project to
+// be billed for this request. Required for Requester Pays buckets.
+func (c *ObjectAccessControlsUpdateCall) UserProject(userProject string) *ObjectAccessControlsUpdateCall {
+ c.urlParams_.Set("userProject", userProject)
+ return c
+}
+
+// Fields allows partial responses to be retrieved. See
+// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
+// for more information.
+func (c *ObjectAccessControlsUpdateCall) Fields(s ...googleapi.Field) *ObjectAccessControlsUpdateCall {
+ c.urlParams_.Set("fields", googleapi.CombineFields(s))
+ return c
+}
+
+// Context sets the context to be used in this call's Do method. Any
+// pending HTTP request will be aborted if the provided context is
+// canceled.
+func (c *ObjectAccessControlsUpdateCall) Context(ctx context.Context) *ObjectAccessControlsUpdateCall {
+ c.ctx_ = ctx
+ return c
+}
+
+// Header returns an http.Header that can be modified by the caller to
+// add HTTP headers to the request.
+func (c *ObjectAccessControlsUpdateCall) Header() http.Header {
+ if c.header_ == nil {
+ c.header_ = make(http.Header)
+ }
+ return c.header_
+}
+
+func (c *ObjectAccessControlsUpdateCall) doRequest(alt string) (*http.Response, error) {
+ reqHeaders := make(http.Header)
+ for k, v := range c.header_ {
+ reqHeaders[k] = v
+ }
+ reqHeaders.Set("User-Agent", c.s.userAgent())
+ var body io.Reader = nil
+ body, err := googleapi.WithoutDataWrapper.JSONReader(c.objectaccesscontrol)
+ if err != nil {
+ return nil, err
+ }
+ reqHeaders.Set("Content-Type", "application/json")
+ c.urlParams_.Set("alt", alt)
+ c.urlParams_.Set("prettyPrint", "false")
+ urls := googleapi.ResolveRelative(c.s.BasePath, "b/{bucket}/o/{object}/acl/{entity}")
+ urls += "?" + c.urlParams_.Encode()
+ req, err := http.NewRequest("PUT", urls, body)
+ if err != nil {
+ return nil, err
+ }
+ req.Header = reqHeaders
+ googleapi.Expand(req.URL, map[string]string{
+ "bucket": c.bucket,
+ "object": c.object,
+ "entity": c.entity,
+ })
+ return gensupport.SendRequest(c.ctx_, c.s.client, req)
+}
+
+// Do executes the "storage.objectAccessControls.update" call.
+// Exactly one of *ObjectAccessControl or error will be non-nil. Any
+// non-2xx status code is an error. Response headers are in either
+// *ObjectAccessControl.ServerResponse.Header or (if a response was
+// returned at all) in error.(*googleapi.Error).Header. Use
+// googleapi.IsNotModified to check whether the returned error was
+// because http.StatusNotModified was returned.
+func (c *ObjectAccessControlsUpdateCall) Do(opts ...googleapi.CallOption) (*ObjectAccessControl, error) {
+ gensupport.SetOptions(c.urlParams_, opts...)
+ res, err := c.doRequest("json")
+ if res != nil && res.StatusCode == http.StatusNotModified {
+ if res.Body != nil {
+ res.Body.Close()
+ }
+ return nil, &googleapi.Error{
+ Code: res.StatusCode,
+ Header: res.Header,
+ }
+ }
+ if err != nil {
+ return nil, err
+ }
+ defer googleapi.CloseBody(res)
+ if err := googleapi.CheckResponse(res); err != nil {
+ return nil, err
+ }
+ ret := &ObjectAccessControl{
+ ServerResponse: googleapi.ServerResponse{
+ Header: res.Header,
+ HTTPStatusCode: res.StatusCode,
+ },
+ }
+ target := &ret
+ if err := gensupport.DecodeResponse(target, res); err != nil {
+ return nil, err
+ }
+ return ret, nil
+ // {
+ // "description": "Updates an ACL entry on the specified object.",
+ // "httpMethod": "PUT",
+ // "id": "storage.objectAccessControls.update",
+ // "parameterOrder": [
+ // "bucket",
+ // "object",
+ // "entity"
+ // ],
+ // "parameters": {
+ // "bucket": {
+ // "description": "Name of a bucket.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "entity": {
+ // "description": "The entity holding the permission. Can be user-userId, user-emailAddress, group-groupId, group-emailAddress, allUsers, or allAuthenticatedUsers.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "generation": {
+ // "description": "If present, selects a specific revision of this object (as opposed to the latest version, the default).",
+ // "format": "int64",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "object": {
+ // "description": "Name of the object. For information about how to URL encode object names to be path safe, see Encoding URI Path Parts.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "userProject": {
+ // "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ // "location": "query",
+ // "type": "string"
+ // }
+ // },
+ // "path": "b/{bucket}/o/{object}/acl/{entity}",
+ // "request": {
+ // "$ref": "ObjectAccessControl"
+ // },
+ // "response": {
+ // "$ref": "ObjectAccessControl"
+ // },
+ // "scopes": [
+ // "https://www.googleapis.com/auth/cloud-platform",
+ // "https://www.googleapis.com/auth/devstorage.full_control"
+ // ]
+ // }
+
+}
+
+// method id "storage.objects.compose":
+
+type ObjectsComposeCall struct {
+ s *Service
+ destinationBucket string
+ destinationObject string
+ composerequest *ComposeRequest
+ urlParams_ gensupport.URLParams
+ ctx_ context.Context
+ header_ http.Header
+}
+
+// Compose: Concatenates a list of existing objects into a new object in
+// the same bucket.
+func (r *ObjectsService) Compose(destinationBucket string, destinationObject string, composerequest *ComposeRequest) *ObjectsComposeCall {
+ c := &ObjectsComposeCall{s: r.s, urlParams_: make(gensupport.URLParams)}
+ c.destinationBucket = destinationBucket
+ c.destinationObject = destinationObject
+ c.composerequest = composerequest
+ return c
+}
+
+// DestinationPredefinedAcl sets the optional parameter
+// "destinationPredefinedAcl": Apply a predefined set of access controls
+// to the destination object.
+//
+// Possible values:
+// "authenticatedRead" - Object owner gets OWNER access, and
+// allAuthenticatedUsers get READER access.
+// "bucketOwnerFullControl" - Object owner gets OWNER access, and
+// project team owners get OWNER access.
+// "bucketOwnerRead" - Object owner gets OWNER access, and project
+// team owners get READER access.
+// "private" - Object owner gets OWNER access.
+// "projectPrivate" - Object owner gets OWNER access, and project team
+// members get access according to their roles.
+// "publicRead" - Object owner gets OWNER access, and allUsers get
+// READER access.
+func (c *ObjectsComposeCall) DestinationPredefinedAcl(destinationPredefinedAcl string) *ObjectsComposeCall {
+ c.urlParams_.Set("destinationPredefinedAcl", destinationPredefinedAcl)
+ return c
+}
+
+// IfGenerationMatch sets the optional parameter "ifGenerationMatch":
+// Makes the operation conditional on whether the object's current
+// generation matches the given value. Setting to 0 makes the operation
+// succeed only if there are no live versions of the object.
+func (c *ObjectsComposeCall) IfGenerationMatch(ifGenerationMatch int64) *ObjectsComposeCall {
+ c.urlParams_.Set("ifGenerationMatch", fmt.Sprint(ifGenerationMatch))
+ return c
+}
+
+// IfMetagenerationMatch sets the optional parameter
+// "ifMetagenerationMatch": Makes the operation conditional on whether
+// the object's current metageneration matches the given value.
+func (c *ObjectsComposeCall) IfMetagenerationMatch(ifMetagenerationMatch int64) *ObjectsComposeCall {
+ c.urlParams_.Set("ifMetagenerationMatch", fmt.Sprint(ifMetagenerationMatch))
+ return c
+}
+
+// KmsKeyName sets the optional parameter "kmsKeyName": Resource name of
+// the Cloud KMS key, of the form
+// projects/my-project/locations/global/keyRings/my-kr/cryptoKeys/my-key,
+// that will be used to encrypt the object. Overrides the object
+// metadata's kms_key_name value, if any.
+func (c *ObjectsComposeCall) KmsKeyName(kmsKeyName string) *ObjectsComposeCall {
+ c.urlParams_.Set("kmsKeyName", kmsKeyName)
+ return c
+}
+
+// UserProject sets the optional parameter "userProject": The project to
+// be billed for this request. Required for Requester Pays buckets.
+func (c *ObjectsComposeCall) UserProject(userProject string) *ObjectsComposeCall {
+ c.urlParams_.Set("userProject", userProject)
+ return c
+}
+
+// Fields allows partial responses to be retrieved. See
+// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
+// for more information.
+func (c *ObjectsComposeCall) Fields(s ...googleapi.Field) *ObjectsComposeCall {
+ c.urlParams_.Set("fields", googleapi.CombineFields(s))
+ return c
+}
+
+// Context sets the context to be used in this call's Do method. Any
+// pending HTTP request will be aborted if the provided context is
+// canceled.
+func (c *ObjectsComposeCall) Context(ctx context.Context) *ObjectsComposeCall {
+ c.ctx_ = ctx
+ return c
+}
+
+// Header returns an http.Header that can be modified by the caller to
+// add HTTP headers to the request.
+func (c *ObjectsComposeCall) Header() http.Header {
+ if c.header_ == nil {
+ c.header_ = make(http.Header)
+ }
+ return c.header_
+}
+
+func (c *ObjectsComposeCall) doRequest(alt string) (*http.Response, error) {
+ reqHeaders := make(http.Header)
+ for k, v := range c.header_ {
+ reqHeaders[k] = v
+ }
+ reqHeaders.Set("User-Agent", c.s.userAgent())
+ var body io.Reader = nil
+ body, err := googleapi.WithoutDataWrapper.JSONReader(c.composerequest)
+ if err != nil {
+ return nil, err
+ }
+ reqHeaders.Set("Content-Type", "application/json")
+ c.urlParams_.Set("alt", alt)
+ c.urlParams_.Set("prettyPrint", "false")
+ urls := googleapi.ResolveRelative(c.s.BasePath, "b/{destinationBucket}/o/{destinationObject}/compose")
+ urls += "?" + c.urlParams_.Encode()
+ req, err := http.NewRequest("POST", urls, body)
+ if err != nil {
+ return nil, err
+ }
+ req.Header = reqHeaders
+ googleapi.Expand(req.URL, map[string]string{
+ "destinationBucket": c.destinationBucket,
+ "destinationObject": c.destinationObject,
+ })
+ return gensupport.SendRequest(c.ctx_, c.s.client, req)
+}
+
+// Do executes the "storage.objects.compose" call.
+// Exactly one of *Object or error will be non-nil. Any non-2xx status
+// code is an error. Response headers are in either
+// *Object.ServerResponse.Header or (if a response was returned at all)
+// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to
+// check whether the returned error was because http.StatusNotModified
+// was returned.
+func (c *ObjectsComposeCall) Do(opts ...googleapi.CallOption) (*Object, error) {
+ gensupport.SetOptions(c.urlParams_, opts...)
+ res, err := c.doRequest("json")
+ if res != nil && res.StatusCode == http.StatusNotModified {
+ if res.Body != nil {
+ res.Body.Close()
+ }
+ return nil, &googleapi.Error{
+ Code: res.StatusCode,
+ Header: res.Header,
+ }
+ }
+ if err != nil {
+ return nil, err
+ }
+ defer googleapi.CloseBody(res)
+ if err := googleapi.CheckResponse(res); err != nil {
+ return nil, err
+ }
+ ret := &Object{
+ ServerResponse: googleapi.ServerResponse{
+ Header: res.Header,
+ HTTPStatusCode: res.StatusCode,
+ },
+ }
+ target := &ret
+ if err := gensupport.DecodeResponse(target, res); err != nil {
+ return nil, err
+ }
+ return ret, nil
+ // {
+ // "description": "Concatenates a list of existing objects into a new object in the same bucket.",
+ // "httpMethod": "POST",
+ // "id": "storage.objects.compose",
+ // "parameterOrder": [
+ // "destinationBucket",
+ // "destinationObject"
+ // ],
+ // "parameters": {
+ // "destinationBucket": {
+ // "description": "Name of the bucket containing the source objects. The destination object is stored in this bucket.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "destinationObject": {
+ // "description": "Name of the new object. For information about how to URL encode object names to be path safe, see Encoding URI Path Parts.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "destinationPredefinedAcl": {
+ // "description": "Apply a predefined set of access controls to the destination object.",
+ // "enum": [
+ // "authenticatedRead",
+ // "bucketOwnerFullControl",
+ // "bucketOwnerRead",
+ // "private",
+ // "projectPrivate",
+ // "publicRead"
+ // ],
+ // "enumDescriptions": [
+ // "Object owner gets OWNER access, and allAuthenticatedUsers get READER access.",
+ // "Object owner gets OWNER access, and project team owners get OWNER access.",
+ // "Object owner gets OWNER access, and project team owners get READER access.",
+ // "Object owner gets OWNER access.",
+ // "Object owner gets OWNER access, and project team members get access according to their roles.",
+ // "Object owner gets OWNER access, and allUsers get READER access."
+ // ],
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "ifGenerationMatch": {
+ // "description": "Makes the operation conditional on whether the object's current generation matches the given value. Setting to 0 makes the operation succeed only if there are no live versions of the object.",
+ // "format": "int64",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "ifMetagenerationMatch": {
+ // "description": "Makes the operation conditional on whether the object's current metageneration matches the given value.",
+ // "format": "int64",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "kmsKeyName": {
+ // "description": "Resource name of the Cloud KMS key, of the form projects/my-project/locations/global/keyRings/my-kr/cryptoKeys/my-key, that will be used to encrypt the object. Overrides the object metadata's kms_key_name value, if any.",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "userProject": {
+ // "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ // "location": "query",
+ // "type": "string"
+ // }
+ // },
+ // "path": "b/{destinationBucket}/o/{destinationObject}/compose",
+ // "request": {
+ // "$ref": "ComposeRequest"
+ // },
+ // "response": {
+ // "$ref": "Object"
+ // },
+ // "scopes": [
+ // "https://www.googleapis.com/auth/cloud-platform",
+ // "https://www.googleapis.com/auth/devstorage.full_control",
+ // "https://www.googleapis.com/auth/devstorage.read_write"
+ // ]
+ // }
+
+}
+
+// method id "storage.objects.copy":
+
+type ObjectsCopyCall struct {
+ s *Service
+ sourceBucket string
+ sourceObject string
+ destinationBucket string
+ destinationObject string
+ object *Object
+ urlParams_ gensupport.URLParams
+ ctx_ context.Context
+ header_ http.Header
+}
+
+// Copy: Copies a source object to a destination object. Optionally
+// overrides metadata.
+func (r *ObjectsService) Copy(sourceBucket string, sourceObject string, destinationBucket string, destinationObject string, object *Object) *ObjectsCopyCall {
+ c := &ObjectsCopyCall{s: r.s, urlParams_: make(gensupport.URLParams)}
+ c.sourceBucket = sourceBucket
+ c.sourceObject = sourceObject
+ c.destinationBucket = destinationBucket
+ c.destinationObject = destinationObject
+ c.object = object
+ return c
+}
+
+// DestinationPredefinedAcl sets the optional parameter
+// "destinationPredefinedAcl": Apply a predefined set of access controls
+// to the destination object.
+//
+// Possible values:
+// "authenticatedRead" - Object owner gets OWNER access, and
+// allAuthenticatedUsers get READER access.
+// "bucketOwnerFullControl" - Object owner gets OWNER access, and
+// project team owners get OWNER access.
+// "bucketOwnerRead" - Object owner gets OWNER access, and project
+// team owners get READER access.
+// "private" - Object owner gets OWNER access.
+// "projectPrivate" - Object owner gets OWNER access, and project team
+// members get access according to their roles.
+// "publicRead" - Object owner gets OWNER access, and allUsers get
+// READER access.
+func (c *ObjectsCopyCall) DestinationPredefinedAcl(destinationPredefinedAcl string) *ObjectsCopyCall {
+ c.urlParams_.Set("destinationPredefinedAcl", destinationPredefinedAcl)
+ return c
+}
+
+// IfGenerationMatch sets the optional parameter "ifGenerationMatch":
+// Makes the operation conditional on whether the destination object's
+// current generation matches the given value. Setting to 0 makes the
+// operation succeed only if there are no live versions of the object.
+func (c *ObjectsCopyCall) IfGenerationMatch(ifGenerationMatch int64) *ObjectsCopyCall {
+ c.urlParams_.Set("ifGenerationMatch", fmt.Sprint(ifGenerationMatch))
+ return c
+}
+
+// IfGenerationNotMatch sets the optional parameter
+// "ifGenerationNotMatch": Makes the operation conditional on whether
+// the destination object's current generation does not match the given
+// value. If no live object exists, the precondition fails. Setting to 0
+// makes the operation succeed only if there is a live version of the
+// object.
+func (c *ObjectsCopyCall) IfGenerationNotMatch(ifGenerationNotMatch int64) *ObjectsCopyCall {
+ c.urlParams_.Set("ifGenerationNotMatch", fmt.Sprint(ifGenerationNotMatch))
+ return c
+}
+
+// IfMetagenerationMatch sets the optional parameter
+// "ifMetagenerationMatch": Makes the operation conditional on whether
+// the destination object's current metageneration matches the given
+// value.
+func (c *ObjectsCopyCall) IfMetagenerationMatch(ifMetagenerationMatch int64) *ObjectsCopyCall {
+ c.urlParams_.Set("ifMetagenerationMatch", fmt.Sprint(ifMetagenerationMatch))
+ return c
+}
+
+// IfMetagenerationNotMatch sets the optional parameter
+// "ifMetagenerationNotMatch": Makes the operation conditional on
+// whether the destination object's current metageneration does not
+// match the given value.
+func (c *ObjectsCopyCall) IfMetagenerationNotMatch(ifMetagenerationNotMatch int64) *ObjectsCopyCall {
+ c.urlParams_.Set("ifMetagenerationNotMatch", fmt.Sprint(ifMetagenerationNotMatch))
+ return c
+}
+
+// IfSourceGenerationMatch sets the optional parameter
+// "ifSourceGenerationMatch": Makes the operation conditional on whether
+// the source object's current generation matches the given value.
+func (c *ObjectsCopyCall) IfSourceGenerationMatch(ifSourceGenerationMatch int64) *ObjectsCopyCall {
+ c.urlParams_.Set("ifSourceGenerationMatch", fmt.Sprint(ifSourceGenerationMatch))
+ return c
+}
+
+// IfSourceGenerationNotMatch sets the optional parameter
+// "ifSourceGenerationNotMatch": Makes the operation conditional on
+// whether the source object's current generation does not match the
+// given value.
+func (c *ObjectsCopyCall) IfSourceGenerationNotMatch(ifSourceGenerationNotMatch int64) *ObjectsCopyCall {
+ c.urlParams_.Set("ifSourceGenerationNotMatch", fmt.Sprint(ifSourceGenerationNotMatch))
+ return c
+}
+
+// IfSourceMetagenerationMatch sets the optional parameter
+// "ifSourceMetagenerationMatch": Makes the operation conditional on
+// whether the source object's current metageneration matches the given
+// value.
+func (c *ObjectsCopyCall) IfSourceMetagenerationMatch(ifSourceMetagenerationMatch int64) *ObjectsCopyCall {
+ c.urlParams_.Set("ifSourceMetagenerationMatch", fmt.Sprint(ifSourceMetagenerationMatch))
+ return c
+}
+
+// IfSourceMetagenerationNotMatch sets the optional parameter
+// "ifSourceMetagenerationNotMatch": Makes the operation conditional on
+// whether the source object's current metageneration does not match the
+// given value.
+func (c *ObjectsCopyCall) IfSourceMetagenerationNotMatch(ifSourceMetagenerationNotMatch int64) *ObjectsCopyCall {
+ c.urlParams_.Set("ifSourceMetagenerationNotMatch", fmt.Sprint(ifSourceMetagenerationNotMatch))
+ return c
+}
+
+// Projection sets the optional parameter "projection": Set of
+// properties to return. Defaults to noAcl, unless the object resource
+// specifies the acl property, when it defaults to full.
+//
+// Possible values:
+// "full" - Include all properties.
+// "noAcl" - Omit the owner, acl property.
+func (c *ObjectsCopyCall) Projection(projection string) *ObjectsCopyCall {
+ c.urlParams_.Set("projection", projection)
+ return c
+}
+
+// SourceGeneration sets the optional parameter "sourceGeneration": If
+// present, selects a specific revision of the source object (as opposed
+// to the latest version, the default).
+func (c *ObjectsCopyCall) SourceGeneration(sourceGeneration int64) *ObjectsCopyCall {
+ c.urlParams_.Set("sourceGeneration", fmt.Sprint(sourceGeneration))
+ return c
+}
+
+// UserProject sets the optional parameter "userProject": The project to
+// be billed for this request. Required for Requester Pays buckets.
+func (c *ObjectsCopyCall) UserProject(userProject string) *ObjectsCopyCall {
+ c.urlParams_.Set("userProject", userProject)
+ return c
+}
+
+// Fields allows partial responses to be retrieved. See
+// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
+// for more information.
+func (c *ObjectsCopyCall) Fields(s ...googleapi.Field) *ObjectsCopyCall {
+ c.urlParams_.Set("fields", googleapi.CombineFields(s))
+ return c
+}
+
+// Context sets the context to be used in this call's Do method. Any
+// pending HTTP request will be aborted if the provided context is
+// canceled.
+func (c *ObjectsCopyCall) Context(ctx context.Context) *ObjectsCopyCall {
+ c.ctx_ = ctx
+ return c
+}
+
+// Header returns an http.Header that can be modified by the caller to
+// add HTTP headers to the request.
+func (c *ObjectsCopyCall) Header() http.Header {
+ if c.header_ == nil {
+ c.header_ = make(http.Header)
+ }
+ return c.header_
+}
+
+func (c *ObjectsCopyCall) doRequest(alt string) (*http.Response, error) {
+ reqHeaders := make(http.Header)
+ for k, v := range c.header_ {
+ reqHeaders[k] = v
+ }
+ reqHeaders.Set("User-Agent", c.s.userAgent())
+ var body io.Reader = nil
+ body, err := googleapi.WithoutDataWrapper.JSONReader(c.object)
+ if err != nil {
+ return nil, err
+ }
+ reqHeaders.Set("Content-Type", "application/json")
+ c.urlParams_.Set("alt", alt)
+ c.urlParams_.Set("prettyPrint", "false")
+ urls := googleapi.ResolveRelative(c.s.BasePath, "b/{sourceBucket}/o/{sourceObject}/copyTo/b/{destinationBucket}/o/{destinationObject}")
+ urls += "?" + c.urlParams_.Encode()
+ req, err := http.NewRequest("POST", urls, body)
+ if err != nil {
+ return nil, err
+ }
+ req.Header = reqHeaders
+ googleapi.Expand(req.URL, map[string]string{
+ "sourceBucket": c.sourceBucket,
+ "sourceObject": c.sourceObject,
+ "destinationBucket": c.destinationBucket,
+ "destinationObject": c.destinationObject,
+ })
+ return gensupport.SendRequest(c.ctx_, c.s.client, req)
+}
+
+// Do executes the "storage.objects.copy" call.
+// Exactly one of *Object or error will be non-nil. Any non-2xx status
+// code is an error. Response headers are in either
+// *Object.ServerResponse.Header or (if a response was returned at all)
+// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to
+// check whether the returned error was because http.StatusNotModified
+// was returned.
+func (c *ObjectsCopyCall) Do(opts ...googleapi.CallOption) (*Object, error) {
+ gensupport.SetOptions(c.urlParams_, opts...)
+ res, err := c.doRequest("json")
+ if res != nil && res.StatusCode == http.StatusNotModified {
+ if res.Body != nil {
+ res.Body.Close()
+ }
+ return nil, &googleapi.Error{
+ Code: res.StatusCode,
+ Header: res.Header,
+ }
+ }
+ if err != nil {
+ return nil, err
+ }
+ defer googleapi.CloseBody(res)
+ if err := googleapi.CheckResponse(res); err != nil {
+ return nil, err
+ }
+ ret := &Object{
+ ServerResponse: googleapi.ServerResponse{
+ Header: res.Header,
+ HTTPStatusCode: res.StatusCode,
+ },
+ }
+ target := &ret
+ if err := gensupport.DecodeResponse(target, res); err != nil {
+ return nil, err
+ }
+ return ret, nil
+ // {
+ // "description": "Copies a source object to a destination object. Optionally overrides metadata.",
+ // "httpMethod": "POST",
+ // "id": "storage.objects.copy",
+ // "parameterOrder": [
+ // "sourceBucket",
+ // "sourceObject",
+ // "destinationBucket",
+ // "destinationObject"
+ // ],
+ // "parameters": {
+ // "destinationBucket": {
+ // "description": "Name of the bucket in which to store the new object. Overrides the provided object metadata's bucket value, if any.For information about how to URL encode object names to be path safe, see Encoding URI Path Parts.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "destinationObject": {
+ // "description": "Name of the new object. Required when the object metadata is not otherwise provided. Overrides the object metadata's name value, if any.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "destinationPredefinedAcl": {
+ // "description": "Apply a predefined set of access controls to the destination object.",
+ // "enum": [
+ // "authenticatedRead",
+ // "bucketOwnerFullControl",
+ // "bucketOwnerRead",
+ // "private",
+ // "projectPrivate",
+ // "publicRead"
+ // ],
+ // "enumDescriptions": [
+ // "Object owner gets OWNER access, and allAuthenticatedUsers get READER access.",
+ // "Object owner gets OWNER access, and project team owners get OWNER access.",
+ // "Object owner gets OWNER access, and project team owners get READER access.",
+ // "Object owner gets OWNER access.",
+ // "Object owner gets OWNER access, and project team members get access according to their roles.",
+ // "Object owner gets OWNER access, and allUsers get READER access."
+ // ],
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "ifGenerationMatch": {
+ // "description": "Makes the operation conditional on whether the destination object's current generation matches the given value. Setting to 0 makes the operation succeed only if there are no live versions of the object.",
+ // "format": "int64",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "ifGenerationNotMatch": {
+ // "description": "Makes the operation conditional on whether the destination object's current generation does not match the given value. If no live object exists, the precondition fails. Setting to 0 makes the operation succeed only if there is a live version of the object.",
+ // "format": "int64",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "ifMetagenerationMatch": {
+ // "description": "Makes the operation conditional on whether the destination object's current metageneration matches the given value.",
+ // "format": "int64",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "ifMetagenerationNotMatch": {
+ // "description": "Makes the operation conditional on whether the destination object's current metageneration does not match the given value.",
+ // "format": "int64",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "ifSourceGenerationMatch": {
+ // "description": "Makes the operation conditional on whether the source object's current generation matches the given value.",
+ // "format": "int64",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "ifSourceGenerationNotMatch": {
+ // "description": "Makes the operation conditional on whether the source object's current generation does not match the given value.",
+ // "format": "int64",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "ifSourceMetagenerationMatch": {
+ // "description": "Makes the operation conditional on whether the source object's current metageneration matches the given value.",
+ // "format": "int64",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "ifSourceMetagenerationNotMatch": {
+ // "description": "Makes the operation conditional on whether the source object's current metageneration does not match the given value.",
+ // "format": "int64",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "projection": {
+ // "description": "Set of properties to return. Defaults to noAcl, unless the object resource specifies the acl property, when it defaults to full.",
+ // "enum": [
+ // "full",
+ // "noAcl"
+ // ],
+ // "enumDescriptions": [
+ // "Include all properties.",
+ // "Omit the owner, acl property."
+ // ],
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "sourceBucket": {
+ // "description": "Name of the bucket in which to find the source object.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "sourceGeneration": {
+ // "description": "If present, selects a specific revision of the source object (as opposed to the latest version, the default).",
+ // "format": "int64",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "sourceObject": {
+ // "description": "Name of the source object. For information about how to URL encode object names to be path safe, see Encoding URI Path Parts.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "userProject": {
+ // "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ // "location": "query",
+ // "type": "string"
+ // }
+ // },
+ // "path": "b/{sourceBucket}/o/{sourceObject}/copyTo/b/{destinationBucket}/o/{destinationObject}",
+ // "request": {
+ // "$ref": "Object"
+ // },
+ // "response": {
+ // "$ref": "Object"
+ // },
+ // "scopes": [
+ // "https://www.googleapis.com/auth/cloud-platform",
+ // "https://www.googleapis.com/auth/devstorage.full_control",
+ // "https://www.googleapis.com/auth/devstorage.read_write"
+ // ]
+ // }
+
+}
+
+// method id "storage.objects.delete":
+
+type ObjectsDeleteCall struct {
+ s *Service
+ bucket string
+ object string
+ urlParams_ gensupport.URLParams
+ ctx_ context.Context
+ header_ http.Header
+}
+
+// Delete: Deletes an object and its metadata. Deletions are permanent
+// if versioning is not enabled for the bucket, or if the generation
+// parameter is used.
+func (r *ObjectsService) Delete(bucket string, object string) *ObjectsDeleteCall {
+ c := &ObjectsDeleteCall{s: r.s, urlParams_: make(gensupport.URLParams)}
+ c.bucket = bucket
+ c.object = object
+ return c
+}
+
+// Generation sets the optional parameter "generation": If present,
+// permanently deletes a specific revision of this object (as opposed to
+// the latest version, the default).
+func (c *ObjectsDeleteCall) Generation(generation int64) *ObjectsDeleteCall {
+ c.urlParams_.Set("generation", fmt.Sprint(generation))
+ return c
+}
+
+// IfGenerationMatch sets the optional parameter "ifGenerationMatch":
+// Makes the operation conditional on whether the object's current
+// generation matches the given value. Setting to 0 makes the operation
+// succeed only if there are no live versions of the object.
+func (c *ObjectsDeleteCall) IfGenerationMatch(ifGenerationMatch int64) *ObjectsDeleteCall {
+ c.urlParams_.Set("ifGenerationMatch", fmt.Sprint(ifGenerationMatch))
+ return c
+}
+
+// IfGenerationNotMatch sets the optional parameter
+// "ifGenerationNotMatch": Makes the operation conditional on whether
+// the object's current generation does not match the given value. If no
+// live object exists, the precondition fails. Setting to 0 makes the
+// operation succeed only if there is a live version of the object.
+func (c *ObjectsDeleteCall) IfGenerationNotMatch(ifGenerationNotMatch int64) *ObjectsDeleteCall {
+ c.urlParams_.Set("ifGenerationNotMatch", fmt.Sprint(ifGenerationNotMatch))
+ return c
+}
+
+// IfMetagenerationMatch sets the optional parameter
+// "ifMetagenerationMatch": Makes the operation conditional on whether
+// the object's current metageneration matches the given value.
+func (c *ObjectsDeleteCall) IfMetagenerationMatch(ifMetagenerationMatch int64) *ObjectsDeleteCall {
+ c.urlParams_.Set("ifMetagenerationMatch", fmt.Sprint(ifMetagenerationMatch))
+ return c
+}
+
+// IfMetagenerationNotMatch sets the optional parameter
+// "ifMetagenerationNotMatch": Makes the operation conditional on
+// whether the object's current metageneration does not match the given
+// value.
+func (c *ObjectsDeleteCall) IfMetagenerationNotMatch(ifMetagenerationNotMatch int64) *ObjectsDeleteCall {
+ c.urlParams_.Set("ifMetagenerationNotMatch", fmt.Sprint(ifMetagenerationNotMatch))
+ return c
+}
+
+// UserProject sets the optional parameter "userProject": The project to
+// be billed for this request. Required for Requester Pays buckets.
+func (c *ObjectsDeleteCall) UserProject(userProject string) *ObjectsDeleteCall {
+ c.urlParams_.Set("userProject", userProject)
+ return c
+}
+
+// Fields allows partial responses to be retrieved. See
+// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
+// for more information.
+func (c *ObjectsDeleteCall) Fields(s ...googleapi.Field) *ObjectsDeleteCall {
+ c.urlParams_.Set("fields", googleapi.CombineFields(s))
+ return c
+}
+
+// Context sets the context to be used in this call's Do method. Any
+// pending HTTP request will be aborted if the provided context is
+// canceled.
+func (c *ObjectsDeleteCall) Context(ctx context.Context) *ObjectsDeleteCall {
+ c.ctx_ = ctx
+ return c
+}
+
+// Header returns an http.Header that can be modified by the caller to
+// add HTTP headers to the request.
+func (c *ObjectsDeleteCall) Header() http.Header {
+ if c.header_ == nil {
+ c.header_ = make(http.Header)
+ }
+ return c.header_
+}
+
+func (c *ObjectsDeleteCall) doRequest(alt string) (*http.Response, error) {
+ reqHeaders := make(http.Header)
+ for k, v := range c.header_ {
+ reqHeaders[k] = v
+ }
+ reqHeaders.Set("User-Agent", c.s.userAgent())
+ var body io.Reader = nil
+ c.urlParams_.Set("alt", alt)
+ c.urlParams_.Set("prettyPrint", "false")
+ urls := googleapi.ResolveRelative(c.s.BasePath, "b/{bucket}/o/{object}")
+ urls += "?" + c.urlParams_.Encode()
+ req, err := http.NewRequest("DELETE", urls, body)
+ if err != nil {
+ return nil, err
+ }
+ req.Header = reqHeaders
+ googleapi.Expand(req.URL, map[string]string{
+ "bucket": c.bucket,
+ "object": c.object,
+ })
+ return gensupport.SendRequest(c.ctx_, c.s.client, req)
+}
+
+// Do executes the "storage.objects.delete" call.
+func (c *ObjectsDeleteCall) Do(opts ...googleapi.CallOption) error {
+ gensupport.SetOptions(c.urlParams_, opts...)
+ res, err := c.doRequest("json")
+ if err != nil {
+ return err
+ }
+ defer googleapi.CloseBody(res)
+ if err := googleapi.CheckResponse(res); err != nil {
+ return err
+ }
+ return nil
+ // {
+ // "description": "Deletes an object and its metadata. Deletions are permanent if versioning is not enabled for the bucket, or if the generation parameter is used.",
+ // "httpMethod": "DELETE",
+ // "id": "storage.objects.delete",
+ // "parameterOrder": [
+ // "bucket",
+ // "object"
+ // ],
+ // "parameters": {
+ // "bucket": {
+ // "description": "Name of the bucket in which the object resides.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "generation": {
+ // "description": "If present, permanently deletes a specific revision of this object (as opposed to the latest version, the default).",
+ // "format": "int64",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "ifGenerationMatch": {
+ // "description": "Makes the operation conditional on whether the object's current generation matches the given value. Setting to 0 makes the operation succeed only if there are no live versions of the object.",
+ // "format": "int64",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "ifGenerationNotMatch": {
+ // "description": "Makes the operation conditional on whether the object's current generation does not match the given value. If no live object exists, the precondition fails. Setting to 0 makes the operation succeed only if there is a live version of the object.",
+ // "format": "int64",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "ifMetagenerationMatch": {
+ // "description": "Makes the operation conditional on whether the object's current metageneration matches the given value.",
+ // "format": "int64",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "ifMetagenerationNotMatch": {
+ // "description": "Makes the operation conditional on whether the object's current metageneration does not match the given value.",
+ // "format": "int64",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "object": {
+ // "description": "Name of the object. For information about how to URL encode object names to be path safe, see Encoding URI Path Parts.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "userProject": {
+ // "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ // "location": "query",
+ // "type": "string"
+ // }
+ // },
+ // "path": "b/{bucket}/o/{object}",
+ // "scopes": [
+ // "https://www.googleapis.com/auth/cloud-platform",
+ // "https://www.googleapis.com/auth/devstorage.full_control",
+ // "https://www.googleapis.com/auth/devstorage.read_write"
+ // ]
+ // }
+
+}
+
+// method id "storage.objects.get":
+
+type ObjectsGetCall struct {
+ s *Service
+ bucket string
+ object string
+ urlParams_ gensupport.URLParams
+ ifNoneMatch_ string
+ ctx_ context.Context
+ header_ http.Header
+}
+
+// Get: Retrieves an object or its metadata.
+func (r *ObjectsService) Get(bucket string, object string) *ObjectsGetCall {
+ c := &ObjectsGetCall{s: r.s, urlParams_: make(gensupport.URLParams)}
+ c.bucket = bucket
+ c.object = object
+ return c
+}
+
+// Generation sets the optional parameter "generation": If present,
+// selects a specific revision of this object (as opposed to the latest
+// version, the default).
+func (c *ObjectsGetCall) Generation(generation int64) *ObjectsGetCall {
+ c.urlParams_.Set("generation", fmt.Sprint(generation))
+ return c
+}
+
+// IfGenerationMatch sets the optional parameter "ifGenerationMatch":
+// Makes the operation conditional on whether the object's current
+// generation matches the given value. Setting to 0 makes the operation
+// succeed only if there are no live versions of the object.
+func (c *ObjectsGetCall) IfGenerationMatch(ifGenerationMatch int64) *ObjectsGetCall {
+ c.urlParams_.Set("ifGenerationMatch", fmt.Sprint(ifGenerationMatch))
+ return c
+}
+
+// IfGenerationNotMatch sets the optional parameter
+// "ifGenerationNotMatch": Makes the operation conditional on whether
+// the object's current generation does not match the given value. If no
+// live object exists, the precondition fails. Setting to 0 makes the
+// operation succeed only if there is a live version of the object.
+func (c *ObjectsGetCall) IfGenerationNotMatch(ifGenerationNotMatch int64) *ObjectsGetCall {
+ c.urlParams_.Set("ifGenerationNotMatch", fmt.Sprint(ifGenerationNotMatch))
+ return c
+}
+
+// IfMetagenerationMatch sets the optional parameter
+// "ifMetagenerationMatch": Makes the operation conditional on whether
+// the object's current metageneration matches the given value.
+func (c *ObjectsGetCall) IfMetagenerationMatch(ifMetagenerationMatch int64) *ObjectsGetCall {
+ c.urlParams_.Set("ifMetagenerationMatch", fmt.Sprint(ifMetagenerationMatch))
+ return c
+}
+
+// IfMetagenerationNotMatch sets the optional parameter
+// "ifMetagenerationNotMatch": Makes the operation conditional on
+// whether the object's current metageneration does not match the given
+// value.
+func (c *ObjectsGetCall) IfMetagenerationNotMatch(ifMetagenerationNotMatch int64) *ObjectsGetCall {
+ c.urlParams_.Set("ifMetagenerationNotMatch", fmt.Sprint(ifMetagenerationNotMatch))
+ return c
+}
+
+// Projection sets the optional parameter "projection": Set of
+// properties to return. Defaults to noAcl.
+//
+// Possible values:
+// "full" - Include all properties.
+// "noAcl" - Omit the owner, acl property.
+func (c *ObjectsGetCall) Projection(projection string) *ObjectsGetCall {
+ c.urlParams_.Set("projection", projection)
+ return c
+}
+
+// UserProject sets the optional parameter "userProject": The project to
+// be billed for this request. Required for Requester Pays buckets.
+func (c *ObjectsGetCall) UserProject(userProject string) *ObjectsGetCall {
+ c.urlParams_.Set("userProject", userProject)
+ return c
+}
+
+// Fields allows partial responses to be retrieved. See
+// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
+// for more information.
+func (c *ObjectsGetCall) Fields(s ...googleapi.Field) *ObjectsGetCall {
+ c.urlParams_.Set("fields", googleapi.CombineFields(s))
+ return c
+}
+
+// IfNoneMatch sets the optional parameter which makes the operation
+// fail if the object's ETag matches the given value. This is useful for
+// getting updates only after the object has changed since the last
+// request. Use googleapi.IsNotModified to check whether the response
+// error from Do is the result of In-None-Match.
+func (c *ObjectsGetCall) IfNoneMatch(entityTag string) *ObjectsGetCall {
+ c.ifNoneMatch_ = entityTag
+ return c
+}
+
+// Context sets the context to be used in this call's Do and Download
+// methods. Any pending HTTP request will be aborted if the provided
+// context is canceled.
+func (c *ObjectsGetCall) Context(ctx context.Context) *ObjectsGetCall {
+ c.ctx_ = ctx
+ return c
+}
+
+// Header returns an http.Header that can be modified by the caller to
+// add HTTP headers to the request.
+func (c *ObjectsGetCall) Header() http.Header {
+ if c.header_ == nil {
+ c.header_ = make(http.Header)
+ }
+ return c.header_
+}
+
+func (c *ObjectsGetCall) doRequest(alt string) (*http.Response, error) {
+ reqHeaders := make(http.Header)
+ for k, v := range c.header_ {
+ reqHeaders[k] = v
+ }
+ reqHeaders.Set("User-Agent", c.s.userAgent())
+ if c.ifNoneMatch_ != "" {
+ reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
+ }
+ var body io.Reader = nil
+ c.urlParams_.Set("alt", alt)
+ c.urlParams_.Set("prettyPrint", "false")
+ urls := googleapi.ResolveRelative(c.s.BasePath, "b/{bucket}/o/{object}")
+ urls += "?" + c.urlParams_.Encode()
+ req, err := http.NewRequest("GET", urls, body)
+ if err != nil {
+ return nil, err
+ }
+ req.Header = reqHeaders
+ googleapi.Expand(req.URL, map[string]string{
+ "bucket": c.bucket,
+ "object": c.object,
+ })
+ return gensupport.SendRequest(c.ctx_, c.s.client, req)
+}
+
+// Download fetches the API endpoint's "media" value, instead of the normal
+// API response value. If the returned error is nil, the Response is guaranteed to
+// have a 2xx status code. Callers must close the Response.Body as usual.
+func (c *ObjectsGetCall) Download(opts ...googleapi.CallOption) (*http.Response, error) {
+ gensupport.SetOptions(c.urlParams_, opts...)
+ res, err := c.doRequest("media")
+ if err != nil {
+ return nil, err
+ }
+ if err := googleapi.CheckMediaResponse(res); err != nil {
+ res.Body.Close()
+ return nil, err
+ }
+ return res, nil
+}
+
+// Do executes the "storage.objects.get" call.
+// Exactly one of *Object or error will be non-nil. Any non-2xx status
+// code is an error. Response headers are in either
+// *Object.ServerResponse.Header or (if a response was returned at all)
+// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to
+// check whether the returned error was because http.StatusNotModified
+// was returned.
+func (c *ObjectsGetCall) Do(opts ...googleapi.CallOption) (*Object, error) {
+ gensupport.SetOptions(c.urlParams_, opts...)
+ res, err := c.doRequest("json")
+ if res != nil && res.StatusCode == http.StatusNotModified {
+ if res.Body != nil {
+ res.Body.Close()
+ }
+ return nil, &googleapi.Error{
+ Code: res.StatusCode,
+ Header: res.Header,
+ }
+ }
+ if err != nil {
+ return nil, err
+ }
+ defer googleapi.CloseBody(res)
+ if err := googleapi.CheckResponse(res); err != nil {
+ return nil, err
+ }
+ ret := &Object{
+ ServerResponse: googleapi.ServerResponse{
+ Header: res.Header,
+ HTTPStatusCode: res.StatusCode,
+ },
+ }
+ target := &ret
+ if err := gensupport.DecodeResponse(target, res); err != nil {
+ return nil, err
+ }
+ return ret, nil
+ // {
+ // "description": "Retrieves an object or its metadata.",
+ // "httpMethod": "GET",
+ // "id": "storage.objects.get",
+ // "parameterOrder": [
+ // "bucket",
+ // "object"
+ // ],
+ // "parameters": {
+ // "bucket": {
+ // "description": "Name of the bucket in which the object resides.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "generation": {
+ // "description": "If present, selects a specific revision of this object (as opposed to the latest version, the default).",
+ // "format": "int64",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "ifGenerationMatch": {
+ // "description": "Makes the operation conditional on whether the object's current generation matches the given value. Setting to 0 makes the operation succeed only if there are no live versions of the object.",
+ // "format": "int64",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "ifGenerationNotMatch": {
+ // "description": "Makes the operation conditional on whether the object's current generation does not match the given value. If no live object exists, the precondition fails. Setting to 0 makes the operation succeed only if there is a live version of the object.",
+ // "format": "int64",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "ifMetagenerationMatch": {
+ // "description": "Makes the operation conditional on whether the object's current metageneration matches the given value.",
+ // "format": "int64",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "ifMetagenerationNotMatch": {
+ // "description": "Makes the operation conditional on whether the object's current metageneration does not match the given value.",
+ // "format": "int64",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "object": {
+ // "description": "Name of the object. For information about how to URL encode object names to be path safe, see Encoding URI Path Parts.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "projection": {
+ // "description": "Set of properties to return. Defaults to noAcl.",
+ // "enum": [
+ // "full",
+ // "noAcl"
+ // ],
+ // "enumDescriptions": [
+ // "Include all properties.",
+ // "Omit the owner, acl property."
+ // ],
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "userProject": {
+ // "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ // "location": "query",
+ // "type": "string"
+ // }
+ // },
+ // "path": "b/{bucket}/o/{object}",
+ // "response": {
+ // "$ref": "Object"
+ // },
+ // "scopes": [
+ // "https://www.googleapis.com/auth/cloud-platform",
+ // "https://www.googleapis.com/auth/cloud-platform.read-only",
+ // "https://www.googleapis.com/auth/devstorage.full_control",
+ // "https://www.googleapis.com/auth/devstorage.read_only",
+ // "https://www.googleapis.com/auth/devstorage.read_write"
+ // ],
+ // "supportsMediaDownload": true,
+ // "useMediaDownloadService": true
+ // }
+
+}
+
+// method id "storage.objects.getIamPolicy":
+
+type ObjectsGetIamPolicyCall struct {
+ s *Service
+ bucket string
+ object string
+ urlParams_ gensupport.URLParams
+ ifNoneMatch_ string
+ ctx_ context.Context
+ header_ http.Header
+}
+
+// GetIamPolicy: Returns an IAM policy for the specified object.
+func (r *ObjectsService) GetIamPolicy(bucket string, object string) *ObjectsGetIamPolicyCall {
+ c := &ObjectsGetIamPolicyCall{s: r.s, urlParams_: make(gensupport.URLParams)}
+ c.bucket = bucket
+ c.object = object
+ return c
+}
+
+// Generation sets the optional parameter "generation": If present,
+// selects a specific revision of this object (as opposed to the latest
+// version, the default).
+func (c *ObjectsGetIamPolicyCall) Generation(generation int64) *ObjectsGetIamPolicyCall {
+ c.urlParams_.Set("generation", fmt.Sprint(generation))
+ return c
+}
+
+// UserProject sets the optional parameter "userProject": The project to
+// be billed for this request. Required for Requester Pays buckets.
+func (c *ObjectsGetIamPolicyCall) UserProject(userProject string) *ObjectsGetIamPolicyCall {
+ c.urlParams_.Set("userProject", userProject)
+ return c
+}
+
+// Fields allows partial responses to be retrieved. See
+// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
+// for more information.
+func (c *ObjectsGetIamPolicyCall) Fields(s ...googleapi.Field) *ObjectsGetIamPolicyCall {
+ c.urlParams_.Set("fields", googleapi.CombineFields(s))
+ return c
+}
+
+// IfNoneMatch sets the optional parameter which makes the operation
+// fail if the object's ETag matches the given value. This is useful for
+// getting updates only after the object has changed since the last
+// request. Use googleapi.IsNotModified to check whether the response
+// error from Do is the result of In-None-Match.
+func (c *ObjectsGetIamPolicyCall) IfNoneMatch(entityTag string) *ObjectsGetIamPolicyCall {
+ c.ifNoneMatch_ = entityTag
+ return c
+}
+
+// Context sets the context to be used in this call's Do method. Any
+// pending HTTP request will be aborted if the provided context is
+// canceled.
+func (c *ObjectsGetIamPolicyCall) Context(ctx context.Context) *ObjectsGetIamPolicyCall {
+ c.ctx_ = ctx
+ return c
+}
+
+// Header returns an http.Header that can be modified by the caller to
+// add HTTP headers to the request.
+func (c *ObjectsGetIamPolicyCall) Header() http.Header {
+ if c.header_ == nil {
+ c.header_ = make(http.Header)
+ }
+ return c.header_
+}
+
+func (c *ObjectsGetIamPolicyCall) doRequest(alt string) (*http.Response, error) {
+ reqHeaders := make(http.Header)
+ for k, v := range c.header_ {
+ reqHeaders[k] = v
+ }
+ reqHeaders.Set("User-Agent", c.s.userAgent())
+ if c.ifNoneMatch_ != "" {
+ reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
+ }
+ var body io.Reader = nil
+ c.urlParams_.Set("alt", alt)
+ c.urlParams_.Set("prettyPrint", "false")
+ urls := googleapi.ResolveRelative(c.s.BasePath, "b/{bucket}/o/{object}/iam")
+ urls += "?" + c.urlParams_.Encode()
+ req, err := http.NewRequest("GET", urls, body)
+ if err != nil {
+ return nil, err
+ }
+ req.Header = reqHeaders
+ googleapi.Expand(req.URL, map[string]string{
+ "bucket": c.bucket,
+ "object": c.object,
+ })
+ return gensupport.SendRequest(c.ctx_, c.s.client, req)
+}
+
+// Do executes the "storage.objects.getIamPolicy" call.
+// Exactly one of *Policy or error will be non-nil. Any non-2xx status
+// code is an error. Response headers are in either
+// *Policy.ServerResponse.Header or (if a response was returned at all)
+// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to
+// check whether the returned error was because http.StatusNotModified
+// was returned.
+func (c *ObjectsGetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, error) {
+ gensupport.SetOptions(c.urlParams_, opts...)
+ res, err := c.doRequest("json")
+ if res != nil && res.StatusCode == http.StatusNotModified {
+ if res.Body != nil {
+ res.Body.Close()
+ }
+ return nil, &googleapi.Error{
+ Code: res.StatusCode,
+ Header: res.Header,
+ }
+ }
+ if err != nil {
+ return nil, err
+ }
+ defer googleapi.CloseBody(res)
+ if err := googleapi.CheckResponse(res); err != nil {
+ return nil, err
+ }
+ ret := &Policy{
+ ServerResponse: googleapi.ServerResponse{
+ Header: res.Header,
+ HTTPStatusCode: res.StatusCode,
+ },
+ }
+ target := &ret
+ if err := gensupport.DecodeResponse(target, res); err != nil {
+ return nil, err
+ }
+ return ret, nil
+ // {
+ // "description": "Returns an IAM policy for the specified object.",
+ // "httpMethod": "GET",
+ // "id": "storage.objects.getIamPolicy",
+ // "parameterOrder": [
+ // "bucket",
+ // "object"
+ // ],
+ // "parameters": {
+ // "bucket": {
+ // "description": "Name of the bucket in which the object resides.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "generation": {
+ // "description": "If present, selects a specific revision of this object (as opposed to the latest version, the default).",
+ // "format": "int64",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "object": {
+ // "description": "Name of the object. For information about how to URL encode object names to be path safe, see Encoding URI Path Parts.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "userProject": {
+ // "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ // "location": "query",
+ // "type": "string"
+ // }
+ // },
+ // "path": "b/{bucket}/o/{object}/iam",
+ // "response": {
+ // "$ref": "Policy"
+ // },
+ // "scopes": [
+ // "https://www.googleapis.com/auth/cloud-platform",
+ // "https://www.googleapis.com/auth/cloud-platform.read-only",
+ // "https://www.googleapis.com/auth/devstorage.full_control",
+ // "https://www.googleapis.com/auth/devstorage.read_only",
+ // "https://www.googleapis.com/auth/devstorage.read_write"
+ // ]
+ // }
+
+}
+
+// method id "storage.objects.insert":
+
+type ObjectsInsertCall struct {
+ s *Service
+ bucket string
+ object *Object
+ urlParams_ gensupport.URLParams
+ mediaInfo_ *gensupport.MediaInfo
+ ctx_ context.Context
+ header_ http.Header
+}
+
+// Insert: Stores a new object and metadata.
+func (r *ObjectsService) Insert(bucket string, object *Object) *ObjectsInsertCall {
+ c := &ObjectsInsertCall{s: r.s, urlParams_: make(gensupport.URLParams)}
+ c.bucket = bucket
+ c.object = object
+ return c
+}
+
+// ContentEncoding sets the optional parameter "contentEncoding": If
+// set, sets the contentEncoding property of the final object to this
+// value. Setting this parameter is equivalent to setting the
+// contentEncoding metadata property. This can be useful when uploading
+// an object with uploadType=media to indicate the encoding of the
+// content being uploaded.
+func (c *ObjectsInsertCall) ContentEncoding(contentEncoding string) *ObjectsInsertCall {
+ c.urlParams_.Set("contentEncoding", contentEncoding)
+ return c
+}
+
+// IfGenerationMatch sets the optional parameter "ifGenerationMatch":
+// Makes the operation conditional on whether the object's current
+// generation matches the given value. Setting to 0 makes the operation
+// succeed only if there are no live versions of the object.
+func (c *ObjectsInsertCall) IfGenerationMatch(ifGenerationMatch int64) *ObjectsInsertCall {
+ c.urlParams_.Set("ifGenerationMatch", fmt.Sprint(ifGenerationMatch))
+ return c
+}
+
+// IfGenerationNotMatch sets the optional parameter
+// "ifGenerationNotMatch": Makes the operation conditional on whether
+// the object's current generation does not match the given value. If no
+// live object exists, the precondition fails. Setting to 0 makes the
+// operation succeed only if there is a live version of the object.
+func (c *ObjectsInsertCall) IfGenerationNotMatch(ifGenerationNotMatch int64) *ObjectsInsertCall {
+ c.urlParams_.Set("ifGenerationNotMatch", fmt.Sprint(ifGenerationNotMatch))
+ return c
+}
+
+// IfMetagenerationMatch sets the optional parameter
+// "ifMetagenerationMatch": Makes the operation conditional on whether
+// the object's current metageneration matches the given value.
+func (c *ObjectsInsertCall) IfMetagenerationMatch(ifMetagenerationMatch int64) *ObjectsInsertCall {
+ c.urlParams_.Set("ifMetagenerationMatch", fmt.Sprint(ifMetagenerationMatch))
+ return c
+}
+
+// IfMetagenerationNotMatch sets the optional parameter
+// "ifMetagenerationNotMatch": Makes the operation conditional on
+// whether the object's current metageneration does not match the given
+// value.
+func (c *ObjectsInsertCall) IfMetagenerationNotMatch(ifMetagenerationNotMatch int64) *ObjectsInsertCall {
+ c.urlParams_.Set("ifMetagenerationNotMatch", fmt.Sprint(ifMetagenerationNotMatch))
+ return c
+}
+
+// KmsKeyName sets the optional parameter "kmsKeyName": Resource name of
+// the Cloud KMS key, of the form
+// projects/my-project/locations/global/keyRings/my-kr/cryptoKeys/my-key,
+// that will be used to encrypt the object. Overrides the object
+// metadata's kms_key_name value, if any.
+func (c *ObjectsInsertCall) KmsKeyName(kmsKeyName string) *ObjectsInsertCall {
+ c.urlParams_.Set("kmsKeyName", kmsKeyName)
+ return c
+}
+
+// Name sets the optional parameter "name": Name of the object. Required
+// when the object metadata is not otherwise provided. Overrides the
+// object metadata's name value, if any. For information about how to
+// URL encode object names to be path safe, see Encoding URI Path Parts.
+func (c *ObjectsInsertCall) Name(name string) *ObjectsInsertCall {
+ c.urlParams_.Set("name", name)
+ return c
+}
+
+// PredefinedAcl sets the optional parameter "predefinedAcl": Apply a
+// predefined set of access controls to this object.
+//
+// Possible values:
+// "authenticatedRead" - Object owner gets OWNER access, and
+// allAuthenticatedUsers get READER access.
+// "bucketOwnerFullControl" - Object owner gets OWNER access, and
+// project team owners get OWNER access.
+// "bucketOwnerRead" - Object owner gets OWNER access, and project
+// team owners get READER access.
+// "private" - Object owner gets OWNER access.
+// "projectPrivate" - Object owner gets OWNER access, and project team
+// members get access according to their roles.
+// "publicRead" - Object owner gets OWNER access, and allUsers get
+// READER access.
+func (c *ObjectsInsertCall) PredefinedAcl(predefinedAcl string) *ObjectsInsertCall {
+ c.urlParams_.Set("predefinedAcl", predefinedAcl)
+ return c
+}
+
+// Projection sets the optional parameter "projection": Set of
+// properties to return. Defaults to noAcl, unless the object resource
+// specifies the acl property, when it defaults to full.
+//
+// Possible values:
+// "full" - Include all properties.
+// "noAcl" - Omit the owner, acl property.
+func (c *ObjectsInsertCall) Projection(projection string) *ObjectsInsertCall {
+ c.urlParams_.Set("projection", projection)
+ return c
+}
+
+// UserProject sets the optional parameter "userProject": The project to
+// be billed for this request. Required for Requester Pays buckets.
+func (c *ObjectsInsertCall) UserProject(userProject string) *ObjectsInsertCall {
+ c.urlParams_.Set("userProject", userProject)
+ return c
+}
+
+// Media specifies the media to upload in one or more chunks. The chunk
+// size may be controlled by supplying a MediaOption generated by
+// googleapi.ChunkSize. The chunk size defaults to
+// googleapi.DefaultUploadChunkSize.The Content-Type header used in the
+// upload request will be determined by sniffing the contents of r,
+// unless a MediaOption generated by googleapi.ContentType is
+// supplied.
+// At most one of Media and ResumableMedia may be set.
+func (c *ObjectsInsertCall) Media(r io.Reader, options ...googleapi.MediaOption) *ObjectsInsertCall {
+ if ct := c.object.ContentType; ct != "" {
+ options = append([]googleapi.MediaOption{googleapi.ContentType(ct)}, options...)
+ }
+ c.mediaInfo_ = gensupport.NewInfoFromMedia(r, options)
+ return c
+}
+
+// ResumableMedia specifies the media to upload in chunks and can be
+// canceled with ctx.
+//
+// Deprecated: use Media instead.
+//
+// At most one of Media and ResumableMedia may be set. mediaType
+// identifies the MIME media type of the upload, such as "image/png". If
+// mediaType is "", it will be auto-detected. The provided ctx will
+// supersede any context previously provided to the Context method.
+func (c *ObjectsInsertCall) ResumableMedia(ctx context.Context, r io.ReaderAt, size int64, mediaType string) *ObjectsInsertCall {
+ c.ctx_ = ctx
+ c.mediaInfo_ = gensupport.NewInfoFromResumableMedia(r, size, mediaType)
+ return c
+}
+
+// ProgressUpdater provides a callback function that will be called
+// after every chunk. It should be a low-latency function in order to
+// not slow down the upload operation. This should only be called when
+// using ResumableMedia (as opposed to Media).
+func (c *ObjectsInsertCall) ProgressUpdater(pu googleapi.ProgressUpdater) *ObjectsInsertCall {
+ c.mediaInfo_.SetProgressUpdater(pu)
+ return c
+}
+
+// Fields allows partial responses to be retrieved. See
+// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
+// for more information.
+func (c *ObjectsInsertCall) Fields(s ...googleapi.Field) *ObjectsInsertCall {
+ c.urlParams_.Set("fields", googleapi.CombineFields(s))
+ return c
+}
+
+// Context sets the context to be used in this call's Do method. Any
+// pending HTTP request will be aborted if the provided context is
+// canceled.
+// This context will supersede any context previously provided to the
+// ResumableMedia method.
+func (c *ObjectsInsertCall) Context(ctx context.Context) *ObjectsInsertCall {
+ c.ctx_ = ctx
+ return c
+}
+
+// Header returns an http.Header that can be modified by the caller to
+// add HTTP headers to the request.
+func (c *ObjectsInsertCall) Header() http.Header {
+ if c.header_ == nil {
+ c.header_ = make(http.Header)
+ }
+ return c.header_
+}
+
+func (c *ObjectsInsertCall) doRequest(alt string) (*http.Response, error) {
+ reqHeaders := make(http.Header)
+ for k, v := range c.header_ {
+ reqHeaders[k] = v
+ }
+ reqHeaders.Set("User-Agent", c.s.userAgent())
+ var body io.Reader = nil
+ body, err := googleapi.WithoutDataWrapper.JSONReader(c.object)
+ if err != nil {
+ return nil, err
+ }
+ reqHeaders.Set("Content-Type", "application/json")
+ c.urlParams_.Set("alt", alt)
+ c.urlParams_.Set("prettyPrint", "false")
+ urls := googleapi.ResolveRelative(c.s.BasePath, "b/{bucket}/o")
+ if c.mediaInfo_ != nil {
+ urls = strings.Replace(urls, "https://www.googleapis.com/", "https://www.googleapis.com/upload/", 1)
+ c.urlParams_.Set("uploadType", c.mediaInfo_.UploadType())
+ }
+ if body == nil {
+ body = new(bytes.Buffer)
+ reqHeaders.Set("Content-Type", "application/json")
+ }
+ body, getBody, cleanup := c.mediaInfo_.UploadRequest(reqHeaders, body)
+ defer cleanup()
+ urls += "?" + c.urlParams_.Encode()
+ req, err := http.NewRequest("POST", urls, body)
+ if err != nil {
+ return nil, err
+ }
+ req.Header = reqHeaders
+ gensupport.SetGetBody(req, getBody)
+ googleapi.Expand(req.URL, map[string]string{
+ "bucket": c.bucket,
+ })
+ return gensupport.SendRequest(c.ctx_, c.s.client, req)
+}
+
+// Do executes the "storage.objects.insert" call.
+// Exactly one of *Object or error will be non-nil. Any non-2xx status
+// code is an error. Response headers are in either
+// *Object.ServerResponse.Header or (if a response was returned at all)
+// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to
+// check whether the returned error was because http.StatusNotModified
+// was returned.
+func (c *ObjectsInsertCall) Do(opts ...googleapi.CallOption) (*Object, error) {
+ gensupport.SetOptions(c.urlParams_, opts...)
+ res, err := c.doRequest("json")
+ if res != nil && res.StatusCode == http.StatusNotModified {
+ if res.Body != nil {
+ res.Body.Close()
+ }
+ return nil, &googleapi.Error{
+ Code: res.StatusCode,
+ Header: res.Header,
+ }
+ }
+ if err != nil {
+ return nil, err
+ }
+ defer googleapi.CloseBody(res)
+ if err := googleapi.CheckResponse(res); err != nil {
+ return nil, err
+ }
+ rx := c.mediaInfo_.ResumableUpload(res.Header.Get("Location"))
+ if rx != nil {
+ rx.Client = c.s.client
+ rx.UserAgent = c.s.userAgent()
+ ctx := c.ctx_
+ if ctx == nil {
+ ctx = context.TODO()
+ }
+ res, err = rx.Upload(ctx)
+ if err != nil {
+ return nil, err
+ }
+ defer res.Body.Close()
+ if err := googleapi.CheckResponse(res); err != nil {
+ return nil, err
+ }
+ }
+ ret := &Object{
+ ServerResponse: googleapi.ServerResponse{
+ Header: res.Header,
+ HTTPStatusCode: res.StatusCode,
+ },
+ }
+ target := &ret
+ if err := gensupport.DecodeResponse(target, res); err != nil {
+ return nil, err
+ }
+ return ret, nil
+ // {
+ // "description": "Stores a new object and metadata.",
+ // "httpMethod": "POST",
+ // "id": "storage.objects.insert",
+ // "mediaUpload": {
+ // "accept": [
+ // "*/*"
+ // ],
+ // "protocols": {
+ // "resumable": {
+ // "multipart": true,
+ // "path": "/resumable/upload/storage/v1/b/{bucket}/o"
+ // },
+ // "simple": {
+ // "multipart": true,
+ // "path": "/upload/storage/v1/b/{bucket}/o"
+ // }
+ // }
+ // },
+ // "parameterOrder": [
+ // "bucket"
+ // ],
+ // "parameters": {
+ // "bucket": {
+ // "description": "Name of the bucket in which to store the new object. Overrides the provided object metadata's bucket value, if any.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "contentEncoding": {
+ // "description": "If set, sets the contentEncoding property of the final object to this value. Setting this parameter is equivalent to setting the contentEncoding metadata property. This can be useful when uploading an object with uploadType=media to indicate the encoding of the content being uploaded.",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "ifGenerationMatch": {
+ // "description": "Makes the operation conditional on whether the object's current generation matches the given value. Setting to 0 makes the operation succeed only if there are no live versions of the object.",
+ // "format": "int64",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "ifGenerationNotMatch": {
+ // "description": "Makes the operation conditional on whether the object's current generation does not match the given value. If no live object exists, the precondition fails. Setting to 0 makes the operation succeed only if there is a live version of the object.",
+ // "format": "int64",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "ifMetagenerationMatch": {
+ // "description": "Makes the operation conditional on whether the object's current metageneration matches the given value.",
+ // "format": "int64",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "ifMetagenerationNotMatch": {
+ // "description": "Makes the operation conditional on whether the object's current metageneration does not match the given value.",
+ // "format": "int64",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "kmsKeyName": {
+ // "description": "Resource name of the Cloud KMS key, of the form projects/my-project/locations/global/keyRings/my-kr/cryptoKeys/my-key, that will be used to encrypt the object. Overrides the object metadata's kms_key_name value, if any.",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "name": {
+ // "description": "Name of the object. Required when the object metadata is not otherwise provided. Overrides the object metadata's name value, if any. For information about how to URL encode object names to be path safe, see Encoding URI Path Parts.",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "predefinedAcl": {
+ // "description": "Apply a predefined set of access controls to this object.",
+ // "enum": [
+ // "authenticatedRead",
+ // "bucketOwnerFullControl",
+ // "bucketOwnerRead",
+ // "private",
+ // "projectPrivate",
+ // "publicRead"
+ // ],
+ // "enumDescriptions": [
+ // "Object owner gets OWNER access, and allAuthenticatedUsers get READER access.",
+ // "Object owner gets OWNER access, and project team owners get OWNER access.",
+ // "Object owner gets OWNER access, and project team owners get READER access.",
+ // "Object owner gets OWNER access.",
+ // "Object owner gets OWNER access, and project team members get access according to their roles.",
+ // "Object owner gets OWNER access, and allUsers get READER access."
+ // ],
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "projection": {
+ // "description": "Set of properties to return. Defaults to noAcl, unless the object resource specifies the acl property, when it defaults to full.",
+ // "enum": [
+ // "full",
+ // "noAcl"
+ // ],
+ // "enumDescriptions": [
+ // "Include all properties.",
+ // "Omit the owner, acl property."
+ // ],
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "userProject": {
+ // "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ // "location": "query",
+ // "type": "string"
+ // }
+ // },
+ // "path": "b/{bucket}/o",
+ // "request": {
+ // "$ref": "Object"
+ // },
+ // "response": {
+ // "$ref": "Object"
+ // },
+ // "scopes": [
+ // "https://www.googleapis.com/auth/cloud-platform",
+ // "https://www.googleapis.com/auth/devstorage.full_control",
+ // "https://www.googleapis.com/auth/devstorage.read_write"
+ // ],
+ // "supportsMediaUpload": true
+ // }
+
+}
+
+// method id "storage.objects.list":
+
+type ObjectsListCall struct {
+ s *Service
+ bucket string
+ urlParams_ gensupport.URLParams
+ ifNoneMatch_ string
+ ctx_ context.Context
+ header_ http.Header
+}
+
+// List: Retrieves a list of objects matching the criteria.
+func (r *ObjectsService) List(bucket string) *ObjectsListCall {
+ c := &ObjectsListCall{s: r.s, urlParams_: make(gensupport.URLParams)}
+ c.bucket = bucket
+ return c
+}
+
+// Delimiter sets the optional parameter "delimiter": Returns results in
+// a directory-like mode. items will contain only objects whose names,
+// aside from the prefix, do not contain delimiter. Objects whose names,
+// aside from the prefix, contain delimiter will have their name,
+// truncated after the delimiter, returned in prefixes. Duplicate
+// prefixes are omitted.
+func (c *ObjectsListCall) Delimiter(delimiter string) *ObjectsListCall {
+ c.urlParams_.Set("delimiter", delimiter)
+ return c
+}
+
+// IncludeTrailingDelimiter sets the optional parameter
+// "includeTrailingDelimiter": If true, objects that end in exactly one
+// instance of delimiter will have their metadata included in items in
+// addition to prefixes.
+func (c *ObjectsListCall) IncludeTrailingDelimiter(includeTrailingDelimiter bool) *ObjectsListCall {
+ c.urlParams_.Set("includeTrailingDelimiter", fmt.Sprint(includeTrailingDelimiter))
+ return c
+}
+
+// MaxResults sets the optional parameter "maxResults": Maximum number
+// of items plus prefixes to return in a single page of responses. As
+// duplicate prefixes are omitted, fewer total results may be returned
+// than requested. The service will use this parameter or 1,000 items,
+// whichever is smaller.
+func (c *ObjectsListCall) MaxResults(maxResults int64) *ObjectsListCall {
+ c.urlParams_.Set("maxResults", fmt.Sprint(maxResults))
+ return c
+}
+
+// PageToken sets the optional parameter "pageToken": A
+// previously-returned page token representing part of the larger set of
+// results to view.
+func (c *ObjectsListCall) PageToken(pageToken string) *ObjectsListCall {
+ c.urlParams_.Set("pageToken", pageToken)
+ return c
+}
+
+// Prefix sets the optional parameter "prefix": Filter results to
+// objects whose names begin with this prefix.
+func (c *ObjectsListCall) Prefix(prefix string) *ObjectsListCall {
+ c.urlParams_.Set("prefix", prefix)
+ return c
+}
+
+// Projection sets the optional parameter "projection": Set of
+// properties to return. Defaults to noAcl.
+//
+// Possible values:
+// "full" - Include all properties.
+// "noAcl" - Omit the owner, acl property.
+func (c *ObjectsListCall) Projection(projection string) *ObjectsListCall {
+ c.urlParams_.Set("projection", projection)
+ return c
+}
+
+// UserProject sets the optional parameter "userProject": The project to
+// be billed for this request. Required for Requester Pays buckets.
+func (c *ObjectsListCall) UserProject(userProject string) *ObjectsListCall {
+ c.urlParams_.Set("userProject", userProject)
+ return c
+}
+
+// Versions sets the optional parameter "versions": If true, lists all
+// versions of an object as distinct results. The default is false. For
+// more information, see Object Versioning.
+func (c *ObjectsListCall) Versions(versions bool) *ObjectsListCall {
+ c.urlParams_.Set("versions", fmt.Sprint(versions))
+ return c
+}
+
+// Fields allows partial responses to be retrieved. See
+// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
+// for more information.
+func (c *ObjectsListCall) Fields(s ...googleapi.Field) *ObjectsListCall {
+ c.urlParams_.Set("fields", googleapi.CombineFields(s))
+ return c
+}
+
+// IfNoneMatch sets the optional parameter which makes the operation
+// fail if the object's ETag matches the given value. This is useful for
+// getting updates only after the object has changed since the last
+// request. Use googleapi.IsNotModified to check whether the response
+// error from Do is the result of In-None-Match.
+func (c *ObjectsListCall) IfNoneMatch(entityTag string) *ObjectsListCall {
+ c.ifNoneMatch_ = entityTag
+ return c
+}
+
+// Context sets the context to be used in this call's Do method. Any
+// pending HTTP request will be aborted if the provided context is
+// canceled.
+func (c *ObjectsListCall) Context(ctx context.Context) *ObjectsListCall {
+ c.ctx_ = ctx
+ return c
+}
+
+// Header returns an http.Header that can be modified by the caller to
+// add HTTP headers to the request.
+func (c *ObjectsListCall) Header() http.Header {
+ if c.header_ == nil {
+ c.header_ = make(http.Header)
+ }
+ return c.header_
+}
+
+func (c *ObjectsListCall) doRequest(alt string) (*http.Response, error) {
+ reqHeaders := make(http.Header)
+ for k, v := range c.header_ {
+ reqHeaders[k] = v
+ }
+ reqHeaders.Set("User-Agent", c.s.userAgent())
+ if c.ifNoneMatch_ != "" {
+ reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
+ }
+ var body io.Reader = nil
+ c.urlParams_.Set("alt", alt)
+ c.urlParams_.Set("prettyPrint", "false")
+ urls := googleapi.ResolveRelative(c.s.BasePath, "b/{bucket}/o")
+ urls += "?" + c.urlParams_.Encode()
+ req, err := http.NewRequest("GET", urls, body)
+ if err != nil {
+ return nil, err
+ }
+ req.Header = reqHeaders
+ googleapi.Expand(req.URL, map[string]string{
+ "bucket": c.bucket,
+ })
+ return gensupport.SendRequest(c.ctx_, c.s.client, req)
+}
+
+// Do executes the "storage.objects.list" call.
+// Exactly one of *Objects or error will be non-nil. Any non-2xx status
+// code is an error. Response headers are in either
+// *Objects.ServerResponse.Header or (if a response was returned at all)
+// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to
+// check whether the returned error was because http.StatusNotModified
+// was returned.
+func (c *ObjectsListCall) Do(opts ...googleapi.CallOption) (*Objects, error) {
+ gensupport.SetOptions(c.urlParams_, opts...)
+ res, err := c.doRequest("json")
+ if res != nil && res.StatusCode == http.StatusNotModified {
+ if res.Body != nil {
+ res.Body.Close()
+ }
+ return nil, &googleapi.Error{
+ Code: res.StatusCode,
+ Header: res.Header,
+ }
+ }
+ if err != nil {
+ return nil, err
+ }
+ defer googleapi.CloseBody(res)
+ if err := googleapi.CheckResponse(res); err != nil {
+ return nil, err
+ }
+ ret := &Objects{
+ ServerResponse: googleapi.ServerResponse{
+ Header: res.Header,
+ HTTPStatusCode: res.StatusCode,
+ },
+ }
+ target := &ret
+ if err := gensupport.DecodeResponse(target, res); err != nil {
+ return nil, err
+ }
+ return ret, nil
+ // {
+ // "description": "Retrieves a list of objects matching the criteria.",
+ // "httpMethod": "GET",
+ // "id": "storage.objects.list",
+ // "parameterOrder": [
+ // "bucket"
+ // ],
+ // "parameters": {
+ // "bucket": {
+ // "description": "Name of the bucket in which to look for objects.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "delimiter": {
+ // "description": "Returns results in a directory-like mode. items will contain only objects whose names, aside from the prefix, do not contain delimiter. Objects whose names, aside from the prefix, contain delimiter will have their name, truncated after the delimiter, returned in prefixes. Duplicate prefixes are omitted.",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "includeTrailingDelimiter": {
+ // "description": "If true, objects that end in exactly one instance of delimiter will have their metadata included in items in addition to prefixes.",
+ // "location": "query",
+ // "type": "boolean"
+ // },
+ // "maxResults": {
+ // "default": "1000",
+ // "description": "Maximum number of items plus prefixes to return in a single page of responses. As duplicate prefixes are omitted, fewer total results may be returned than requested. The service will use this parameter or 1,000 items, whichever is smaller.",
+ // "format": "uint32",
+ // "location": "query",
+ // "minimum": "0",
+ // "type": "integer"
+ // },
+ // "pageToken": {
+ // "description": "A previously-returned page token representing part of the larger set of results to view.",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "prefix": {
+ // "description": "Filter results to objects whose names begin with this prefix.",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "projection": {
+ // "description": "Set of properties to return. Defaults to noAcl.",
+ // "enum": [
+ // "full",
+ // "noAcl"
+ // ],
+ // "enumDescriptions": [
+ // "Include all properties.",
+ // "Omit the owner, acl property."
+ // ],
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "userProject": {
+ // "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "versions": {
+ // "description": "If true, lists all versions of an object as distinct results. The default is false. For more information, see Object Versioning.",
+ // "location": "query",
+ // "type": "boolean"
+ // }
+ // },
+ // "path": "b/{bucket}/o",
+ // "response": {
+ // "$ref": "Objects"
+ // },
+ // "scopes": [
+ // "https://www.googleapis.com/auth/cloud-platform",
+ // "https://www.googleapis.com/auth/cloud-platform.read-only",
+ // "https://www.googleapis.com/auth/devstorage.full_control",
+ // "https://www.googleapis.com/auth/devstorage.read_only",
+ // "https://www.googleapis.com/auth/devstorage.read_write"
+ // ],
+ // "supportsSubscription": true
+ // }
+
+}
+
+// Pages invokes f for each page of results.
+// A non-nil error returned from f will halt the iteration.
+// The provided context supersedes any context provided to the Context method.
+func (c *ObjectsListCall) Pages(ctx context.Context, f func(*Objects) error) error {
+ c.ctx_ = ctx
+ defer c.PageToken(c.urlParams_.Get("pageToken")) // reset paging to original point
+ for {
+ x, err := c.Do()
+ if err != nil {
+ return err
+ }
+ if err := f(x); err != nil {
+ return err
+ }
+ if x.NextPageToken == "" {
+ return nil
+ }
+ c.PageToken(x.NextPageToken)
+ }
+}
+
+// method id "storage.objects.patch":
+
+type ObjectsPatchCall struct {
+ s *Service
+ bucket string
+ object string
+ object2 *Object
+ urlParams_ gensupport.URLParams
+ ctx_ context.Context
+ header_ http.Header
+}
+
+// Patch: Patches an object's metadata.
+func (r *ObjectsService) Patch(bucket string, object string, object2 *Object) *ObjectsPatchCall {
+ c := &ObjectsPatchCall{s: r.s, urlParams_: make(gensupport.URLParams)}
+ c.bucket = bucket
+ c.object = object
+ c.object2 = object2
+ return c
+}
+
+// Generation sets the optional parameter "generation": If present,
+// selects a specific revision of this object (as opposed to the latest
+// version, the default).
+func (c *ObjectsPatchCall) Generation(generation int64) *ObjectsPatchCall {
+ c.urlParams_.Set("generation", fmt.Sprint(generation))
+ return c
+}
+
+// IfGenerationMatch sets the optional parameter "ifGenerationMatch":
+// Makes the operation conditional on whether the object's current
+// generation matches the given value. Setting to 0 makes the operation
+// succeed only if there are no live versions of the object.
+func (c *ObjectsPatchCall) IfGenerationMatch(ifGenerationMatch int64) *ObjectsPatchCall {
+ c.urlParams_.Set("ifGenerationMatch", fmt.Sprint(ifGenerationMatch))
+ return c
+}
+
+// IfGenerationNotMatch sets the optional parameter
+// "ifGenerationNotMatch": Makes the operation conditional on whether
+// the object's current generation does not match the given value. If no
+// live object exists, the precondition fails. Setting to 0 makes the
+// operation succeed only if there is a live version of the object.
+func (c *ObjectsPatchCall) IfGenerationNotMatch(ifGenerationNotMatch int64) *ObjectsPatchCall {
+ c.urlParams_.Set("ifGenerationNotMatch", fmt.Sprint(ifGenerationNotMatch))
+ return c
+}
+
+// IfMetagenerationMatch sets the optional parameter
+// "ifMetagenerationMatch": Makes the operation conditional on whether
+// the object's current metageneration matches the given value.
+func (c *ObjectsPatchCall) IfMetagenerationMatch(ifMetagenerationMatch int64) *ObjectsPatchCall {
+ c.urlParams_.Set("ifMetagenerationMatch", fmt.Sprint(ifMetagenerationMatch))
+ return c
+}
+
+// IfMetagenerationNotMatch sets the optional parameter
+// "ifMetagenerationNotMatch": Makes the operation conditional on
+// whether the object's current metageneration does not match the given
+// value.
+func (c *ObjectsPatchCall) IfMetagenerationNotMatch(ifMetagenerationNotMatch int64) *ObjectsPatchCall {
+ c.urlParams_.Set("ifMetagenerationNotMatch", fmt.Sprint(ifMetagenerationNotMatch))
+ return c
+}
+
+// PredefinedAcl sets the optional parameter "predefinedAcl": Apply a
+// predefined set of access controls to this object.
+//
+// Possible values:
+// "authenticatedRead" - Object owner gets OWNER access, and
+// allAuthenticatedUsers get READER access.
+// "bucketOwnerFullControl" - Object owner gets OWNER access, and
+// project team owners get OWNER access.
+// "bucketOwnerRead" - Object owner gets OWNER access, and project
+// team owners get READER access.
+// "private" - Object owner gets OWNER access.
+// "projectPrivate" - Object owner gets OWNER access, and project team
+// members get access according to their roles.
+// "publicRead" - Object owner gets OWNER access, and allUsers get
+// READER access.
+func (c *ObjectsPatchCall) PredefinedAcl(predefinedAcl string) *ObjectsPatchCall {
+ c.urlParams_.Set("predefinedAcl", predefinedAcl)
+ return c
+}
+
+// Projection sets the optional parameter "projection": Set of
+// properties to return. Defaults to full.
+//
+// Possible values:
+// "full" - Include all properties.
+// "noAcl" - Omit the owner, acl property.
+func (c *ObjectsPatchCall) Projection(projection string) *ObjectsPatchCall {
+ c.urlParams_.Set("projection", projection)
+ return c
+}
+
+// UserProject sets the optional parameter "userProject": The project to
+// be billed for this request, for Requester Pays buckets.
+func (c *ObjectsPatchCall) UserProject(userProject string) *ObjectsPatchCall {
+ c.urlParams_.Set("userProject", userProject)
+ return c
+}
+
+// Fields allows partial responses to be retrieved. See
+// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
+// for more information.
+func (c *ObjectsPatchCall) Fields(s ...googleapi.Field) *ObjectsPatchCall {
+ c.urlParams_.Set("fields", googleapi.CombineFields(s))
+ return c
+}
+
+// Context sets the context to be used in this call's Do method. Any
+// pending HTTP request will be aborted if the provided context is
+// canceled.
+func (c *ObjectsPatchCall) Context(ctx context.Context) *ObjectsPatchCall {
+ c.ctx_ = ctx
+ return c
+}
+
+// Header returns an http.Header that can be modified by the caller to
+// add HTTP headers to the request.
+func (c *ObjectsPatchCall) Header() http.Header {
+ if c.header_ == nil {
+ c.header_ = make(http.Header)
+ }
+ return c.header_
+}
+
+func (c *ObjectsPatchCall) doRequest(alt string) (*http.Response, error) {
+ reqHeaders := make(http.Header)
+ for k, v := range c.header_ {
+ reqHeaders[k] = v
+ }
+ reqHeaders.Set("User-Agent", c.s.userAgent())
+ var body io.Reader = nil
+ body, err := googleapi.WithoutDataWrapper.JSONReader(c.object2)
+ if err != nil {
+ return nil, err
+ }
+ reqHeaders.Set("Content-Type", "application/json")
+ c.urlParams_.Set("alt", alt)
+ c.urlParams_.Set("prettyPrint", "false")
+ urls := googleapi.ResolveRelative(c.s.BasePath, "b/{bucket}/o/{object}")
+ urls += "?" + c.urlParams_.Encode()
+ req, err := http.NewRequest("PATCH", urls, body)
+ if err != nil {
+ return nil, err
+ }
+ req.Header = reqHeaders
+ googleapi.Expand(req.URL, map[string]string{
+ "bucket": c.bucket,
+ "object": c.object,
+ })
+ return gensupport.SendRequest(c.ctx_, c.s.client, req)
+}
+
+// Do executes the "storage.objects.patch" call.
+// Exactly one of *Object or error will be non-nil. Any non-2xx status
+// code is an error. Response headers are in either
+// *Object.ServerResponse.Header or (if a response was returned at all)
+// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to
+// check whether the returned error was because http.StatusNotModified
+// was returned.
+func (c *ObjectsPatchCall) Do(opts ...googleapi.CallOption) (*Object, error) {
+ gensupport.SetOptions(c.urlParams_, opts...)
+ res, err := c.doRequest("json")
+ if res != nil && res.StatusCode == http.StatusNotModified {
+ if res.Body != nil {
+ res.Body.Close()
+ }
+ return nil, &googleapi.Error{
+ Code: res.StatusCode,
+ Header: res.Header,
+ }
+ }
+ if err != nil {
+ return nil, err
+ }
+ defer googleapi.CloseBody(res)
+ if err := googleapi.CheckResponse(res); err != nil {
+ return nil, err
+ }
+ ret := &Object{
+ ServerResponse: googleapi.ServerResponse{
+ Header: res.Header,
+ HTTPStatusCode: res.StatusCode,
+ },
+ }
+ target := &ret
+ if err := gensupport.DecodeResponse(target, res); err != nil {
+ return nil, err
+ }
+ return ret, nil
+ // {
+ // "description": "Patches an object's metadata.",
+ // "httpMethod": "PATCH",
+ // "id": "storage.objects.patch",
+ // "parameterOrder": [
+ // "bucket",
+ // "object"
+ // ],
+ // "parameters": {
+ // "bucket": {
+ // "description": "Name of the bucket in which the object resides.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "generation": {
+ // "description": "If present, selects a specific revision of this object (as opposed to the latest version, the default).",
+ // "format": "int64",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "ifGenerationMatch": {
+ // "description": "Makes the operation conditional on whether the object's current generation matches the given value. Setting to 0 makes the operation succeed only if there are no live versions of the object.",
+ // "format": "int64",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "ifGenerationNotMatch": {
+ // "description": "Makes the operation conditional on whether the object's current generation does not match the given value. If no live object exists, the precondition fails. Setting to 0 makes the operation succeed only if there is a live version of the object.",
+ // "format": "int64",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "ifMetagenerationMatch": {
+ // "description": "Makes the operation conditional on whether the object's current metageneration matches the given value.",
+ // "format": "int64",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "ifMetagenerationNotMatch": {
+ // "description": "Makes the operation conditional on whether the object's current metageneration does not match the given value.",
+ // "format": "int64",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "object": {
+ // "description": "Name of the object. For information about how to URL encode object names to be path safe, see Encoding URI Path Parts.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "predefinedAcl": {
+ // "description": "Apply a predefined set of access controls to this object.",
+ // "enum": [
+ // "authenticatedRead",
+ // "bucketOwnerFullControl",
+ // "bucketOwnerRead",
+ // "private",
+ // "projectPrivate",
+ // "publicRead"
+ // ],
+ // "enumDescriptions": [
+ // "Object owner gets OWNER access, and allAuthenticatedUsers get READER access.",
+ // "Object owner gets OWNER access, and project team owners get OWNER access.",
+ // "Object owner gets OWNER access, and project team owners get READER access.",
+ // "Object owner gets OWNER access.",
+ // "Object owner gets OWNER access, and project team members get access according to their roles.",
+ // "Object owner gets OWNER access, and allUsers get READER access."
+ // ],
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "projection": {
+ // "description": "Set of properties to return. Defaults to full.",
+ // "enum": [
+ // "full",
+ // "noAcl"
+ // ],
+ // "enumDescriptions": [
+ // "Include all properties.",
+ // "Omit the owner, acl property."
+ // ],
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "userProject": {
+ // "description": "The project to be billed for this request, for Requester Pays buckets.",
+ // "location": "query",
+ // "type": "string"
+ // }
+ // },
+ // "path": "b/{bucket}/o/{object}",
+ // "request": {
+ // "$ref": "Object"
+ // },
+ // "response": {
+ // "$ref": "Object"
+ // },
+ // "scopes": [
+ // "https://www.googleapis.com/auth/cloud-platform",
+ // "https://www.googleapis.com/auth/devstorage.full_control"
+ // ]
+ // }
+
+}
+
+// method id "storage.objects.rewrite":
+
+type ObjectsRewriteCall struct {
+ s *Service
+ sourceBucket string
+ sourceObject string
+ destinationBucket string
+ destinationObject string
+ object *Object
+ urlParams_ gensupport.URLParams
+ ctx_ context.Context
+ header_ http.Header
+}
+
+// Rewrite: Rewrites a source object to a destination object. Optionally
+// overrides metadata.
+func (r *ObjectsService) Rewrite(sourceBucket string, sourceObject string, destinationBucket string, destinationObject string, object *Object) *ObjectsRewriteCall {
+ c := &ObjectsRewriteCall{s: r.s, urlParams_: make(gensupport.URLParams)}
+ c.sourceBucket = sourceBucket
+ c.sourceObject = sourceObject
+ c.destinationBucket = destinationBucket
+ c.destinationObject = destinationObject
+ c.object = object
+ return c
+}
+
+// DestinationKmsKeyName sets the optional parameter
+// "destinationKmsKeyName": Resource name of the Cloud KMS key, of the
+// form
+// projects/my-project/locations/global/keyRings/my-kr/cryptoKeys/my-key,
+// that will be used to encrypt the object. Overrides the object
+// metadata's kms_key_name value, if any.
+func (c *ObjectsRewriteCall) DestinationKmsKeyName(destinationKmsKeyName string) *ObjectsRewriteCall {
+ c.urlParams_.Set("destinationKmsKeyName", destinationKmsKeyName)
+ return c
+}
+
+// DestinationPredefinedAcl sets the optional parameter
+// "destinationPredefinedAcl": Apply a predefined set of access controls
+// to the destination object.
+//
+// Possible values:
+// "authenticatedRead" - Object owner gets OWNER access, and
+// allAuthenticatedUsers get READER access.
+// "bucketOwnerFullControl" - Object owner gets OWNER access, and
+// project team owners get OWNER access.
+// "bucketOwnerRead" - Object owner gets OWNER access, and project
+// team owners get READER access.
+// "private" - Object owner gets OWNER access.
+// "projectPrivate" - Object owner gets OWNER access, and project team
+// members get access according to their roles.
+// "publicRead" - Object owner gets OWNER access, and allUsers get
+// READER access.
+func (c *ObjectsRewriteCall) DestinationPredefinedAcl(destinationPredefinedAcl string) *ObjectsRewriteCall {
+ c.urlParams_.Set("destinationPredefinedAcl", destinationPredefinedAcl)
+ return c
+}
+
+// IfGenerationMatch sets the optional parameter "ifGenerationMatch":
+// Makes the operation conditional on whether the object's current
+// generation matches the given value. Setting to 0 makes the operation
+// succeed only if there are no live versions of the object.
+func (c *ObjectsRewriteCall) IfGenerationMatch(ifGenerationMatch int64) *ObjectsRewriteCall {
+ c.urlParams_.Set("ifGenerationMatch", fmt.Sprint(ifGenerationMatch))
+ return c
+}
+
+// IfGenerationNotMatch sets the optional parameter
+// "ifGenerationNotMatch": Makes the operation conditional on whether
+// the object's current generation does not match the given value. If no
+// live object exists, the precondition fails. Setting to 0 makes the
+// operation succeed only if there is a live version of the object.
+func (c *ObjectsRewriteCall) IfGenerationNotMatch(ifGenerationNotMatch int64) *ObjectsRewriteCall {
+ c.urlParams_.Set("ifGenerationNotMatch", fmt.Sprint(ifGenerationNotMatch))
+ return c
+}
+
+// IfMetagenerationMatch sets the optional parameter
+// "ifMetagenerationMatch": Makes the operation conditional on whether
+// the destination object's current metageneration matches the given
+// value.
+func (c *ObjectsRewriteCall) IfMetagenerationMatch(ifMetagenerationMatch int64) *ObjectsRewriteCall {
+ c.urlParams_.Set("ifMetagenerationMatch", fmt.Sprint(ifMetagenerationMatch))
+ return c
+}
+
+// IfMetagenerationNotMatch sets the optional parameter
+// "ifMetagenerationNotMatch": Makes the operation conditional on
+// whether the destination object's current metageneration does not
+// match the given value.
+func (c *ObjectsRewriteCall) IfMetagenerationNotMatch(ifMetagenerationNotMatch int64) *ObjectsRewriteCall {
+ c.urlParams_.Set("ifMetagenerationNotMatch", fmt.Sprint(ifMetagenerationNotMatch))
+ return c
+}
+
+// IfSourceGenerationMatch sets the optional parameter
+// "ifSourceGenerationMatch": Makes the operation conditional on whether
+// the source object's current generation matches the given value.
+func (c *ObjectsRewriteCall) IfSourceGenerationMatch(ifSourceGenerationMatch int64) *ObjectsRewriteCall {
+ c.urlParams_.Set("ifSourceGenerationMatch", fmt.Sprint(ifSourceGenerationMatch))
+ return c
+}
+
+// IfSourceGenerationNotMatch sets the optional parameter
+// "ifSourceGenerationNotMatch": Makes the operation conditional on
+// whether the source object's current generation does not match the
+// given value.
+func (c *ObjectsRewriteCall) IfSourceGenerationNotMatch(ifSourceGenerationNotMatch int64) *ObjectsRewriteCall {
+ c.urlParams_.Set("ifSourceGenerationNotMatch", fmt.Sprint(ifSourceGenerationNotMatch))
+ return c
+}
+
+// IfSourceMetagenerationMatch sets the optional parameter
+// "ifSourceMetagenerationMatch": Makes the operation conditional on
+// whether the source object's current metageneration matches the given
+// value.
+func (c *ObjectsRewriteCall) IfSourceMetagenerationMatch(ifSourceMetagenerationMatch int64) *ObjectsRewriteCall {
+ c.urlParams_.Set("ifSourceMetagenerationMatch", fmt.Sprint(ifSourceMetagenerationMatch))
+ return c
+}
+
+// IfSourceMetagenerationNotMatch sets the optional parameter
+// "ifSourceMetagenerationNotMatch": Makes the operation conditional on
+// whether the source object's current metageneration does not match the
+// given value.
+func (c *ObjectsRewriteCall) IfSourceMetagenerationNotMatch(ifSourceMetagenerationNotMatch int64) *ObjectsRewriteCall {
+ c.urlParams_.Set("ifSourceMetagenerationNotMatch", fmt.Sprint(ifSourceMetagenerationNotMatch))
+ return c
+}
+
+// MaxBytesRewrittenPerCall sets the optional parameter
+// "maxBytesRewrittenPerCall": The maximum number of bytes that will be
+// rewritten per rewrite request. Most callers shouldn't need to specify
+// this parameter - it is primarily in place to support testing. If
+// specified the value must be an integral multiple of 1 MiB (1048576).
+// Also, this only applies to requests where the source and destination
+// span locations and/or storage classes. Finally, this value must not
+// change across rewrite calls else you'll get an error that the
+// rewriteToken is invalid.
+func (c *ObjectsRewriteCall) MaxBytesRewrittenPerCall(maxBytesRewrittenPerCall int64) *ObjectsRewriteCall {
+ c.urlParams_.Set("maxBytesRewrittenPerCall", fmt.Sprint(maxBytesRewrittenPerCall))
+ return c
+}
+
+// Projection sets the optional parameter "projection": Set of
+// properties to return. Defaults to noAcl, unless the object resource
+// specifies the acl property, when it defaults to full.
+//
+// Possible values:
+// "full" - Include all properties.
+// "noAcl" - Omit the owner, acl property.
+func (c *ObjectsRewriteCall) Projection(projection string) *ObjectsRewriteCall {
+ c.urlParams_.Set("projection", projection)
+ return c
+}
+
+// RewriteToken sets the optional parameter "rewriteToken": Include this
+// field (from the previous rewrite response) on each rewrite request
+// after the first one, until the rewrite response 'done' flag is true.
+// Calls that provide a rewriteToken can omit all other request fields,
+// but if included those fields must match the values provided in the
+// first rewrite request.
+func (c *ObjectsRewriteCall) RewriteToken(rewriteToken string) *ObjectsRewriteCall {
+ c.urlParams_.Set("rewriteToken", rewriteToken)
+ return c
+}
+
+// SourceGeneration sets the optional parameter "sourceGeneration": If
+// present, selects a specific revision of the source object (as opposed
+// to the latest version, the default).
+func (c *ObjectsRewriteCall) SourceGeneration(sourceGeneration int64) *ObjectsRewriteCall {
+ c.urlParams_.Set("sourceGeneration", fmt.Sprint(sourceGeneration))
+ return c
+}
+
+// UserProject sets the optional parameter "userProject": The project to
+// be billed for this request. Required for Requester Pays buckets.
+func (c *ObjectsRewriteCall) UserProject(userProject string) *ObjectsRewriteCall {
+ c.urlParams_.Set("userProject", userProject)
+ return c
+}
+
+// Fields allows partial responses to be retrieved. See
+// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
+// for more information.
+func (c *ObjectsRewriteCall) Fields(s ...googleapi.Field) *ObjectsRewriteCall {
+ c.urlParams_.Set("fields", googleapi.CombineFields(s))
+ return c
+}
+
+// Context sets the context to be used in this call's Do method. Any
+// pending HTTP request will be aborted if the provided context is
+// canceled.
+func (c *ObjectsRewriteCall) Context(ctx context.Context) *ObjectsRewriteCall {
+ c.ctx_ = ctx
+ return c
+}
+
+// Header returns an http.Header that can be modified by the caller to
+// add HTTP headers to the request.
+func (c *ObjectsRewriteCall) Header() http.Header {
+ if c.header_ == nil {
+ c.header_ = make(http.Header)
+ }
+ return c.header_
+}
+
+func (c *ObjectsRewriteCall) doRequest(alt string) (*http.Response, error) {
+ reqHeaders := make(http.Header)
+ for k, v := range c.header_ {
+ reqHeaders[k] = v
+ }
+ reqHeaders.Set("User-Agent", c.s.userAgent())
+ var body io.Reader = nil
+ body, err := googleapi.WithoutDataWrapper.JSONReader(c.object)
+ if err != nil {
+ return nil, err
+ }
+ reqHeaders.Set("Content-Type", "application/json")
+ c.urlParams_.Set("alt", alt)
+ c.urlParams_.Set("prettyPrint", "false")
+ urls := googleapi.ResolveRelative(c.s.BasePath, "b/{sourceBucket}/o/{sourceObject}/rewriteTo/b/{destinationBucket}/o/{destinationObject}")
+ urls += "?" + c.urlParams_.Encode()
+ req, err := http.NewRequest("POST", urls, body)
+ if err != nil {
+ return nil, err
+ }
+ req.Header = reqHeaders
+ googleapi.Expand(req.URL, map[string]string{
+ "sourceBucket": c.sourceBucket,
+ "sourceObject": c.sourceObject,
+ "destinationBucket": c.destinationBucket,
+ "destinationObject": c.destinationObject,
+ })
+ return gensupport.SendRequest(c.ctx_, c.s.client, req)
+}
+
+// Do executes the "storage.objects.rewrite" call.
+// Exactly one of *RewriteResponse or error will be non-nil. Any non-2xx
+// status code is an error. Response headers are in either
+// *RewriteResponse.ServerResponse.Header or (if a response was returned
+// at all) in error.(*googleapi.Error).Header. Use
+// googleapi.IsNotModified to check whether the returned error was
+// because http.StatusNotModified was returned.
+func (c *ObjectsRewriteCall) Do(opts ...googleapi.CallOption) (*RewriteResponse, error) {
+ gensupport.SetOptions(c.urlParams_, opts...)
+ res, err := c.doRequest("json")
+ if res != nil && res.StatusCode == http.StatusNotModified {
+ if res.Body != nil {
+ res.Body.Close()
+ }
+ return nil, &googleapi.Error{
+ Code: res.StatusCode,
+ Header: res.Header,
+ }
+ }
+ if err != nil {
+ return nil, err
+ }
+ defer googleapi.CloseBody(res)
+ if err := googleapi.CheckResponse(res); err != nil {
+ return nil, err
+ }
+ ret := &RewriteResponse{
+ ServerResponse: googleapi.ServerResponse{
+ Header: res.Header,
+ HTTPStatusCode: res.StatusCode,
+ },
+ }
+ target := &ret
+ if err := gensupport.DecodeResponse(target, res); err != nil {
+ return nil, err
+ }
+ return ret, nil
+ // {
+ // "description": "Rewrites a source object to a destination object. Optionally overrides metadata.",
+ // "httpMethod": "POST",
+ // "id": "storage.objects.rewrite",
+ // "parameterOrder": [
+ // "sourceBucket",
+ // "sourceObject",
+ // "destinationBucket",
+ // "destinationObject"
+ // ],
+ // "parameters": {
+ // "destinationBucket": {
+ // "description": "Name of the bucket in which to store the new object. Overrides the provided object metadata's bucket value, if any.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "destinationKmsKeyName": {
+ // "description": "Resource name of the Cloud KMS key, of the form projects/my-project/locations/global/keyRings/my-kr/cryptoKeys/my-key, that will be used to encrypt the object. Overrides the object metadata's kms_key_name value, if any.",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "destinationObject": {
+ // "description": "Name of the new object. Required when the object metadata is not otherwise provided. Overrides the object metadata's name value, if any. For information about how to URL encode object names to be path safe, see Encoding URI Path Parts.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "destinationPredefinedAcl": {
+ // "description": "Apply a predefined set of access controls to the destination object.",
+ // "enum": [
+ // "authenticatedRead",
+ // "bucketOwnerFullControl",
+ // "bucketOwnerRead",
+ // "private",
+ // "projectPrivate",
+ // "publicRead"
+ // ],
+ // "enumDescriptions": [
+ // "Object owner gets OWNER access, and allAuthenticatedUsers get READER access.",
+ // "Object owner gets OWNER access, and project team owners get OWNER access.",
+ // "Object owner gets OWNER access, and project team owners get READER access.",
+ // "Object owner gets OWNER access.",
+ // "Object owner gets OWNER access, and project team members get access according to their roles.",
+ // "Object owner gets OWNER access, and allUsers get READER access."
+ // ],
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "ifGenerationMatch": {
+ // "description": "Makes the operation conditional on whether the object's current generation matches the given value. Setting to 0 makes the operation succeed only if there are no live versions of the object.",
+ // "format": "int64",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "ifGenerationNotMatch": {
+ // "description": "Makes the operation conditional on whether the object's current generation does not match the given value. If no live object exists, the precondition fails. Setting to 0 makes the operation succeed only if there is a live version of the object.",
+ // "format": "int64",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "ifMetagenerationMatch": {
+ // "description": "Makes the operation conditional on whether the destination object's current metageneration matches the given value.",
+ // "format": "int64",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "ifMetagenerationNotMatch": {
+ // "description": "Makes the operation conditional on whether the destination object's current metageneration does not match the given value.",
+ // "format": "int64",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "ifSourceGenerationMatch": {
+ // "description": "Makes the operation conditional on whether the source object's current generation matches the given value.",
+ // "format": "int64",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "ifSourceGenerationNotMatch": {
+ // "description": "Makes the operation conditional on whether the source object's current generation does not match the given value.",
+ // "format": "int64",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "ifSourceMetagenerationMatch": {
+ // "description": "Makes the operation conditional on whether the source object's current metageneration matches the given value.",
+ // "format": "int64",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "ifSourceMetagenerationNotMatch": {
+ // "description": "Makes the operation conditional on whether the source object's current metageneration does not match the given value.",
+ // "format": "int64",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "maxBytesRewrittenPerCall": {
+ // "description": "The maximum number of bytes that will be rewritten per rewrite request. Most callers shouldn't need to specify this parameter - it is primarily in place to support testing. If specified the value must be an integral multiple of 1 MiB (1048576). Also, this only applies to requests where the source and destination span locations and/or storage classes. Finally, this value must not change across rewrite calls else you'll get an error that the rewriteToken is invalid.",
+ // "format": "int64",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "projection": {
+ // "description": "Set of properties to return. Defaults to noAcl, unless the object resource specifies the acl property, when it defaults to full.",
+ // "enum": [
+ // "full",
+ // "noAcl"
+ // ],
+ // "enumDescriptions": [
+ // "Include all properties.",
+ // "Omit the owner, acl property."
+ // ],
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "rewriteToken": {
+ // "description": "Include this field (from the previous rewrite response) on each rewrite request after the first one, until the rewrite response 'done' flag is true. Calls that provide a rewriteToken can omit all other request fields, but if included those fields must match the values provided in the first rewrite request.",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "sourceBucket": {
+ // "description": "Name of the bucket in which to find the source object.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "sourceGeneration": {
+ // "description": "If present, selects a specific revision of the source object (as opposed to the latest version, the default).",
+ // "format": "int64",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "sourceObject": {
+ // "description": "Name of the source object. For information about how to URL encode object names to be path safe, see Encoding URI Path Parts.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "userProject": {
+ // "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ // "location": "query",
+ // "type": "string"
+ // }
+ // },
+ // "path": "b/{sourceBucket}/o/{sourceObject}/rewriteTo/b/{destinationBucket}/o/{destinationObject}",
+ // "request": {
+ // "$ref": "Object"
+ // },
+ // "response": {
+ // "$ref": "RewriteResponse"
+ // },
+ // "scopes": [
+ // "https://www.googleapis.com/auth/cloud-platform",
+ // "https://www.googleapis.com/auth/devstorage.full_control",
+ // "https://www.googleapis.com/auth/devstorage.read_write"
+ // ]
+ // }
+
+}
+
+// method id "storage.objects.setIamPolicy":
+
+type ObjectsSetIamPolicyCall struct {
+ s *Service
+ bucket string
+ object string
+ policy *Policy
+ urlParams_ gensupport.URLParams
+ ctx_ context.Context
+ header_ http.Header
+}
+
+// SetIamPolicy: Updates an IAM policy for the specified object.
+func (r *ObjectsService) SetIamPolicy(bucket string, object string, policy *Policy) *ObjectsSetIamPolicyCall {
+ c := &ObjectsSetIamPolicyCall{s: r.s, urlParams_: make(gensupport.URLParams)}
+ c.bucket = bucket
+ c.object = object
+ c.policy = policy
+ return c
+}
+
+// Generation sets the optional parameter "generation": If present,
+// selects a specific revision of this object (as opposed to the latest
+// version, the default).
+func (c *ObjectsSetIamPolicyCall) Generation(generation int64) *ObjectsSetIamPolicyCall {
+ c.urlParams_.Set("generation", fmt.Sprint(generation))
+ return c
+}
+
+// UserProject sets the optional parameter "userProject": The project to
+// be billed for this request. Required for Requester Pays buckets.
+func (c *ObjectsSetIamPolicyCall) UserProject(userProject string) *ObjectsSetIamPolicyCall {
+ c.urlParams_.Set("userProject", userProject)
+ return c
+}
+
+// Fields allows partial responses to be retrieved. See
+// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
+// for more information.
+func (c *ObjectsSetIamPolicyCall) Fields(s ...googleapi.Field) *ObjectsSetIamPolicyCall {
+ c.urlParams_.Set("fields", googleapi.CombineFields(s))
+ return c
+}
+
+// Context sets the context to be used in this call's Do method. Any
+// pending HTTP request will be aborted if the provided context is
+// canceled.
+func (c *ObjectsSetIamPolicyCall) Context(ctx context.Context) *ObjectsSetIamPolicyCall {
+ c.ctx_ = ctx
+ return c
+}
+
+// Header returns an http.Header that can be modified by the caller to
+// add HTTP headers to the request.
+func (c *ObjectsSetIamPolicyCall) Header() http.Header {
+ if c.header_ == nil {
+ c.header_ = make(http.Header)
+ }
+ return c.header_
+}
+
+func (c *ObjectsSetIamPolicyCall) doRequest(alt string) (*http.Response, error) {
+ reqHeaders := make(http.Header)
+ for k, v := range c.header_ {
+ reqHeaders[k] = v
+ }
+ reqHeaders.Set("User-Agent", c.s.userAgent())
+ var body io.Reader = nil
+ body, err := googleapi.WithoutDataWrapper.JSONReader(c.policy)
+ if err != nil {
+ return nil, err
+ }
+ reqHeaders.Set("Content-Type", "application/json")
+ c.urlParams_.Set("alt", alt)
+ c.urlParams_.Set("prettyPrint", "false")
+ urls := googleapi.ResolveRelative(c.s.BasePath, "b/{bucket}/o/{object}/iam")
+ urls += "?" + c.urlParams_.Encode()
+ req, err := http.NewRequest("PUT", urls, body)
+ if err != nil {
+ return nil, err
+ }
+ req.Header = reqHeaders
+ googleapi.Expand(req.URL, map[string]string{
+ "bucket": c.bucket,
+ "object": c.object,
+ })
+ return gensupport.SendRequest(c.ctx_, c.s.client, req)
+}
+
+// Do executes the "storage.objects.setIamPolicy" call.
+// Exactly one of *Policy or error will be non-nil. Any non-2xx status
+// code is an error. Response headers are in either
+// *Policy.ServerResponse.Header or (if a response was returned at all)
+// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to
+// check whether the returned error was because http.StatusNotModified
+// was returned.
+func (c *ObjectsSetIamPolicyCall) Do(opts ...googleapi.CallOption) (*Policy, error) {
+ gensupport.SetOptions(c.urlParams_, opts...)
+ res, err := c.doRequest("json")
+ if res != nil && res.StatusCode == http.StatusNotModified {
+ if res.Body != nil {
+ res.Body.Close()
+ }
+ return nil, &googleapi.Error{
+ Code: res.StatusCode,
+ Header: res.Header,
+ }
+ }
+ if err != nil {
+ return nil, err
+ }
+ defer googleapi.CloseBody(res)
+ if err := googleapi.CheckResponse(res); err != nil {
+ return nil, err
+ }
+ ret := &Policy{
+ ServerResponse: googleapi.ServerResponse{
+ Header: res.Header,
+ HTTPStatusCode: res.StatusCode,
+ },
+ }
+ target := &ret
+ if err := gensupport.DecodeResponse(target, res); err != nil {
+ return nil, err
+ }
+ return ret, nil
+ // {
+ // "description": "Updates an IAM policy for the specified object.",
+ // "httpMethod": "PUT",
+ // "id": "storage.objects.setIamPolicy",
+ // "parameterOrder": [
+ // "bucket",
+ // "object"
+ // ],
+ // "parameters": {
+ // "bucket": {
+ // "description": "Name of the bucket in which the object resides.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "generation": {
+ // "description": "If present, selects a specific revision of this object (as opposed to the latest version, the default).",
+ // "format": "int64",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "object": {
+ // "description": "Name of the object. For information about how to URL encode object names to be path safe, see Encoding URI Path Parts.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "userProject": {
+ // "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ // "location": "query",
+ // "type": "string"
+ // }
+ // },
+ // "path": "b/{bucket}/o/{object}/iam",
+ // "request": {
+ // "$ref": "Policy"
+ // },
+ // "response": {
+ // "$ref": "Policy"
+ // },
+ // "scopes": [
+ // "https://www.googleapis.com/auth/cloud-platform",
+ // "https://www.googleapis.com/auth/devstorage.full_control",
+ // "https://www.googleapis.com/auth/devstorage.read_write"
+ // ]
+ // }
+
+}
+
+// method id "storage.objects.testIamPermissions":
+
+type ObjectsTestIamPermissionsCall struct {
+ s *Service
+ bucket string
+ object string
+ urlParams_ gensupport.URLParams
+ ifNoneMatch_ string
+ ctx_ context.Context
+ header_ http.Header
+}
+
+// TestIamPermissions: Tests a set of permissions on the given object to
+// see which, if any, are held by the caller.
+func (r *ObjectsService) TestIamPermissions(bucket string, object string, permissions []string) *ObjectsTestIamPermissionsCall {
+ c := &ObjectsTestIamPermissionsCall{s: r.s, urlParams_: make(gensupport.URLParams)}
+ c.bucket = bucket
+ c.object = object
+ c.urlParams_.SetMulti("permissions", append([]string{}, permissions...))
+ return c
+}
+
+// Generation sets the optional parameter "generation": If present,
+// selects a specific revision of this object (as opposed to the latest
+// version, the default).
+func (c *ObjectsTestIamPermissionsCall) Generation(generation int64) *ObjectsTestIamPermissionsCall {
+ c.urlParams_.Set("generation", fmt.Sprint(generation))
+ return c
+}
+
+// UserProject sets the optional parameter "userProject": The project to
+// be billed for this request. Required for Requester Pays buckets.
+func (c *ObjectsTestIamPermissionsCall) UserProject(userProject string) *ObjectsTestIamPermissionsCall {
+ c.urlParams_.Set("userProject", userProject)
+ return c
+}
+
+// Fields allows partial responses to be retrieved. See
+// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
+// for more information.
+func (c *ObjectsTestIamPermissionsCall) Fields(s ...googleapi.Field) *ObjectsTestIamPermissionsCall {
+ c.urlParams_.Set("fields", googleapi.CombineFields(s))
+ return c
+}
+
+// IfNoneMatch sets the optional parameter which makes the operation
+// fail if the object's ETag matches the given value. This is useful for
+// getting updates only after the object has changed since the last
+// request. Use googleapi.IsNotModified to check whether the response
+// error from Do is the result of In-None-Match.
+func (c *ObjectsTestIamPermissionsCall) IfNoneMatch(entityTag string) *ObjectsTestIamPermissionsCall {
+ c.ifNoneMatch_ = entityTag
+ return c
+}
+
+// Context sets the context to be used in this call's Do method. Any
+// pending HTTP request will be aborted if the provided context is
+// canceled.
+func (c *ObjectsTestIamPermissionsCall) Context(ctx context.Context) *ObjectsTestIamPermissionsCall {
+ c.ctx_ = ctx
+ return c
+}
+
+// Header returns an http.Header that can be modified by the caller to
+// add HTTP headers to the request.
+func (c *ObjectsTestIamPermissionsCall) Header() http.Header {
+ if c.header_ == nil {
+ c.header_ = make(http.Header)
+ }
+ return c.header_
+}
+
+func (c *ObjectsTestIamPermissionsCall) doRequest(alt string) (*http.Response, error) {
+ reqHeaders := make(http.Header)
+ for k, v := range c.header_ {
+ reqHeaders[k] = v
+ }
+ reqHeaders.Set("User-Agent", c.s.userAgent())
+ if c.ifNoneMatch_ != "" {
+ reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
+ }
+ var body io.Reader = nil
+ c.urlParams_.Set("alt", alt)
+ c.urlParams_.Set("prettyPrint", "false")
+ urls := googleapi.ResolveRelative(c.s.BasePath, "b/{bucket}/o/{object}/iam/testPermissions")
+ urls += "?" + c.urlParams_.Encode()
+ req, err := http.NewRequest("GET", urls, body)
+ if err != nil {
+ return nil, err
+ }
+ req.Header = reqHeaders
+ googleapi.Expand(req.URL, map[string]string{
+ "bucket": c.bucket,
+ "object": c.object,
+ })
+ return gensupport.SendRequest(c.ctx_, c.s.client, req)
+}
+
+// Do executes the "storage.objects.testIamPermissions" call.
+// Exactly one of *TestIamPermissionsResponse or error will be non-nil.
+// Any non-2xx status code is an error. Response headers are in either
+// *TestIamPermissionsResponse.ServerResponse.Header or (if a response
+// was returned at all) in error.(*googleapi.Error).Header. Use
+// googleapi.IsNotModified to check whether the returned error was
+// because http.StatusNotModified was returned.
+func (c *ObjectsTestIamPermissionsCall) Do(opts ...googleapi.CallOption) (*TestIamPermissionsResponse, error) {
+ gensupport.SetOptions(c.urlParams_, opts...)
+ res, err := c.doRequest("json")
+ if res != nil && res.StatusCode == http.StatusNotModified {
+ if res.Body != nil {
+ res.Body.Close()
+ }
+ return nil, &googleapi.Error{
+ Code: res.StatusCode,
+ Header: res.Header,
+ }
+ }
+ if err != nil {
+ return nil, err
+ }
+ defer googleapi.CloseBody(res)
+ if err := googleapi.CheckResponse(res); err != nil {
+ return nil, err
+ }
+ ret := &TestIamPermissionsResponse{
+ ServerResponse: googleapi.ServerResponse{
+ Header: res.Header,
+ HTTPStatusCode: res.StatusCode,
+ },
+ }
+ target := &ret
+ if err := gensupport.DecodeResponse(target, res); err != nil {
+ return nil, err
+ }
+ return ret, nil
+ // {
+ // "description": "Tests a set of permissions on the given object to see which, if any, are held by the caller.",
+ // "httpMethod": "GET",
+ // "id": "storage.objects.testIamPermissions",
+ // "parameterOrder": [
+ // "bucket",
+ // "object",
+ // "permissions"
+ // ],
+ // "parameters": {
+ // "bucket": {
+ // "description": "Name of the bucket in which the object resides.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "generation": {
+ // "description": "If present, selects a specific revision of this object (as opposed to the latest version, the default).",
+ // "format": "int64",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "object": {
+ // "description": "Name of the object. For information about how to URL encode object names to be path safe, see Encoding URI Path Parts.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "permissions": {
+ // "description": "Permissions to test.",
+ // "location": "query",
+ // "repeated": true,
+ // "required": true,
+ // "type": "string"
+ // },
+ // "userProject": {
+ // "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ // "location": "query",
+ // "type": "string"
+ // }
+ // },
+ // "path": "b/{bucket}/o/{object}/iam/testPermissions",
+ // "response": {
+ // "$ref": "TestIamPermissionsResponse"
+ // },
+ // "scopes": [
+ // "https://www.googleapis.com/auth/cloud-platform",
+ // "https://www.googleapis.com/auth/cloud-platform.read-only",
+ // "https://www.googleapis.com/auth/devstorage.full_control",
+ // "https://www.googleapis.com/auth/devstorage.read_only",
+ // "https://www.googleapis.com/auth/devstorage.read_write"
+ // ]
+ // }
+
+}
+
+// method id "storage.objects.update":
+
+type ObjectsUpdateCall struct {
+ s *Service
+ bucket string
+ object string
+ object2 *Object
+ urlParams_ gensupport.URLParams
+ ctx_ context.Context
+ header_ http.Header
+}
+
+// Update: Updates an object's metadata.
+func (r *ObjectsService) Update(bucket string, object string, object2 *Object) *ObjectsUpdateCall {
+ c := &ObjectsUpdateCall{s: r.s, urlParams_: make(gensupport.URLParams)}
+ c.bucket = bucket
+ c.object = object
+ c.object2 = object2
+ return c
+}
+
+// Generation sets the optional parameter "generation": If present,
+// selects a specific revision of this object (as opposed to the latest
+// version, the default).
+func (c *ObjectsUpdateCall) Generation(generation int64) *ObjectsUpdateCall {
+ c.urlParams_.Set("generation", fmt.Sprint(generation))
+ return c
+}
+
+// IfGenerationMatch sets the optional parameter "ifGenerationMatch":
+// Makes the operation conditional on whether the object's current
+// generation matches the given value. Setting to 0 makes the operation
+// succeed only if there are no live versions of the object.
+func (c *ObjectsUpdateCall) IfGenerationMatch(ifGenerationMatch int64) *ObjectsUpdateCall {
+ c.urlParams_.Set("ifGenerationMatch", fmt.Sprint(ifGenerationMatch))
+ return c
+}
+
+// IfGenerationNotMatch sets the optional parameter
+// "ifGenerationNotMatch": Makes the operation conditional on whether
+// the object's current generation does not match the given value. If no
+// live object exists, the precondition fails. Setting to 0 makes the
+// operation succeed only if there is a live version of the object.
+func (c *ObjectsUpdateCall) IfGenerationNotMatch(ifGenerationNotMatch int64) *ObjectsUpdateCall {
+ c.urlParams_.Set("ifGenerationNotMatch", fmt.Sprint(ifGenerationNotMatch))
+ return c
+}
+
+// IfMetagenerationMatch sets the optional parameter
+// "ifMetagenerationMatch": Makes the operation conditional on whether
+// the object's current metageneration matches the given value.
+func (c *ObjectsUpdateCall) IfMetagenerationMatch(ifMetagenerationMatch int64) *ObjectsUpdateCall {
+ c.urlParams_.Set("ifMetagenerationMatch", fmt.Sprint(ifMetagenerationMatch))
+ return c
+}
+
+// IfMetagenerationNotMatch sets the optional parameter
+// "ifMetagenerationNotMatch": Makes the operation conditional on
+// whether the object's current metageneration does not match the given
+// value.
+func (c *ObjectsUpdateCall) IfMetagenerationNotMatch(ifMetagenerationNotMatch int64) *ObjectsUpdateCall {
+ c.urlParams_.Set("ifMetagenerationNotMatch", fmt.Sprint(ifMetagenerationNotMatch))
+ return c
+}
+
+// PredefinedAcl sets the optional parameter "predefinedAcl": Apply a
+// predefined set of access controls to this object.
+//
+// Possible values:
+// "authenticatedRead" - Object owner gets OWNER access, and
+// allAuthenticatedUsers get READER access.
+// "bucketOwnerFullControl" - Object owner gets OWNER access, and
+// project team owners get OWNER access.
+// "bucketOwnerRead" - Object owner gets OWNER access, and project
+// team owners get READER access.
+// "private" - Object owner gets OWNER access.
+// "projectPrivate" - Object owner gets OWNER access, and project team
+// members get access according to their roles.
+// "publicRead" - Object owner gets OWNER access, and allUsers get
+// READER access.
+func (c *ObjectsUpdateCall) PredefinedAcl(predefinedAcl string) *ObjectsUpdateCall {
+ c.urlParams_.Set("predefinedAcl", predefinedAcl)
+ return c
+}
+
+// Projection sets the optional parameter "projection": Set of
+// properties to return. Defaults to full.
+//
+// Possible values:
+// "full" - Include all properties.
+// "noAcl" - Omit the owner, acl property.
+func (c *ObjectsUpdateCall) Projection(projection string) *ObjectsUpdateCall {
+ c.urlParams_.Set("projection", projection)
+ return c
+}
+
+// UserProject sets the optional parameter "userProject": The project to
+// be billed for this request. Required for Requester Pays buckets.
+func (c *ObjectsUpdateCall) UserProject(userProject string) *ObjectsUpdateCall {
+ c.urlParams_.Set("userProject", userProject)
+ return c
+}
+
+// Fields allows partial responses to be retrieved. See
+// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
+// for more information.
+func (c *ObjectsUpdateCall) Fields(s ...googleapi.Field) *ObjectsUpdateCall {
+ c.urlParams_.Set("fields", googleapi.CombineFields(s))
+ return c
+}
+
+// Context sets the context to be used in this call's Do method. Any
+// pending HTTP request will be aborted if the provided context is
+// canceled.
+func (c *ObjectsUpdateCall) Context(ctx context.Context) *ObjectsUpdateCall {
+ c.ctx_ = ctx
+ return c
+}
+
+// Header returns an http.Header that can be modified by the caller to
+// add HTTP headers to the request.
+func (c *ObjectsUpdateCall) Header() http.Header {
+ if c.header_ == nil {
+ c.header_ = make(http.Header)
+ }
+ return c.header_
+}
+
+func (c *ObjectsUpdateCall) doRequest(alt string) (*http.Response, error) {
+ reqHeaders := make(http.Header)
+ for k, v := range c.header_ {
+ reqHeaders[k] = v
+ }
+ reqHeaders.Set("User-Agent", c.s.userAgent())
+ var body io.Reader = nil
+ body, err := googleapi.WithoutDataWrapper.JSONReader(c.object2)
+ if err != nil {
+ return nil, err
+ }
+ reqHeaders.Set("Content-Type", "application/json")
+ c.urlParams_.Set("alt", alt)
+ c.urlParams_.Set("prettyPrint", "false")
+ urls := googleapi.ResolveRelative(c.s.BasePath, "b/{bucket}/o/{object}")
+ urls += "?" + c.urlParams_.Encode()
+ req, err := http.NewRequest("PUT", urls, body)
+ if err != nil {
+ return nil, err
+ }
+ req.Header = reqHeaders
+ googleapi.Expand(req.URL, map[string]string{
+ "bucket": c.bucket,
+ "object": c.object,
+ })
+ return gensupport.SendRequest(c.ctx_, c.s.client, req)
+}
+
+// Do executes the "storage.objects.update" call.
+// Exactly one of *Object or error will be non-nil. Any non-2xx status
+// code is an error. Response headers are in either
+// *Object.ServerResponse.Header or (if a response was returned at all)
+// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to
+// check whether the returned error was because http.StatusNotModified
+// was returned.
+func (c *ObjectsUpdateCall) Do(opts ...googleapi.CallOption) (*Object, error) {
+ gensupport.SetOptions(c.urlParams_, opts...)
+ res, err := c.doRequest("json")
+ if res != nil && res.StatusCode == http.StatusNotModified {
+ if res.Body != nil {
+ res.Body.Close()
+ }
+ return nil, &googleapi.Error{
+ Code: res.StatusCode,
+ Header: res.Header,
+ }
+ }
+ if err != nil {
+ return nil, err
+ }
+ defer googleapi.CloseBody(res)
+ if err := googleapi.CheckResponse(res); err != nil {
+ return nil, err
+ }
+ ret := &Object{
+ ServerResponse: googleapi.ServerResponse{
+ Header: res.Header,
+ HTTPStatusCode: res.StatusCode,
+ },
+ }
+ target := &ret
+ if err := gensupport.DecodeResponse(target, res); err != nil {
+ return nil, err
+ }
+ return ret, nil
+ // {
+ // "description": "Updates an object's metadata.",
+ // "httpMethod": "PUT",
+ // "id": "storage.objects.update",
+ // "parameterOrder": [
+ // "bucket",
+ // "object"
+ // ],
+ // "parameters": {
+ // "bucket": {
+ // "description": "Name of the bucket in which the object resides.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "generation": {
+ // "description": "If present, selects a specific revision of this object (as opposed to the latest version, the default).",
+ // "format": "int64",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "ifGenerationMatch": {
+ // "description": "Makes the operation conditional on whether the object's current generation matches the given value. Setting to 0 makes the operation succeed only if there are no live versions of the object.",
+ // "format": "int64",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "ifGenerationNotMatch": {
+ // "description": "Makes the operation conditional on whether the object's current generation does not match the given value. If no live object exists, the precondition fails. Setting to 0 makes the operation succeed only if there is a live version of the object.",
+ // "format": "int64",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "ifMetagenerationMatch": {
+ // "description": "Makes the operation conditional on whether the object's current metageneration matches the given value.",
+ // "format": "int64",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "ifMetagenerationNotMatch": {
+ // "description": "Makes the operation conditional on whether the object's current metageneration does not match the given value.",
+ // "format": "int64",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "object": {
+ // "description": "Name of the object. For information about how to URL encode object names to be path safe, see Encoding URI Path Parts.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "predefinedAcl": {
+ // "description": "Apply a predefined set of access controls to this object.",
+ // "enum": [
+ // "authenticatedRead",
+ // "bucketOwnerFullControl",
+ // "bucketOwnerRead",
+ // "private",
+ // "projectPrivate",
+ // "publicRead"
+ // ],
+ // "enumDescriptions": [
+ // "Object owner gets OWNER access, and allAuthenticatedUsers get READER access.",
+ // "Object owner gets OWNER access, and project team owners get OWNER access.",
+ // "Object owner gets OWNER access, and project team owners get READER access.",
+ // "Object owner gets OWNER access.",
+ // "Object owner gets OWNER access, and project team members get access according to their roles.",
+ // "Object owner gets OWNER access, and allUsers get READER access."
+ // ],
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "projection": {
+ // "description": "Set of properties to return. Defaults to full.",
+ // "enum": [
+ // "full",
+ // "noAcl"
+ // ],
+ // "enumDescriptions": [
+ // "Include all properties.",
+ // "Omit the owner, acl property."
+ // ],
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "userProject": {
+ // "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ // "location": "query",
+ // "type": "string"
+ // }
+ // },
+ // "path": "b/{bucket}/o/{object}",
+ // "request": {
+ // "$ref": "Object"
+ // },
+ // "response": {
+ // "$ref": "Object"
+ // },
+ // "scopes": [
+ // "https://www.googleapis.com/auth/cloud-platform",
+ // "https://www.googleapis.com/auth/devstorage.full_control"
+ // ]
+ // }
+
+}
+
+// method id "storage.objects.watchAll":
+
+type ObjectsWatchAllCall struct {
+ s *Service
+ bucket string
+ channel *Channel
+ urlParams_ gensupport.URLParams
+ ctx_ context.Context
+ header_ http.Header
+}
+
+// WatchAll: Watch for changes on all objects in a bucket.
+func (r *ObjectsService) WatchAll(bucket string, channel *Channel) *ObjectsWatchAllCall {
+ c := &ObjectsWatchAllCall{s: r.s, urlParams_: make(gensupport.URLParams)}
+ c.bucket = bucket
+ c.channel = channel
+ return c
+}
+
+// Delimiter sets the optional parameter "delimiter": Returns results in
+// a directory-like mode. items will contain only objects whose names,
+// aside from the prefix, do not contain delimiter. Objects whose names,
+// aside from the prefix, contain delimiter will have their name,
+// truncated after the delimiter, returned in prefixes. Duplicate
+// prefixes are omitted.
+func (c *ObjectsWatchAllCall) Delimiter(delimiter string) *ObjectsWatchAllCall {
+ c.urlParams_.Set("delimiter", delimiter)
+ return c
+}
+
+// IncludeTrailingDelimiter sets the optional parameter
+// "includeTrailingDelimiter": If true, objects that end in exactly one
+// instance of delimiter will have their metadata included in items in
+// addition to prefixes.
+func (c *ObjectsWatchAllCall) IncludeTrailingDelimiter(includeTrailingDelimiter bool) *ObjectsWatchAllCall {
+ c.urlParams_.Set("includeTrailingDelimiter", fmt.Sprint(includeTrailingDelimiter))
+ return c
+}
+
+// MaxResults sets the optional parameter "maxResults": Maximum number
+// of items plus prefixes to return in a single page of responses. As
+// duplicate prefixes are omitted, fewer total results may be returned
+// than requested. The service will use this parameter or 1,000 items,
+// whichever is smaller.
+func (c *ObjectsWatchAllCall) MaxResults(maxResults int64) *ObjectsWatchAllCall {
+ c.urlParams_.Set("maxResults", fmt.Sprint(maxResults))
+ return c
+}
+
+// PageToken sets the optional parameter "pageToken": A
+// previously-returned page token representing part of the larger set of
+// results to view.
+func (c *ObjectsWatchAllCall) PageToken(pageToken string) *ObjectsWatchAllCall {
+ c.urlParams_.Set("pageToken", pageToken)
+ return c
+}
+
+// Prefix sets the optional parameter "prefix": Filter results to
+// objects whose names begin with this prefix.
+func (c *ObjectsWatchAllCall) Prefix(prefix string) *ObjectsWatchAllCall {
+ c.urlParams_.Set("prefix", prefix)
+ return c
+}
+
+// Projection sets the optional parameter "projection": Set of
+// properties to return. Defaults to noAcl.
+//
+// Possible values:
+// "full" - Include all properties.
+// "noAcl" - Omit the owner, acl property.
+func (c *ObjectsWatchAllCall) Projection(projection string) *ObjectsWatchAllCall {
+ c.urlParams_.Set("projection", projection)
+ return c
+}
+
+// UserProject sets the optional parameter "userProject": The project to
+// be billed for this request. Required for Requester Pays buckets.
+func (c *ObjectsWatchAllCall) UserProject(userProject string) *ObjectsWatchAllCall {
+ c.urlParams_.Set("userProject", userProject)
+ return c
+}
+
+// Versions sets the optional parameter "versions": If true, lists all
+// versions of an object as distinct results. The default is false. For
+// more information, see Object Versioning.
+func (c *ObjectsWatchAllCall) Versions(versions bool) *ObjectsWatchAllCall {
+ c.urlParams_.Set("versions", fmt.Sprint(versions))
+ return c
+}
+
+// Fields allows partial responses to be retrieved. See
+// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
+// for more information.
+func (c *ObjectsWatchAllCall) Fields(s ...googleapi.Field) *ObjectsWatchAllCall {
+ c.urlParams_.Set("fields", googleapi.CombineFields(s))
+ return c
+}
+
+// Context sets the context to be used in this call's Do method. Any
+// pending HTTP request will be aborted if the provided context is
+// canceled.
+func (c *ObjectsWatchAllCall) Context(ctx context.Context) *ObjectsWatchAllCall {
+ c.ctx_ = ctx
+ return c
+}
+
+// Header returns an http.Header that can be modified by the caller to
+// add HTTP headers to the request.
+func (c *ObjectsWatchAllCall) Header() http.Header {
+ if c.header_ == nil {
+ c.header_ = make(http.Header)
+ }
+ return c.header_
+}
+
+func (c *ObjectsWatchAllCall) doRequest(alt string) (*http.Response, error) {
+ reqHeaders := make(http.Header)
+ for k, v := range c.header_ {
+ reqHeaders[k] = v
+ }
+ reqHeaders.Set("User-Agent", c.s.userAgent())
+ var body io.Reader = nil
+ body, err := googleapi.WithoutDataWrapper.JSONReader(c.channel)
+ if err != nil {
+ return nil, err
+ }
+ reqHeaders.Set("Content-Type", "application/json")
+ c.urlParams_.Set("alt", alt)
+ c.urlParams_.Set("prettyPrint", "false")
+ urls := googleapi.ResolveRelative(c.s.BasePath, "b/{bucket}/o/watch")
+ urls += "?" + c.urlParams_.Encode()
+ req, err := http.NewRequest("POST", urls, body)
+ if err != nil {
+ return nil, err
+ }
+ req.Header = reqHeaders
+ googleapi.Expand(req.URL, map[string]string{
+ "bucket": c.bucket,
+ })
+ return gensupport.SendRequest(c.ctx_, c.s.client, req)
+}
+
+// Do executes the "storage.objects.watchAll" call.
+// Exactly one of *Channel or error will be non-nil. Any non-2xx status
+// code is an error. Response headers are in either
+// *Channel.ServerResponse.Header or (if a response was returned at all)
+// in error.(*googleapi.Error).Header. Use googleapi.IsNotModified to
+// check whether the returned error was because http.StatusNotModified
+// was returned.
+func (c *ObjectsWatchAllCall) Do(opts ...googleapi.CallOption) (*Channel, error) {
+ gensupport.SetOptions(c.urlParams_, opts...)
+ res, err := c.doRequest("json")
+ if res != nil && res.StatusCode == http.StatusNotModified {
+ if res.Body != nil {
+ res.Body.Close()
+ }
+ return nil, &googleapi.Error{
+ Code: res.StatusCode,
+ Header: res.Header,
+ }
+ }
+ if err != nil {
+ return nil, err
+ }
+ defer googleapi.CloseBody(res)
+ if err := googleapi.CheckResponse(res); err != nil {
+ return nil, err
+ }
+ ret := &Channel{
+ ServerResponse: googleapi.ServerResponse{
+ Header: res.Header,
+ HTTPStatusCode: res.StatusCode,
+ },
+ }
+ target := &ret
+ if err := gensupport.DecodeResponse(target, res); err != nil {
+ return nil, err
+ }
+ return ret, nil
+ // {
+ // "description": "Watch for changes on all objects in a bucket.",
+ // "httpMethod": "POST",
+ // "id": "storage.objects.watchAll",
+ // "parameterOrder": [
+ // "bucket"
+ // ],
+ // "parameters": {
+ // "bucket": {
+ // "description": "Name of the bucket in which to look for objects.",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "delimiter": {
+ // "description": "Returns results in a directory-like mode. items will contain only objects whose names, aside from the prefix, do not contain delimiter. Objects whose names, aside from the prefix, contain delimiter will have their name, truncated after the delimiter, returned in prefixes. Duplicate prefixes are omitted.",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "includeTrailingDelimiter": {
+ // "description": "If true, objects that end in exactly one instance of delimiter will have their metadata included in items in addition to prefixes.",
+ // "location": "query",
+ // "type": "boolean"
+ // },
+ // "maxResults": {
+ // "default": "1000",
+ // "description": "Maximum number of items plus prefixes to return in a single page of responses. As duplicate prefixes are omitted, fewer total results may be returned than requested. The service will use this parameter or 1,000 items, whichever is smaller.",
+ // "format": "uint32",
+ // "location": "query",
+ // "minimum": "0",
+ // "type": "integer"
+ // },
+ // "pageToken": {
+ // "description": "A previously-returned page token representing part of the larger set of results to view.",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "prefix": {
+ // "description": "Filter results to objects whose names begin with this prefix.",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "projection": {
+ // "description": "Set of properties to return. Defaults to noAcl.",
+ // "enum": [
+ // "full",
+ // "noAcl"
+ // ],
+ // "enumDescriptions": [
+ // "Include all properties.",
+ // "Omit the owner, acl property."
+ // ],
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "userProject": {
+ // "description": "The project to be billed for this request. Required for Requester Pays buckets.",
+ // "location": "query",
+ // "type": "string"
+ // },
+ // "versions": {
+ // "description": "If true, lists all versions of an object as distinct results. The default is false. For more information, see Object Versioning.",
+ // "location": "query",
+ // "type": "boolean"
+ // }
+ // },
+ // "path": "b/{bucket}/o/watch",
+ // "request": {
+ // "$ref": "Channel",
+ // "parameterName": "resource"
+ // },
+ // "response": {
+ // "$ref": "Channel"
+ // },
+ // "scopes": [
+ // "https://www.googleapis.com/auth/cloud-platform",
+ // "https://www.googleapis.com/auth/cloud-platform.read-only",
+ // "https://www.googleapis.com/auth/devstorage.full_control",
+ // "https://www.googleapis.com/auth/devstorage.read_only",
+ // "https://www.googleapis.com/auth/devstorage.read_write"
+ // ],
+ // "supportsSubscription": true
+ // }
+
+}
+
+// method id "storage.projects.serviceAccount.get":
+
+type ProjectsServiceAccountGetCall struct {
+ s *Service
+ projectId string
+ urlParams_ gensupport.URLParams
+ ifNoneMatch_ string
+ ctx_ context.Context
+ header_ http.Header
+}
+
+// Get: Get the email address of this project's Google Cloud Storage
+// service account.
+func (r *ProjectsServiceAccountService) Get(projectId string) *ProjectsServiceAccountGetCall {
+ c := &ProjectsServiceAccountGetCall{s: r.s, urlParams_: make(gensupport.URLParams)}
+ c.projectId = projectId
+ return c
+}
+
+// UserProject sets the optional parameter "userProject": The project to
+// be billed for this request.
+func (c *ProjectsServiceAccountGetCall) UserProject(userProject string) *ProjectsServiceAccountGetCall {
+ c.urlParams_.Set("userProject", userProject)
+ return c
+}
+
+// Fields allows partial responses to be retrieved. See
+// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse
+// for more information.
+func (c *ProjectsServiceAccountGetCall) Fields(s ...googleapi.Field) *ProjectsServiceAccountGetCall {
+ c.urlParams_.Set("fields", googleapi.CombineFields(s))
+ return c
+}
+
+// IfNoneMatch sets the optional parameter which makes the operation
+// fail if the object's ETag matches the given value. This is useful for
+// getting updates only after the object has changed since the last
+// request. Use googleapi.IsNotModified to check whether the response
+// error from Do is the result of In-None-Match.
+func (c *ProjectsServiceAccountGetCall) IfNoneMatch(entityTag string) *ProjectsServiceAccountGetCall {
+ c.ifNoneMatch_ = entityTag
+ return c
+}
+
+// Context sets the context to be used in this call's Do method. Any
+// pending HTTP request will be aborted if the provided context is
+// canceled.
+func (c *ProjectsServiceAccountGetCall) Context(ctx context.Context) *ProjectsServiceAccountGetCall {
+ c.ctx_ = ctx
+ return c
+}
+
+// Header returns an http.Header that can be modified by the caller to
+// add HTTP headers to the request.
+func (c *ProjectsServiceAccountGetCall) Header() http.Header {
+ if c.header_ == nil {
+ c.header_ = make(http.Header)
+ }
+ return c.header_
+}
+
+func (c *ProjectsServiceAccountGetCall) doRequest(alt string) (*http.Response, error) {
+ reqHeaders := make(http.Header)
+ for k, v := range c.header_ {
+ reqHeaders[k] = v
+ }
+ reqHeaders.Set("User-Agent", c.s.userAgent())
+ if c.ifNoneMatch_ != "" {
+ reqHeaders.Set("If-None-Match", c.ifNoneMatch_)
+ }
+ var body io.Reader = nil
+ c.urlParams_.Set("alt", alt)
+ c.urlParams_.Set("prettyPrint", "false")
+ urls := googleapi.ResolveRelative(c.s.BasePath, "projects/{projectId}/serviceAccount")
+ urls += "?" + c.urlParams_.Encode()
+ req, err := http.NewRequest("GET", urls, body)
+ if err != nil {
+ return nil, err
+ }
+ req.Header = reqHeaders
+ googleapi.Expand(req.URL, map[string]string{
+ "projectId": c.projectId,
+ })
+ return gensupport.SendRequest(c.ctx_, c.s.client, req)
+}
+
+// Do executes the "storage.projects.serviceAccount.get" call.
+// Exactly one of *ServiceAccount or error will be non-nil. Any non-2xx
+// status code is an error. Response headers are in either
+// *ServiceAccount.ServerResponse.Header or (if a response was returned
+// at all) in error.(*googleapi.Error).Header. Use
+// googleapi.IsNotModified to check whether the returned error was
+// because http.StatusNotModified was returned.
+func (c *ProjectsServiceAccountGetCall) Do(opts ...googleapi.CallOption) (*ServiceAccount, error) {
+ gensupport.SetOptions(c.urlParams_, opts...)
+ res, err := c.doRequest("json")
+ if res != nil && res.StatusCode == http.StatusNotModified {
+ if res.Body != nil {
+ res.Body.Close()
+ }
+ return nil, &googleapi.Error{
+ Code: res.StatusCode,
+ Header: res.Header,
+ }
+ }
+ if err != nil {
+ return nil, err
+ }
+ defer googleapi.CloseBody(res)
+ if err := googleapi.CheckResponse(res); err != nil {
+ return nil, err
+ }
+ ret := &ServiceAccount{
+ ServerResponse: googleapi.ServerResponse{
+ Header: res.Header,
+ HTTPStatusCode: res.StatusCode,
+ },
+ }
+ target := &ret
+ if err := gensupport.DecodeResponse(target, res); err != nil {
+ return nil, err
+ }
+ return ret, nil
+ // {
+ // "description": "Get the email address of this project's Google Cloud Storage service account.",
+ // "httpMethod": "GET",
+ // "id": "storage.projects.serviceAccount.get",
+ // "parameterOrder": [
+ // "projectId"
+ // ],
+ // "parameters": {
+ // "projectId": {
+ // "description": "Project ID",
+ // "location": "path",
+ // "required": true,
+ // "type": "string"
+ // },
+ // "userProject": {
+ // "description": "The project to be billed for this request.",
+ // "location": "query",
+ // "type": "string"
+ // }
+ // },
+ // "path": "projects/{projectId}/serviceAccount",
+ // "response": {
+ // "$ref": "ServiceAccount"
+ // },
+ // "scopes": [
+ // "https://www.googleapis.com/auth/cloud-platform",
+ // "https://www.googleapis.com/auth/cloud-platform.read-only",
+ // "https://www.googleapis.com/auth/devstorage.full_control",
+ // "https://www.googleapis.com/auth/devstorage.read_only",
+ // "https://www.googleapis.com/auth/devstorage.read_write"
+ // ]
+ // }
+
+}
diff --git a/vendor/google.golang.org/api/transport/http/dial.go b/vendor/google.golang.org/api/transport/http/dial.go
new file mode 100644
index 000000000..a25da6741
--- /dev/null
+++ b/vendor/google.golang.org/api/transport/http/dial.go
@@ -0,0 +1,147 @@
+// Copyright 2015 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package http supports network connections to HTTP servers.
+// This package is not intended for use by end developers. Use the
+// google.golang.org/api/option package to configure API clients.
+package http
+
+import (
+ "context"
+ "errors"
+ "net/http"
+
+ "go.opencensus.io/plugin/ochttp"
+ "golang.org/x/oauth2"
+ "google.golang.org/api/googleapi/transport"
+ "google.golang.org/api/internal"
+ "google.golang.org/api/option"
+ "google.golang.org/api/transport/http/internal/propagation"
+)
+
+// NewClient returns an HTTP client for use communicating with a Google cloud
+// service, configured with the given ClientOptions. It also returns the endpoint
+// for the service as specified in the options.
+func NewClient(ctx context.Context, opts ...option.ClientOption) (*http.Client, string, error) {
+ settings, err := newSettings(opts)
+ if err != nil {
+ return nil, "", err
+ }
+ // TODO(cbro): consider injecting the User-Agent even if an explicit HTTP client is provided?
+ if settings.HTTPClient != nil {
+ return settings.HTTPClient, settings.Endpoint, nil
+ }
+ trans, err := newTransport(ctx, defaultBaseTransport(ctx), settings)
+ if err != nil {
+ return nil, "", err
+ }
+ return &http.Client{Transport: trans}, settings.Endpoint, nil
+}
+
+// NewTransport creates an http.RoundTripper for use communicating with a Google
+// cloud service, configured with the given ClientOptions. Its RoundTrip method delegates to base.
+func NewTransport(ctx context.Context, base http.RoundTripper, opts ...option.ClientOption) (http.RoundTripper, error) {
+ settings, err := newSettings(opts)
+ if err != nil {
+ return nil, err
+ }
+ if settings.HTTPClient != nil {
+ return nil, errors.New("transport/http: WithHTTPClient passed to NewTransport")
+ }
+ return newTransport(ctx, base, settings)
+}
+
+func newTransport(ctx context.Context, base http.RoundTripper, settings *internal.DialSettings) (http.RoundTripper, error) {
+ trans := base
+ trans = userAgentTransport{
+ base: trans,
+ userAgent: settings.UserAgent,
+ }
+ trans = addOCTransport(trans)
+ switch {
+ case settings.NoAuth:
+ // Do nothing.
+ case settings.APIKey != "":
+ trans = &transport.APIKey{
+ Transport: trans,
+ Key: settings.APIKey,
+ }
+ default:
+ creds, err := internal.Creds(ctx, settings)
+ if err != nil {
+ return nil, err
+ }
+ trans = &oauth2.Transport{
+ Base: trans,
+ Source: creds.TokenSource,
+ }
+ }
+ return trans, nil
+}
+
+func newSettings(opts []option.ClientOption) (*internal.DialSettings, error) {
+ var o internal.DialSettings
+ for _, opt := range opts {
+ opt.Apply(&o)
+ }
+ if err := o.Validate(); err != nil {
+ return nil, err
+ }
+ if o.GRPCConn != nil {
+ return nil, errors.New("unsupported gRPC connection specified")
+ }
+ return &o, nil
+}
+
+type userAgentTransport struct {
+ userAgent string
+ base http.RoundTripper
+}
+
+func (t userAgentTransport) RoundTrip(req *http.Request) (*http.Response, error) {
+ rt := t.base
+ if rt == nil {
+ return nil, errors.New("transport: no Transport specified")
+ }
+ if t.userAgent == "" {
+ return rt.RoundTrip(req)
+ }
+ newReq := *req
+ newReq.Header = make(http.Header)
+ for k, vv := range req.Header {
+ newReq.Header[k] = vv
+ }
+ // TODO(cbro): append to existing User-Agent header?
+ newReq.Header["User-Agent"] = []string{t.userAgent}
+ return rt.RoundTrip(&newReq)
+}
+
+// Set at init time by dial_appengine.go. If nil, we're not on App Engine.
+var appengineUrlfetchHook func(context.Context) http.RoundTripper
+
+// defaultBaseTransport returns the base HTTP transport.
+// On App Engine, this is urlfetch.Transport, otherwise it's http.DefaultTransport.
+func defaultBaseTransport(ctx context.Context) http.RoundTripper {
+ if appengineUrlfetchHook != nil {
+ return appengineUrlfetchHook(ctx)
+ }
+ return http.DefaultTransport
+}
+
+func addOCTransport(trans http.RoundTripper) http.RoundTripper {
+ return &ochttp.Transport{
+ Base: trans,
+ Propagation: &propagation.HTTPFormat{},
+ }
+}
diff --git a/vendor/google.golang.org/api/transport/http/dial_appengine.go b/vendor/google.golang.org/api/transport/http/dial_appengine.go
new file mode 100644
index 000000000..04c81413c
--- /dev/null
+++ b/vendor/google.golang.org/api/transport/http/dial_appengine.go
@@ -0,0 +1,30 @@
+// Copyright 2016 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// +build appengine
+
+package http
+
+import (
+ "context"
+ "net/http"
+
+ "google.golang.org/appengine/urlfetch"
+)
+
+func init() {
+ appengineUrlfetchHook = func(ctx context.Context) http.RoundTripper {
+ return &urlfetch.Transport{Context: ctx}
+ }
+}
diff --git a/vendor/google.golang.org/api/transport/http/internal/propagation/http.go b/vendor/google.golang.org/api/transport/http/internal/propagation/http.go
new file mode 100644
index 000000000..24b4f0d29
--- /dev/null
+++ b/vendor/google.golang.org/api/transport/http/internal/propagation/http.go
@@ -0,0 +1,96 @@
+// Copyright 2018 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// +build go1.8
+
+// Package propagation implements X-Cloud-Trace-Context header propagation used
+// by Google Cloud products.
+package propagation
+
+import (
+ "encoding/binary"
+ "encoding/hex"
+ "fmt"
+ "net/http"
+ "strconv"
+ "strings"
+
+ "go.opencensus.io/trace"
+ "go.opencensus.io/trace/propagation"
+)
+
+const (
+ httpHeaderMaxSize = 200
+ httpHeader = `X-Cloud-Trace-Context`
+)
+
+var _ propagation.HTTPFormat = (*HTTPFormat)(nil)
+
+// HTTPFormat implements propagation.HTTPFormat to propagate
+// traces in HTTP headers for Google Cloud Platform and Stackdriver Trace.
+type HTTPFormat struct{}
+
+// SpanContextFromRequest extracts a Stackdriver Trace span context from incoming requests.
+func (f *HTTPFormat) SpanContextFromRequest(req *http.Request) (sc trace.SpanContext, ok bool) {
+ h := req.Header.Get(httpHeader)
+ // See https://cloud.google.com/trace/docs/faq for the header HTTPFormat.
+ // Return if the header is empty or missing, or if the header is unreasonably
+ // large, to avoid making unnecessary copies of a large string.
+ if h == "" || len(h) > httpHeaderMaxSize {
+ return trace.SpanContext{}, false
+ }
+
+ // Parse the trace id field.
+ slash := strings.Index(h, `/`)
+ if slash == -1 {
+ return trace.SpanContext{}, false
+ }
+ tid, h := h[:slash], h[slash+1:]
+
+ buf, err := hex.DecodeString(tid)
+ if err != nil {
+ return trace.SpanContext{}, false
+ }
+ copy(sc.TraceID[:], buf)
+
+ // Parse the span id field.
+ spanstr := h
+ semicolon := strings.Index(h, `;`)
+ if semicolon != -1 {
+ spanstr, h = h[:semicolon], h[semicolon+1:]
+ }
+ sid, err := strconv.ParseUint(spanstr, 10, 64)
+ if err != nil {
+ return trace.SpanContext{}, false
+ }
+ binary.BigEndian.PutUint64(sc.SpanID[:], sid)
+
+ // Parse the options field, options field is optional.
+ if !strings.HasPrefix(h, "o=") {
+ return sc, true
+ }
+ o, err := strconv.ParseUint(h[2:], 10, 64)
+ if err != nil {
+ return trace.SpanContext{}, false
+ }
+ sc.TraceOptions = trace.TraceOptions(o)
+ return sc, true
+}
+
+// SpanContextToRequest modifies the given request to include a Stackdriver Trace header.
+func (f *HTTPFormat) SpanContextToRequest(sc trace.SpanContext, req *http.Request) {
+ sid := binary.BigEndian.Uint64(sc.SpanID[:])
+ header := fmt.Sprintf("%s/%d;o=%d", hex.EncodeToString(sc.TraceID[:]), sid, int64(sc.TraceOptions))
+ req.Header.Set(httpHeader, header)
+}
diff --git a/vendor/google.golang.org/appengine/CONTRIBUTING.md b/vendor/google.golang.org/appengine/CONTRIBUTING.md
new file mode 100644
index 000000000..ffc298520
--- /dev/null
+++ b/vendor/google.golang.org/appengine/CONTRIBUTING.md
@@ -0,0 +1,90 @@
+# Contributing
+
+1. Sign one of the contributor license agreements below.
+1. Get the package:
+
+ `go get -d google.golang.org/appengine`
+1. Change into the checked out source:
+
+ `cd $GOPATH/src/google.golang.org/appengine`
+1. Fork the repo.
+1. Set your fork as a remote:
+
+ `git remote add fork git@github.com:GITHUB_USERNAME/appengine.git`
+1. Make changes, commit to your fork.
+1. Send a pull request with your changes.
+ The first line of your commit message is conventionally a one-line summary of the change, prefixed by the primary affected package, and is used as the title of your pull request.
+
+# Testing
+
+## Running system tests
+
+Download and install the [Go App Engine SDK](https://cloud.google.com/appengine/docs/go/download). Make sure the `go_appengine` dir is in your `PATH`.
+
+Set the `APPENGINE_DEV_APPSERVER` environment variable to `/path/to/go_appengine/dev_appserver.py`.
+
+Run tests with `goapp test`:
+
+```
+goapp test -v google.golang.org/appengine/...
+```
+
+## Contributor License Agreements
+
+Before we can accept your pull requests you'll need to sign a Contributor
+License Agreement (CLA):
+
+- **If you are an individual writing original source code** and **you own the
+intellectual property**, then you'll need to sign an [individual CLA][indvcla].
+- **If you work for a company that wants to allow you to contribute your work**,
+then you'll need to sign a [corporate CLA][corpcla].
+
+You can sign these electronically (just scroll to the bottom). After that,
+we'll be able to accept your pull requests.
+
+## Contributor Code of Conduct
+
+As contributors and maintainers of this project,
+and in the interest of fostering an open and welcoming community,
+we pledge to respect all people who contribute through reporting issues,
+posting feature requests, updating documentation,
+submitting pull requests or patches, and other activities.
+
+We are committed to making participation in this project
+a harassment-free experience for everyone,
+regardless of level of experience, gender, gender identity and expression,
+sexual orientation, disability, personal appearance,
+body size, race, ethnicity, age, religion, or nationality.
+
+Examples of unacceptable behavior by participants include:
+
+* The use of sexualized language or imagery
+* Personal attacks
+* Trolling or insulting/derogatory comments
+* Public or private harassment
+* Publishing other's private information,
+such as physical or electronic
+addresses, without explicit permission
+* Other unethical or unprofessional conduct.
+
+Project maintainers have the right and responsibility to remove, edit, or reject
+comments, commits, code, wiki edits, issues, and other contributions
+that are not aligned to this Code of Conduct.
+By adopting this Code of Conduct,
+project maintainers commit themselves to fairly and consistently
+applying these principles to every aspect of managing this project.
+Project maintainers who do not follow or enforce the Code of Conduct
+may be permanently removed from the project team.
+
+This code of conduct applies both within project spaces and in public spaces
+when an individual is representing the project or its community.
+
+Instances of abusive, harassing, or otherwise unacceptable behavior
+may be reported by opening an issue
+or contacting one or more of the project maintainers.
+
+This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.2.0,
+available at [http://contributor-covenant.org/version/1/2/0/](http://contributor-covenant.org/version/1/2/0/)
+
+[indvcla]: https://developers.google.com/open-source/cla/individual
+[corpcla]: https://developers.google.com/open-source/cla/corporate
diff --git a/vendor/google.golang.org/appengine/LICENSE b/vendor/google.golang.org/appengine/LICENSE
new file mode 100644
index 000000000..d64569567
--- /dev/null
+++ b/vendor/google.golang.org/appengine/LICENSE
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/vendor/google.golang.org/appengine/README.md b/vendor/google.golang.org/appengine/README.md
new file mode 100644
index 000000000..d86768a2c
--- /dev/null
+++ b/vendor/google.golang.org/appengine/README.md
@@ -0,0 +1,73 @@
+# Go App Engine packages
+
+[![Build Status](https://travis-ci.org/golang/appengine.svg)](https://travis-ci.org/golang/appengine)
+
+This repository supports the Go runtime on *App Engine standard*.
+It provides APIs for interacting with App Engine services.
+Its canonical import path is `google.golang.org/appengine`.
+
+See https://cloud.google.com/appengine/docs/go/
+for more information.
+
+File issue reports and feature requests on the [GitHub's issue
+tracker](https://github.com/golang/appengine/issues).
+
+## Upgrading an App Engine app to the flexible environment
+
+This package does not work on *App Engine flexible*.
+
+There are many differences between the App Engine standard environment and
+the flexible environment.
+
+See the [documentation on upgrading to the flexible environment](https://cloud.google.com/appengine/docs/flexible/go/upgrading).
+
+## Directory structure
+
+The top level directory of this repository is the `appengine` package. It
+contains the
+basic APIs (e.g. `appengine.NewContext`) that apply across APIs. Specific API
+packages are in subdirectories (e.g. `datastore`).
+
+There is an `internal` subdirectory that contains service protocol buffers,
+plus packages required for connectivity to make API calls. App Engine apps
+should not directly import any package under `internal`.
+
+## Updating from legacy (`import "appengine"`) packages
+
+If you're currently using the bare `appengine` packages
+(that is, not these ones, imported via `google.golang.org/appengine`),
+then you can use the `aefix` tool to help automate an upgrade to these packages.
+
+Run `go get google.golang.org/appengine/cmd/aefix` to install it.
+
+### 1. Update import paths
+
+The import paths for App Engine packages are now fully qualified, based at `google.golang.org/appengine`.
+You will need to update your code to use import paths starting with that; for instance,
+code importing `appengine/datastore` will now need to import `google.golang.org/appengine/datastore`.
+
+### 2. Update code using deprecated, removed or modified APIs
+
+Most App Engine services are available with exactly the same API.
+A few APIs were cleaned up, and there are some differences:
+
+* `appengine.Context` has been replaced with the `Context` type from `golang.org/x/net/context`.
+* Logging methods that were on `appengine.Context` are now functions in `google.golang.org/appengine/log`.
+* `appengine.Timeout` has been removed. Use `context.WithTimeout` instead.
+* `appengine.Datacenter` now takes a `context.Context` argument.
+* `datastore.PropertyLoadSaver` has been simplified to use slices in place of channels.
+* `delay.Call` now returns an error.
+* `search.FieldLoadSaver` now handles document metadata.
+* `urlfetch.Transport` no longer has a Deadline field; set a deadline on the
+ `context.Context` instead.
+* `aetest` no longer declares its own Context type, and uses the standard one instead.
+* `taskqueue.QueueStats` no longer takes a maxTasks argument. That argument has been
+ deprecated and unused for a long time.
+* `appengine.BackendHostname` and `appengine.BackendInstance` were for the deprecated backends feature.
+ Use `appengine.ModuleHostname`and `appengine.ModuleName` instead.
+* Most of `appengine/file` and parts of `appengine/blobstore` are deprecated.
+ Use [Google Cloud Storage](https://godoc.org/cloud.google.com/go/storage) if the
+ feature you require is not present in the new
+ [blobstore package](https://google.golang.org/appengine/blobstore).
+* `appengine/socket` is not required on App Engine flexible environment / Managed VMs.
+ Use the standard `net` package instead.
diff --git a/vendor/google.golang.org/appengine/appengine.go b/vendor/google.golang.org/appengine/appengine.go
new file mode 100644
index 000000000..0cca033d3
--- /dev/null
+++ b/vendor/google.golang.org/appengine/appengine.go
@@ -0,0 +1,137 @@
+// Copyright 2011 Google Inc. All rights reserved.
+// Use of this source code is governed by the Apache 2.0
+// license that can be found in the LICENSE file.
+
+// Package appengine provides basic functionality for Google App Engine.
+//
+// For more information on how to write Go apps for Google App Engine, see:
+// https://cloud.google.com/appengine/docs/go/
+package appengine // import "google.golang.org/appengine"
+
+import (
+ "net/http"
+
+ "github.com/golang/protobuf/proto"
+ "golang.org/x/net/context"
+
+ "google.golang.org/appengine/internal"
+)
+
+// The gophers party all night; the rabbits provide the beats.
+
+// Main is the principal entry point for an app running in App Engine.
+//
+// On App Engine Flexible it installs a trivial health checker if one isn't
+// already registered, and starts listening on port 8080 (overridden by the
+// $PORT environment variable).
+//
+// See https://cloud.google.com/appengine/docs/flexible/custom-runtimes#health_check_requests
+// for details on how to do your own health checking.
+//
+// On App Engine Standard it ensures the server has started and is prepared to
+// receive requests.
+//
+// Main never returns.
+//
+// Main is designed so that the app's main package looks like this:
+//
+// package main
+//
+// import (
+// "google.golang.org/appengine"
+//
+// _ "myapp/package0"
+// _ "myapp/package1"
+// )
+//
+// func main() {
+// appengine.Main()
+// }
+//
+// The "myapp/packageX" packages are expected to register HTTP handlers
+// in their init functions.
+func Main() {
+ internal.Main()
+}
+
+// IsDevAppServer reports whether the App Engine app is running in the
+// development App Server.
+func IsDevAppServer() bool {
+ return internal.IsDevAppServer()
+}
+
+// IsStandard reports whether the App Engine app is running in the standard
+// environment. This includes both the first generation runtimes (<= Go 1.9)
+// and the second generation runtimes (>= Go 1.11).
+func IsStandard() bool {
+ return internal.IsStandard()
+}
+
+// IsFlex reports whether the App Engine app is running in the flexible environment.
+func IsFlex() bool {
+ return internal.IsFlex()
+}
+
+// IsAppEngine reports whether the App Engine app is running on App Engine, in either
+// the standard or flexible environment.
+func IsAppEngine() bool {
+ return internal.IsAppEngine()
+}
+
+// IsSecondGen reports whether the App Engine app is running on the second generation
+// runtimes (>= Go 1.11).
+func IsSecondGen() bool {
+ return internal.IsSecondGen()
+}
+
+// NewContext returns a context for an in-flight HTTP request.
+// This function is cheap.
+func NewContext(req *http.Request) context.Context {
+ return internal.ReqContext(req)
+}
+
+// WithContext returns a copy of the parent context
+// and associates it with an in-flight HTTP request.
+// This function is cheap.
+func WithContext(parent context.Context, req *http.Request) context.Context {
+ return internal.WithContext(parent, req)
+}
+
+// TODO(dsymonds): Add a Call function here? Otherwise other packages can't access internal.Call.
+
+// BlobKey is a key for a blobstore blob.
+//
+// Conceptually, this type belongs in the blobstore package, but it lives in
+// the appengine package to avoid a circular dependency: blobstore depends on
+// datastore, and datastore needs to refer to the BlobKey type.
+type BlobKey string
+
+// GeoPoint represents a location as latitude/longitude in degrees.
+type GeoPoint struct {
+ Lat, Lng float64
+}
+
+// Valid returns whether a GeoPoint is within [-90, 90] latitude and [-180, 180] longitude.
+func (g GeoPoint) Valid() bool {
+ return -90 <= g.Lat && g.Lat <= 90 && -180 <= g.Lng && g.Lng <= 180
+}
+
+// APICallFunc defines a function type for handling an API call.
+// See WithCallOverride.
+type APICallFunc func(ctx context.Context, service, method string, in, out proto.Message) error
+
+// WithAPICallFunc returns a copy of the parent context
+// that will cause API calls to invoke f instead of their normal operation.
+//
+// This is intended for advanced users only.
+func WithAPICallFunc(ctx context.Context, f APICallFunc) context.Context {
+ return internal.WithCallOverride(ctx, internal.CallOverrideFunc(f))
+}
+
+// APICall performs an API call.
+//
+// This is not intended for general use; it is exported for use in conjunction
+// with WithAPICallFunc.
+func APICall(ctx context.Context, service, method string, in, out proto.Message) error {
+ return internal.Call(ctx, service, method, in, out)
+}
diff --git a/vendor/google.golang.org/appengine/appengine_vm.go b/vendor/google.golang.org/appengine/appengine_vm.go
new file mode 100644
index 000000000..f4b645aad
--- /dev/null
+++ b/vendor/google.golang.org/appengine/appengine_vm.go
@@ -0,0 +1,20 @@
+// Copyright 2015 Google Inc. All rights reserved.
+// Use of this source code is governed by the Apache 2.0
+// license that can be found in the LICENSE file.
+
+// +build !appengine
+
+package appengine
+
+import (
+ "golang.org/x/net/context"
+
+ "google.golang.org/appengine/internal"
+)
+
+// BackgroundContext returns a context not associated with a request.
+// This should only be used when not servicing a request.
+// This only works in App Engine "flexible environment".
+func BackgroundContext() context.Context {
+ return internal.BackgroundContext()
+}
diff --git a/vendor/google.golang.org/appengine/errors.go b/vendor/google.golang.org/appengine/errors.go
new file mode 100644
index 000000000..16d0772e2
--- /dev/null
+++ b/vendor/google.golang.org/appengine/errors.go
@@ -0,0 +1,46 @@
+// Copyright 2011 Google Inc. All rights reserved.
+// Use of this source code is governed by the Apache 2.0
+// license that can be found in the LICENSE file.
+
+// This file provides error functions for common API failure modes.
+
+package appengine
+
+import (
+ "fmt"
+
+ "google.golang.org/appengine/internal"
+)
+
+// IsOverQuota reports whether err represents an API call failure
+// due to insufficient available quota.
+func IsOverQuota(err error) bool {
+ callErr, ok := err.(*internal.CallError)
+ return ok && callErr.Code == 4
+}
+
+// MultiError is returned by batch operations when there are errors with
+// particular elements. Errors will be in a one-to-one correspondence with
+// the input elements; successful elements will have a nil entry.
+type MultiError []error
+
+func (m MultiError) Error() string {
+ s, n := "", 0
+ for _, e := range m {
+ if e != nil {
+ if n == 0 {
+ s = e.Error()
+ }
+ n++
+ }
+ }
+ switch n {
+ case 0:
+ return "(0 errors)"
+ case 1:
+ return s
+ case 2:
+ return s + " (and 1 other error)"
+ }
+ return fmt.Sprintf("%s (and %d other errors)", s, n-1)
+}
diff --git a/vendor/google.golang.org/appengine/go.mod b/vendor/google.golang.org/appengine/go.mod
new file mode 100644
index 000000000..f449359d2
--- /dev/null
+++ b/vendor/google.golang.org/appengine/go.mod
@@ -0,0 +1,7 @@
+module google.golang.org/appengine
+
+require (
+ github.com/golang/protobuf v1.2.0
+ golang.org/x/net v0.0.0-20180724234803-3673e40ba225
+ golang.org/x/text v0.3.0
+)
diff --git a/vendor/google.golang.org/appengine/go.sum b/vendor/google.golang.org/appengine/go.sum
new file mode 100644
index 000000000..1a221c089
--- /dev/null
+++ b/vendor/google.golang.org/appengine/go.sum
@@ -0,0 +1,6 @@
+github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
+github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+golang.org/x/net v0.0.0-20180724234803-3673e40ba225 h1:kNX+jCowfMYzvlSvJu5pQWEmyWFrBXJ3PBy10xKMXK8=
+golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
diff --git a/vendor/google.golang.org/appengine/identity.go b/vendor/google.golang.org/appengine/identity.go
new file mode 100644
index 000000000..b8dcf8f36
--- /dev/null
+++ b/vendor/google.golang.org/appengine/identity.go
@@ -0,0 +1,142 @@
+// Copyright 2011 Google Inc. All rights reserved.
+// Use of this source code is governed by the Apache 2.0
+// license that can be found in the LICENSE file.
+
+package appengine
+
+import (
+ "time"
+
+ "golang.org/x/net/context"
+
+ "google.golang.org/appengine/internal"
+ pb "google.golang.org/appengine/internal/app_identity"
+ modpb "google.golang.org/appengine/internal/modules"
+)
+
+// AppID returns the application ID for the current application.
+// The string will be a plain application ID (e.g. "appid"), with a
+// domain prefix for custom domain deployments (e.g. "example.com:appid").
+func AppID(c context.Context) string { return internal.AppID(c) }
+
+// DefaultVersionHostname returns the standard hostname of the default version
+// of the current application (e.g. "my-app.appspot.com"). This is suitable for
+// use in constructing URLs.
+func DefaultVersionHostname(c context.Context) string {
+ return internal.DefaultVersionHostname(c)
+}
+
+// ModuleName returns the module name of the current instance.
+func ModuleName(c context.Context) string {
+ return internal.ModuleName(c)
+}
+
+// ModuleHostname returns a hostname of a module instance.
+// If module is the empty string, it refers to the module of the current instance.
+// If version is empty, it refers to the version of the current instance if valid,
+// or the default version of the module of the current instance.
+// If instance is empty, ModuleHostname returns the load-balancing hostname.
+func ModuleHostname(c context.Context, module, version, instance string) (string, error) {
+ req := &modpb.GetHostnameRequest{}
+ if module != "" {
+ req.Module = &module
+ }
+ if version != "" {
+ req.Version = &version
+ }
+ if instance != "" {
+ req.Instance = &instance
+ }
+ res := &modpb.GetHostnameResponse{}
+ if err := internal.Call(c, "modules", "GetHostname", req, res); err != nil {
+ return "", err
+ }
+ return *res.Hostname, nil
+}
+
+// VersionID returns the version ID for the current application.
+// It will be of the form "X.Y", where X is specified in app.yaml,
+// and Y is a number generated when each version of the app is uploaded.
+// It does not include a module name.
+func VersionID(c context.Context) string { return internal.VersionID(c) }
+
+// InstanceID returns a mostly-unique identifier for this instance.
+func InstanceID() string { return internal.InstanceID() }
+
+// Datacenter returns an identifier for the datacenter that the instance is running in.
+func Datacenter(c context.Context) string { return internal.Datacenter(c) }
+
+// ServerSoftware returns the App Engine release version.
+// In production, it looks like "Google App Engine/X.Y.Z".
+// In the development appserver, it looks like "Development/X.Y".
+func ServerSoftware() string { return internal.ServerSoftware() }
+
+// RequestID returns a string that uniquely identifies the request.
+func RequestID(c context.Context) string { return internal.RequestID(c) }
+
+// AccessToken generates an OAuth2 access token for the specified scopes on
+// behalf of service account of this application. This token will expire after
+// the returned time.
+func AccessToken(c context.Context, scopes ...string) (token string, expiry time.Time, err error) {
+ req := &pb.GetAccessTokenRequest{Scope: scopes}
+ res := &pb.GetAccessTokenResponse{}
+
+ err = internal.Call(c, "app_identity_service", "GetAccessToken", req, res)
+ if err != nil {
+ return "", time.Time{}, err
+ }
+ return res.GetAccessToken(), time.Unix(res.GetExpirationTime(), 0), nil
+}
+
+// Certificate represents a public certificate for the app.
+type Certificate struct {
+ KeyName string
+ Data []byte // PEM-encoded X.509 certificate
+}
+
+// PublicCertificates retrieves the public certificates for the app.
+// They can be used to verify a signature returned by SignBytes.
+func PublicCertificates(c context.Context) ([]Certificate, error) {
+ req := &pb.GetPublicCertificateForAppRequest{}
+ res := &pb.GetPublicCertificateForAppResponse{}
+ if err := internal.Call(c, "app_identity_service", "GetPublicCertificatesForApp", req, res); err != nil {
+ return nil, err
+ }
+ var cs []Certificate
+ for _, pc := range res.PublicCertificateList {
+ cs = append(cs, Certificate{
+ KeyName: pc.GetKeyName(),
+ Data: []byte(pc.GetX509CertificatePem()),
+ })
+ }
+ return cs, nil
+}
+
+// ServiceAccount returns a string representing the service account name, in
+// the form of an email address (typically app_id@appspot.gserviceaccount.com).
+func ServiceAccount(c context.Context) (string, error) {
+ req := &pb.GetServiceAccountNameRequest{}
+ res := &pb.GetServiceAccountNameResponse{}
+
+ err := internal.Call(c, "app_identity_service", "GetServiceAccountName", req, res)
+ if err != nil {
+ return "", err
+ }
+ return res.GetServiceAccountName(), err
+}
+
+// SignBytes signs bytes using a private key unique to your application.
+func SignBytes(c context.Context, bytes []byte) (keyName string, signature []byte, err error) {
+ req := &pb.SignForAppRequest{BytesToSign: bytes}
+ res := &pb.SignForAppResponse{}
+
+ if err := internal.Call(c, "app_identity_service", "SignForApp", req, res); err != nil {
+ return "", nil, err
+ }
+ return res.GetKeyName(), res.GetSignatureBytes(), nil
+}
+
+func init() {
+ internal.RegisterErrorCodeMap("app_identity_service", pb.AppIdentityServiceError_ErrorCode_name)
+ internal.RegisterErrorCodeMap("modules", modpb.ModulesServiceError_ErrorCode_name)
+}
diff --git a/vendor/google.golang.org/appengine/internal/api.go b/vendor/google.golang.org/appengine/internal/api.go
new file mode 100644
index 000000000..bbc1cb9c3
--- /dev/null
+++ b/vendor/google.golang.org/appengine/internal/api.go
@@ -0,0 +1,671 @@
+// Copyright 2011 Google Inc. All rights reserved.
+// Use of this source code is governed by the Apache 2.0
+// license that can be found in the LICENSE file.
+
+// +build !appengine
+
+package internal
+
+import (
+ "bytes"
+ "errors"
+ "fmt"
+ "io/ioutil"
+ "log"
+ "net"
+ "net/http"
+ "net/url"
+ "os"
+ "runtime"
+ "strconv"
+ "strings"
+ "sync"
+ "sync/atomic"
+ "time"
+
+ "github.com/golang/protobuf/proto"
+ netcontext "golang.org/x/net/context"
+
+ basepb "google.golang.org/appengine/internal/base"
+ logpb "google.golang.org/appengine/internal/log"
+ remotepb "google.golang.org/appengine/internal/remote_api"
+)
+
+const (
+ apiPath = "/rpc_http"
+ defaultTicketSuffix = "/default.20150612t184001.0"
+)
+
+var (
+ // Incoming headers.
+ ticketHeader = http.CanonicalHeaderKey("X-AppEngine-API-Ticket")
+ dapperHeader = http.CanonicalHeaderKey("X-Google-DapperTraceInfo")
+ traceHeader = http.CanonicalHeaderKey("X-Cloud-Trace-Context")
+ curNamespaceHeader = http.CanonicalHeaderKey("X-AppEngine-Current-Namespace")
+ userIPHeader = http.CanonicalHeaderKey("X-AppEngine-User-IP")
+ remoteAddrHeader = http.CanonicalHeaderKey("X-AppEngine-Remote-Addr")
+
+ // Outgoing headers.
+ apiEndpointHeader = http.CanonicalHeaderKey("X-Google-RPC-Service-Endpoint")
+ apiEndpointHeaderValue = []string{"app-engine-apis"}
+ apiMethodHeader = http.CanonicalHeaderKey("X-Google-RPC-Service-Method")
+ apiMethodHeaderValue = []string{"/VMRemoteAPI.CallRemoteAPI"}
+ apiDeadlineHeader = http.CanonicalHeaderKey("X-Google-RPC-Service-Deadline")
+ apiContentType = http.CanonicalHeaderKey("Content-Type")
+ apiContentTypeValue = []string{"application/octet-stream"}
+ logFlushHeader = http.CanonicalHeaderKey("X-AppEngine-Log-Flush-Count")
+
+ apiHTTPClient = &http.Client{
+ Transport: &http.Transport{
+ Proxy: http.ProxyFromEnvironment,
+ Dial: limitDial,
+ },
+ }
+
+ defaultTicketOnce sync.Once
+ defaultTicket string
+ backgroundContextOnce sync.Once
+ backgroundContext netcontext.Context
+)
+
+func apiURL() *url.URL {
+ host, port := "appengine.googleapis.internal", "10001"
+ if h := os.Getenv("API_HOST"); h != "" {
+ host = h
+ }
+ if p := os.Getenv("API_PORT"); p != "" {
+ port = p
+ }
+ return &url.URL{
+ Scheme: "http",
+ Host: host + ":" + port,
+ Path: apiPath,
+ }
+}
+
+func handleHTTP(w http.ResponseWriter, r *http.Request) {
+ c := &context{
+ req: r,
+ outHeader: w.Header(),
+ apiURL: apiURL(),
+ }
+ r = r.WithContext(withContext(r.Context(), c))
+ c.req = r
+
+ stopFlushing := make(chan int)
+
+ // Patch up RemoteAddr so it looks reasonable.
+ if addr := r.Header.Get(userIPHeader); addr != "" {
+ r.RemoteAddr = addr
+ } else if addr = r.Header.Get(remoteAddrHeader); addr != "" {
+ r.RemoteAddr = addr
+ } else {
+ // Should not normally reach here, but pick a sensible default anyway.
+ r.RemoteAddr = "127.0.0.1"
+ }
+ // The address in the headers will most likely be of these forms:
+ // 123.123.123.123
+ // 2001:db8::1
+ // net/http.Request.RemoteAddr is specified to be in "IP:port" form.
+ if _, _, err := net.SplitHostPort(r.RemoteAddr); err != nil {
+ // Assume the remote address is only a host; add a default port.
+ r.RemoteAddr = net.JoinHostPort(r.RemoteAddr, "80")
+ }
+
+ // Start goroutine responsible for flushing app logs.
+ // This is done after adding c to ctx.m (and stopped before removing it)
+ // because flushing logs requires making an API call.
+ go c.logFlusher(stopFlushing)
+
+ executeRequestSafely(c, r)
+ c.outHeader = nil // make sure header changes aren't respected any more
+
+ stopFlushing <- 1 // any logging beyond this point will be dropped
+
+ // Flush any pending logs asynchronously.
+ c.pendingLogs.Lock()
+ flushes := c.pendingLogs.flushes
+ if len(c.pendingLogs.lines) > 0 {
+ flushes++
+ }
+ c.pendingLogs.Unlock()
+ flushed := make(chan struct{})
+ go func() {
+ defer close(flushed)
+ // Force a log flush, because with very short requests we
+ // may not ever flush logs.
+ c.flushLog(true)
+ }()
+ w.Header().Set(logFlushHeader, strconv.Itoa(flushes))
+
+ // Avoid nil Write call if c.Write is never called.
+ if c.outCode != 0 {
+ w.WriteHeader(c.outCode)
+ }
+ if c.outBody != nil {
+ w.Write(c.outBody)
+ }
+ // Wait for the last flush to complete before returning,
+ // otherwise the security ticket will not be valid.
+ <-flushed
+}
+
+func executeRequestSafely(c *context, r *http.Request) {
+ defer func() {
+ if x := recover(); x != nil {
+ logf(c, 4, "%s", renderPanic(x)) // 4 == critical
+ c.outCode = 500
+ }
+ }()
+
+ http.DefaultServeMux.ServeHTTP(c, r)
+}
+
+func renderPanic(x interface{}) string {
+ buf := make([]byte, 16<<10) // 16 KB should be plenty
+ buf = buf[:runtime.Stack(buf, false)]
+
+ // Remove the first few stack frames:
+ // this func
+ // the recover closure in the caller
+ // That will root the stack trace at the site of the panic.
+ const (
+ skipStart = "internal.renderPanic"
+ skipFrames = 2
+ )
+ start := bytes.Index(buf, []byte(skipStart))
+ p := start
+ for i := 0; i < skipFrames*2 && p+1 < len(buf); i++ {
+ p = bytes.IndexByte(buf[p+1:], '\n') + p + 1
+ if p < 0 {
+ break
+ }
+ }
+ if p >= 0 {
+ // buf[start:p+1] is the block to remove.
+ // Copy buf[p+1:] over buf[start:] and shrink buf.
+ copy(buf[start:], buf[p+1:])
+ buf = buf[:len(buf)-(p+1-start)]
+ }
+
+ // Add panic heading.
+ head := fmt.Sprintf("panic: %v\n\n", x)
+ if len(head) > len(buf) {
+ // Extremely unlikely to happen.
+ return head
+ }
+ copy(buf[len(head):], buf)
+ copy(buf, head)
+
+ return string(buf)
+}
+
+// context represents the context of an in-flight HTTP request.
+// It implements the appengine.Context and http.ResponseWriter interfaces.
+type context struct {
+ req *http.Request
+
+ outCode int
+ outHeader http.Header
+ outBody []byte
+
+ pendingLogs struct {
+ sync.Mutex
+ lines []*logpb.UserAppLogLine
+ flushes int
+ }
+
+ apiURL *url.URL
+}
+
+var contextKey = "holds a *context"
+
+// jointContext joins two contexts in a superficial way.
+// It takes values and timeouts from a base context, and only values from another context.
+type jointContext struct {
+ base netcontext.Context
+ valuesOnly netcontext.Context
+}
+
+func (c jointContext) Deadline() (time.Time, bool) {
+ return c.base.Deadline()
+}
+
+func (c jointContext) Done() <-chan struct{} {
+ return c.base.Done()
+}
+
+func (c jointContext) Err() error {
+ return c.base.Err()
+}
+
+func (c jointContext) Value(key interface{}) interface{} {
+ if val := c.base.Value(key); val != nil {
+ return val
+ }
+ return c.valuesOnly.Value(key)
+}
+
+// fromContext returns the App Engine context or nil if ctx is not
+// derived from an App Engine context.
+func fromContext(ctx netcontext.Context) *context {
+ c, _ := ctx.Value(&contextKey).(*context)
+ return c
+}
+
+func withContext(parent netcontext.Context, c *context) netcontext.Context {
+ ctx := netcontext.WithValue(parent, &contextKey, c)
+ if ns := c.req.Header.Get(curNamespaceHeader); ns != "" {
+ ctx = withNamespace(ctx, ns)
+ }
+ return ctx
+}
+
+func toContext(c *context) netcontext.Context {
+ return withContext(netcontext.Background(), c)
+}
+
+func IncomingHeaders(ctx netcontext.Context) http.Header {
+ if c := fromContext(ctx); c != nil {
+ return c.req.Header
+ }
+ return nil
+}
+
+func ReqContext(req *http.Request) netcontext.Context {
+ return req.Context()
+}
+
+func WithContext(parent netcontext.Context, req *http.Request) netcontext.Context {
+ return jointContext{
+ base: parent,
+ valuesOnly: req.Context(),
+ }
+}
+
+// DefaultTicket returns a ticket used for background context or dev_appserver.
+func DefaultTicket() string {
+ defaultTicketOnce.Do(func() {
+ if IsDevAppServer() {
+ defaultTicket = "testapp" + defaultTicketSuffix
+ return
+ }
+ appID := partitionlessAppID()
+ escAppID := strings.Replace(strings.Replace(appID, ":", "_", -1), ".", "_", -1)
+ majVersion := VersionID(nil)
+ if i := strings.Index(majVersion, "."); i > 0 {
+ majVersion = majVersion[:i]
+ }
+ defaultTicket = fmt.Sprintf("%s/%s.%s.%s", escAppID, ModuleName(nil), majVersion, InstanceID())
+ })
+ return defaultTicket
+}
+
+func BackgroundContext() netcontext.Context {
+ backgroundContextOnce.Do(func() {
+ // Compute background security ticket.
+ ticket := DefaultTicket()
+
+ c := &context{
+ req: &http.Request{
+ Header: http.Header{
+ ticketHeader: []string{ticket},
+ },
+ },
+ apiURL: apiURL(),
+ }
+ backgroundContext = toContext(c)
+
+ // TODO(dsymonds): Wire up the shutdown handler to do a final flush.
+ go c.logFlusher(make(chan int))
+ })
+
+ return backgroundContext
+}
+
+// RegisterTestRequest registers the HTTP request req for testing, such that
+// any API calls are sent to the provided URL. It returns a closure to delete
+// the registration.
+// It should only be used by aetest package.
+func RegisterTestRequest(req *http.Request, apiURL *url.URL, decorate func(netcontext.Context) netcontext.Context) (*http.Request, func()) {
+ c := &context{
+ req: req,
+ apiURL: apiURL,
+ }
+ ctx := withContext(decorate(req.Context()), c)
+ req = req.WithContext(ctx)
+ c.req = req
+ return req, func() {}
+}
+
+var errTimeout = &CallError{
+ Detail: "Deadline exceeded",
+ Code: int32(remotepb.RpcError_CANCELLED),
+ Timeout: true,
+}
+
+func (c *context) Header() http.Header { return c.outHeader }
+
+// Copied from $GOROOT/src/pkg/net/http/transfer.go. Some response status
+// codes do not permit a response body (nor response entity headers such as
+// Content-Length, Content-Type, etc).
+func bodyAllowedForStatus(status int) bool {
+ switch {
+ case status >= 100 && status <= 199:
+ return false
+ case status == 204:
+ return false
+ case status == 304:
+ return false
+ }
+ return true
+}
+
+func (c *context) Write(b []byte) (int, error) {
+ if c.outCode == 0 {
+ c.WriteHeader(http.StatusOK)
+ }
+ if len(b) > 0 && !bodyAllowedForStatus(c.outCode) {
+ return 0, http.ErrBodyNotAllowed
+ }
+ c.outBody = append(c.outBody, b...)
+ return len(b), nil
+}
+
+func (c *context) WriteHeader(code int) {
+ if c.outCode != 0 {
+ logf(c, 3, "WriteHeader called multiple times on request.") // error level
+ return
+ }
+ c.outCode = code
+}
+
+func (c *context) post(body []byte, timeout time.Duration) (b []byte, err error) {
+ hreq := &http.Request{
+ Method: "POST",
+ URL: c.apiURL,
+ Header: http.Header{
+ apiEndpointHeader: apiEndpointHeaderValue,
+ apiMethodHeader: apiMethodHeaderValue,
+ apiContentType: apiContentTypeValue,
+ apiDeadlineHeader: []string{strconv.FormatFloat(timeout.Seconds(), 'f', -1, 64)},
+ },
+ Body: ioutil.NopCloser(bytes.NewReader(body)),
+ ContentLength: int64(len(body)),
+ Host: c.apiURL.Host,
+ }
+ if info := c.req.Header.Get(dapperHeader); info != "" {
+ hreq.Header.Set(dapperHeader, info)
+ }
+ if info := c.req.Header.Get(traceHeader); info != "" {
+ hreq.Header.Set(traceHeader, info)
+ }
+
+ tr := apiHTTPClient.Transport.(*http.Transport)
+
+ var timedOut int32 // atomic; set to 1 if timed out
+ t := time.AfterFunc(timeout, func() {
+ atomic.StoreInt32(&timedOut, 1)
+ tr.CancelRequest(hreq)
+ })
+ defer t.Stop()
+ defer func() {
+ // Check if timeout was exceeded.
+ if atomic.LoadInt32(&timedOut) != 0 {
+ err = errTimeout
+ }
+ }()
+
+ hresp, err := apiHTTPClient.Do(hreq)
+ if err != nil {
+ return nil, &CallError{
+ Detail: fmt.Sprintf("service bridge HTTP failed: %v", err),
+ Code: int32(remotepb.RpcError_UNKNOWN),
+ }
+ }
+ defer hresp.Body.Close()
+ hrespBody, err := ioutil.ReadAll(hresp.Body)
+ if hresp.StatusCode != 200 {
+ return nil, &CallError{
+ Detail: fmt.Sprintf("service bridge returned HTTP %d (%q)", hresp.StatusCode, hrespBody),
+ Code: int32(remotepb.RpcError_UNKNOWN),
+ }
+ }
+ if err != nil {
+ return nil, &CallError{
+ Detail: fmt.Sprintf("service bridge response bad: %v", err),
+ Code: int32(remotepb.RpcError_UNKNOWN),
+ }
+ }
+ return hrespBody, nil
+}
+
+func Call(ctx netcontext.Context, service, method string, in, out proto.Message) error {
+ if ns := NamespaceFromContext(ctx); ns != "" {
+ if fn, ok := NamespaceMods[service]; ok {
+ fn(in, ns)
+ }
+ }
+
+ if f, ctx, ok := callOverrideFromContext(ctx); ok {
+ return f(ctx, service, method, in, out)
+ }
+
+ // Handle already-done contexts quickly.
+ select {
+ case <-ctx.Done():
+ return ctx.Err()
+ default:
+ }
+
+ c := fromContext(ctx)
+ if c == nil {
+ // Give a good error message rather than a panic lower down.
+ return errNotAppEngineContext
+ }
+
+ // Apply transaction modifications if we're in a transaction.
+ if t := transactionFromContext(ctx); t != nil {
+ if t.finished {
+ return errors.New("transaction context has expired")
+ }
+ applyTransaction(in, &t.transaction)
+ }
+
+ // Default RPC timeout is 60s.
+ timeout := 60 * time.Second
+ if deadline, ok := ctx.Deadline(); ok {
+ timeout = deadline.Sub(time.Now())
+ }
+
+ data, err := proto.Marshal(in)
+ if err != nil {
+ return err
+ }
+
+ ticket := c.req.Header.Get(ticketHeader)
+ // Use a test ticket under test environment.
+ if ticket == "" {
+ if appid := ctx.Value(&appIDOverrideKey); appid != nil {
+ ticket = appid.(string) + defaultTicketSuffix
+ }
+ }
+ // Fall back to use background ticket when the request ticket is not available in Flex or dev_appserver.
+ if ticket == "" {
+ ticket = DefaultTicket()
+ }
+ req := &remotepb.Request{
+ ServiceName: &service,
+ Method: &method,
+ Request: data,
+ RequestId: &ticket,
+ }
+ hreqBody, err := proto.Marshal(req)
+ if err != nil {
+ return err
+ }
+
+ hrespBody, err := c.post(hreqBody, timeout)
+ if err != nil {
+ return err
+ }
+
+ res := &remotepb.Response{}
+ if err := proto.Unmarshal(hrespBody, res); err != nil {
+ return err
+ }
+ if res.RpcError != nil {
+ ce := &CallError{
+ Detail: res.RpcError.GetDetail(),
+ Code: *res.RpcError.Code,
+ }
+ switch remotepb.RpcError_ErrorCode(ce.Code) {
+ case remotepb.RpcError_CANCELLED, remotepb.RpcError_DEADLINE_EXCEEDED:
+ ce.Timeout = true
+ }
+ return ce
+ }
+ if res.ApplicationError != nil {
+ return &APIError{
+ Service: *req.ServiceName,
+ Detail: res.ApplicationError.GetDetail(),
+ Code: *res.ApplicationError.Code,
+ }
+ }
+ if res.Exception != nil || res.JavaException != nil {
+ // This shouldn't happen, but let's be defensive.
+ return &CallError{
+ Detail: "service bridge returned exception",
+ Code: int32(remotepb.RpcError_UNKNOWN),
+ }
+ }
+ return proto.Unmarshal(res.Response, out)
+}
+
+func (c *context) Request() *http.Request {
+ return c.req
+}
+
+func (c *context) addLogLine(ll *logpb.UserAppLogLine) {
+ // Truncate long log lines.
+ // TODO(dsymonds): Check if this is still necessary.
+ const lim = 8 << 10
+ if len(*ll.Message) > lim {
+ suffix := fmt.Sprintf("...(length %d)", len(*ll.Message))
+ ll.Message = proto.String((*ll.Message)[:lim-len(suffix)] + suffix)
+ }
+
+ c.pendingLogs.Lock()
+ c.pendingLogs.lines = append(c.pendingLogs.lines, ll)
+ c.pendingLogs.Unlock()
+}
+
+var logLevelName = map[int64]string{
+ 0: "DEBUG",
+ 1: "INFO",
+ 2: "WARNING",
+ 3: "ERROR",
+ 4: "CRITICAL",
+}
+
+func logf(c *context, level int64, format string, args ...interface{}) {
+ if c == nil {
+ panic("not an App Engine context")
+ }
+ s := fmt.Sprintf(format, args...)
+ s = strings.TrimRight(s, "\n") // Remove any trailing newline characters.
+ c.addLogLine(&logpb.UserAppLogLine{
+ TimestampUsec: proto.Int64(time.Now().UnixNano() / 1e3),
+ Level: &level,
+ Message: &s,
+ })
+ // Only duplicate log to stderr if not running on App Engine second generation
+ if !IsSecondGen() {
+ log.Print(logLevelName[level] + ": " + s)
+ }
+}
+
+// flushLog attempts to flush any pending logs to the appserver.
+// It should not be called concurrently.
+func (c *context) flushLog(force bool) (flushed bool) {
+ c.pendingLogs.Lock()
+ // Grab up to 30 MB. We can get away with up to 32 MB, but let's be cautious.
+ n, rem := 0, 30<<20
+ for ; n < len(c.pendingLogs.lines); n++ {
+ ll := c.pendingLogs.lines[n]
+ // Each log line will require about 3 bytes of overhead.
+ nb := proto.Size(ll) + 3
+ if nb > rem {
+ break
+ }
+ rem -= nb
+ }
+ lines := c.pendingLogs.lines[:n]
+ c.pendingLogs.lines = c.pendingLogs.lines[n:]
+ c.pendingLogs.Unlock()
+
+ if len(lines) == 0 && !force {
+ // Nothing to flush.
+ return false
+ }
+
+ rescueLogs := false
+ defer func() {
+ if rescueLogs {
+ c.pendingLogs.Lock()
+ c.pendingLogs.lines = append(lines, c.pendingLogs.lines...)
+ c.pendingLogs.Unlock()
+ }
+ }()
+
+ buf, err := proto.Marshal(&logpb.UserAppLogGroup{
+ LogLine: lines,
+ })
+ if err != nil {
+ log.Printf("internal.flushLog: marshaling UserAppLogGroup: %v", err)
+ rescueLogs = true
+ return false
+ }
+
+ req := &logpb.FlushRequest{
+ Logs: buf,
+ }
+ res := &basepb.VoidProto{}
+ c.pendingLogs.Lock()
+ c.pendingLogs.flushes++
+ c.pendingLogs.Unlock()
+ if err := Call(toContext(c), "logservice", "Flush", req, res); err != nil {
+ log.Printf("internal.flushLog: Flush RPC: %v", err)
+ rescueLogs = true
+ return false
+ }
+ return true
+}
+
+const (
+ // Log flushing parameters.
+ flushInterval = 1 * time.Second
+ forceFlushInterval = 60 * time.Second
+)
+
+func (c *context) logFlusher(stop <-chan int) {
+ lastFlush := time.Now()
+ tick := time.NewTicker(flushInterval)
+ for {
+ select {
+ case <-stop:
+ // Request finished.
+ tick.Stop()
+ return
+ case <-tick.C:
+ force := time.Now().Sub(lastFlush) > forceFlushInterval
+ if c.flushLog(force) {
+ lastFlush = time.Now()
+ }
+ }
+ }
+}
+
+func ContextForTesting(req *http.Request) netcontext.Context {
+ return toContext(&context{req: req})
+}
diff --git a/vendor/google.golang.org/appengine/internal/api_classic.go b/vendor/google.golang.org/appengine/internal/api_classic.go
new file mode 100644
index 000000000..f0f40b2e3
--- /dev/null
+++ b/vendor/google.golang.org/appengine/internal/api_classic.go
@@ -0,0 +1,169 @@
+// Copyright 2015 Google Inc. All rights reserved.
+// Use of this source code is governed by the Apache 2.0
+// license that can be found in the LICENSE file.
+
+// +build appengine
+
+package internal
+
+import (
+ "errors"
+ "fmt"
+ "net/http"
+ "time"
+
+ "appengine"
+ "appengine_internal"
+ basepb "appengine_internal/base"
+
+ "github.com/golang/protobuf/proto"
+ netcontext "golang.org/x/net/context"
+)
+
+var contextKey = "holds an appengine.Context"
+
+// fromContext returns the App Engine context or nil if ctx is not
+// derived from an App Engine context.
+func fromContext(ctx netcontext.Context) appengine.Context {
+ c, _ := ctx.Value(&contextKey).(appengine.Context)
+ return c
+}
+
+// This is only for classic App Engine adapters.
+func ClassicContextFromContext(ctx netcontext.Context) (appengine.Context, error) {
+ c := fromContext(ctx)
+ if c == nil {
+ return nil, errNotAppEngineContext
+ }
+ return c, nil
+}
+
+func withContext(parent netcontext.Context, c appengine.Context) netcontext.Context {
+ ctx := netcontext.WithValue(parent, &contextKey, c)
+
+ s := &basepb.StringProto{}
+ c.Call("__go__", "GetNamespace", &basepb.VoidProto{}, s, nil)
+ if ns := s.GetValue(); ns != "" {
+ ctx = NamespacedContext(ctx, ns)
+ }
+
+ return ctx
+}
+
+func IncomingHeaders(ctx netcontext.Context) http.Header {
+ if c := fromContext(ctx); c != nil {
+ if req, ok := c.Request().(*http.Request); ok {
+ return req.Header
+ }
+ }
+ return nil
+}
+
+func ReqContext(req *http.Request) netcontext.Context {
+ return WithContext(netcontext.Background(), req)
+}
+
+func WithContext(parent netcontext.Context, req *http.Request) netcontext.Context {
+ c := appengine.NewContext(req)
+ return withContext(parent, c)
+}
+
+type testingContext struct {
+ appengine.Context
+
+ req *http.Request
+}
+
+func (t *testingContext) FullyQualifiedAppID() string { return "dev~testcontext" }
+func (t *testingContext) Call(service, method string, _, _ appengine_internal.ProtoMessage, _ *appengine_internal.CallOptions) error {
+ if service == "__go__" && method == "GetNamespace" {
+ return nil
+ }
+ return fmt.Errorf("testingContext: unsupported Call")
+}
+func (t *testingContext) Request() interface{} { return t.req }
+
+func ContextForTesting(req *http.Request) netcontext.Context {
+ return withContext(netcontext.Background(), &testingContext{req: req})
+}
+
+func Call(ctx netcontext.Context, service, method string, in, out proto.Message) error {
+ if ns := NamespaceFromContext(ctx); ns != "" {
+ if fn, ok := NamespaceMods[service]; ok {
+ fn(in, ns)
+ }
+ }
+
+ if f, ctx, ok := callOverrideFromContext(ctx); ok {
+ return f(ctx, service, method, in, out)
+ }
+
+ // Handle already-done contexts quickly.
+ select {
+ case <-ctx.Done():
+ return ctx.Err()
+ default:
+ }
+
+ c := fromContext(ctx)
+ if c == nil {
+ // Give a good error message rather than a panic lower down.
+ return errNotAppEngineContext
+ }
+
+ // Apply transaction modifications if we're in a transaction.
+ if t := transactionFromContext(ctx); t != nil {
+ if t.finished {
+ return errors.New("transaction context has expired")
+ }
+ applyTransaction(in, &t.transaction)
+ }
+
+ var opts *appengine_internal.CallOptions
+ if d, ok := ctx.Deadline(); ok {
+ opts = &appengine_internal.CallOptions{
+ Timeout: d.Sub(time.Now()),
+ }
+ }
+
+ err := c.Call(service, method, in, out, opts)
+ switch v := err.(type) {
+ case *appengine_internal.APIError:
+ return &APIError{
+ Service: v.Service,
+ Detail: v.Detail,
+ Code: v.Code,
+ }
+ case *appengine_internal.CallError:
+ return &CallError{
+ Detail: v.Detail,
+ Code: v.Code,
+ Timeout: v.Timeout,
+ }
+ }
+ return err
+}
+
+func handleHTTP(w http.ResponseWriter, r *http.Request) {
+ panic("handleHTTP called; this should be impossible")
+}
+
+func logf(c appengine.Context, level int64, format string, args ...interface{}) {
+ var fn func(format string, args ...interface{})
+ switch level {
+ case 0:
+ fn = c.Debugf
+ case 1:
+ fn = c.Infof
+ case 2:
+ fn = c.Warningf
+ case 3:
+ fn = c.Errorf
+ case 4:
+ fn = c.Criticalf
+ default:
+ // This shouldn't happen.
+ fn = c.Criticalf
+ }
+ fn(format, args...)
+}
diff --git a/vendor/google.golang.org/appengine/internal/api_common.go b/vendor/google.golang.org/appengine/internal/api_common.go
new file mode 100644
index 000000000..e0c0b214b
--- /dev/null
+++ b/vendor/google.golang.org/appengine/internal/api_common.go
@@ -0,0 +1,123 @@
+// Copyright 2015 Google Inc. All rights reserved.
+// Use of this source code is governed by the Apache 2.0
+// license that can be found in the LICENSE file.
+
+package internal
+
+import (
+ "errors"
+ "os"
+
+ "github.com/golang/protobuf/proto"
+ netcontext "golang.org/x/net/context"
+)
+
+var errNotAppEngineContext = errors.New("not an App Engine context")
+
+type CallOverrideFunc func(ctx netcontext.Context, service, method string, in, out proto.Message) error
+
+var callOverrideKey = "holds []CallOverrideFunc"
+
+func WithCallOverride(ctx netcontext.Context, f CallOverrideFunc) netcontext.Context {
+ // We avoid appending to any existing call override
+ // so we don't risk overwriting a popped stack below.
+ var cofs []CallOverrideFunc
+ if uf, ok := ctx.Value(&callOverrideKey).([]CallOverrideFunc); ok {
+ cofs = append(cofs, uf...)
+ }
+ cofs = append(cofs, f)
+ return netcontext.WithValue(ctx, &callOverrideKey, cofs)
+}
+
+func callOverrideFromContext(ctx netcontext.Context) (CallOverrideFunc, netcontext.Context, bool) {
+ cofs, _ := ctx.Value(&callOverrideKey).([]CallOverrideFunc)
+ if len(cofs) == 0 {
+ return nil, nil, false
+ }
+ // We found a list of overrides; grab the last, and reconstitute a
+ // context that will hide it.
+ f := cofs[len(cofs)-1]
+ ctx = netcontext.WithValue(ctx, &callOverrideKey, cofs[:len(cofs)-1])
+ return f, ctx, true
+}
+
+type logOverrideFunc func(level int64, format string, args ...interface{})
+
+var logOverrideKey = "holds a logOverrideFunc"
+
+func WithLogOverride(ctx netcontext.Context, f logOverrideFunc) netcontext.Context {
+ return netcontext.WithValue(ctx, &logOverrideKey, f)
+}
+
+var appIDOverrideKey = "holds a string, being the full app ID"
+
+func WithAppIDOverride(ctx netcontext.Context, appID string) netcontext.Context {
+ return netcontext.WithValue(ctx, &appIDOverrideKey, appID)
+}
+
+var namespaceKey = "holds the namespace string"
+
+func withNamespace(ctx netcontext.Context, ns string) netcontext.Context {
+ return netcontext.WithValue(ctx, &namespaceKey, ns)
+}
+
+func NamespaceFromContext(ctx netcontext.Context) string {
+ // If there's no namespace, return the empty string.
+ ns, _ := ctx.Value(&namespaceKey).(string)
+ return ns
+}
+
+// FullyQualifiedAppID returns the fully-qualified application ID.
+// This may contain a partition prefix (e.g. "s~" for High Replication apps),
+// or a domain prefix (e.g. "example.com:").
+func FullyQualifiedAppID(ctx netcontext.Context) string {
+ if id, ok := ctx.Value(&appIDOverrideKey).(string); ok {
+ return id
+ }
+ return fullyQualifiedAppID(ctx)
+}
+
+func Logf(ctx netcontext.Context, level int64, format string, args ...interface{}) {
+ if f, ok := ctx.Value(&logOverrideKey).(logOverrideFunc); ok {
+ f(level, format, args...)
+ return
+ }
+ c := fromContext(ctx)
+ if c == nil {
+ panic(errNotAppEngineContext)
+ }
+ logf(c, level, format, args...)
+}
+
+// NamespacedContext wraps a Context to support namespaces.
+func NamespacedContext(ctx netcontext.Context, namespace string) netcontext.Context {
+ return withNamespace(ctx, namespace)
+}
+
+// SetTestEnv sets the env variables for testing background ticket in Flex.
+func SetTestEnv() func() {
+ var environ = []struct {
+ key, value string
+ }{
+ {"GAE_LONG_APP_ID", "my-app-id"},
+ {"GAE_MINOR_VERSION", "067924799508853122"},
+ {"GAE_MODULE_INSTANCE", "0"},
+ {"GAE_MODULE_NAME", "default"},
+ {"GAE_MODULE_VERSION", "20150612t184001"},
+ }
+
+ for _, v := range environ {
+ old := os.Getenv(v.key)
+ os.Setenv(v.key, v.value)
+ v.value = old
+ }
+ return func() { // Restore old environment after the test completes.
+ for _, v := range environ {
+ if v.value == "" {
+ os.Unsetenv(v.key)
+ continue
+ }
+ os.Setenv(v.key, v.value)
+ }
+ }
+}
diff --git a/vendor/google.golang.org/appengine/internal/app_id.go b/vendor/google.golang.org/appengine/internal/app_id.go
new file mode 100644
index 000000000..11df8c07b
--- /dev/null
+++ b/vendor/google.golang.org/appengine/internal/app_id.go
@@ -0,0 +1,28 @@
+// Copyright 2011 Google Inc. All rights reserved.
+// Use of this source code is governed by the Apache 2.0
+// license that can be found in the LICENSE file.
+
+package internal
+
+import (
+ "strings"
+)
+
+func parseFullAppID(appid string) (partition, domain, displayID string) {
+ if i := strings.Index(appid, "~"); i != -1 {
+ partition, appid = appid[:i], appid[i+1:]
+ }
+ if i := strings.Index(appid, ":"); i != -1 {
+ domain, appid = appid[:i], appid[i+1:]
+ }
+ return partition, domain, appid
+}
+
+// appID returns "appid" or "domain.com:appid".
+func appID(fullAppID string) string {
+ _, dom, dis := parseFullAppID(fullAppID)
+ if dom != "" {
+ return dom + ":" + dis
+ }
+ return dis
+}
diff --git a/vendor/google.golang.org/appengine/internal/app_identity/app_identity_service.pb.go b/vendor/google.golang.org/appengine/internal/app_identity/app_identity_service.pb.go
new file mode 100644
index 000000000..9a2ff77ab
--- /dev/null
+++ b/vendor/google.golang.org/appengine/internal/app_identity/app_identity_service.pb.go
@@ -0,0 +1,611 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// source: google.golang.org/appengine/internal/app_identity/app_identity_service.proto
+
+package app_identity
+
+import proto "github.com/golang/protobuf/proto"
+import fmt "fmt"
+import math "math"
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
+
+type AppIdentityServiceError_ErrorCode int32
+
+const (
+ AppIdentityServiceError_SUCCESS AppIdentityServiceError_ErrorCode = 0
+ AppIdentityServiceError_UNKNOWN_SCOPE AppIdentityServiceError_ErrorCode = 9
+ AppIdentityServiceError_BLOB_TOO_LARGE AppIdentityServiceError_ErrorCode = 1000
+ AppIdentityServiceError_DEADLINE_EXCEEDED AppIdentityServiceError_ErrorCode = 1001
+ AppIdentityServiceError_NOT_A_VALID_APP AppIdentityServiceError_ErrorCode = 1002
+ AppIdentityServiceError_UNKNOWN_ERROR AppIdentityServiceError_ErrorCode = 1003
+ AppIdentityServiceError_NOT_ALLOWED AppIdentityServiceError_ErrorCode = 1005
+ AppIdentityServiceError_NOT_IMPLEMENTED AppIdentityServiceError_ErrorCode = 1006
+)
+
+var AppIdentityServiceError_ErrorCode_name = map[int32]string{
+ 0: "SUCCESS",
+ 9: "UNKNOWN_SCOPE",
+ 1000: "BLOB_TOO_LARGE",
+ 1001: "DEADLINE_EXCEEDED",
+ 1002: "NOT_A_VALID_APP",
+ 1003: "UNKNOWN_ERROR",
+ 1005: "NOT_ALLOWED",
+ 1006: "NOT_IMPLEMENTED",
+}
+var AppIdentityServiceError_ErrorCode_value = map[string]int32{
+ "SUCCESS": 0,
+ "UNKNOWN_SCOPE": 9,
+ "BLOB_TOO_LARGE": 1000,
+ "DEADLINE_EXCEEDED": 1001,
+ "NOT_A_VALID_APP": 1002,
+ "UNKNOWN_ERROR": 1003,
+ "NOT_ALLOWED": 1005,
+ "NOT_IMPLEMENTED": 1006,
+}
+
+func (x AppIdentityServiceError_ErrorCode) Enum() *AppIdentityServiceError_ErrorCode {
+ p := new(AppIdentityServiceError_ErrorCode)
+ *p = x
+ return p
+}
+func (x AppIdentityServiceError_ErrorCode) String() string {
+ return proto.EnumName(AppIdentityServiceError_ErrorCode_name, int32(x))
+}
+func (x *AppIdentityServiceError_ErrorCode) UnmarshalJSON(data []byte) error {
+ value, err := proto.UnmarshalJSONEnum(AppIdentityServiceError_ErrorCode_value, data, "AppIdentityServiceError_ErrorCode")
+ if err != nil {
+ return err
+ }
+ *x = AppIdentityServiceError_ErrorCode(value)
+ return nil
+}
+func (AppIdentityServiceError_ErrorCode) EnumDescriptor() ([]byte, []int) {
+ return fileDescriptor_app_identity_service_08a6e3f74b04cfa4, []int{0, 0}
+}
+
+type AppIdentityServiceError struct {
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *AppIdentityServiceError) Reset() { *m = AppIdentityServiceError{} }
+func (m *AppIdentityServiceError) String() string { return proto.CompactTextString(m) }
+func (*AppIdentityServiceError) ProtoMessage() {}
+func (*AppIdentityServiceError) Descriptor() ([]byte, []int) {
+ return fileDescriptor_app_identity_service_08a6e3f74b04cfa4, []int{0}
+}
+func (m *AppIdentityServiceError) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_AppIdentityServiceError.Unmarshal(m, b)
+}
+func (m *AppIdentityServiceError) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_AppIdentityServiceError.Marshal(b, m, deterministic)
+}
+func (dst *AppIdentityServiceError) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_AppIdentityServiceError.Merge(dst, src)
+}
+func (m *AppIdentityServiceError) XXX_Size() int {
+ return xxx_messageInfo_AppIdentityServiceError.Size(m)
+}
+func (m *AppIdentityServiceError) XXX_DiscardUnknown() {
+ xxx_messageInfo_AppIdentityServiceError.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_AppIdentityServiceError proto.InternalMessageInfo
+
+type SignForAppRequest struct {
+ BytesToSign []byte `protobuf:"bytes,1,opt,name=bytes_to_sign,json=bytesToSign" json:"bytes_to_sign,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *SignForAppRequest) Reset() { *m = SignForAppRequest{} }
+func (m *SignForAppRequest) String() string { return proto.CompactTextString(m) }
+func (*SignForAppRequest) ProtoMessage() {}
+func (*SignForAppRequest) Descriptor() ([]byte, []int) {
+ return fileDescriptor_app_identity_service_08a6e3f74b04cfa4, []int{1}
+}
+func (m *SignForAppRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_SignForAppRequest.Unmarshal(m, b)
+}
+func (m *SignForAppRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_SignForAppRequest.Marshal(b, m, deterministic)
+}
+func (dst *SignForAppRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_SignForAppRequest.Merge(dst, src)
+}
+func (m *SignForAppRequest) XXX_Size() int {
+ return xxx_messageInfo_SignForAppRequest.Size(m)
+}
+func (m *SignForAppRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_SignForAppRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_SignForAppRequest proto.InternalMessageInfo
+
+func (m *SignForAppRequest) GetBytesToSign() []byte {
+ if m != nil {
+ return m.BytesToSign
+ }
+ return nil
+}
+
+type SignForAppResponse struct {
+ KeyName *string `protobuf:"bytes,1,opt,name=key_name,json=keyName" json:"key_name,omitempty"`
+ SignatureBytes []byte `protobuf:"bytes,2,opt,name=signature_bytes,json=signatureBytes" json:"signature_bytes,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *SignForAppResponse) Reset() { *m = SignForAppResponse{} }
+func (m *SignForAppResponse) String() string { return proto.CompactTextString(m) }
+func (*SignForAppResponse) ProtoMessage() {}
+func (*SignForAppResponse) Descriptor() ([]byte, []int) {
+ return fileDescriptor_app_identity_service_08a6e3f74b04cfa4, []int{2}
+}
+func (m *SignForAppResponse) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_SignForAppResponse.Unmarshal(m, b)
+}
+func (m *SignForAppResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_SignForAppResponse.Marshal(b, m, deterministic)
+}
+func (dst *SignForAppResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_SignForAppResponse.Merge(dst, src)
+}
+func (m *SignForAppResponse) XXX_Size() int {
+ return xxx_messageInfo_SignForAppResponse.Size(m)
+}
+func (m *SignForAppResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_SignForAppResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_SignForAppResponse proto.InternalMessageInfo
+
+func (m *SignForAppResponse) GetKeyName() string {
+ if m != nil && m.KeyName != nil {
+ return *m.KeyName
+ }
+ return ""
+}
+
+func (m *SignForAppResponse) GetSignatureBytes() []byte {
+ if m != nil {
+ return m.SignatureBytes
+ }
+ return nil
+}
+
+type GetPublicCertificateForAppRequest struct {
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *GetPublicCertificateForAppRequest) Reset() { *m = GetPublicCertificateForAppRequest{} }
+func (m *GetPublicCertificateForAppRequest) String() string { return proto.CompactTextString(m) }
+func (*GetPublicCertificateForAppRequest) ProtoMessage() {}
+func (*GetPublicCertificateForAppRequest) Descriptor() ([]byte, []int) {
+ return fileDescriptor_app_identity_service_08a6e3f74b04cfa4, []int{3}
+}
+func (m *GetPublicCertificateForAppRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GetPublicCertificateForAppRequest.Unmarshal(m, b)
+}
+func (m *GetPublicCertificateForAppRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GetPublicCertificateForAppRequest.Marshal(b, m, deterministic)
+}
+func (dst *GetPublicCertificateForAppRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GetPublicCertificateForAppRequest.Merge(dst, src)
+}
+func (m *GetPublicCertificateForAppRequest) XXX_Size() int {
+ return xxx_messageInfo_GetPublicCertificateForAppRequest.Size(m)
+}
+func (m *GetPublicCertificateForAppRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_GetPublicCertificateForAppRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetPublicCertificateForAppRequest proto.InternalMessageInfo
+
+type PublicCertificate struct {
+ KeyName *string `protobuf:"bytes,1,opt,name=key_name,json=keyName" json:"key_name,omitempty"`
+ X509CertificatePem *string `protobuf:"bytes,2,opt,name=x509_certificate_pem,json=x509CertificatePem" json:"x509_certificate_pem,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *PublicCertificate) Reset() { *m = PublicCertificate{} }
+func (m *PublicCertificate) String() string { return proto.CompactTextString(m) }
+func (*PublicCertificate) ProtoMessage() {}
+func (*PublicCertificate) Descriptor() ([]byte, []int) {
+ return fileDescriptor_app_identity_service_08a6e3f74b04cfa4, []int{4}
+}
+func (m *PublicCertificate) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_PublicCertificate.Unmarshal(m, b)
+}
+func (m *PublicCertificate) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_PublicCertificate.Marshal(b, m, deterministic)
+}
+func (dst *PublicCertificate) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_PublicCertificate.Merge(dst, src)
+}
+func (m *PublicCertificate) XXX_Size() int {
+ return xxx_messageInfo_PublicCertificate.Size(m)
+}
+func (m *PublicCertificate) XXX_DiscardUnknown() {
+ xxx_messageInfo_PublicCertificate.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_PublicCertificate proto.InternalMessageInfo
+
+func (m *PublicCertificate) GetKeyName() string {
+ if m != nil && m.KeyName != nil {
+ return *m.KeyName
+ }
+ return ""
+}
+
+func (m *PublicCertificate) GetX509CertificatePem() string {
+ if m != nil && m.X509CertificatePem != nil {
+ return *m.X509CertificatePem
+ }
+ return ""
+}
+
+type GetPublicCertificateForAppResponse struct {
+ PublicCertificateList []*PublicCertificate `protobuf:"bytes,1,rep,name=public_certificate_list,json=publicCertificateList" json:"public_certificate_list,omitempty"`
+ MaxClientCacheTimeInSecond *int64 `protobuf:"varint,2,opt,name=max_client_cache_time_in_second,json=maxClientCacheTimeInSecond" json:"max_client_cache_time_in_second,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *GetPublicCertificateForAppResponse) Reset() { *m = GetPublicCertificateForAppResponse{} }
+func (m *GetPublicCertificateForAppResponse) String() string { return proto.CompactTextString(m) }
+func (*GetPublicCertificateForAppResponse) ProtoMessage() {}
+func (*GetPublicCertificateForAppResponse) Descriptor() ([]byte, []int) {
+ return fileDescriptor_app_identity_service_08a6e3f74b04cfa4, []int{5}
+}
+func (m *GetPublicCertificateForAppResponse) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GetPublicCertificateForAppResponse.Unmarshal(m, b)
+}
+func (m *GetPublicCertificateForAppResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GetPublicCertificateForAppResponse.Marshal(b, m, deterministic)
+}
+func (dst *GetPublicCertificateForAppResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GetPublicCertificateForAppResponse.Merge(dst, src)
+}
+func (m *GetPublicCertificateForAppResponse) XXX_Size() int {
+ return xxx_messageInfo_GetPublicCertificateForAppResponse.Size(m)
+}
+func (m *GetPublicCertificateForAppResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_GetPublicCertificateForAppResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetPublicCertificateForAppResponse proto.InternalMessageInfo
+
+func (m *GetPublicCertificateForAppResponse) GetPublicCertificateList() []*PublicCertificate {
+ if m != nil {
+ return m.PublicCertificateList
+ }
+ return nil
+}
+
+func (m *GetPublicCertificateForAppResponse) GetMaxClientCacheTimeInSecond() int64 {
+ if m != nil && m.MaxClientCacheTimeInSecond != nil {
+ return *m.MaxClientCacheTimeInSecond
+ }
+ return 0
+}
+
+type GetServiceAccountNameRequest struct {
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *GetServiceAccountNameRequest) Reset() { *m = GetServiceAccountNameRequest{} }
+func (m *GetServiceAccountNameRequest) String() string { return proto.CompactTextString(m) }
+func (*GetServiceAccountNameRequest) ProtoMessage() {}
+func (*GetServiceAccountNameRequest) Descriptor() ([]byte, []int) {
+ return fileDescriptor_app_identity_service_08a6e3f74b04cfa4, []int{6}
+}
+func (m *GetServiceAccountNameRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GetServiceAccountNameRequest.Unmarshal(m, b)
+}
+func (m *GetServiceAccountNameRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GetServiceAccountNameRequest.Marshal(b, m, deterministic)
+}
+func (dst *GetServiceAccountNameRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GetServiceAccountNameRequest.Merge(dst, src)
+}
+func (m *GetServiceAccountNameRequest) XXX_Size() int {
+ return xxx_messageInfo_GetServiceAccountNameRequest.Size(m)
+}
+func (m *GetServiceAccountNameRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_GetServiceAccountNameRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetServiceAccountNameRequest proto.InternalMessageInfo
+
+type GetServiceAccountNameResponse struct {
+ ServiceAccountName *string `protobuf:"bytes,1,opt,name=service_account_name,json=serviceAccountName" json:"service_account_name,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *GetServiceAccountNameResponse) Reset() { *m = GetServiceAccountNameResponse{} }
+func (m *GetServiceAccountNameResponse) String() string { return proto.CompactTextString(m) }
+func (*GetServiceAccountNameResponse) ProtoMessage() {}
+func (*GetServiceAccountNameResponse) Descriptor() ([]byte, []int) {
+ return fileDescriptor_app_identity_service_08a6e3f74b04cfa4, []int{7}
+}
+func (m *GetServiceAccountNameResponse) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GetServiceAccountNameResponse.Unmarshal(m, b)
+}
+func (m *GetServiceAccountNameResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GetServiceAccountNameResponse.Marshal(b, m, deterministic)
+}
+func (dst *GetServiceAccountNameResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GetServiceAccountNameResponse.Merge(dst, src)
+}
+func (m *GetServiceAccountNameResponse) XXX_Size() int {
+ return xxx_messageInfo_GetServiceAccountNameResponse.Size(m)
+}
+func (m *GetServiceAccountNameResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_GetServiceAccountNameResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetServiceAccountNameResponse proto.InternalMessageInfo
+
+func (m *GetServiceAccountNameResponse) GetServiceAccountName() string {
+ if m != nil && m.ServiceAccountName != nil {
+ return *m.ServiceAccountName
+ }
+ return ""
+}
+
+type GetAccessTokenRequest struct {
+ Scope []string `protobuf:"bytes,1,rep,name=scope" json:"scope,omitempty"`
+ ServiceAccountId *int64 `protobuf:"varint,2,opt,name=service_account_id,json=serviceAccountId" json:"service_account_id,omitempty"`
+ ServiceAccountName *string `protobuf:"bytes,3,opt,name=service_account_name,json=serviceAccountName" json:"service_account_name,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *GetAccessTokenRequest) Reset() { *m = GetAccessTokenRequest{} }
+func (m *GetAccessTokenRequest) String() string { return proto.CompactTextString(m) }
+func (*GetAccessTokenRequest) ProtoMessage() {}
+func (*GetAccessTokenRequest) Descriptor() ([]byte, []int) {
+ return fileDescriptor_app_identity_service_08a6e3f74b04cfa4, []int{8}
+}
+func (m *GetAccessTokenRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GetAccessTokenRequest.Unmarshal(m, b)
+}
+func (m *GetAccessTokenRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GetAccessTokenRequest.Marshal(b, m, deterministic)
+}
+func (dst *GetAccessTokenRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GetAccessTokenRequest.Merge(dst, src)
+}
+func (m *GetAccessTokenRequest) XXX_Size() int {
+ return xxx_messageInfo_GetAccessTokenRequest.Size(m)
+}
+func (m *GetAccessTokenRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_GetAccessTokenRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetAccessTokenRequest proto.InternalMessageInfo
+
+func (m *GetAccessTokenRequest) GetScope() []string {
+ if m != nil {
+ return m.Scope
+ }
+ return nil
+}
+
+func (m *GetAccessTokenRequest) GetServiceAccountId() int64 {
+ if m != nil && m.ServiceAccountId != nil {
+ return *m.ServiceAccountId
+ }
+ return 0
+}
+
+func (m *GetAccessTokenRequest) GetServiceAccountName() string {
+ if m != nil && m.ServiceAccountName != nil {
+ return *m.ServiceAccountName
+ }
+ return ""
+}
+
+type GetAccessTokenResponse struct {
+ AccessToken *string `protobuf:"bytes,1,opt,name=access_token,json=accessToken" json:"access_token,omitempty"`
+ ExpirationTime *int64 `protobuf:"varint,2,opt,name=expiration_time,json=expirationTime" json:"expiration_time,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *GetAccessTokenResponse) Reset() { *m = GetAccessTokenResponse{} }
+func (m *GetAccessTokenResponse) String() string { return proto.CompactTextString(m) }
+func (*GetAccessTokenResponse) ProtoMessage() {}
+func (*GetAccessTokenResponse) Descriptor() ([]byte, []int) {
+ return fileDescriptor_app_identity_service_08a6e3f74b04cfa4, []int{9}
+}
+func (m *GetAccessTokenResponse) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GetAccessTokenResponse.Unmarshal(m, b)
+}
+func (m *GetAccessTokenResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GetAccessTokenResponse.Marshal(b, m, deterministic)
+}
+func (dst *GetAccessTokenResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GetAccessTokenResponse.Merge(dst, src)
+}
+func (m *GetAccessTokenResponse) XXX_Size() int {
+ return xxx_messageInfo_GetAccessTokenResponse.Size(m)
+}
+func (m *GetAccessTokenResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_GetAccessTokenResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetAccessTokenResponse proto.InternalMessageInfo
+
+func (m *GetAccessTokenResponse) GetAccessToken() string {
+ if m != nil && m.AccessToken != nil {
+ return *m.AccessToken
+ }
+ return ""
+}
+
+func (m *GetAccessTokenResponse) GetExpirationTime() int64 {
+ if m != nil && m.ExpirationTime != nil {
+ return *m.ExpirationTime
+ }
+ return 0
+}
+
+type GetDefaultGcsBucketNameRequest struct {
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *GetDefaultGcsBucketNameRequest) Reset() { *m = GetDefaultGcsBucketNameRequest{} }
+func (m *GetDefaultGcsBucketNameRequest) String() string { return proto.CompactTextString(m) }
+func (*GetDefaultGcsBucketNameRequest) ProtoMessage() {}
+func (*GetDefaultGcsBucketNameRequest) Descriptor() ([]byte, []int) {
+ return fileDescriptor_app_identity_service_08a6e3f74b04cfa4, []int{10}
+}
+func (m *GetDefaultGcsBucketNameRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GetDefaultGcsBucketNameRequest.Unmarshal(m, b)
+}
+func (m *GetDefaultGcsBucketNameRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GetDefaultGcsBucketNameRequest.Marshal(b, m, deterministic)
+}
+func (dst *GetDefaultGcsBucketNameRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GetDefaultGcsBucketNameRequest.Merge(dst, src)
+}
+func (m *GetDefaultGcsBucketNameRequest) XXX_Size() int {
+ return xxx_messageInfo_GetDefaultGcsBucketNameRequest.Size(m)
+}
+func (m *GetDefaultGcsBucketNameRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_GetDefaultGcsBucketNameRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetDefaultGcsBucketNameRequest proto.InternalMessageInfo
+
+type GetDefaultGcsBucketNameResponse struct {
+ DefaultGcsBucketName *string `protobuf:"bytes,1,opt,name=default_gcs_bucket_name,json=defaultGcsBucketName" json:"default_gcs_bucket_name,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *GetDefaultGcsBucketNameResponse) Reset() { *m = GetDefaultGcsBucketNameResponse{} }
+func (m *GetDefaultGcsBucketNameResponse) String() string { return proto.CompactTextString(m) }
+func (*GetDefaultGcsBucketNameResponse) ProtoMessage() {}
+func (*GetDefaultGcsBucketNameResponse) Descriptor() ([]byte, []int) {
+ return fileDescriptor_app_identity_service_08a6e3f74b04cfa4, []int{11}
+}
+func (m *GetDefaultGcsBucketNameResponse) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GetDefaultGcsBucketNameResponse.Unmarshal(m, b)
+}
+func (m *GetDefaultGcsBucketNameResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GetDefaultGcsBucketNameResponse.Marshal(b, m, deterministic)
+}
+func (dst *GetDefaultGcsBucketNameResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GetDefaultGcsBucketNameResponse.Merge(dst, src)
+}
+func (m *GetDefaultGcsBucketNameResponse) XXX_Size() int {
+ return xxx_messageInfo_GetDefaultGcsBucketNameResponse.Size(m)
+}
+func (m *GetDefaultGcsBucketNameResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_GetDefaultGcsBucketNameResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetDefaultGcsBucketNameResponse proto.InternalMessageInfo
+
+func (m *GetDefaultGcsBucketNameResponse) GetDefaultGcsBucketName() string {
+ if m != nil && m.DefaultGcsBucketName != nil {
+ return *m.DefaultGcsBucketName
+ }
+ return ""
+}
+
+func init() {
+ proto.RegisterType((*AppIdentityServiceError)(nil), "appengine.AppIdentityServiceError")
+ proto.RegisterType((*SignForAppRequest)(nil), "appengine.SignForAppRequest")
+ proto.RegisterType((*SignForAppResponse)(nil), "appengine.SignForAppResponse")
+ proto.RegisterType((*GetPublicCertificateForAppRequest)(nil), "appengine.GetPublicCertificateForAppRequest")
+ proto.RegisterType((*PublicCertificate)(nil), "appengine.PublicCertificate")
+ proto.RegisterType((*GetPublicCertificateForAppResponse)(nil), "appengine.GetPublicCertificateForAppResponse")
+ proto.RegisterType((*GetServiceAccountNameRequest)(nil), "appengine.GetServiceAccountNameRequest")
+ proto.RegisterType((*GetServiceAccountNameResponse)(nil), "appengine.GetServiceAccountNameResponse")
+ proto.RegisterType((*GetAccessTokenRequest)(nil), "appengine.GetAccessTokenRequest")
+ proto.RegisterType((*GetAccessTokenResponse)(nil), "appengine.GetAccessTokenResponse")
+ proto.RegisterType((*GetDefaultGcsBucketNameRequest)(nil), "appengine.GetDefaultGcsBucketNameRequest")
+ proto.RegisterType((*GetDefaultGcsBucketNameResponse)(nil), "appengine.GetDefaultGcsBucketNameResponse")
+}
+
+func init() {
+ proto.RegisterFile("google.golang.org/appengine/internal/app_identity/app_identity_service.proto", fileDescriptor_app_identity_service_08a6e3f74b04cfa4)
+}
+
+var fileDescriptor_app_identity_service_08a6e3f74b04cfa4 = []byte{
+ // 676 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x54, 0xdb, 0x6e, 0xda, 0x58,
+ 0x14, 0x1d, 0x26, 0x1a, 0x31, 0x6c, 0x12, 0x62, 0xce, 0x90, 0xcb, 0x8c, 0x32, 0xb9, 0x78, 0x1e,
+ 0x26, 0x0f, 0x15, 0x89, 0x2a, 0x45, 0x55, 0x1f, 0x8d, 0xed, 0x22, 0x54, 0x07, 0x53, 0x43, 0x9a,
+ 0xa8, 0x2f, 0xa7, 0xce, 0x61, 0xc7, 0x3d, 0x02, 0x9f, 0xe3, 0xda, 0x87, 0x0a, 0x3e, 0xa2, 0x3f,
+ 0xd2, 0x9f, 0xe8, 0x5b, 0xbf, 0xa5, 0x17, 0xb5, 0xdf, 0x50, 0xd9, 0x38, 0x5c, 0x92, 0x92, 0x37,
+ 0xbc, 0xf6, 0x5a, 0xcb, 0x6b, 0x2f, 0x6d, 0x0c, 0x4e, 0x20, 0x65, 0x30, 0xc4, 0x7a, 0x20, 0x87,
+ 0xbe, 0x08, 0xea, 0x32, 0x0e, 0x4e, 0xfc, 0x28, 0x42, 0x11, 0x70, 0x81, 0x27, 0x5c, 0x28, 0x8c,
+ 0x85, 0x3f, 0x4c, 0x21, 0xca, 0xfb, 0x28, 0x14, 0x57, 0x93, 0xa5, 0x07, 0x9a, 0x60, 0xfc, 0x8e,
+ 0x33, 0xac, 0x47, 0xb1, 0x54, 0x92, 0x94, 0x66, 0x5a, 0xfd, 0x53, 0x01, 0x76, 0x8c, 0x28, 0x6a,
+ 0xe5, 0xc4, 0xee, 0x94, 0x67, 0xc7, 0xb1, 0x8c, 0xf5, 0x0f, 0x05, 0x28, 0x65, 0xbf, 0x4c, 0xd9,
+ 0x47, 0x52, 0x86, 0x62, 0xf7, 0xc2, 0x34, 0xed, 0x6e, 0x57, 0xfb, 0x8d, 0x54, 0x61, 0xe3, 0xa2,
+ 0xfd, 0xbc, 0xed, 0x5e, 0xb6, 0x69, 0xd7, 0x74, 0x3b, 0xb6, 0x56, 0x22, 0x7f, 0x41, 0xa5, 0xe1,
+ 0xb8, 0x0d, 0xda, 0x73, 0x5d, 0xea, 0x18, 0x5e, 0xd3, 0xd6, 0x3e, 0x17, 0xc9, 0x36, 0x54, 0x2d,
+ 0xdb, 0xb0, 0x9c, 0x56, 0xdb, 0xa6, 0xf6, 0x95, 0x69, 0xdb, 0x96, 0x6d, 0x69, 0x5f, 0x8a, 0xa4,
+ 0x06, 0x9b, 0x6d, 0xb7, 0x47, 0x0d, 0xfa, 0xd2, 0x70, 0x5a, 0x16, 0x35, 0x3a, 0x1d, 0xed, 0x6b,
+ 0x91, 0x90, 0xb9, 0xab, 0xed, 0x79, 0xae, 0xa7, 0x7d, 0x2b, 0x12, 0x0d, 0xca, 0x19, 0xd3, 0x71,
+ 0xdc, 0x4b, 0xdb, 0xd2, 0xbe, 0xcf, 0xb4, 0xad, 0xf3, 0x8e, 0x63, 0x9f, 0xdb, 0xed, 0x9e, 0x6d,
+ 0x69, 0x3f, 0x8a, 0xfa, 0x13, 0xa8, 0x76, 0x79, 0x20, 0x9e, 0xc9, 0xd8, 0x88, 0x22, 0x0f, 0xdf,
+ 0x8e, 0x30, 0x51, 0x44, 0x87, 0x8d, 0xeb, 0x89, 0xc2, 0x84, 0x2a, 0x49, 0x13, 0x1e, 0x88, 0xdd,
+ 0xc2, 0x61, 0xe1, 0x78, 0xdd, 0x2b, 0x67, 0x60, 0x4f, 0xa6, 0x02, 0xfd, 0x0a, 0xc8, 0xa2, 0x30,
+ 0x89, 0xa4, 0x48, 0x90, 0xfc, 0x0d, 0x7f, 0x0e, 0x70, 0x42, 0x85, 0x1f, 0x62, 0x26, 0x2a, 0x79,
+ 0xc5, 0x01, 0x4e, 0xda, 0x7e, 0x88, 0xe4, 0x7f, 0xd8, 0x4c, 0xbd, 0x7c, 0x35, 0x8a, 0x91, 0x66,
+ 0x4e, 0xbb, 0xbf, 0x67, 0xb6, 0x95, 0x19, 0xdc, 0x48, 0x51, 0xfd, 0x3f, 0x38, 0x6a, 0xa2, 0xea,
+ 0x8c, 0xae, 0x87, 0x9c, 0x99, 0x18, 0x2b, 0x7e, 0xc3, 0x99, 0xaf, 0x70, 0x29, 0xa2, 0xfe, 0x1a,
+ 0xaa, 0xf7, 0x18, 0x0f, 0xbd, 0xfd, 0x14, 0x6a, 0xe3, 0xb3, 0xd3, 0xa7, 0x94, 0xcd, 0xe9, 0x34,
+ 0xc2, 0x30, 0x8b, 0x50, 0xf2, 0x48, 0x3a, 0x5b, 0x70, 0xea, 0x60, 0xa8, 0x7f, 0x2c, 0x80, 0xfe,
+ 0x50, 0x8e, 0x7c, 0xe3, 0x1e, 0xec, 0x44, 0x19, 0x65, 0xc9, 0x7a, 0xc8, 0x13, 0xb5, 0x5b, 0x38,
+ 0x5c, 0x3b, 0x2e, 0x3f, 0xde, 0xab, 0xcf, 0xce, 0xa6, 0x7e, 0xcf, 0xcc, 0xdb, 0x8a, 0xee, 0x42,
+ 0x0e, 0x4f, 0x14, 0x31, 0xe1, 0x20, 0xf4, 0xc7, 0x94, 0x0d, 0x39, 0x0a, 0x45, 0x99, 0xcf, 0xde,
+ 0x20, 0x55, 0x3c, 0x44, 0xca, 0x05, 0x4d, 0x90, 0x49, 0xd1, 0xcf, 0x92, 0xaf, 0x79, 0xff, 0x84,
+ 0xfe, 0xd8, 0xcc, 0x58, 0x66, 0x4a, 0xea, 0xf1, 0x10, 0x5b, 0xa2, 0x9b, 0x31, 0xf4, 0x7d, 0xd8,
+ 0x6b, 0xa2, 0xca, 0x6f, 0xd3, 0x60, 0x4c, 0x8e, 0x84, 0x4a, 0xcb, 0xb8, 0xed, 0xf0, 0x05, 0xfc,
+ 0xbb, 0x62, 0x9e, 0xef, 0x76, 0x0a, 0xb5, 0xfc, 0x1f, 0x40, 0xfd, 0xe9, 0x78, 0xb1, 0x5b, 0x92,
+ 0xdc, 0x53, 0xea, 0xef, 0x0b, 0xb0, 0xd5, 0x44, 0x65, 0x30, 0x86, 0x49, 0xd2, 0x93, 0x03, 0x14,
+ 0xb7, 0x37, 0x55, 0x83, 0x3f, 0x12, 0x26, 0x23, 0xcc, 0x5a, 0x29, 0x79, 0xd3, 0x07, 0xf2, 0x08,
+ 0xc8, 0xdd, 0x37, 0xf0, 0xdb, 0xd5, 0xb4, 0x65, 0xff, 0x56, 0x7f, 0x65, 0x9e, 0xb5, 0x95, 0x79,
+ 0xfa, 0xb0, 0x7d, 0x37, 0x4e, 0xbe, 0xdb, 0x11, 0xac, 0xfb, 0x19, 0x4c, 0x55, 0x8a, 0xe7, 0x3b,
+ 0x95, 0xfd, 0x39, 0x35, 0xbd, 0x58, 0x1c, 0x47, 0x3c, 0xf6, 0x15, 0x97, 0x22, 0xab, 0x3f, 0x4f,
+ 0x56, 0x99, 0xc3, 0x69, 0xe1, 0xfa, 0x21, 0xec, 0x37, 0x51, 0x59, 0x78, 0xe3, 0x8f, 0x86, 0xaa,
+ 0xc9, 0x92, 0xc6, 0x88, 0x0d, 0x70, 0xa9, 0xea, 0x2b, 0x38, 0x58, 0xc9, 0xc8, 0x03, 0x9d, 0xc1,
+ 0x4e, 0x7f, 0x3a, 0xa7, 0x01, 0x4b, 0xe8, 0x75, 0xc6, 0x58, 0xec, 0xbb, 0xd6, 0xff, 0x85, 0xbc,
+ 0x51, 0x79, 0xb5, 0xbe, 0xf8, 0xc9, 0xfa, 0x19, 0x00, 0x00, 0xff, 0xff, 0x37, 0x4c, 0x56, 0x38,
+ 0xf3, 0x04, 0x00, 0x00,
+}
diff --git a/vendor/google.golang.org/appengine/internal/app_identity/app_identity_service.proto b/vendor/google.golang.org/appengine/internal/app_identity/app_identity_service.proto
new file mode 100644
index 000000000..19610ca5b
--- /dev/null
+++ b/vendor/google.golang.org/appengine/internal/app_identity/app_identity_service.proto
@@ -0,0 +1,64 @@
+syntax = "proto2";
+option go_package = "app_identity";
+
+package appengine;
+
+message AppIdentityServiceError {
+ enum ErrorCode {
+ SUCCESS = 0;
+ UNKNOWN_SCOPE = 9;
+ BLOB_TOO_LARGE = 1000;
+ DEADLINE_EXCEEDED = 1001;
+ NOT_A_VALID_APP = 1002;
+ UNKNOWN_ERROR = 1003;
+ NOT_ALLOWED = 1005;
+ NOT_IMPLEMENTED = 1006;
+ }
+}
+
+message SignForAppRequest {
+ optional bytes bytes_to_sign = 1;
+}
+
+message SignForAppResponse {
+ optional string key_name = 1;
+ optional bytes signature_bytes = 2;
+}
+
+message GetPublicCertificateForAppRequest {
+}
+
+message PublicCertificate {
+ optional string key_name = 1;
+ optional string x509_certificate_pem = 2;
+}
+
+message GetPublicCertificateForAppResponse {
+ repeated PublicCertificate public_certificate_list = 1;
+ optional int64 max_client_cache_time_in_second = 2;
+}
+
+message GetServiceAccountNameRequest {
+}
+
+message GetServiceAccountNameResponse {
+ optional string service_account_name = 1;
+}
+
+message GetAccessTokenRequest {
+ repeated string scope = 1;
+ optional int64 service_account_id = 2;
+ optional string service_account_name = 3;
+}
+
+message GetAccessTokenResponse {
+ optional string access_token = 1;
+ optional int64 expiration_time = 2;
+}
+
+message GetDefaultGcsBucketNameRequest {
+}
+
+message GetDefaultGcsBucketNameResponse {
+ optional string default_gcs_bucket_name = 1;
+}
diff --git a/vendor/google.golang.org/appengine/internal/identity.go b/vendor/google.golang.org/appengine/internal/identity.go
new file mode 100644
index 000000000..9b4134e42
--- /dev/null
+++ b/vendor/google.golang.org/appengine/internal/identity.go
@@ -0,0 +1,55 @@
+// Copyright 2011 Google Inc. All rights reserved.
+// Use of this source code is governed by the Apache 2.0
+// license that can be found in the LICENSE file.
+
+package internal
+
+import (
+ "os"
+
+ netcontext "golang.org/x/net/context"
+)
+
+var (
+ // This is set to true in identity_classic.go, which is behind the appengine build tag.
+ // The appengine build tag is set for the first generation runtimes (<= Go 1.9) but not
+ // the second generation runtimes (>= Go 1.11), so this indicates whether we're on a
+ // first-gen runtime. See IsStandard below for the second-gen check.
+ appengineStandard bool
+
+ // This is set to true in identity_flex.go, which is behind the appenginevm build tag.
+ appengineFlex bool
+)
+
+// AppID is the implementation of the wrapper function of the same name in
+// ../identity.go. See that file for commentary.
+func AppID(c netcontext.Context) string {
+ return appID(FullyQualifiedAppID(c))
+}
+
+// IsStandard is the implementation of the wrapper function of the same name in
+// ../appengine.go. See that file for commentary.
+func IsStandard() bool {
+ // appengineStandard will be true for first-gen runtimes (<= Go 1.9) but not
+ // second-gen (>= Go 1.11).
+ return appengineStandard || IsSecondGen()
+}
+
+// IsStandard is the implementation of the wrapper function of the same name in
+// ../appengine.go. See that file for commentary.
+func IsSecondGen() bool {
+ // Second-gen runtimes set $GAE_ENV so we use that to check if we're on a second-gen runtime.
+ return os.Getenv("GAE_ENV") == "standard"
+}
+
+// IsFlex is the implementation of the wrapper function of the same name in
+// ../appengine.go. See that file for commentary.
+func IsFlex() bool {
+ return appengineFlex
+}
+
+// IsAppEngine is the implementation of the wrapper function of the same name in
+// ../appengine.go. See that file for commentary.
+func IsAppEngine() bool {
+ return IsStandard() || IsFlex()
+}
diff --git a/vendor/google.golang.org/appengine/internal/identity_classic.go b/vendor/google.golang.org/appengine/internal/identity_classic.go
new file mode 100644
index 000000000..4e979f45e
--- /dev/null
+++ b/vendor/google.golang.org/appengine/internal/identity_classic.go
@@ -0,0 +1,61 @@
+// Copyright 2015 Google Inc. All rights reserved.
+// Use of this source code is governed by the Apache 2.0
+// license that can be found in the LICENSE file.
+
+// +build appengine
+
+package internal
+
+import (
+ "appengine"
+
+ netcontext "golang.org/x/net/context"
+)
+
+func init() {
+ appengineStandard = true
+}
+
+func DefaultVersionHostname(ctx netcontext.Context) string {
+ c := fromContext(ctx)
+ if c == nil {
+ panic(errNotAppEngineContext)
+ }
+ return appengine.DefaultVersionHostname(c)
+}
+
+func Datacenter(_ netcontext.Context) string { return appengine.Datacenter() }
+func ServerSoftware() string { return appengine.ServerSoftware() }
+func InstanceID() string { return appengine.InstanceID() }
+func IsDevAppServer() bool { return appengine.IsDevAppServer() }
+
+func RequestID(ctx netcontext.Context) string {
+ c := fromContext(ctx)
+ if c == nil {
+ panic(errNotAppEngineContext)
+ }
+ return appengine.RequestID(c)
+}
+
+func ModuleName(ctx netcontext.Context) string {
+ c := fromContext(ctx)
+ if c == nil {
+ panic(errNotAppEngineContext)
+ }
+ return appengine.ModuleName(c)
+}
+func VersionID(ctx netcontext.Context) string {
+ c := fromContext(ctx)
+ if c == nil {
+ panic(errNotAppEngineContext)
+ }
+ return appengine.VersionID(c)
+}
+
+func fullyQualifiedAppID(ctx netcontext.Context) string {
+ c := fromContext(ctx)
+ if c == nil {
+ panic(errNotAppEngineContext)
+ }
+ return c.FullyQualifiedAppID()
+}
diff --git a/vendor/google.golang.org/appengine/internal/identity_flex.go b/vendor/google.golang.org/appengine/internal/identity_flex.go
new file mode 100644
index 000000000..d5e2e7b5e
--- /dev/null
+++ b/vendor/google.golang.org/appengine/internal/identity_flex.go
@@ -0,0 +1,11 @@
+// Copyright 2018 Google LLC. All rights reserved.
+// Use of this source code is governed by the Apache 2.0
+// license that can be found in the LICENSE file.
+
+// +build appenginevm
+
+package internal
+
+func init() {
+ appengineFlex = true
+}
diff --git a/vendor/google.golang.org/appengine/internal/identity_vm.go b/vendor/google.golang.org/appengine/internal/identity_vm.go
new file mode 100644
index 000000000..5d8067263
--- /dev/null
+++ b/vendor/google.golang.org/appengine/internal/identity_vm.go
@@ -0,0 +1,134 @@
+// Copyright 2011 Google Inc. All rights reserved.
+// Use of this source code is governed by the Apache 2.0
+// license that can be found in the LICENSE file.
+
+// +build !appengine
+
+package internal
+
+import (
+ "log"
+ "net/http"
+ "os"
+ "strings"
+
+ netcontext "golang.org/x/net/context"
+)
+
+// These functions are implementations of the wrapper functions
+// in ../appengine/identity.go. See that file for commentary.
+
+const (
+ hDefaultVersionHostname = "X-AppEngine-Default-Version-Hostname"
+ hRequestLogId = "X-AppEngine-Request-Log-Id"
+ hDatacenter = "X-AppEngine-Datacenter"
+)
+
+func ctxHeaders(ctx netcontext.Context) http.Header {
+ c := fromContext(ctx)
+ if c == nil {
+ return nil
+ }
+ return c.Request().Header
+}
+
+func DefaultVersionHostname(ctx netcontext.Context) string {
+ return ctxHeaders(ctx).Get(hDefaultVersionHostname)
+}
+
+func RequestID(ctx netcontext.Context) string {
+ return ctxHeaders(ctx).Get(hRequestLogId)
+}
+
+func Datacenter(ctx netcontext.Context) string {
+ if dc := ctxHeaders(ctx).Get(hDatacenter); dc != "" {
+ return dc
+ }
+ // If the header isn't set, read zone from the metadata service.
+ // It has the format projects/[NUMERIC_PROJECT_ID]/zones/[ZONE]
+ zone, err := getMetadata("instance/zone")
+ if err != nil {
+ log.Printf("Datacenter: %v", err)
+ return ""
+ }
+ parts := strings.Split(string(zone), "/")
+ if len(parts) == 0 {
+ return ""
+ }
+ return parts[len(parts)-1]
+}
+
+func ServerSoftware() string {
+ // TODO(dsymonds): Remove fallback when we've verified this.
+ if s := os.Getenv("SERVER_SOFTWARE"); s != "" {
+ return s
+ }
+ if s := os.Getenv("GAE_ENV"); s != "" {
+ return s
+ }
+ return "Google App Engine/1.x.x"
+}
+
+// TODO(dsymonds): Remove the metadata fetches.
+
+func ModuleName(_ netcontext.Context) string {
+ if s := os.Getenv("GAE_MODULE_NAME"); s != "" {
+ return s
+ }
+ if s := os.Getenv("GAE_SERVICE"); s != "" {
+ return s
+ }
+ return string(mustGetMetadata("instance/attributes/gae_backend_name"))
+}
+
+func VersionID(_ netcontext.Context) string {
+ if s1, s2 := os.Getenv("GAE_MODULE_VERSION"), os.Getenv("GAE_MINOR_VERSION"); s1 != "" && s2 != "" {
+ return s1 + "." + s2
+ }
+ if s1, s2 := os.Getenv("GAE_VERSION"), os.Getenv("GAE_DEPLOYMENT_ID"); s1 != "" && s2 != "" {
+ return s1 + "." + s2
+ }
+ return string(mustGetMetadata("instance/attributes/gae_backend_version")) + "." + string(mustGetMetadata("instance/attributes/gae_backend_minor_version"))
+}
+
+func InstanceID() string {
+ if s := os.Getenv("GAE_MODULE_INSTANCE"); s != "" {
+ return s
+ }
+ if s := os.Getenv("GAE_INSTANCE"); s != "" {
+ return s
+ }
+ return string(mustGetMetadata("instance/attributes/gae_backend_instance"))
+}
+
+func partitionlessAppID() string {
+ // gae_project has everything except the partition prefix.
+ if appID := os.Getenv("GAE_LONG_APP_ID"); appID != "" {
+ return appID
+ }
+ if project := os.Getenv("GOOGLE_CLOUD_PROJECT"); project != "" {
+ return project
+ }
+ return string(mustGetMetadata("instance/attributes/gae_project"))
+}
+
+func fullyQualifiedAppID(_ netcontext.Context) string {
+ if s := os.Getenv("GAE_APPLICATION"); s != "" {
+ return s
+ }
+ appID := partitionlessAppID()
+
+ part := os.Getenv("GAE_PARTITION")
+ if part == "" {
+ part = string(mustGetMetadata("instance/attributes/gae_partition"))
+ }
+
+ if part != "" {
+ appID = part + "~" + appID
+ }
+ return appID
+}
+
+func IsDevAppServer() bool {
+ return os.Getenv("RUN_WITH_DEVAPPSERVER") != ""
+}
diff --git a/vendor/google.golang.org/appengine/internal/internal.go b/vendor/google.golang.org/appengine/internal/internal.go
new file mode 100644
index 000000000..051ea3980
--- /dev/null
+++ b/vendor/google.golang.org/appengine/internal/internal.go
@@ -0,0 +1,110 @@
+// Copyright 2011 Google Inc. All rights reserved.
+// Use of this source code is governed by the Apache 2.0
+// license that can be found in the LICENSE file.
+
+// Package internal provides support for package appengine.
+//
+// Programs should not use this package directly. Its API is not stable.
+// Use packages appengine and appengine/* instead.
+package internal
+
+import (
+ "fmt"
+
+ "github.com/golang/protobuf/proto"
+
+ remotepb "google.golang.org/appengine/internal/remote_api"
+)
+
+// errorCodeMaps is a map of service name to the error code map for the service.
+var errorCodeMaps = make(map[string]map[int32]string)
+
+// RegisterErrorCodeMap is called from API implementations to register their
+// error code map. This should only be called from init functions.
+func RegisterErrorCodeMap(service string, m map[int32]string) {
+ errorCodeMaps[service] = m
+}
+
+type timeoutCodeKey struct {
+ service string
+ code int32
+}
+
+// timeoutCodes is the set of service+code pairs that represent timeouts.
+var timeoutCodes = make(map[timeoutCodeKey]bool)
+
+func RegisterTimeoutErrorCode(service string, code int32) {
+ timeoutCodes[timeoutCodeKey{service, code}] = true
+}
+
+// APIError is the type returned by appengine.Context's Call method
+// when an API call fails in an API-specific way. This may be, for instance,
+// a taskqueue API call failing with TaskQueueServiceError::UNKNOWN_QUEUE.
+type APIError struct {
+ Service string
+ Detail string
+ Code int32 // API-specific error code
+}
+
+func (e *APIError) Error() string {
+ if e.Code == 0 {
+ if e.Detail == "" {
+ return "APIError <empty>"
+ }
+ return e.Detail
+ }
+ s := fmt.Sprintf("API error %d", e.Code)
+ if m, ok := errorCodeMaps[e.Service]; ok {
+ s += " (" + e.Service + ": " + m[e.Code] + ")"
+ } else {
+ // Shouldn't happen, but provide a bit more detail if it does.
+ s = e.Service + " " + s
+ }
+ if e.Detail != "" {
+ s += ": " + e.Detail
+ }
+ return s
+}
+
+func (e *APIError) IsTimeout() bool {
+ return timeoutCodes[timeoutCodeKey{e.Service, e.Code}]
+}
+
+// CallError is the type returned by appengine.Context's Call method when an
+// API call fails in a generic way, such as RpcError::CAPABILITY_DISABLED.
+type CallError struct {
+ Detail string
+ Code int32
+ // TODO: Remove this if we get a distinguishable error code.
+ Timeout bool
+}
+
+func (e *CallError) Error() string {
+ var msg string
+ switch remotepb.RpcError_ErrorCode(e.Code) {
+ case remotepb.RpcError_UNKNOWN:
+ return e.Detail
+ case remotepb.RpcError_OVER_QUOTA:
+ msg = "Over quota"
+ case remotepb.RpcError_CAPABILITY_DISABLED:
+ msg = "Capability disabled"
+ case remotepb.RpcError_CANCELLED:
+ msg = "Canceled"
+ default:
+ msg = fmt.Sprintf("Call error %d", e.Code)
+ }
+ s := msg + ": " + e.Detail
+ if e.Timeout {
+ s += " (timeout)"
+ }
+ return s
+}
+
+func (e *CallError) IsTimeout() bool {
+ return e.Timeout
+}
+
+// NamespaceMods is a map from API service to a function that will mutate an RPC request to attach a namespace.
+// The function should be prepared to be called on the same message more than once; it should only modify the
+// RPC request the first time.
+var NamespaceMods = make(map[string]func(m proto.Message, namespace string))
diff --git a/vendor/google.golang.org/appengine/internal/main.go b/vendor/google.golang.org/appengine/internal/main.go
new file mode 100644
index 000000000..49036163c
--- /dev/null
+++ b/vendor/google.golang.org/appengine/internal/main.go
@@ -0,0 +1,15 @@
+// Copyright 2011 Google Inc. All rights reserved.
+// Use of this source code is governed by the Apache 2.0
+// license that can be found in the LICENSE file.
+
+// +build appengine
+
+package internal
+
+import (
+ "appengine_internal"
+)
+
+func Main() {
+ appengine_internal.Main()
+}
diff --git a/vendor/google.golang.org/appengine/internal/main_vm.go b/vendor/google.golang.org/appengine/internal/main_vm.go
new file mode 100644
index 000000000..822e784a4
--- /dev/null
+++ b/vendor/google.golang.org/appengine/internal/main_vm.go
@@ -0,0 +1,48 @@
+// Copyright 2011 Google Inc. All rights reserved.
+// Use of this source code is governed by the Apache 2.0
+// license that can be found in the LICENSE file.
+
+// +build !appengine
+
+package internal
+
+import (
+ "io"
+ "log"
+ "net/http"
+ "net/url"
+ "os"
+)
+
+func Main() {
+ installHealthChecker(http.DefaultServeMux)
+
+ port := "8080"
+ if s := os.Getenv("PORT"); s != "" {
+ port = s
+ }
+
+ host := ""
+ if IsDevAppServer() {
+ host = "127.0.0.1"
+ }
+ if err := http.ListenAndServe(host+":"+port, http.HandlerFunc(handleHTTP)); err != nil {
+ log.Fatalf("http.ListenAndServe: %v", err)
+ }
+}
+
+func installHealthChecker(mux *http.ServeMux) {
+ // If no health check handler has been installed by this point, add a trivial one.
+ const healthPath = "/_ah/health"
+ hreq := &http.Request{
+ Method: "GET",
+ URL: &url.URL{
+ Path: healthPath,
+ },
+ }
+ if _, pat := mux.Handler(hreq); pat != healthPath {
+ mux.HandleFunc(healthPath, func(w http.ResponseWriter, r *http.Request) {
+ io.WriteString(w, "ok")
+ })
+ }
+}
diff --git a/vendor/google.golang.org/appengine/internal/metadata.go b/vendor/google.golang.org/appengine/internal/metadata.go
new file mode 100644
index 000000000..c4ba63bb4
--- /dev/null
+++ b/vendor/google.golang.org/appengine/internal/metadata.go
@@ -0,0 +1,60 @@
+// Copyright 2014 Google Inc. All rights reserved.
+// Use of this source code is governed by the Apache 2.0
+// license that can be found in the LICENSE file.
+
+package internal
+
+// This file has code for accessing metadata.
+//
+// References:
+// https://cloud.google.com/compute/docs/metadata
+
+import (
+ "fmt"
+ "io/ioutil"
+ "net/http"
+ "net/url"
+)
+
+const (
+ metadataHost = "metadata"
+ metadataPath = "/computeMetadata/v1/"
+)
+
+var (
+ metadataRequestHeaders = http.Header{
+ "Metadata-Flavor": []string{"Google"},
+ }
+)
+
+// TODO(dsymonds): Do we need to support default values, like Python?
+func mustGetMetadata(key string) []byte {
+ b, err := getMetadata(key)
+ if err != nil {
+ panic(fmt.Sprintf("Metadata fetch failed for '%s': %v", key, err))
+ }
+ return b
+}
+
+func getMetadata(key string) ([]byte, error) {
+ // TODO(dsymonds): May need to use url.Parse to support keys with query args.
+ req := &http.Request{
+ Method: "GET",
+ URL: &url.URL{
+ Scheme: "http",
+ Host: metadataHost,
+ Path: metadataPath + key,
+ },
+ Header: metadataRequestHeaders,
+ Host: metadataHost,
+ }
+ resp, err := http.DefaultClient.Do(req)
+ if err != nil {
+ return nil, err
+ }
+ defer resp.Body.Close()
+ if resp.StatusCode != 200 {
+ return nil, fmt.Errorf("metadata server returned HTTP %d", resp.StatusCode)
+ }
+ return ioutil.ReadAll(resp.Body)
+}
diff --git a/vendor/google.golang.org/appengine/internal/modules/modules_service.pb.go b/vendor/google.golang.org/appengine/internal/modules/modules_service.pb.go
new file mode 100644
index 000000000..ddfc0c04a
--- /dev/null
+++ b/vendor/google.golang.org/appengine/internal/modules/modules_service.pb.go
@@ -0,0 +1,786 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// source: google.golang.org/appengine/internal/modules/modules_service.proto
+
+package modules
+
+import proto "github.com/golang/protobuf/proto"
+import fmt "fmt"
+import math "math"
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
+
+type ModulesServiceError_ErrorCode int32
+
+const (
+ ModulesServiceError_OK ModulesServiceError_ErrorCode = 0
+ ModulesServiceError_INVALID_MODULE ModulesServiceError_ErrorCode = 1
+ ModulesServiceError_INVALID_VERSION ModulesServiceError_ErrorCode = 2
+ ModulesServiceError_INVALID_INSTANCES ModulesServiceError_ErrorCode = 3
+ ModulesServiceError_TRANSIENT_ERROR ModulesServiceError_ErrorCode = 4
+ ModulesServiceError_UNEXPECTED_STATE ModulesServiceError_ErrorCode = 5
+)
+
+var ModulesServiceError_ErrorCode_name = map[int32]string{
+ 0: "OK",
+ 1: "INVALID_MODULE",
+ 2: "INVALID_VERSION",
+ 3: "INVALID_INSTANCES",
+ 4: "TRANSIENT_ERROR",
+ 5: "UNEXPECTED_STATE",
+}
+var ModulesServiceError_ErrorCode_value = map[string]int32{
+ "OK": 0,
+ "INVALID_MODULE": 1,
+ "INVALID_VERSION": 2,
+ "INVALID_INSTANCES": 3,
+ "TRANSIENT_ERROR": 4,
+ "UNEXPECTED_STATE": 5,
+}
+
+func (x ModulesServiceError_ErrorCode) Enum() *ModulesServiceError_ErrorCode {
+ p := new(ModulesServiceError_ErrorCode)
+ *p = x
+ return p
+}
+func (x ModulesServiceError_ErrorCode) String() string {
+ return proto.EnumName(ModulesServiceError_ErrorCode_name, int32(x))
+}
+func (x *ModulesServiceError_ErrorCode) UnmarshalJSON(data []byte) error {
+ value, err := proto.UnmarshalJSONEnum(ModulesServiceError_ErrorCode_value, data, "ModulesServiceError_ErrorCode")
+ if err != nil {
+ return err
+ }
+ *x = ModulesServiceError_ErrorCode(value)
+ return nil
+}
+func (ModulesServiceError_ErrorCode) EnumDescriptor() ([]byte, []int) {
+ return fileDescriptor_modules_service_9cd3bffe4e91c59a, []int{0, 0}
+}
+
+type ModulesServiceError struct {
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *ModulesServiceError) Reset() { *m = ModulesServiceError{} }
+func (m *ModulesServiceError) String() string { return proto.CompactTextString(m) }
+func (*ModulesServiceError) ProtoMessage() {}
+func (*ModulesServiceError) Descriptor() ([]byte, []int) {
+ return fileDescriptor_modules_service_9cd3bffe4e91c59a, []int{0}
+}
+func (m *ModulesServiceError) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_ModulesServiceError.Unmarshal(m, b)
+}
+func (m *ModulesServiceError) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_ModulesServiceError.Marshal(b, m, deterministic)
+}
+func (dst *ModulesServiceError) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_ModulesServiceError.Merge(dst, src)
+}
+func (m *ModulesServiceError) XXX_Size() int {
+ return xxx_messageInfo_ModulesServiceError.Size(m)
+}
+func (m *ModulesServiceError) XXX_DiscardUnknown() {
+ xxx_messageInfo_ModulesServiceError.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_ModulesServiceError proto.InternalMessageInfo
+
+type GetModulesRequest struct {
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *GetModulesRequest) Reset() { *m = GetModulesRequest{} }
+func (m *GetModulesRequest) String() string { return proto.CompactTextString(m) }
+func (*GetModulesRequest) ProtoMessage() {}
+func (*GetModulesRequest) Descriptor() ([]byte, []int) {
+ return fileDescriptor_modules_service_9cd3bffe4e91c59a, []int{1}
+}
+func (m *GetModulesRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GetModulesRequest.Unmarshal(m, b)
+}
+func (m *GetModulesRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GetModulesRequest.Marshal(b, m, deterministic)
+}
+func (dst *GetModulesRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GetModulesRequest.Merge(dst, src)
+}
+func (m *GetModulesRequest) XXX_Size() int {
+ return xxx_messageInfo_GetModulesRequest.Size(m)
+}
+func (m *GetModulesRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_GetModulesRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetModulesRequest proto.InternalMessageInfo
+
+type GetModulesResponse struct {
+ Module []string `protobuf:"bytes,1,rep,name=module" json:"module,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *GetModulesResponse) Reset() { *m = GetModulesResponse{} }
+func (m *GetModulesResponse) String() string { return proto.CompactTextString(m) }
+func (*GetModulesResponse) ProtoMessage() {}
+func (*GetModulesResponse) Descriptor() ([]byte, []int) {
+ return fileDescriptor_modules_service_9cd3bffe4e91c59a, []int{2}
+}
+func (m *GetModulesResponse) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GetModulesResponse.Unmarshal(m, b)
+}
+func (m *GetModulesResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GetModulesResponse.Marshal(b, m, deterministic)
+}
+func (dst *GetModulesResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GetModulesResponse.Merge(dst, src)
+}
+func (m *GetModulesResponse) XXX_Size() int {
+ return xxx_messageInfo_GetModulesResponse.Size(m)
+}
+func (m *GetModulesResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_GetModulesResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetModulesResponse proto.InternalMessageInfo
+
+func (m *GetModulesResponse) GetModule() []string {
+ if m != nil {
+ return m.Module
+ }
+ return nil
+}
+
+type GetVersionsRequest struct {
+ Module *string `protobuf:"bytes,1,opt,name=module" json:"module,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *GetVersionsRequest) Reset() { *m = GetVersionsRequest{} }
+func (m *GetVersionsRequest) String() string { return proto.CompactTextString(m) }
+func (*GetVersionsRequest) ProtoMessage() {}
+func (*GetVersionsRequest) Descriptor() ([]byte, []int) {
+ return fileDescriptor_modules_service_9cd3bffe4e91c59a, []int{3}
+}
+func (m *GetVersionsRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GetVersionsRequest.Unmarshal(m, b)
+}
+func (m *GetVersionsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GetVersionsRequest.Marshal(b, m, deterministic)
+}
+func (dst *GetVersionsRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GetVersionsRequest.Merge(dst, src)
+}
+func (m *GetVersionsRequest) XXX_Size() int {
+ return xxx_messageInfo_GetVersionsRequest.Size(m)
+}
+func (m *GetVersionsRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_GetVersionsRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetVersionsRequest proto.InternalMessageInfo
+
+func (m *GetVersionsRequest) GetModule() string {
+ if m != nil && m.Module != nil {
+ return *m.Module
+ }
+ return ""
+}
+
+type GetVersionsResponse struct {
+ Version []string `protobuf:"bytes,1,rep,name=version" json:"version,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *GetVersionsResponse) Reset() { *m = GetVersionsResponse{} }
+func (m *GetVersionsResponse) String() string { return proto.CompactTextString(m) }
+func (*GetVersionsResponse) ProtoMessage() {}
+func (*GetVersionsResponse) Descriptor() ([]byte, []int) {
+ return fileDescriptor_modules_service_9cd3bffe4e91c59a, []int{4}
+}
+func (m *GetVersionsResponse) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GetVersionsResponse.Unmarshal(m, b)
+}
+func (m *GetVersionsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GetVersionsResponse.Marshal(b, m, deterministic)
+}
+func (dst *GetVersionsResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GetVersionsResponse.Merge(dst, src)
+}
+func (m *GetVersionsResponse) XXX_Size() int {
+ return xxx_messageInfo_GetVersionsResponse.Size(m)
+}
+func (m *GetVersionsResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_GetVersionsResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetVersionsResponse proto.InternalMessageInfo
+
+func (m *GetVersionsResponse) GetVersion() []string {
+ if m != nil {
+ return m.Version
+ }
+ return nil
+}
+
+type GetDefaultVersionRequest struct {
+ Module *string `protobuf:"bytes,1,opt,name=module" json:"module,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *GetDefaultVersionRequest) Reset() { *m = GetDefaultVersionRequest{} }
+func (m *GetDefaultVersionRequest) String() string { return proto.CompactTextString(m) }
+func (*GetDefaultVersionRequest) ProtoMessage() {}
+func (*GetDefaultVersionRequest) Descriptor() ([]byte, []int) {
+ return fileDescriptor_modules_service_9cd3bffe4e91c59a, []int{5}
+}
+func (m *GetDefaultVersionRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GetDefaultVersionRequest.Unmarshal(m, b)
+}
+func (m *GetDefaultVersionRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GetDefaultVersionRequest.Marshal(b, m, deterministic)
+}
+func (dst *GetDefaultVersionRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GetDefaultVersionRequest.Merge(dst, src)
+}
+func (m *GetDefaultVersionRequest) XXX_Size() int {
+ return xxx_messageInfo_GetDefaultVersionRequest.Size(m)
+}
+func (m *GetDefaultVersionRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_GetDefaultVersionRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetDefaultVersionRequest proto.InternalMessageInfo
+
+func (m *GetDefaultVersionRequest) GetModule() string {
+ if m != nil && m.Module != nil {
+ return *m.Module
+ }
+ return ""
+}
+
+type GetDefaultVersionResponse struct {
+ Version *string `protobuf:"bytes,1,req,name=version" json:"version,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *GetDefaultVersionResponse) Reset() { *m = GetDefaultVersionResponse{} }
+func (m *GetDefaultVersionResponse) String() string { return proto.CompactTextString(m) }
+func (*GetDefaultVersionResponse) ProtoMessage() {}
+func (*GetDefaultVersionResponse) Descriptor() ([]byte, []int) {
+ return fileDescriptor_modules_service_9cd3bffe4e91c59a, []int{6}
+}
+func (m *GetDefaultVersionResponse) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GetDefaultVersionResponse.Unmarshal(m, b)
+}
+func (m *GetDefaultVersionResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GetDefaultVersionResponse.Marshal(b, m, deterministic)
+}
+func (dst *GetDefaultVersionResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GetDefaultVersionResponse.Merge(dst, src)
+}
+func (m *GetDefaultVersionResponse) XXX_Size() int {
+ return xxx_messageInfo_GetDefaultVersionResponse.Size(m)
+}
+func (m *GetDefaultVersionResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_GetDefaultVersionResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetDefaultVersionResponse proto.InternalMessageInfo
+
+func (m *GetDefaultVersionResponse) GetVersion() string {
+ if m != nil && m.Version != nil {
+ return *m.Version
+ }
+ return ""
+}
+
+type GetNumInstancesRequest struct {
+ Module *string `protobuf:"bytes,1,opt,name=module" json:"module,omitempty"`
+ Version *string `protobuf:"bytes,2,opt,name=version" json:"version,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *GetNumInstancesRequest) Reset() { *m = GetNumInstancesRequest{} }
+func (m *GetNumInstancesRequest) String() string { return proto.CompactTextString(m) }
+func (*GetNumInstancesRequest) ProtoMessage() {}
+func (*GetNumInstancesRequest) Descriptor() ([]byte, []int) {
+ return fileDescriptor_modules_service_9cd3bffe4e91c59a, []int{7}
+}
+func (m *GetNumInstancesRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GetNumInstancesRequest.Unmarshal(m, b)
+}
+func (m *GetNumInstancesRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GetNumInstancesRequest.Marshal(b, m, deterministic)
+}
+func (dst *GetNumInstancesRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GetNumInstancesRequest.Merge(dst, src)
+}
+func (m *GetNumInstancesRequest) XXX_Size() int {
+ return xxx_messageInfo_GetNumInstancesRequest.Size(m)
+}
+func (m *GetNumInstancesRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_GetNumInstancesRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetNumInstancesRequest proto.InternalMessageInfo
+
+func (m *GetNumInstancesRequest) GetModule() string {
+ if m != nil && m.Module != nil {
+ return *m.Module
+ }
+ return ""
+}
+
+func (m *GetNumInstancesRequest) GetVersion() string {
+ if m != nil && m.Version != nil {
+ return *m.Version
+ }
+ return ""
+}
+
+type GetNumInstancesResponse struct {
+ Instances *int64 `protobuf:"varint,1,req,name=instances" json:"instances,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *GetNumInstancesResponse) Reset() { *m = GetNumInstancesResponse{} }
+func (m *GetNumInstancesResponse) String() string { return proto.CompactTextString(m) }
+func (*GetNumInstancesResponse) ProtoMessage() {}
+func (*GetNumInstancesResponse) Descriptor() ([]byte, []int) {
+ return fileDescriptor_modules_service_9cd3bffe4e91c59a, []int{8}
+}
+func (m *GetNumInstancesResponse) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GetNumInstancesResponse.Unmarshal(m, b)
+}
+func (m *GetNumInstancesResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GetNumInstancesResponse.Marshal(b, m, deterministic)
+}
+func (dst *GetNumInstancesResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GetNumInstancesResponse.Merge(dst, src)
+}
+func (m *GetNumInstancesResponse) XXX_Size() int {
+ return xxx_messageInfo_GetNumInstancesResponse.Size(m)
+}
+func (m *GetNumInstancesResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_GetNumInstancesResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetNumInstancesResponse proto.InternalMessageInfo
+
+func (m *GetNumInstancesResponse) GetInstances() int64 {
+ if m != nil && m.Instances != nil {
+ return *m.Instances
+ }
+ return 0
+}
+
+type SetNumInstancesRequest struct {
+ Module *string `protobuf:"bytes,1,opt,name=module" json:"module,omitempty"`
+ Version *string `protobuf:"bytes,2,opt,name=version" json:"version,omitempty"`
+ Instances *int64 `protobuf:"varint,3,req,name=instances" json:"instances,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *SetNumInstancesRequest) Reset() { *m = SetNumInstancesRequest{} }
+func (m *SetNumInstancesRequest) String() string { return proto.CompactTextString(m) }
+func (*SetNumInstancesRequest) ProtoMessage() {}
+func (*SetNumInstancesRequest) Descriptor() ([]byte, []int) {
+ return fileDescriptor_modules_service_9cd3bffe4e91c59a, []int{9}
+}
+func (m *SetNumInstancesRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_SetNumInstancesRequest.Unmarshal(m, b)
+}
+func (m *SetNumInstancesRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_SetNumInstancesRequest.Marshal(b, m, deterministic)
+}
+func (dst *SetNumInstancesRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_SetNumInstancesRequest.Merge(dst, src)
+}
+func (m *SetNumInstancesRequest) XXX_Size() int {
+ return xxx_messageInfo_SetNumInstancesRequest.Size(m)
+}
+func (m *SetNumInstancesRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_SetNumInstancesRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_SetNumInstancesRequest proto.InternalMessageInfo
+
+func (m *SetNumInstancesRequest) GetModule() string {
+ if m != nil && m.Module != nil {
+ return *m.Module
+ }
+ return ""
+}
+
+func (m *SetNumInstancesRequest) GetVersion() string {
+ if m != nil && m.Version != nil {
+ return *m.Version
+ }
+ return ""
+}
+
+func (m *SetNumInstancesRequest) GetInstances() int64 {
+ if m != nil && m.Instances != nil {
+ return *m.Instances
+ }
+ return 0
+}
+
+type SetNumInstancesResponse struct {
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *SetNumInstancesResponse) Reset() { *m = SetNumInstancesResponse{} }
+func (m *SetNumInstancesResponse) String() string { return proto.CompactTextString(m) }
+func (*SetNumInstancesResponse) ProtoMessage() {}
+func (*SetNumInstancesResponse) Descriptor() ([]byte, []int) {
+ return fileDescriptor_modules_service_9cd3bffe4e91c59a, []int{10}
+}
+func (m *SetNumInstancesResponse) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_SetNumInstancesResponse.Unmarshal(m, b)
+}
+func (m *SetNumInstancesResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_SetNumInstancesResponse.Marshal(b, m, deterministic)
+}
+func (dst *SetNumInstancesResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_SetNumInstancesResponse.Merge(dst, src)
+}
+func (m *SetNumInstancesResponse) XXX_Size() int {
+ return xxx_messageInfo_SetNumInstancesResponse.Size(m)
+}
+func (m *SetNumInstancesResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_SetNumInstancesResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_SetNumInstancesResponse proto.InternalMessageInfo
+
+type StartModuleRequest struct {
+ Module *string `protobuf:"bytes,1,req,name=module" json:"module,omitempty"`
+ Version *string `protobuf:"bytes,2,req,name=version" json:"version,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *StartModuleRequest) Reset() { *m = StartModuleRequest{} }
+func (m *StartModuleRequest) String() string { return proto.CompactTextString(m) }
+func (*StartModuleRequest) ProtoMessage() {}
+func (*StartModuleRequest) Descriptor() ([]byte, []int) {
+ return fileDescriptor_modules_service_9cd3bffe4e91c59a, []int{11}
+}
+func (m *StartModuleRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_StartModuleRequest.Unmarshal(m, b)
+}
+func (m *StartModuleRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_StartModuleRequest.Marshal(b, m, deterministic)
+}
+func (dst *StartModuleRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_StartModuleRequest.Merge(dst, src)
+}
+func (m *StartModuleRequest) XXX_Size() int {
+ return xxx_messageInfo_StartModuleRequest.Size(m)
+}
+func (m *StartModuleRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_StartModuleRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_StartModuleRequest proto.InternalMessageInfo
+
+func (m *StartModuleRequest) GetModule() string {
+ if m != nil && m.Module != nil {
+ return *m.Module
+ }
+ return ""
+}
+
+func (m *StartModuleRequest) GetVersion() string {
+ if m != nil && m.Version != nil {
+ return *m.Version
+ }
+ return ""
+}
+
+type StartModuleResponse struct {
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *StartModuleResponse) Reset() { *m = StartModuleResponse{} }
+func (m *StartModuleResponse) String() string { return proto.CompactTextString(m) }
+func (*StartModuleResponse) ProtoMessage() {}
+func (*StartModuleResponse) Descriptor() ([]byte, []int) {
+ return fileDescriptor_modules_service_9cd3bffe4e91c59a, []int{12}
+}
+func (m *StartModuleResponse) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_StartModuleResponse.Unmarshal(m, b)
+}
+func (m *StartModuleResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_StartModuleResponse.Marshal(b, m, deterministic)
+}
+func (dst *StartModuleResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_StartModuleResponse.Merge(dst, src)
+}
+func (m *StartModuleResponse) XXX_Size() int {
+ return xxx_messageInfo_StartModuleResponse.Size(m)
+}
+func (m *StartModuleResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_StartModuleResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_StartModuleResponse proto.InternalMessageInfo
+
+type StopModuleRequest struct {
+ Module *string `protobuf:"bytes,1,opt,name=module" json:"module,omitempty"`
+ Version *string `protobuf:"bytes,2,opt,name=version" json:"version,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *StopModuleRequest) Reset() { *m = StopModuleRequest{} }
+func (m *StopModuleRequest) String() string { return proto.CompactTextString(m) }
+func (*StopModuleRequest) ProtoMessage() {}
+func (*StopModuleRequest) Descriptor() ([]byte, []int) {
+ return fileDescriptor_modules_service_9cd3bffe4e91c59a, []int{13}
+}
+func (m *StopModuleRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_StopModuleRequest.Unmarshal(m, b)
+}
+func (m *StopModuleRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_StopModuleRequest.Marshal(b, m, deterministic)
+}
+func (dst *StopModuleRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_StopModuleRequest.Merge(dst, src)
+}
+func (m *StopModuleRequest) XXX_Size() int {
+ return xxx_messageInfo_StopModuleRequest.Size(m)
+}
+func (m *StopModuleRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_StopModuleRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_StopModuleRequest proto.InternalMessageInfo
+
+func (m *StopModuleRequest) GetModule() string {
+ if m != nil && m.Module != nil {
+ return *m.Module
+ }
+ return ""
+}
+
+func (m *StopModuleRequest) GetVersion() string {
+ if m != nil && m.Version != nil {
+ return *m.Version
+ }
+ return ""
+}
+
+type StopModuleResponse struct {
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *StopModuleResponse) Reset() { *m = StopModuleResponse{} }
+func (m *StopModuleResponse) String() string { return proto.CompactTextString(m) }
+func (*StopModuleResponse) ProtoMessage() {}
+func (*StopModuleResponse) Descriptor() ([]byte, []int) {
+ return fileDescriptor_modules_service_9cd3bffe4e91c59a, []int{14}
+}
+func (m *StopModuleResponse) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_StopModuleResponse.Unmarshal(m, b)
+}
+func (m *StopModuleResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_StopModuleResponse.Marshal(b, m, deterministic)
+}
+func (dst *StopModuleResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_StopModuleResponse.Merge(dst, src)
+}
+func (m *StopModuleResponse) XXX_Size() int {
+ return xxx_messageInfo_StopModuleResponse.Size(m)
+}
+func (m *StopModuleResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_StopModuleResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_StopModuleResponse proto.InternalMessageInfo
+
+type GetHostnameRequest struct {
+ Module *string `protobuf:"bytes,1,opt,name=module" json:"module,omitempty"`
+ Version *string `protobuf:"bytes,2,opt,name=version" json:"version,omitempty"`
+ Instance *string `protobuf:"bytes,3,opt,name=instance" json:"instance,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *GetHostnameRequest) Reset() { *m = GetHostnameRequest{} }
+func (m *GetHostnameRequest) String() string { return proto.CompactTextString(m) }
+func (*GetHostnameRequest) ProtoMessage() {}
+func (*GetHostnameRequest) Descriptor() ([]byte, []int) {
+ return fileDescriptor_modules_service_9cd3bffe4e91c59a, []int{15}
+}
+func (m *GetHostnameRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GetHostnameRequest.Unmarshal(m, b)
+}
+func (m *GetHostnameRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GetHostnameRequest.Marshal(b, m, deterministic)
+}
+func (dst *GetHostnameRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GetHostnameRequest.Merge(dst, src)
+}
+func (m *GetHostnameRequest) XXX_Size() int {
+ return xxx_messageInfo_GetHostnameRequest.Size(m)
+}
+func (m *GetHostnameRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_GetHostnameRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetHostnameRequest proto.InternalMessageInfo
+
+func (m *GetHostnameRequest) GetModule() string {
+ if m != nil && m.Module != nil {
+ return *m.Module
+ }
+ return ""
+}
+
+func (m *GetHostnameRequest) GetVersion() string {
+ if m != nil && m.Version != nil {
+ return *m.Version
+ }
+ return ""
+}
+
+func (m *GetHostnameRequest) GetInstance() string {
+ if m != nil && m.Instance != nil {
+ return *m.Instance
+ }
+ return ""
+}
+
+type GetHostnameResponse struct {
+ Hostname *string `protobuf:"bytes,1,req,name=hostname" json:"hostname,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *GetHostnameResponse) Reset() { *m = GetHostnameResponse{} }
+func (m *GetHostnameResponse) String() string { return proto.CompactTextString(m) }
+func (*GetHostnameResponse) ProtoMessage() {}
+func (*GetHostnameResponse) Descriptor() ([]byte, []int) {
+ return fileDescriptor_modules_service_9cd3bffe4e91c59a, []int{16}
+}
+func (m *GetHostnameResponse) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GetHostnameResponse.Unmarshal(m, b)
+}
+func (m *GetHostnameResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GetHostnameResponse.Marshal(b, m, deterministic)
+}
+func (dst *GetHostnameResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GetHostnameResponse.Merge(dst, src)
+}
+func (m *GetHostnameResponse) XXX_Size() int {
+ return xxx_messageInfo_GetHostnameResponse.Size(m)
+}
+func (m *GetHostnameResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_GetHostnameResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetHostnameResponse proto.InternalMessageInfo
+
+func (m *GetHostnameResponse) GetHostname() string {
+ if m != nil && m.Hostname != nil {
+ return *m.Hostname
+ }
+ return ""
+}
+
+func init() {
+ proto.RegisterType((*ModulesServiceError)(nil), "appengine.ModulesServiceError")
+ proto.RegisterType((*GetModulesRequest)(nil), "appengine.GetModulesRequest")
+ proto.RegisterType((*GetModulesResponse)(nil), "appengine.GetModulesResponse")
+ proto.RegisterType((*GetVersionsRequest)(nil), "appengine.GetVersionsRequest")
+ proto.RegisterType((*GetVersionsResponse)(nil), "appengine.GetVersionsResponse")
+ proto.RegisterType((*GetDefaultVersionRequest)(nil), "appengine.GetDefaultVersionRequest")
+ proto.RegisterType((*GetDefaultVersionResponse)(nil), "appengine.GetDefaultVersionResponse")
+ proto.RegisterType((*GetNumInstancesRequest)(nil), "appengine.GetNumInstancesRequest")
+ proto.RegisterType((*GetNumInstancesResponse)(nil), "appengine.GetNumInstancesResponse")
+ proto.RegisterType((*SetNumInstancesRequest)(nil), "appengine.SetNumInstancesRequest")
+ proto.RegisterType((*SetNumInstancesResponse)(nil), "appengine.SetNumInstancesResponse")
+ proto.RegisterType((*StartModuleRequest)(nil), "appengine.StartModuleRequest")
+ proto.RegisterType((*StartModuleResponse)(nil), "appengine.StartModuleResponse")
+ proto.RegisterType((*StopModuleRequest)(nil), "appengine.StopModuleRequest")
+ proto.RegisterType((*StopModuleResponse)(nil), "appengine.StopModuleResponse")
+ proto.RegisterType((*GetHostnameRequest)(nil), "appengine.GetHostnameRequest")
+ proto.RegisterType((*GetHostnameResponse)(nil), "appengine.GetHostnameResponse")
+}
+
+func init() {
+ proto.RegisterFile("google.golang.org/appengine/internal/modules/modules_service.proto", fileDescriptor_modules_service_9cd3bffe4e91c59a)
+}
+
+var fileDescriptor_modules_service_9cd3bffe4e91c59a = []byte{
+ // 457 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x94, 0xc1, 0x6f, 0xd3, 0x30,
+ 0x14, 0xc6, 0x69, 0x02, 0xdb, 0xf2, 0x0e, 0x90, 0x3a, 0x5b, 0xd7, 0x4d, 0x1c, 0x50, 0x4e, 0x1c,
+ 0x50, 0x2b, 0x90, 0x10, 0xe7, 0xae, 0x35, 0x25, 0xb0, 0xa5, 0x28, 0xce, 0x2a, 0xc4, 0xa5, 0x0a,
+ 0xdb, 0x23, 0x8b, 0x94, 0xda, 0xc1, 0x76, 0x77, 0xe4, 0xbf, 0xe0, 0xff, 0x45, 0x4b, 0xed, 0xb6,
+ 0x81, 0x4e, 0x45, 0x68, 0xa7, 0xe4, 0x7d, 0xfe, 0xfc, 0x7b, 0x9f, 0x5f, 0xac, 0xc0, 0x59, 0x2e,
+ 0x44, 0x5e, 0x62, 0x2f, 0x17, 0x65, 0xc6, 0xf3, 0x9e, 0x90, 0x79, 0x3f, 0xab, 0x2a, 0xe4, 0x79,
+ 0xc1, 0xb1, 0x5f, 0x70, 0x8d, 0x92, 0x67, 0x65, 0x7f, 0x2e, 0xae, 0x17, 0x25, 0x2a, 0xfb, 0x9c,
+ 0x29, 0x94, 0xb7, 0xc5, 0x15, 0xf6, 0x2a, 0x29, 0xb4, 0x20, 0xde, 0x6a, 0x47, 0xf8, 0xab, 0x05,
+ 0xc1, 0xc5, 0xd2, 0xc4, 0x96, 0x1e, 0x2a, 0xa5, 0x90, 0xe1, 0x4f, 0xf0, 0xea, 0x97, 0xa1, 0xb8,
+ 0x46, 0xb2, 0x07, 0xce, 0xe4, 0x93, 0xff, 0x88, 0x10, 0x78, 0x1a, 0xc5, 0xd3, 0xc1, 0x79, 0x34,
+ 0x9a, 0x5d, 0x4c, 0x46, 0x97, 0xe7, 0xd4, 0x6f, 0x91, 0x00, 0x9e, 0x59, 0x6d, 0x4a, 0x13, 0x16,
+ 0x4d, 0x62, 0xdf, 0x21, 0x47, 0xd0, 0xb6, 0x62, 0x14, 0xb3, 0x74, 0x10, 0x0f, 0x29, 0xf3, 0xdd,
+ 0x3b, 0x6f, 0x9a, 0x0c, 0x62, 0x16, 0xd1, 0x38, 0x9d, 0xd1, 0x24, 0x99, 0x24, 0xfe, 0x63, 0x72,
+ 0x08, 0xfe, 0x65, 0x4c, 0xbf, 0x7c, 0xa6, 0xc3, 0x94, 0x8e, 0x66, 0x2c, 0x1d, 0xa4, 0xd4, 0x7f,
+ 0x12, 0x06, 0xd0, 0x1e, 0xa3, 0x36, 0xc9, 0x12, 0xfc, 0xb1, 0x40, 0xa5, 0xc3, 0x57, 0x40, 0x36,
+ 0x45, 0x55, 0x09, 0xae, 0x90, 0x74, 0x60, 0x6f, 0x79, 0xcc, 0x6e, 0xeb, 0x85, 0xfb, 0xd2, 0x4b,
+ 0x4c, 0x65, 0xdc, 0x53, 0x94, 0xaa, 0x10, 0xdc, 0x32, 0x1a, 0xee, 0xd6, 0x86, 0xbb, 0x0f, 0x41,
+ 0xc3, 0x6d, 0xe0, 0x5d, 0xd8, 0xbf, 0x5d, 0x6a, 0x86, 0x6e, 0xcb, 0xf0, 0x0d, 0x74, 0xc7, 0xa8,
+ 0x47, 0xf8, 0x3d, 0x5b, 0x94, 0x76, 0xdf, 0xae, 0x26, 0x6f, 0xe1, 0x64, 0xcb, 0x9e, 0x6d, 0xad,
+ 0x9c, 0xcd, 0x56, 0x1f, 0xa1, 0x33, 0x46, 0x1d, 0x2f, 0xe6, 0x11, 0x57, 0x3a, 0xe3, 0x57, 0xb8,
+ 0xeb, 0x34, 0x9b, 0x2c, 0xa7, 0x5e, 0x58, 0xb1, 0xde, 0xc1, 0xf1, 0x5f, 0x2c, 0x13, 0xe0, 0x39,
+ 0x78, 0x85, 0x15, 0xeb, 0x08, 0x6e, 0xb2, 0x16, 0xc2, 0x1b, 0xe8, 0xb0, 0x07, 0x0a, 0xd1, 0xec,
+ 0xe4, 0xfe, 0xd9, 0xe9, 0x04, 0x8e, 0xd9, 0xf6, 0x88, 0xe1, 0x7b, 0x20, 0x4c, 0x67, 0xd2, 0xdc,
+ 0x81, 0x6d, 0x01, 0x9c, 0xfb, 0x02, 0x34, 0x26, 0x7a, 0x04, 0x41, 0x83, 0x63, 0xf0, 0x14, 0xda,
+ 0x4c, 0x8b, 0xea, 0x7e, 0xfa, 0xbf, 0xcd, 0xf8, 0xf0, 0x2e, 0xe5, 0x1a, 0x63, 0xe0, 0xdf, 0xea,
+ 0xfb, 0xf8, 0x41, 0x28, 0xcd, 0xb3, 0xf9, 0xff, 0xd3, 0xc9, 0x29, 0x1c, 0xd8, 0x59, 0x75, 0xdd,
+ 0x7a, 0x69, 0x55, 0x87, 0xaf, 0xeb, 0x5b, 0xbc, 0xee, 0x61, 0xbe, 0xec, 0x29, 0x1c, 0xdc, 0x18,
+ 0xcd, 0x8c, 0x68, 0x55, 0x9f, 0x79, 0x5f, 0xf7, 0xcd, 0x5f, 0xe2, 0x77, 0x00, 0x00, 0x00, 0xff,
+ 0xff, 0x6e, 0xbc, 0xe0, 0x61, 0x5c, 0x04, 0x00, 0x00,
+}
diff --git a/vendor/google.golang.org/appengine/internal/modules/modules_service.proto b/vendor/google.golang.org/appengine/internal/modules/modules_service.proto
new file mode 100644
index 000000000..d29f0065a
--- /dev/null
+++ b/vendor/google.golang.org/appengine/internal/modules/modules_service.proto
@@ -0,0 +1,80 @@
+syntax = "proto2";
+option go_package = "modules";
+
+package appengine;
+
+message ModulesServiceError {
+ enum ErrorCode {
+ OK = 0;
+ INVALID_MODULE = 1;
+ INVALID_VERSION = 2;
+ INVALID_INSTANCES = 3;
+ TRANSIENT_ERROR = 4;
+ UNEXPECTED_STATE = 5;
+ }
+}
+
+message GetModulesRequest {
+}
+
+message GetModulesResponse {
+ repeated string module = 1;
+}
+
+message GetVersionsRequest {
+ optional string module = 1;
+}
+
+message GetVersionsResponse {
+ repeated string version = 1;
+}
+
+message GetDefaultVersionRequest {
+ optional string module = 1;
+}
+
+message GetDefaultVersionResponse {
+ required string version = 1;
+}
+
+message GetNumInstancesRequest {
+ optional string module = 1;
+ optional string version = 2;
+}
+
+message GetNumInstancesResponse {
+ required int64 instances = 1;
+}
+
+message SetNumInstancesRequest {
+ optional string module = 1;
+ optional string version = 2;
+ required int64 instances = 3;
+}
+
+message SetNumInstancesResponse {}
+
+message StartModuleRequest {
+ required string module = 1;
+ required string version = 2;
+}
+
+message StartModuleResponse {}
+
+message StopModuleRequest {
+ optional string module = 1;
+ optional string version = 2;
+}
+
+message StopModuleResponse {}
+
+message GetHostnameRequest {
+ optional string module = 1;
+ optional string version = 2;
+ optional string instance = 3;
+}
+
+message GetHostnameResponse {
+ required string hostname = 1;
+}
+
diff --git a/vendor/google.golang.org/appengine/internal/net.go b/vendor/google.golang.org/appengine/internal/net.go
new file mode 100644
index 000000000..3b94cf0c6
--- /dev/null
+++ b/vendor/google.golang.org/appengine/internal/net.go
@@ -0,0 +1,56 @@
+// Copyright 2014 Google Inc. All rights reserved.
+// Use of this source code is governed by the Apache 2.0
+// license that can be found in the LICENSE file.
+
+package internal
+
+// This file implements a network dialer that limits the number of concurrent connections.
+// It is only used for API calls.
+
+import (
+ "log"
+ "net"
+ "runtime"
+ "sync"
+ "time"
+)
+
+var limitSem = make(chan int, 100) // TODO(dsymonds): Use environment variable.
+
+func limitRelease() {
+ // non-blocking
+ select {
+ case <-limitSem:
+ default:
+ // This should not normally happen.
+ log.Print("appengine: unbalanced limitSem release!")
+ }
+}
+
+func limitDial(network, addr string) (net.Conn, error) {
+ limitSem <- 1
+
+ // Dial with a timeout in case the API host is MIA.
+ // The connection should normally be very fast.
+ conn, err := net.DialTimeout(network, addr, 500*time.Millisecond)
+ if err != nil {
+ limitRelease()
+ return nil, err
+ }
+ lc := &limitConn{Conn: conn}
+ runtime.SetFinalizer(lc, (*limitConn).Close) // shouldn't usually be required
+ return lc, nil
+}
+
+type limitConn struct {
+ close sync.Once
+ net.Conn
+}
+
+func (lc *limitConn) Close() error {
+ defer lc.close.Do(func() {
+ limitRelease()
+ runtime.SetFinalizer(lc, nil)
+ })
+ return lc.Conn.Close()
+}
diff --git a/vendor/google.golang.org/appengine/internal/regen.sh b/vendor/google.golang.org/appengine/internal/regen.sh
new file mode 100755
index 000000000..2fdb546a6
--- /dev/null
+++ b/vendor/google.golang.org/appengine/internal/regen.sh
@@ -0,0 +1,40 @@
+#!/bin/bash -e
+#
+# This script rebuilds the generated code for the protocol buffers.
+# To run this you will need protoc and goprotobuf installed;
+# see https://github.com/golang/protobuf for instructions.
+
+PKG=google.golang.org/appengine
+
+function die() {
+ echo 1>&2 $*
+ exit 1
+}
+
+# Sanity check that the right tools are accessible.
+for tool in go protoc protoc-gen-go; do
+ q=$(which $tool) || die "didn't find $tool"
+ echo 1>&2 "$tool: $q"
+done
+
+echo -n 1>&2 "finding package dir... "
+pkgdir=$(go list -f '{{.Dir}}' $PKG)
+echo 1>&2 $pkgdir
+base=$(echo $pkgdir | sed "s,/$PKG\$,,")
+echo 1>&2 "base: $base"
+cd $base
+
+# Run protoc once per package.
+for dir in $(find $PKG/internal -name '*.proto' | xargs dirname | sort | uniq); do
+ echo 1>&2 "* $dir"
+ protoc --go_out=. $dir/*.proto
+done
+
+for f in $(find $PKG/internal -name '*.pb.go'); do
+ # Remove proto.RegisterEnum calls.
+ # These cause duplicate registration panics when these packages
+ # are used on classic App Engine. proto.RegisterEnum only affects
+ # parsing the text format; we don't care about that.
+ # https://code.google.com/p/googleappengine/issues/detail?id=11670#c17
+ sed -i '/proto.RegisterEnum/d' $f
+done
diff --git a/vendor/google.golang.org/appengine/internal/remote_api/remote_api.pb.go b/vendor/google.golang.org/appengine/internal/remote_api/remote_api.pb.go
new file mode 100644
index 000000000..8d782a38e
--- /dev/null
+++ b/vendor/google.golang.org/appengine/internal/remote_api/remote_api.pb.go
@@ -0,0 +1,361 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// source: google.golang.org/appengine/internal/remote_api/remote_api.proto
+
+package remote_api
+
+import proto "github.com/golang/protobuf/proto"
+import fmt "fmt"
+import math "math"
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
+
+type RpcError_ErrorCode int32
+
+const (
+ RpcError_UNKNOWN RpcError_ErrorCode = 0
+ RpcError_CALL_NOT_FOUND RpcError_ErrorCode = 1
+ RpcError_PARSE_ERROR RpcError_ErrorCode = 2
+ RpcError_SECURITY_VIOLATION RpcError_ErrorCode = 3
+ RpcError_OVER_QUOTA RpcError_ErrorCode = 4
+ RpcError_REQUEST_TOO_LARGE RpcError_ErrorCode = 5
+ RpcError_CAPABILITY_DISABLED RpcError_ErrorCode = 6
+ RpcError_FEATURE_DISABLED RpcError_ErrorCode = 7
+ RpcError_BAD_REQUEST RpcError_ErrorCode = 8
+ RpcError_RESPONSE_TOO_LARGE RpcError_ErrorCode = 9
+ RpcError_CANCELLED RpcError_ErrorCode = 10
+ RpcError_REPLAY_ERROR RpcError_ErrorCode = 11
+ RpcError_DEADLINE_EXCEEDED RpcError_ErrorCode = 12
+)
+
+var RpcError_ErrorCode_name = map[int32]string{
+ 0: "UNKNOWN",
+ 1: "CALL_NOT_FOUND",
+ 2: "PARSE_ERROR",
+ 3: "SECURITY_VIOLATION",
+ 4: "OVER_QUOTA",
+ 5: "REQUEST_TOO_LARGE",
+ 6: "CAPABILITY_DISABLED",
+ 7: "FEATURE_DISABLED",
+ 8: "BAD_REQUEST",
+ 9: "RESPONSE_TOO_LARGE",
+ 10: "CANCELLED",
+ 11: "REPLAY_ERROR",
+ 12: "DEADLINE_EXCEEDED",
+}
+var RpcError_ErrorCode_value = map[string]int32{
+ "UNKNOWN": 0,
+ "CALL_NOT_FOUND": 1,
+ "PARSE_ERROR": 2,
+ "SECURITY_VIOLATION": 3,
+ "OVER_QUOTA": 4,
+ "REQUEST_TOO_LARGE": 5,
+ "CAPABILITY_DISABLED": 6,
+ "FEATURE_DISABLED": 7,
+ "BAD_REQUEST": 8,
+ "RESPONSE_TOO_LARGE": 9,
+ "CANCELLED": 10,
+ "REPLAY_ERROR": 11,
+ "DEADLINE_EXCEEDED": 12,
+}
+
+func (x RpcError_ErrorCode) Enum() *RpcError_ErrorCode {
+ p := new(RpcError_ErrorCode)
+ *p = x
+ return p
+}
+func (x RpcError_ErrorCode) String() string {
+ return proto.EnumName(RpcError_ErrorCode_name, int32(x))
+}
+func (x *RpcError_ErrorCode) UnmarshalJSON(data []byte) error {
+ value, err := proto.UnmarshalJSONEnum(RpcError_ErrorCode_value, data, "RpcError_ErrorCode")
+ if err != nil {
+ return err
+ }
+ *x = RpcError_ErrorCode(value)
+ return nil
+}
+func (RpcError_ErrorCode) EnumDescriptor() ([]byte, []int) {
+ return fileDescriptor_remote_api_1978114ec33a273d, []int{2, 0}
+}
+
+type Request struct {
+ ServiceName *string `protobuf:"bytes,2,req,name=service_name,json=serviceName" json:"service_name,omitempty"`
+ Method *string `protobuf:"bytes,3,req,name=method" json:"method,omitempty"`
+ Request []byte `protobuf:"bytes,4,req,name=request" json:"request,omitempty"`
+ RequestId *string `protobuf:"bytes,5,opt,name=request_id,json=requestId" json:"request_id,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *Request) Reset() { *m = Request{} }
+func (m *Request) String() string { return proto.CompactTextString(m) }
+func (*Request) ProtoMessage() {}
+func (*Request) Descriptor() ([]byte, []int) {
+ return fileDescriptor_remote_api_1978114ec33a273d, []int{0}
+}
+func (m *Request) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_Request.Unmarshal(m, b)
+}
+func (m *Request) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_Request.Marshal(b, m, deterministic)
+}
+func (dst *Request) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_Request.Merge(dst, src)
+}
+func (m *Request) XXX_Size() int {
+ return xxx_messageInfo_Request.Size(m)
+}
+func (m *Request) XXX_DiscardUnknown() {
+ xxx_messageInfo_Request.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Request proto.InternalMessageInfo
+
+func (m *Request) GetServiceName() string {
+ if m != nil && m.ServiceName != nil {
+ return *m.ServiceName
+ }
+ return ""
+}
+
+func (m *Request) GetMethod() string {
+ if m != nil && m.Method != nil {
+ return *m.Method
+ }
+ return ""
+}
+
+func (m *Request) GetRequest() []byte {
+ if m != nil {
+ return m.Request
+ }
+ return nil
+}
+
+func (m *Request) GetRequestId() string {
+ if m != nil && m.RequestId != nil {
+ return *m.RequestId
+ }
+ return ""
+}
+
+type ApplicationError struct {
+ Code *int32 `protobuf:"varint,1,req,name=code" json:"code,omitempty"`
+ Detail *string `protobuf:"bytes,2,req,name=detail" json:"detail,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *ApplicationError) Reset() { *m = ApplicationError{} }
+func (m *ApplicationError) String() string { return proto.CompactTextString(m) }
+func (*ApplicationError) ProtoMessage() {}
+func (*ApplicationError) Descriptor() ([]byte, []int) {
+ return fileDescriptor_remote_api_1978114ec33a273d, []int{1}
+}
+func (m *ApplicationError) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_ApplicationError.Unmarshal(m, b)
+}
+func (m *ApplicationError) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_ApplicationError.Marshal(b, m, deterministic)
+}
+func (dst *ApplicationError) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_ApplicationError.Merge(dst, src)
+}
+func (m *ApplicationError) XXX_Size() int {
+ return xxx_messageInfo_ApplicationError.Size(m)
+}
+func (m *ApplicationError) XXX_DiscardUnknown() {
+ xxx_messageInfo_ApplicationError.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_ApplicationError proto.InternalMessageInfo
+
+func (m *ApplicationError) GetCode() int32 {
+ if m != nil && m.Code != nil {
+ return *m.Code
+ }
+ return 0
+}
+
+func (m *ApplicationError) GetDetail() string {
+ if m != nil && m.Detail != nil {
+ return *m.Detail
+ }
+ return ""
+}
+
+type RpcError struct {
+ Code *int32 `protobuf:"varint,1,req,name=code" json:"code,omitempty"`
+ Detail *string `protobuf:"bytes,2,opt,name=detail" json:"detail,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *RpcError) Reset() { *m = RpcError{} }
+func (m *RpcError) String() string { return proto.CompactTextString(m) }
+func (*RpcError) ProtoMessage() {}
+func (*RpcError) Descriptor() ([]byte, []int) {
+ return fileDescriptor_remote_api_1978114ec33a273d, []int{2}
+}
+func (m *RpcError) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_RpcError.Unmarshal(m, b)
+}
+func (m *RpcError) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_RpcError.Marshal(b, m, deterministic)
+}
+func (dst *RpcError) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_RpcError.Merge(dst, src)
+}
+func (m *RpcError) XXX_Size() int {
+ return xxx_messageInfo_RpcError.Size(m)
+}
+func (m *RpcError) XXX_DiscardUnknown() {
+ xxx_messageInfo_RpcError.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_RpcError proto.InternalMessageInfo
+
+func (m *RpcError) GetCode() int32 {
+ if m != nil && m.Code != nil {
+ return *m.Code
+ }
+ return 0
+}
+
+func (m *RpcError) GetDetail() string {
+ if m != nil && m.Detail != nil {
+ return *m.Detail
+ }
+ return ""
+}
+
+type Response struct {
+ Response []byte `protobuf:"bytes,1,opt,name=response" json:"response,omitempty"`
+ Exception []byte `protobuf:"bytes,2,opt,name=exception" json:"exception,omitempty"`
+ ApplicationError *ApplicationError `protobuf:"bytes,3,opt,name=application_error,json=applicationError" json:"application_error,omitempty"`
+ JavaException []byte `protobuf:"bytes,4,opt,name=java_exception,json=javaException" json:"java_exception,omitempty"`
+ RpcError *RpcError `protobuf:"bytes,5,opt,name=rpc_error,json=rpcError" json:"rpc_error,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *Response) Reset() { *m = Response{} }
+func (m *Response) String() string { return proto.CompactTextString(m) }
+func (*Response) ProtoMessage() {}
+func (*Response) Descriptor() ([]byte, []int) {
+ return fileDescriptor_remote_api_1978114ec33a273d, []int{3}
+}
+func (m *Response) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_Response.Unmarshal(m, b)
+}
+func (m *Response) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_Response.Marshal(b, m, deterministic)
+}
+func (dst *Response) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_Response.Merge(dst, src)
+}
+func (m *Response) XXX_Size() int {
+ return xxx_messageInfo_Response.Size(m)
+}
+func (m *Response) XXX_DiscardUnknown() {
+ xxx_messageInfo_Response.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Response proto.InternalMessageInfo
+
+func (m *Response) GetResponse() []byte {
+ if m != nil {
+ return m.Response
+ }
+ return nil
+}
+
+func (m *Response) GetException() []byte {
+ if m != nil {
+ return m.Exception
+ }
+ return nil
+}
+
+func (m *Response) GetApplicationError() *ApplicationError {
+ if m != nil {
+ return m.ApplicationError
+ }
+ return nil
+}
+
+func (m *Response) GetJavaException() []byte {
+ if m != nil {
+ return m.JavaException
+ }
+ return nil
+}
+
+func (m *Response) GetRpcError() *RpcError {
+ if m != nil {
+ return m.RpcError
+ }
+ return nil
+}
+
+func init() {
+ proto.RegisterType((*Request)(nil), "remote_api.Request")
+ proto.RegisterType((*ApplicationError)(nil), "remote_api.ApplicationError")
+ proto.RegisterType((*RpcError)(nil), "remote_api.RpcError")
+ proto.RegisterType((*Response)(nil), "remote_api.Response")
+}
+
+func init() {
+ proto.RegisterFile("google.golang.org/appengine/internal/remote_api/remote_api.proto", fileDescriptor_remote_api_1978114ec33a273d)
+}
+
+var fileDescriptor_remote_api_1978114ec33a273d = []byte{
+ // 531 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x93, 0x51, 0x6e, 0xd3, 0x40,
+ 0x10, 0x86, 0xb1, 0x9b, 0x34, 0xf1, 0xc4, 0x2d, 0xdb, 0xa5, 0x14, 0x0b, 0x15, 0x29, 0x44, 0x42,
+ 0xca, 0x53, 0x2a, 0x38, 0x00, 0x62, 0x63, 0x6f, 0x91, 0x85, 0x65, 0xa7, 0x6b, 0xbb, 0x50, 0x5e,
+ 0x56, 0x2b, 0x67, 0x65, 0x8c, 0x12, 0xaf, 0xd9, 0x98, 0x8a, 0x17, 0x6e, 0xc0, 0xb5, 0x38, 0x0c,
+ 0xb7, 0x40, 0x36, 0x6e, 0x63, 0xf5, 0x89, 0xb7, 0x7f, 0x7e, 0x7b, 0xe6, 0x1b, 0xcd, 0xcc, 0xc2,
+ 0xbb, 0x5c, 0xa9, 0x7c, 0x23, 0x17, 0xb9, 0xda, 0x88, 0x32, 0x5f, 0x28, 0x9d, 0x5f, 0x88, 0xaa,
+ 0x92, 0x65, 0x5e, 0x94, 0xf2, 0xa2, 0x28, 0x6b, 0xa9, 0x4b, 0xb1, 0xb9, 0xd0, 0x72, 0xab, 0x6a,
+ 0xc9, 0x45, 0x55, 0xf4, 0xe4, 0xa2, 0xd2, 0xaa, 0x56, 0x18, 0xf6, 0xce, 0xec, 0x27, 0x8c, 0x98,
+ 0xfc, 0xf6, 0x5d, 0xee, 0x6a, 0xfc, 0x12, 0xec, 0x9d, 0xd4, 0xb7, 0x45, 0x26, 0x79, 0x29, 0xb6,
+ 0xd2, 0x31, 0xa7, 0xe6, 0xdc, 0x62, 0x93, 0xce, 0x0b, 0xc5, 0x56, 0xe2, 0x33, 0x38, 0xdc, 0xca,
+ 0xfa, 0x8b, 0x5a, 0x3b, 0x07, 0xed, 0xc7, 0x2e, 0xc2, 0x0e, 0x8c, 0xf4, 0xbf, 0x2a, 0xce, 0x60,
+ 0x6a, 0xce, 0x6d, 0x76, 0x17, 0xe2, 0x17, 0x00, 0x9d, 0xe4, 0xc5, 0xda, 0x19, 0x4e, 0x8d, 0xb9,
+ 0xc5, 0xac, 0xce, 0xf1, 0xd7, 0xb3, 0xb7, 0x80, 0x48, 0x55, 0x6d, 0x8a, 0x4c, 0xd4, 0x85, 0x2a,
+ 0xa9, 0xd6, 0x4a, 0x63, 0x0c, 0x83, 0x4c, 0xad, 0xa5, 0x63, 0x4c, 0xcd, 0xf9, 0x90, 0xb5, 0xba,
+ 0x01, 0xaf, 0x65, 0x2d, 0x8a, 0x4d, 0xd7, 0x55, 0x17, 0xcd, 0x7e, 0x9b, 0x30, 0x66, 0x55, 0xf6,
+ 0x7f, 0x89, 0x46, 0x2f, 0xf1, 0x97, 0x09, 0x56, 0x9b, 0xe5, 0x36, 0x7f, 0x4d, 0x60, 0x94, 0x86,
+ 0x1f, 0xc2, 0xe8, 0x63, 0x88, 0x1e, 0x61, 0x0c, 0xc7, 0x2e, 0x09, 0x02, 0x1e, 0x46, 0x09, 0xbf,
+ 0x8c, 0xd2, 0xd0, 0x43, 0x06, 0x7e, 0x0c, 0x93, 0x15, 0x61, 0x31, 0xe5, 0x94, 0xb1, 0x88, 0x21,
+ 0x13, 0x9f, 0x01, 0x8e, 0xa9, 0x9b, 0x32, 0x3f, 0xb9, 0xe1, 0xd7, 0x7e, 0x14, 0x90, 0xc4, 0x8f,
+ 0x42, 0x74, 0x80, 0x8f, 0x01, 0xa2, 0x6b, 0xca, 0xf8, 0x55, 0x1a, 0x25, 0x04, 0x0d, 0xf0, 0x53,
+ 0x38, 0x61, 0xf4, 0x2a, 0xa5, 0x71, 0xc2, 0x93, 0x28, 0xe2, 0x01, 0x61, 0xef, 0x29, 0x1a, 0xe2,
+ 0x67, 0xf0, 0xc4, 0x25, 0x2b, 0xb2, 0xf4, 0x83, 0xa6, 0x80, 0xe7, 0xc7, 0x64, 0x19, 0x50, 0x0f,
+ 0x1d, 0xe2, 0x53, 0x40, 0x97, 0x94, 0x24, 0x29, 0xa3, 0x7b, 0x77, 0xd4, 0xe0, 0x97, 0xc4, 0xe3,
+ 0x5d, 0x25, 0x34, 0x6e, 0xf0, 0x8c, 0xc6, 0xab, 0x28, 0x8c, 0x69, 0xaf, 0xae, 0x85, 0x8f, 0xc0,
+ 0x72, 0x49, 0xe8, 0xd2, 0xa0, 0xc9, 0x03, 0x8c, 0xc0, 0x66, 0x74, 0x15, 0x90, 0x9b, 0xae, 0xef,
+ 0x49, 0xd3, 0x8f, 0x47, 0x89, 0x17, 0xf8, 0x21, 0xe5, 0xf4, 0x93, 0x4b, 0xa9, 0x47, 0x3d, 0x64,
+ 0xcf, 0xfe, 0x18, 0x30, 0x66, 0x72, 0x57, 0xa9, 0x72, 0x27, 0xf1, 0x73, 0x18, 0xeb, 0x4e, 0x3b,
+ 0xc6, 0xd4, 0x98, 0xdb, 0xec, 0x3e, 0xc6, 0xe7, 0x60, 0xc9, 0x1f, 0x99, 0xac, 0x9a, 0x75, 0xb5,
+ 0x23, 0xb5, 0xd9, 0xde, 0xc0, 0x3e, 0x9c, 0x88, 0xfd, 0x3a, 0xb9, 0x6c, 0x06, 0xec, 0x1c, 0x4c,
+ 0x8d, 0xf9, 0xe4, 0xcd, 0xf9, 0xa2, 0x77, 0x87, 0x0f, 0x77, 0xce, 0x90, 0x78, 0x78, 0x05, 0xaf,
+ 0xe0, 0xf8, 0xab, 0xb8, 0x15, 0x7c, 0x4f, 0x1b, 0xb4, 0xb4, 0xa3, 0xc6, 0xa5, 0xf7, 0xc4, 0xd7,
+ 0x60, 0xe9, 0x2a, 0xeb, 0x48, 0xc3, 0x96, 0x74, 0xda, 0x27, 0xdd, 0x1d, 0x07, 0x1b, 0xeb, 0x4e,
+ 0x2d, 0xed, 0xcf, 0xbd, 0x07, 0xf0, 0x37, 0x00, 0x00, 0xff, 0xff, 0x38, 0xd1, 0x0f, 0x22, 0x4f,
+ 0x03, 0x00, 0x00,
+}
diff --git a/vendor/google.golang.org/appengine/internal/remote_api/remote_api.proto b/vendor/google.golang.org/appengine/internal/remote_api/remote_api.proto
new file mode 100644
index 000000000..f21763a4e
--- /dev/null
+++ b/vendor/google.golang.org/appengine/internal/remote_api/remote_api.proto
@@ -0,0 +1,44 @@
+syntax = "proto2";
+option go_package = "remote_api";
+
+package remote_api;
+
+message Request {
+ required string service_name = 2;
+ required string method = 3;
+ required bytes request = 4;
+ optional string request_id = 5;
+}
+
+message ApplicationError {
+ required int32 code = 1;
+ required string detail = 2;
+}
+
+message RpcError {
+ enum ErrorCode {
+ UNKNOWN = 0;
+ CALL_NOT_FOUND = 1;
+ PARSE_ERROR = 2;
+ SECURITY_VIOLATION = 3;
+ OVER_QUOTA = 4;
+ REQUEST_TOO_LARGE = 5;
+ CAPABILITY_DISABLED = 6;
+ FEATURE_DISABLED = 7;
+ BAD_REQUEST = 8;
+ RESPONSE_TOO_LARGE = 9;
+ CANCELLED = 10;
+ REPLAY_ERROR = 11;
+ DEADLINE_EXCEEDED = 12;
+ }
+ required int32 code = 1;
+ optional string detail = 2;
+}
+
+message Response {
+ optional bytes response = 1;
+ optional bytes exception = 2;
+ optional ApplicationError application_error = 3;
+ optional bytes java_exception = 4;
+ optional RpcError rpc_error = 5;
+}
diff --git a/vendor/google.golang.org/appengine/internal/transaction.go b/vendor/google.golang.org/appengine/internal/transaction.go
new file mode 100644
index 000000000..9006ae653
--- /dev/null
+++ b/vendor/google.golang.org/appengine/internal/transaction.go
@@ -0,0 +1,115 @@
+// Copyright 2014 Google Inc. All rights reserved.
+// Use of this source code is governed by the Apache 2.0
+// license that can be found in the LICENSE file.
+
+package internal
+
+// This file implements hooks for applying datastore transactions.
+
+import (
+ "errors"
+ "reflect"
+
+ "github.com/golang/protobuf/proto"
+ netcontext "golang.org/x/net/context"
+
+ basepb "google.golang.org/appengine/internal/base"
+ pb "google.golang.org/appengine/internal/datastore"
+)
+
+var transactionSetters = make(map[reflect.Type]reflect.Value)
+
+// RegisterTransactionSetter registers a function that sets transaction information
+// in a protocol buffer message. f should be a function with two arguments,
+// the first being a protocol buffer type, and the second being *datastore.Transaction.
+func RegisterTransactionSetter(f interface{}) {
+ v := reflect.ValueOf(f)
+ transactionSetters[v.Type().In(0)] = v
+}
+
+// applyTransaction applies the transaction t to message pb
+// by using the relevant setter passed to RegisterTransactionSetter.
+func applyTransaction(pb proto.Message, t *pb.Transaction) {
+ v := reflect.ValueOf(pb)
+ if f, ok := transactionSetters[v.Type()]; ok {
+ f.Call([]reflect.Value{v, reflect.ValueOf(t)})
+ }
+}
+
+var transactionKey = "used for *Transaction"
+
+func transactionFromContext(ctx netcontext.Context) *transaction {
+ t, _ := ctx.Value(&transactionKey).(*transaction)
+ return t
+}
+
+func withTransaction(ctx netcontext.Context, t *transaction) netcontext.Context {
+ return netcontext.WithValue(ctx, &transactionKey, t)
+}
+
+type transaction struct {
+ transaction pb.Transaction
+ finished bool
+}
+
+var ErrConcurrentTransaction = errors.New("internal: concurrent transaction")
+
+func RunTransactionOnce(c netcontext.Context, f func(netcontext.Context) error, xg bool, readOnly bool, previousTransaction *pb.Transaction) (*pb.Transaction, error) {
+ if transactionFromContext(c) != nil {
+ return nil, errors.New("nested transactions are not supported")
+ }
+
+ // Begin the transaction.
+ t := &transaction{}
+ req := &pb.BeginTransactionRequest{
+ App: proto.String(FullyQualifiedAppID(c)),
+ }
+ if xg {
+ req.AllowMultipleEg = proto.Bool(true)
+ }
+ if previousTransaction != nil {
+ req.PreviousTransaction = previousTransaction
+ }
+ if readOnly {
+ req.Mode = pb.BeginTransactionRequest_READ_ONLY.Enum()
+ } else {
+ req.Mode = pb.BeginTransactionRequest_READ_WRITE.Enum()
+ }
+ if err := Call(c, "datastore_v3", "BeginTransaction", req, &t.transaction); err != nil {
+ return nil, err
+ }
+
+ // Call f, rolling back the transaction if f returns a non-nil error, or panics.
+ // The panic is not recovered.
+ defer func() {
+ if t.finished {
+ return
+ }
+ t.finished = true
+ // Ignore the error return value, since we are already returning a non-nil
+ // error (or we're panicking).
+ Call(c, "datastore_v3", "Rollback", &t.transaction, &basepb.VoidProto{})
+ }()
+ if err := f(withTransaction(c, t)); err != nil {
+ return &t.transaction, err
+ }
+ t.finished = true
+
+ // Commit the transaction.
+ res := &pb.CommitResponse{}
+ err := Call(c, "datastore_v3", "Commit", &t.transaction, res)
+ if ae, ok := err.(*APIError); ok {
+ /* TODO: restore this conditional
+ if appengine.IsDevAppServer() {
+ */
+ // The Python Dev AppServer raises an ApplicationError with error code 2 (which is
+ // Error.CONCURRENT_TRANSACTION) and message "Concurrency exception.".
+ if ae.Code == int32(pb.Error_BAD_REQUEST) && ae.Detail == "ApplicationError: 2 Concurrency exception." {
+ return &t.transaction, ErrConcurrentTransaction
+ }
+ if ae.Code == int32(pb.Error_CONCURRENT_TRANSACTION) {
+ return &t.transaction, ErrConcurrentTransaction
+ }
+ }
+ return &t.transaction, err
+}
diff --git a/vendor/google.golang.org/appengine/namespace.go b/vendor/google.golang.org/appengine/namespace.go
new file mode 100644
index 000000000..21860ca08
--- /dev/null
+++ b/vendor/google.golang.org/appengine/namespace.go
@@ -0,0 +1,25 @@
+// Copyright 2012 Google Inc. All rights reserved.
+// Use of this source code is governed by the Apache 2.0
+// license that can be found in the LICENSE file.
+
+package appengine
+
+import (
+ "fmt"
+ "regexp"
+
+ "golang.org/x/net/context"
+
+ "google.golang.org/appengine/internal"
+)
+
+// Namespace returns a replacement context that operates within the given namespace.
+func Namespace(c context.Context, namespace string) (context.Context, error) {
+ if !validNamespace.MatchString(namespace) {
+ return nil, fmt.Errorf("appengine: namespace %q does not match /%s/", namespace, validNamespace)
+ }
+ return internal.NamespacedContext(c, namespace), nil
+}
+
+// validNamespace matches valid namespace names.
+var validNamespace = regexp.MustCompile(`^[0-9A-Za-z._-]{0,100}$`)
diff --git a/vendor/google.golang.org/appengine/timeout.go b/vendor/google.golang.org/appengine/timeout.go
new file mode 100644
index 000000000..05642a992
--- /dev/null
+++ b/vendor/google.golang.org/appengine/timeout.go
@@ -0,0 +1,20 @@
+// Copyright 2013 Google Inc. All rights reserved.
+// Use of this source code is governed by the Apache 2.0
+// license that can be found in the LICENSE file.
+
+package appengine
+
+import "golang.org/x/net/context"
+
+// IsTimeoutError reports whether err is a timeout error.
+func IsTimeoutError(err error) bool {
+ if err == context.DeadlineExceeded {
+ return true
+ }
+ if t, ok := err.(interface {
+ IsTimeout() bool
+ }); ok {
+ return t.IsTimeout()
+ }
+ return false
+}
diff --git a/vendor/google.golang.org/appengine/travis_install.sh b/vendor/google.golang.org/appengine/travis_install.sh
new file mode 100755
index 000000000..785b62f46
--- /dev/null
+++ b/vendor/google.golang.org/appengine/travis_install.sh
@@ -0,0 +1,18 @@
+#!/bin/bash
+set -e
+
+if [[ $GO111MODULE == "on" ]]; then
+ go get .
+else
+ go get -u -v $(go list -f '{{join .Imports "\n"}}{{"\n"}}{{join .TestImports "\n"}}' ./... | sort | uniq | grep -v appengine)
+fi
+
+if [[ $GOAPP == "true" ]]; then
+ mkdir /tmp/sdk
+ curl -o /tmp/sdk.zip "https://storage.googleapis.com/appengine-sdks/featured/go_appengine_sdk_linux_amd64-1.9.68.zip"
+ unzip -q /tmp/sdk.zip -d /tmp/sdk
+ # NOTE: Set the following env vars in the test script:
+ # export PATH="$PATH:/tmp/sdk/go_appengine"
+ # export APPENGINE_DEV_APPSERVER=/tmp/sdk/go_appengine/dev_appserver.py
+fi
+
diff --git a/vendor/google.golang.org/appengine/travis_test.sh b/vendor/google.golang.org/appengine/travis_test.sh
new file mode 100755
index 000000000..d4390f045
--- /dev/null
+++ b/vendor/google.golang.org/appengine/travis_test.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+set -e
+
+go version
+go test -v google.golang.org/appengine/...
+go test -v -race google.golang.org/appengine/...
+if [[ $GOAPP == "true" ]]; then
+ export PATH="$PATH:/tmp/sdk/go_appengine"
+ export APPENGINE_DEV_APPSERVER=/tmp/sdk/go_appengine/dev_appserver.py
+ goapp version
+ goapp test -v google.golang.org/appengine/...
+fi
diff --git a/vendor/google.golang.org/appengine/urlfetch/urlfetch.go b/vendor/google.golang.org/appengine/urlfetch/urlfetch.go
new file mode 100644
index 000000000..6ffe1e6d9
--- /dev/null
+++ b/vendor/google.golang.org/appengine/urlfetch/urlfetch.go
@@ -0,0 +1,210 @@
+// Copyright 2011 Google Inc. All rights reserved.
+// Use of this source code is governed by the Apache 2.0
+// license that can be found in the LICENSE file.
+
+// Package urlfetch provides an http.RoundTripper implementation
+// for fetching URLs via App Engine's urlfetch service.
+package urlfetch // import "google.golang.org/appengine/urlfetch"
+
+import (
+ "errors"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "net/http"
+ "net/url"
+ "strconv"
+ "strings"
+ "time"
+
+ "github.com/golang/protobuf/proto"
+ "golang.org/x/net/context"
+
+ "google.golang.org/appengine/internal"
+ pb "google.golang.org/appengine/internal/urlfetch"
+)
+
+// Transport is an implementation of http.RoundTripper for
+// App Engine. Users should generally create an http.Client using
+// this transport and use the Client rather than using this transport
+// directly.
+type Transport struct {
+ Context context.Context
+
+ // Controls whether the application checks the validity of SSL certificates
+ // over HTTPS connections. A value of false (the default) instructs the
+ // application to send a request to the server only if the certificate is
+ // valid and signed by a trusted certificate authority (CA), and also
+ // includes a hostname that matches the certificate. A value of true
+ // instructs the application to perform no certificate validation.
+ AllowInvalidServerCertificate bool
+}
+
+// Verify statically that *Transport implements http.RoundTripper.
+var _ http.RoundTripper = (*Transport)(nil)
+
+// Client returns an *http.Client using a default urlfetch Transport. This
+// client will have the default deadline of 5 seconds, and will check the
+// validity of SSL certificates.
+//
+// Any deadline of the provided context will be used for requests through this client;
+// if the client does not have a deadline then a 5 second default is used.
+func Client(ctx context.Context) *http.Client {
+ return &http.Client{
+ Transport: &Transport{
+ Context: ctx,
+ },
+ }
+}
+
+type bodyReader struct {
+ content []byte
+ truncated bool
+ closed bool
+}
+
+// ErrTruncatedBody is the error returned after the final Read() from a
+// response's Body if the body has been truncated by App Engine's proxy.
+var ErrTruncatedBody = errors.New("urlfetch: truncated body")
+
+func statusCodeToText(code int) string {
+ if t := http.StatusText(code); t != "" {
+ return t
+ }
+ return strconv.Itoa(code)
+}
+
+func (br *bodyReader) Read(p []byte) (n int, err error) {
+ if br.closed {
+ if br.truncated {
+ return 0, ErrTruncatedBody
+ }
+ return 0, io.EOF
+ }
+ n = copy(p, br.content)
+ if n > 0 {
+ br.content = br.content[n:]
+ return
+ }
+ if br.truncated {
+ br.closed = true
+ return 0, ErrTruncatedBody
+ }
+ return 0, io.EOF
+}
+
+func (br *bodyReader) Close() error {
+ br.closed = true
+ br.content = nil
+ return nil
+}
+
+// A map of the URL Fetch-accepted methods that take a request body.
+var methodAcceptsRequestBody = map[string]bool{
+ "POST": true,
+ "PUT": true,
+ "PATCH": true,
+}
+
+// urlString returns a valid string given a URL. This function is necessary because
+// the String method of URL doesn't correctly handle URLs with non-empty Opaque values.
+// See http://code.google.com/p/go/issues/detail?id=4860.
+func urlString(u *url.URL) string {
+ if u.Opaque == "" || strings.HasPrefix(u.Opaque, "//") {
+ return u.String()
+ }
+ aux := *u
+ aux.Opaque = "//" + aux.Host + aux.Opaque
+ return aux.String()
+}
+
+// RoundTrip issues a single HTTP request and returns its response. Per the
+// http.RoundTripper interface, RoundTrip only returns an error if there
+// was an unsupported request or the URL Fetch proxy fails.
+// Note that HTTP response codes such as 5xx, 403, 404, etc are not
+// errors as far as the transport is concerned and will be returned
+// with err set to nil.
+func (t *Transport) RoundTrip(req *http.Request) (res *http.Response, err error) {
+ methNum, ok := pb.URLFetchRequest_RequestMethod_value[req.Method]
+ if !ok {
+ return nil, fmt.Errorf("urlfetch: unsupported HTTP method %q", req.Method)
+ }
+
+ method := pb.URLFetchRequest_RequestMethod(methNum)
+
+ freq := &pb.URLFetchRequest{
+ Method: &method,
+ Url: proto.String(urlString(req.URL)),
+ FollowRedirects: proto.Bool(false), // http.Client's responsibility
+ MustValidateServerCertificate: proto.Bool(!t.AllowInvalidServerCertificate),
+ }
+ if deadline, ok := t.Context.Deadline(); ok {
+ freq.Deadline = proto.Float64(deadline.Sub(time.Now()).Seconds())
+ }
+
+ for k, vals := range req.Header {
+ for _, val := range vals {
+ freq.Header = append(freq.Header, &pb.URLFetchRequest_Header{
+ Key: proto.String(k),
+ Value: proto.String(val),
+ })
+ }
+ }
+ if methodAcceptsRequestBody[req.Method] && req.Body != nil {
+ // Avoid a []byte copy if req.Body has a Bytes method.
+ switch b := req.Body.(type) {
+ case interface {
+ Bytes() []byte
+ }:
+ freq.Payload = b.Bytes()
+ default:
+ freq.Payload, err = ioutil.ReadAll(req.Body)
+ if err != nil {
+ return nil, err
+ }
+ }
+ }
+
+ fres := &pb.URLFetchResponse{}
+ if err := internal.Call(t.Context, "urlfetch", "Fetch", freq, fres); err != nil {
+ return nil, err
+ }
+
+ res = &http.Response{}
+ res.StatusCode = int(*fres.StatusCode)
+ res.Status = fmt.Sprintf("%d %s", res.StatusCode, statusCodeToText(res.StatusCode))
+ res.Header = make(http.Header)
+ res.Request = req
+
+ // Faked:
+ res.ProtoMajor = 1
+ res.ProtoMinor = 1
+ res.Proto = "HTTP/1.1"
+ res.Close = true
+
+ for _, h := range fres.Header {
+ hkey := http.CanonicalHeaderKey(*h.Key)
+ hval := *h.Value
+ if hkey == "Content-Length" {
+ // Will get filled in below for all but HEAD requests.
+ if req.Method == "HEAD" {
+ res.ContentLength, _ = strconv.ParseInt(hval, 10, 64)
+ }
+ continue
+ }
+ res.Header.Add(hkey, hval)
+ }
+
+ if req.Method != "HEAD" {
+ res.ContentLength = int64(len(fres.Content))
+ }
+
+ truncated := fres.GetContentWasTruncated()
+ res.Body = &bodyReader{content: fres.Content, truncated: truncated}
+ return
+}
+
+func init() {
+ internal.RegisterErrorCodeMap("urlfetch", pb.URLFetchServiceError_ErrorCode_name)
+ internal.RegisterTimeoutErrorCode("urlfetch", int32(pb.URLFetchServiceError_DEADLINE_EXCEEDED))
+}
diff --git a/vendor/google.golang.org/genproto/LICENSE b/vendor/google.golang.org/genproto/LICENSE
new file mode 100644
index 000000000..d64569567
--- /dev/null
+++ b/vendor/google.golang.org/genproto/LICENSE
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/vendor/google.golang.org/genproto/googleapis/api/annotations/annotations.pb.go b/vendor/google.golang.org/genproto/googleapis/api/annotations/annotations.pb.go
new file mode 100644
index 000000000..9521b50e9
--- /dev/null
+++ b/vendor/google.golang.org/genproto/googleapis/api/annotations/annotations.pb.go
@@ -0,0 +1,54 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// source: google/api/annotations.proto
+
+package annotations // import "google.golang.org/genproto/googleapis/api/annotations"
+
+import proto "github.com/golang/protobuf/proto"
+import fmt "fmt"
+import math "math"
+import descriptor "github.com/golang/protobuf/protoc-gen-go/descriptor"
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
+
+var E_Http = &proto.ExtensionDesc{
+ ExtendedType: (*descriptor.MethodOptions)(nil),
+ ExtensionType: (*HttpRule)(nil),
+ Field: 72295728,
+ Name: "google.api.http",
+ Tag: "bytes,72295728,opt,name=http",
+ Filename: "google/api/annotations.proto",
+}
+
+func init() {
+ proto.RegisterExtension(E_Http)
+}
+
+func init() {
+ proto.RegisterFile("google/api/annotations.proto", fileDescriptor_annotations_55609bb51d80951d)
+}
+
+var fileDescriptor_annotations_55609bb51d80951d = []byte{
+ // 208 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x49, 0xcf, 0xcf, 0x4f,
+ 0xcf, 0x49, 0xd5, 0x4f, 0x2c, 0xc8, 0xd4, 0x4f, 0xcc, 0xcb, 0xcb, 0x2f, 0x49, 0x2c, 0xc9, 0xcc,
+ 0xcf, 0x2b, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x82, 0xc8, 0xea, 0x25, 0x16, 0x64,
+ 0x4a, 0x89, 0x22, 0xa9, 0xcc, 0x28, 0x29, 0x29, 0x80, 0x28, 0x91, 0x52, 0x80, 0x0a, 0x83, 0x79,
+ 0x49, 0xa5, 0x69, 0xfa, 0x29, 0xa9, 0xc5, 0xc9, 0x45, 0x99, 0x05, 0x25, 0xf9, 0x45, 0x10, 0x15,
+ 0x56, 0xde, 0x5c, 0x2c, 0x20, 0xf5, 0x42, 0x72, 0x7a, 0x50, 0xd3, 0x60, 0x4a, 0xf5, 0x7c, 0x53,
+ 0x4b, 0x32, 0xf2, 0x53, 0xfc, 0x0b, 0xc0, 0x56, 0x4a, 0x6c, 0x38, 0xb5, 0x47, 0x49, 0x81, 0x51,
+ 0x83, 0xdb, 0x48, 0x44, 0x0f, 0x61, 0xad, 0x9e, 0x47, 0x49, 0x49, 0x41, 0x50, 0x69, 0x4e, 0x6a,
+ 0x10, 0xd8, 0x10, 0xa7, 0x3c, 0x2e, 0xbe, 0xe4, 0xfc, 0x5c, 0x24, 0x05, 0x4e, 0x02, 0x8e, 0x08,
+ 0x67, 0x07, 0x80, 0x4c, 0x0e, 0x60, 0x8c, 0x72, 0x84, 0xca, 0xa7, 0xe7, 0xe7, 0x24, 0xe6, 0xa5,
+ 0xeb, 0xe5, 0x17, 0xa5, 0xeb, 0xa7, 0xa7, 0xe6, 0x81, 0xed, 0xd5, 0x87, 0x48, 0x25, 0x16, 0x64,
+ 0x16, 0xa3, 0x7b, 0xda, 0x1a, 0x89, 0xbd, 0x88, 0x89, 0xc5, 0xdd, 0x31, 0xc0, 0x33, 0x89, 0x0d,
+ 0xac, 0xc9, 0x18, 0x10, 0x00, 0x00, 0xff, 0xff, 0xe3, 0x29, 0x19, 0x62, 0x28, 0x01, 0x00, 0x00,
+}
diff --git a/vendor/google.golang.org/genproto/googleapis/api/annotations/http.pb.go b/vendor/google.golang.org/genproto/googleapis/api/annotations/http.pb.go
new file mode 100644
index 000000000..1a8a27b65
--- /dev/null
+++ b/vendor/google.golang.org/genproto/googleapis/api/annotations/http.pb.go
@@ -0,0 +1,688 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// source: google/api/http.proto
+
+package annotations // import "google.golang.org/genproto/googleapis/api/annotations"
+
+import proto "github.com/golang/protobuf/proto"
+import fmt "fmt"
+import math "math"
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
+
+// Defines the HTTP configuration for an API service. It contains a list of
+// [HttpRule][google.api.HttpRule], each specifying the mapping of an RPC method
+// to one or more HTTP REST API methods.
+type Http struct {
+ // A list of HTTP configuration rules that apply to individual API methods.
+ //
+ // **NOTE:** All service configuration rules follow "last one wins" order.
+ Rules []*HttpRule `protobuf:"bytes,1,rep,name=rules,proto3" json:"rules,omitempty"`
+ // When set to true, URL path parmeters will be fully URI-decoded except in
+ // cases of single segment matches in reserved expansion, where "%2F" will be
+ // left encoded.
+ //
+ // The default behavior is to not decode RFC 6570 reserved characters in multi
+ // segment matches.
+ FullyDecodeReservedExpansion bool `protobuf:"varint,2,opt,name=fully_decode_reserved_expansion,json=fullyDecodeReservedExpansion,proto3" json:"fully_decode_reserved_expansion,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *Http) Reset() { *m = Http{} }
+func (m *Http) String() string { return proto.CompactTextString(m) }
+func (*Http) ProtoMessage() {}
+func (*Http) Descriptor() ([]byte, []int) {
+ return fileDescriptor_http_e457621dddd7365b, []int{0}
+}
+func (m *Http) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_Http.Unmarshal(m, b)
+}
+func (m *Http) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_Http.Marshal(b, m, deterministic)
+}
+func (dst *Http) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_Http.Merge(dst, src)
+}
+func (m *Http) XXX_Size() int {
+ return xxx_messageInfo_Http.Size(m)
+}
+func (m *Http) XXX_DiscardUnknown() {
+ xxx_messageInfo_Http.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Http proto.InternalMessageInfo
+
+func (m *Http) GetRules() []*HttpRule {
+ if m != nil {
+ return m.Rules
+ }
+ return nil
+}
+
+func (m *Http) GetFullyDecodeReservedExpansion() bool {
+ if m != nil {
+ return m.FullyDecodeReservedExpansion
+ }
+ return false
+}
+
+// `HttpRule` defines the mapping of an RPC method to one or more HTTP
+// REST API methods. The mapping specifies how different portions of the RPC
+// request message are mapped to URL path, URL query parameters, and
+// HTTP request body. The mapping is typically specified as an
+// `google.api.http` annotation on the RPC method,
+// see "google/api/annotations.proto" for details.
+//
+// The mapping consists of a field specifying the path template and
+// method kind. The path template can refer to fields in the request
+// message, as in the example below which describes a REST GET
+// operation on a resource collection of messages:
+//
+//
+// service Messaging {
+// rpc GetMessage(GetMessageRequest) returns (Message) {
+// option (google.api.http).get = "/v1/messages/{message_id}/{sub.subfield}";
+// }
+// }
+// message GetMessageRequest {
+// message SubMessage {
+// string subfield = 1;
+// }
+// string message_id = 1; // mapped to the URL
+// SubMessage sub = 2; // `sub.subfield` is url-mapped
+// }
+// message Message {
+// string text = 1; // content of the resource
+// }
+//
+// The same http annotation can alternatively be expressed inside the
+// `GRPC API Configuration` YAML file.
+//
+// http:
+// rules:
+// - selector: <proto_package_name>.Messaging.GetMessage
+// get: /v1/messages/{message_id}/{sub.subfield}
+//
+// This definition enables an automatic, bidrectional mapping of HTTP
+// JSON to RPC. Example:
+//
+// HTTP | RPC
+// -----|-----
+// `GET /v1/messages/123456/foo` | `GetMessage(message_id: "123456" sub: SubMessage(subfield: "foo"))`
+//
+// In general, not only fields but also field paths can be referenced
+// from a path pattern. Fields mapped to the path pattern cannot be
+// repeated and must have a primitive (non-message) type.
+//
+// Any fields in the request message which are not bound by the path
+// pattern automatically become (optional) HTTP query
+// parameters. Assume the following definition of the request message:
+//
+//
+// service Messaging {
+// rpc GetMessage(GetMessageRequest) returns (Message) {
+// option (google.api.http).get = "/v1/messages/{message_id}";
+// }
+// }
+// message GetMessageRequest {
+// message SubMessage {
+// string subfield = 1;
+// }
+// string message_id = 1; // mapped to the URL
+// int64 revision = 2; // becomes a parameter
+// SubMessage sub = 3; // `sub.subfield` becomes a parameter
+// }
+//
+//
+// This enables a HTTP JSON to RPC mapping as below:
+//
+// HTTP | RPC
+// -----|-----
+// `GET /v1/messages/123456?revision=2&sub.subfield=foo` | `GetMessage(message_id: "123456" revision: 2 sub: SubMessage(subfield: "foo"))`
+//
+// Note that fields which are mapped to HTTP parameters must have a
+// primitive type or a repeated primitive type. Message types are not
+// allowed. In the case of a repeated type, the parameter can be
+// repeated in the URL, as in `...?param=A&param=B`.
+//
+// For HTTP method kinds which allow a request body, the `body` field
+// specifies the mapping. Consider a REST update method on the
+// message resource collection:
+//
+//
+// service Messaging {
+// rpc UpdateMessage(UpdateMessageRequest) returns (Message) {
+// option (google.api.http) = {
+// put: "/v1/messages/{message_id}"
+// body: "message"
+// };
+// }
+// }
+// message UpdateMessageRequest {
+// string message_id = 1; // mapped to the URL
+// Message message = 2; // mapped to the body
+// }
+//
+//
+// The following HTTP JSON to RPC mapping is enabled, where the
+// representation of the JSON in the request body is determined by
+// protos JSON encoding:
+//
+// HTTP | RPC
+// -----|-----
+// `PUT /v1/messages/123456 { "text": "Hi!" }` | `UpdateMessage(message_id: "123456" message { text: "Hi!" })`
+//
+// The special name `*` can be used in the body mapping to define that
+// every field not bound by the path template should be mapped to the
+// request body. This enables the following alternative definition of
+// the update method:
+//
+// service Messaging {
+// rpc UpdateMessage(Message) returns (Message) {
+// option (google.api.http) = {
+// put: "/v1/messages/{message_id}"
+// body: "*"
+// };
+// }
+// }
+// message Message {
+// string message_id = 1;
+// string text = 2;
+// }
+//
+//
+// The following HTTP JSON to RPC mapping is enabled:
+//
+// HTTP | RPC
+// -----|-----
+// `PUT /v1/messages/123456 { "text": "Hi!" }` | `UpdateMessage(message_id: "123456" text: "Hi!")`
+//
+// Note that when using `*` in the body mapping, it is not possible to
+// have HTTP parameters, as all fields not bound by the path end in
+// the body. This makes this option more rarely used in practice of
+// defining REST APIs. The common usage of `*` is in custom methods
+// which don't use the URL at all for transferring data.
+//
+// It is possible to define multiple HTTP methods for one RPC by using
+// the `additional_bindings` option. Example:
+//
+// service Messaging {
+// rpc GetMessage(GetMessageRequest) returns (Message) {
+// option (google.api.http) = {
+// get: "/v1/messages/{message_id}"
+// additional_bindings {
+// get: "/v1/users/{user_id}/messages/{message_id}"
+// }
+// };
+// }
+// }
+// message GetMessageRequest {
+// string message_id = 1;
+// string user_id = 2;
+// }
+//
+//
+// This enables the following two alternative HTTP JSON to RPC
+// mappings:
+//
+// HTTP | RPC
+// -----|-----
+// `GET /v1/messages/123456` | `GetMessage(message_id: "123456")`
+// `GET /v1/users/me/messages/123456` | `GetMessage(user_id: "me" message_id: "123456")`
+//
+// # Rules for HTTP mapping
+//
+// The rules for mapping HTTP path, query parameters, and body fields
+// to the request message are as follows:
+//
+// 1. The `body` field specifies either `*` or a field path, or is
+// omitted. If omitted, it indicates there is no HTTP request body.
+// 2. Leaf fields (recursive expansion of nested messages in the
+// request) can be classified into three types:
+// (a) Matched in the URL template.
+// (b) Covered by body (if body is `*`, everything except (a) fields;
+// else everything under the body field)
+// (c) All other fields.
+// 3. URL query parameters found in the HTTP request are mapped to (c) fields.
+// 4. Any body sent with an HTTP request can contain only (b) fields.
+//
+// The syntax of the path template is as follows:
+//
+// Template = "/" Segments [ Verb ] ;
+// Segments = Segment { "/" Segment } ;
+// Segment = "*" | "**" | LITERAL | Variable ;
+// Variable = "{" FieldPath [ "=" Segments ] "}" ;
+// FieldPath = IDENT { "." IDENT } ;
+// Verb = ":" LITERAL ;
+//
+// The syntax `*` matches a single path segment. The syntax `**` matches zero
+// or more path segments, which must be the last part of the path except the
+// `Verb`. The syntax `LITERAL` matches literal text in the path.
+//
+// The syntax `Variable` matches part of the URL path as specified by its
+// template. A variable template must not contain other variables. If a variable
+// matches a single path segment, its template may be omitted, e.g. `{var}`
+// is equivalent to `{var=*}`.
+//
+// If a variable contains exactly one path segment, such as `"{var}"` or
+// `"{var=*}"`, when such a variable is expanded into a URL path, all characters
+// except `[-_.~0-9a-zA-Z]` are percent-encoded. Such variables show up in the
+// Discovery Document as `{var}`.
+//
+// If a variable contains one or more path segments, such as `"{var=foo/*}"`
+// or `"{var=**}"`, when such a variable is expanded into a URL path, all
+// characters except `[-_.~/0-9a-zA-Z]` are percent-encoded. Such variables
+// show up in the Discovery Document as `{+var}`.
+//
+// NOTE: While the single segment variable matches the semantics of
+// [RFC 6570](https://tools.ietf.org/html/rfc6570) Section 3.2.2
+// Simple String Expansion, the multi segment variable **does not** match
+// RFC 6570 Reserved Expansion. The reason is that the Reserved Expansion
+// does not expand special characters like `?` and `#`, which would lead
+// to invalid URLs.
+//
+// NOTE: the field paths in variables and in the `body` must not refer to
+// repeated fields or map fields.
+type HttpRule struct {
+ // Selects methods to which this rule applies.
+ //
+ // Refer to [selector][google.api.DocumentationRule.selector] for syntax details.
+ Selector string `protobuf:"bytes,1,opt,name=selector,proto3" json:"selector,omitempty"`
+ // Determines the URL pattern is matched by this rules. This pattern can be
+ // used with any of the {get|put|post|delete|patch} methods. A custom method
+ // can be defined using the 'custom' field.
+ //
+ // Types that are valid to be assigned to Pattern:
+ // *HttpRule_Get
+ // *HttpRule_Put
+ // *HttpRule_Post
+ // *HttpRule_Delete
+ // *HttpRule_Patch
+ // *HttpRule_Custom
+ Pattern isHttpRule_Pattern `protobuf_oneof:"pattern"`
+ // The name of the request field whose value is mapped to the HTTP body, or
+ // `*` for mapping all fields not captured by the path pattern to the HTTP
+ // body. NOTE: the referred field must not be a repeated field and must be
+ // present at the top-level of request message type.
+ Body string `protobuf:"bytes,7,opt,name=body,proto3" json:"body,omitempty"`
+ // Optional. The name of the response field whose value is mapped to the HTTP
+ // body of response. Other response fields are ignored. When
+ // not set, the response message will be used as HTTP body of response.
+ ResponseBody string `protobuf:"bytes,12,opt,name=response_body,json=responseBody,proto3" json:"response_body,omitempty"`
+ // Additional HTTP bindings for the selector. Nested bindings must
+ // not contain an `additional_bindings` field themselves (that is,
+ // the nesting may only be one level deep).
+ AdditionalBindings []*HttpRule `protobuf:"bytes,11,rep,name=additional_bindings,json=additionalBindings,proto3" json:"additional_bindings,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *HttpRule) Reset() { *m = HttpRule{} }
+func (m *HttpRule) String() string { return proto.CompactTextString(m) }
+func (*HttpRule) ProtoMessage() {}
+func (*HttpRule) Descriptor() ([]byte, []int) {
+ return fileDescriptor_http_e457621dddd7365b, []int{1}
+}
+func (m *HttpRule) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_HttpRule.Unmarshal(m, b)
+}
+func (m *HttpRule) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_HttpRule.Marshal(b, m, deterministic)
+}
+func (dst *HttpRule) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_HttpRule.Merge(dst, src)
+}
+func (m *HttpRule) XXX_Size() int {
+ return xxx_messageInfo_HttpRule.Size(m)
+}
+func (m *HttpRule) XXX_DiscardUnknown() {
+ xxx_messageInfo_HttpRule.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_HttpRule proto.InternalMessageInfo
+
+func (m *HttpRule) GetSelector() string {
+ if m != nil {
+ return m.Selector
+ }
+ return ""
+}
+
+type isHttpRule_Pattern interface {
+ isHttpRule_Pattern()
+}
+
+type HttpRule_Get struct {
+ Get string `protobuf:"bytes,2,opt,name=get,proto3,oneof"`
+}
+
+type HttpRule_Put struct {
+ Put string `protobuf:"bytes,3,opt,name=put,proto3,oneof"`
+}
+
+type HttpRule_Post struct {
+ Post string `protobuf:"bytes,4,opt,name=post,proto3,oneof"`
+}
+
+type HttpRule_Delete struct {
+ Delete string `protobuf:"bytes,5,opt,name=delete,proto3,oneof"`
+}
+
+type HttpRule_Patch struct {
+ Patch string `protobuf:"bytes,6,opt,name=patch,proto3,oneof"`
+}
+
+type HttpRule_Custom struct {
+ Custom *CustomHttpPattern `protobuf:"bytes,8,opt,name=custom,proto3,oneof"`
+}
+
+func (*HttpRule_Get) isHttpRule_Pattern() {}
+
+func (*HttpRule_Put) isHttpRule_Pattern() {}
+
+func (*HttpRule_Post) isHttpRule_Pattern() {}
+
+func (*HttpRule_Delete) isHttpRule_Pattern() {}
+
+func (*HttpRule_Patch) isHttpRule_Pattern() {}
+
+func (*HttpRule_Custom) isHttpRule_Pattern() {}
+
+func (m *HttpRule) GetPattern() isHttpRule_Pattern {
+ if m != nil {
+ return m.Pattern
+ }
+ return nil
+}
+
+func (m *HttpRule) GetGet() string {
+ if x, ok := m.GetPattern().(*HttpRule_Get); ok {
+ return x.Get
+ }
+ return ""
+}
+
+func (m *HttpRule) GetPut() string {
+ if x, ok := m.GetPattern().(*HttpRule_Put); ok {
+ return x.Put
+ }
+ return ""
+}
+
+func (m *HttpRule) GetPost() string {
+ if x, ok := m.GetPattern().(*HttpRule_Post); ok {
+ return x.Post
+ }
+ return ""
+}
+
+func (m *HttpRule) GetDelete() string {
+ if x, ok := m.GetPattern().(*HttpRule_Delete); ok {
+ return x.Delete
+ }
+ return ""
+}
+
+func (m *HttpRule) GetPatch() string {
+ if x, ok := m.GetPattern().(*HttpRule_Patch); ok {
+ return x.Patch
+ }
+ return ""
+}
+
+func (m *HttpRule) GetCustom() *CustomHttpPattern {
+ if x, ok := m.GetPattern().(*HttpRule_Custom); ok {
+ return x.Custom
+ }
+ return nil
+}
+
+func (m *HttpRule) GetBody() string {
+ if m != nil {
+ return m.Body
+ }
+ return ""
+}
+
+func (m *HttpRule) GetResponseBody() string {
+ if m != nil {
+ return m.ResponseBody
+ }
+ return ""
+}
+
+func (m *HttpRule) GetAdditionalBindings() []*HttpRule {
+ if m != nil {
+ return m.AdditionalBindings
+ }
+ return nil
+}
+
+// XXX_OneofFuncs is for the internal use of the proto package.
+func (*HttpRule) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) {
+ return _HttpRule_OneofMarshaler, _HttpRule_OneofUnmarshaler, _HttpRule_OneofSizer, []interface{}{
+ (*HttpRule_Get)(nil),
+ (*HttpRule_Put)(nil),
+ (*HttpRule_Post)(nil),
+ (*HttpRule_Delete)(nil),
+ (*HttpRule_Patch)(nil),
+ (*HttpRule_Custom)(nil),
+ }
+}
+
+func _HttpRule_OneofMarshaler(msg proto.Message, b *proto.Buffer) error {
+ m := msg.(*HttpRule)
+ // pattern
+ switch x := m.Pattern.(type) {
+ case *HttpRule_Get:
+ b.EncodeVarint(2<<3 | proto.WireBytes)
+ b.EncodeStringBytes(x.Get)
+ case *HttpRule_Put:
+ b.EncodeVarint(3<<3 | proto.WireBytes)
+ b.EncodeStringBytes(x.Put)
+ case *HttpRule_Post:
+ b.EncodeVarint(4<<3 | proto.WireBytes)
+ b.EncodeStringBytes(x.Post)
+ case *HttpRule_Delete:
+ b.EncodeVarint(5<<3 | proto.WireBytes)
+ b.EncodeStringBytes(x.Delete)
+ case *HttpRule_Patch:
+ b.EncodeVarint(6<<3 | proto.WireBytes)
+ b.EncodeStringBytes(x.Patch)
+ case *HttpRule_Custom:
+ b.EncodeVarint(8<<3 | proto.WireBytes)
+ if err := b.EncodeMessage(x.Custom); err != nil {
+ return err
+ }
+ case nil:
+ default:
+ return fmt.Errorf("HttpRule.Pattern has unexpected type %T", x)
+ }
+ return nil
+}
+
+func _HttpRule_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) {
+ m := msg.(*HttpRule)
+ switch tag {
+ case 2: // pattern.get
+ if wire != proto.WireBytes {
+ return true, proto.ErrInternalBadWireType
+ }
+ x, err := b.DecodeStringBytes()
+ m.Pattern = &HttpRule_Get{x}
+ return true, err
+ case 3: // pattern.put
+ if wire != proto.WireBytes {
+ return true, proto.ErrInternalBadWireType
+ }
+ x, err := b.DecodeStringBytes()
+ m.Pattern = &HttpRule_Put{x}
+ return true, err
+ case 4: // pattern.post
+ if wire != proto.WireBytes {
+ return true, proto.ErrInternalBadWireType
+ }
+ x, err := b.DecodeStringBytes()
+ m.Pattern = &HttpRule_Post{x}
+ return true, err
+ case 5: // pattern.delete
+ if wire != proto.WireBytes {
+ return true, proto.ErrInternalBadWireType
+ }
+ x, err := b.DecodeStringBytes()
+ m.Pattern = &HttpRule_Delete{x}
+ return true, err
+ case 6: // pattern.patch
+ if wire != proto.WireBytes {
+ return true, proto.ErrInternalBadWireType
+ }
+ x, err := b.DecodeStringBytes()
+ m.Pattern = &HttpRule_Patch{x}
+ return true, err
+ case 8: // pattern.custom
+ if wire != proto.WireBytes {
+ return true, proto.ErrInternalBadWireType
+ }
+ msg := new(CustomHttpPattern)
+ err := b.DecodeMessage(msg)
+ m.Pattern = &HttpRule_Custom{msg}
+ return true, err
+ default:
+ return false, nil
+ }
+}
+
+func _HttpRule_OneofSizer(msg proto.Message) (n int) {
+ m := msg.(*HttpRule)
+ // pattern
+ switch x := m.Pattern.(type) {
+ case *HttpRule_Get:
+ n += 1 // tag and wire
+ n += proto.SizeVarint(uint64(len(x.Get)))
+ n += len(x.Get)
+ case *HttpRule_Put:
+ n += 1 // tag and wire
+ n += proto.SizeVarint(uint64(len(x.Put)))
+ n += len(x.Put)
+ case *HttpRule_Post:
+ n += 1 // tag and wire
+ n += proto.SizeVarint(uint64(len(x.Post)))
+ n += len(x.Post)
+ case *HttpRule_Delete:
+ n += 1 // tag and wire
+ n += proto.SizeVarint(uint64(len(x.Delete)))
+ n += len(x.Delete)
+ case *HttpRule_Patch:
+ n += 1 // tag and wire
+ n += proto.SizeVarint(uint64(len(x.Patch)))
+ n += len(x.Patch)
+ case *HttpRule_Custom:
+ s := proto.Size(x.Custom)
+ n += 1 // tag and wire
+ n += proto.SizeVarint(uint64(s))
+ n += s
+ case nil:
+ default:
+ panic(fmt.Sprintf("proto: unexpected type %T in oneof", x))
+ }
+ return n
+}
+
+// A custom pattern is used for defining custom HTTP verb.
+type CustomHttpPattern struct {
+ // The name of this custom HTTP verb.
+ Kind string `protobuf:"bytes,1,opt,name=kind,proto3" json:"kind,omitempty"`
+ // The path matched by this custom verb.
+ Path string `protobuf:"bytes,2,opt,name=path,proto3" json:"path,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *CustomHttpPattern) Reset() { *m = CustomHttpPattern{} }
+func (m *CustomHttpPattern) String() string { return proto.CompactTextString(m) }
+func (*CustomHttpPattern) ProtoMessage() {}
+func (*CustomHttpPattern) Descriptor() ([]byte, []int) {
+ return fileDescriptor_http_e457621dddd7365b, []int{2}
+}
+func (m *CustomHttpPattern) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_CustomHttpPattern.Unmarshal(m, b)
+}
+func (m *CustomHttpPattern) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_CustomHttpPattern.Marshal(b, m, deterministic)
+}
+func (dst *CustomHttpPattern) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_CustomHttpPattern.Merge(dst, src)
+}
+func (m *CustomHttpPattern) XXX_Size() int {
+ return xxx_messageInfo_CustomHttpPattern.Size(m)
+}
+func (m *CustomHttpPattern) XXX_DiscardUnknown() {
+ xxx_messageInfo_CustomHttpPattern.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_CustomHttpPattern proto.InternalMessageInfo
+
+func (m *CustomHttpPattern) GetKind() string {
+ if m != nil {
+ return m.Kind
+ }
+ return ""
+}
+
+func (m *CustomHttpPattern) GetPath() string {
+ if m != nil {
+ return m.Path
+ }
+ return ""
+}
+
+func init() {
+ proto.RegisterType((*Http)(nil), "google.api.Http")
+ proto.RegisterType((*HttpRule)(nil), "google.api.HttpRule")
+ proto.RegisterType((*CustomHttpPattern)(nil), "google.api.CustomHttpPattern")
+}
+
+func init() { proto.RegisterFile("google/api/http.proto", fileDescriptor_http_e457621dddd7365b) }
+
+var fileDescriptor_http_e457621dddd7365b = []byte{
+ // 419 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x92, 0xc1, 0x8e, 0xd3, 0x30,
+ 0x10, 0x86, 0x49, 0x9b, 0x76, 0xdb, 0xe9, 0x82, 0x84, 0x59, 0x90, 0x85, 0x40, 0x54, 0xe5, 0x52,
+ 0x71, 0x48, 0xa5, 0xe5, 0xc0, 0x61, 0x4f, 0x1b, 0xa8, 0x58, 0x6e, 0x55, 0x8e, 0x5c, 0x22, 0x37,
+ 0x1e, 0x52, 0x83, 0xd7, 0xb6, 0xe2, 0x09, 0xa2, 0xaf, 0xc3, 0x63, 0xf1, 0x24, 0x1c, 0x91, 0x9d,
+ 0x84, 0x56, 0x42, 0xe2, 0x36, 0xf3, 0xff, 0x9f, 0xa7, 0x7f, 0x27, 0x03, 0x4f, 0x6b, 0x6b, 0x6b,
+ 0x8d, 0x1b, 0xe1, 0xd4, 0xe6, 0x40, 0xe4, 0x32, 0xd7, 0x58, 0xb2, 0x0c, 0x3a, 0x39, 0x13, 0x4e,
+ 0xad, 0x8e, 0x90, 0xde, 0x11, 0x39, 0xf6, 0x06, 0x26, 0x4d, 0xab, 0xd1, 0xf3, 0x64, 0x39, 0x5e,
+ 0x2f, 0xae, 0xaf, 0xb2, 0x13, 0x93, 0x05, 0xa0, 0x68, 0x35, 0x16, 0x1d, 0xc2, 0xb6, 0xf0, 0xea,
+ 0x4b, 0xab, 0xf5, 0xb1, 0x94, 0x58, 0x59, 0x89, 0x65, 0x83, 0x1e, 0x9b, 0xef, 0x28, 0x4b, 0xfc,
+ 0xe1, 0x84, 0xf1, 0xca, 0x1a, 0x3e, 0x5a, 0x26, 0xeb, 0x59, 0xf1, 0x22, 0x62, 0x1f, 0x22, 0x55,
+ 0xf4, 0xd0, 0x76, 0x60, 0x56, 0xbf, 0x46, 0x30, 0x1b, 0x46, 0xb3, 0xe7, 0x30, 0xf3, 0xa8, 0xb1,
+ 0x22, 0xdb, 0xf0, 0x64, 0x99, 0xac, 0xe7, 0xc5, 0xdf, 0x9e, 0x31, 0x18, 0xd7, 0x48, 0x71, 0xe6,
+ 0xfc, 0xee, 0x41, 0x11, 0x9a, 0xa0, 0xb9, 0x96, 0xf8, 0x78, 0xd0, 0x5c, 0x4b, 0xec, 0x0a, 0x52,
+ 0x67, 0x3d, 0xf1, 0xb4, 0x17, 0x63, 0xc7, 0x38, 0x4c, 0x25, 0x6a, 0x24, 0xe4, 0x93, 0x5e, 0xef,
+ 0x7b, 0xf6, 0x0c, 0x26, 0x4e, 0x50, 0x75, 0xe0, 0xd3, 0xde, 0xe8, 0x5a, 0xf6, 0x0e, 0xa6, 0x55,
+ 0xeb, 0xc9, 0xde, 0xf3, 0xd9, 0x32, 0x59, 0x2f, 0xae, 0x5f, 0x9e, 0x2f, 0xe3, 0x7d, 0x74, 0x42,
+ 0xee, 0x9d, 0x20, 0xc2, 0xc6, 0x84, 0x81, 0x1d, 0xce, 0x18, 0xa4, 0x7b, 0x2b, 0x8f, 0xfc, 0x22,
+ 0xfe, 0x81, 0x58, 0xb3, 0xd7, 0xf0, 0xb0, 0x41, 0xef, 0xac, 0xf1, 0x58, 0x46, 0xf3, 0x32, 0x9a,
+ 0x97, 0x83, 0x98, 0x07, 0x68, 0x0b, 0x4f, 0x84, 0x94, 0x8a, 0x94, 0x35, 0x42, 0x97, 0x7b, 0x65,
+ 0xa4, 0x32, 0xb5, 0xe7, 0x8b, 0xff, 0x7c, 0x0b, 0x76, 0x7a, 0x90, 0xf7, 0x7c, 0x3e, 0x87, 0x0b,
+ 0xd7, 0x85, 0x5a, 0xdd, 0xc0, 0xe3, 0x7f, 0x92, 0x86, 0x7c, 0xdf, 0x94, 0x91, 0xfd, 0x82, 0x63,
+ 0x1d, 0x34, 0x27, 0xe8, 0xd0, 0x6d, 0xb7, 0x88, 0x75, 0xfe, 0x15, 0x1e, 0x55, 0xf6, 0xfe, 0xec,
+ 0x67, 0xf3, 0x79, 0x1c, 0x13, 0xae, 0x67, 0x97, 0x7c, 0xbe, 0xed, 0x8d, 0xda, 0x6a, 0x61, 0xea,
+ 0xcc, 0x36, 0xf5, 0xa6, 0x46, 0x13, 0x6f, 0x6b, 0xd3, 0x59, 0xc2, 0x29, 0x1f, 0xaf, 0x4e, 0x18,
+ 0x63, 0x49, 0x84, 0x98, 0xfe, 0xe6, 0xac, 0xfe, 0x9d, 0x24, 0x3f, 0x47, 0xe9, 0xc7, 0xdb, 0xdd,
+ 0xa7, 0xfd, 0x34, 0xbe, 0x7b, 0xfb, 0x27, 0x00, 0x00, 0xff, 0xff, 0xae, 0xde, 0xa1, 0xd0, 0xac,
+ 0x02, 0x00, 0x00,
+}
diff --git a/vendor/google.golang.org/genproto/googleapis/iam/v1/iam_policy.pb.go b/vendor/google.golang.org/genproto/googleapis/iam/v1/iam_policy.pb.go
new file mode 100644
index 000000000..e29438eb0
--- /dev/null
+++ b/vendor/google.golang.org/genproto/googleapis/iam/v1/iam_policy.pb.go
@@ -0,0 +1,412 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// source: google/iam/v1/iam_policy.proto
+
+package iam // import "google.golang.org/genproto/googleapis/iam/v1"
+
+import proto "github.com/golang/protobuf/proto"
+import fmt "fmt"
+import math "math"
+import _ "google.golang.org/genproto/googleapis/api/annotations"
+
+import (
+ // TODO(bojie): remove this when googleapis updated
+ "context"
+ grpc "google.golang.org/grpc"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
+
+// Request message for `SetIamPolicy` method.
+type SetIamPolicyRequest struct {
+ // REQUIRED: The resource for which the policy is being specified.
+ // `resource` is usually specified as a path. For example, a Project
+ // resource is specified as `projects/{project}`.
+ Resource string `protobuf:"bytes,1,opt,name=resource,proto3" json:"resource,omitempty"`
+ // REQUIRED: The complete policy to be applied to the `resource`. The size of
+ // the policy is limited to a few 10s of KB. An empty policy is a
+ // valid policy but certain Cloud Platform services (such as Projects)
+ // might reject them.
+ Policy *Policy `protobuf:"bytes,2,opt,name=policy,proto3" json:"policy,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *SetIamPolicyRequest) Reset() { *m = SetIamPolicyRequest{} }
+func (m *SetIamPolicyRequest) String() string { return proto.CompactTextString(m) }
+func (*SetIamPolicyRequest) ProtoMessage() {}
+func (*SetIamPolicyRequest) Descriptor() ([]byte, []int) {
+ return fileDescriptor_iam_policy_58547b5cf2e9d67a, []int{0}
+}
+func (m *SetIamPolicyRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_SetIamPolicyRequest.Unmarshal(m, b)
+}
+func (m *SetIamPolicyRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_SetIamPolicyRequest.Marshal(b, m, deterministic)
+}
+func (dst *SetIamPolicyRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_SetIamPolicyRequest.Merge(dst, src)
+}
+func (m *SetIamPolicyRequest) XXX_Size() int {
+ return xxx_messageInfo_SetIamPolicyRequest.Size(m)
+}
+func (m *SetIamPolicyRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_SetIamPolicyRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_SetIamPolicyRequest proto.InternalMessageInfo
+
+func (m *SetIamPolicyRequest) GetResource() string {
+ if m != nil {
+ return m.Resource
+ }
+ return ""
+}
+
+func (m *SetIamPolicyRequest) GetPolicy() *Policy {
+ if m != nil {
+ return m.Policy
+ }
+ return nil
+}
+
+// Request message for `GetIamPolicy` method.
+type GetIamPolicyRequest struct {
+ // REQUIRED: The resource for which the policy is being requested.
+ // `resource` is usually specified as a path. For example, a Project
+ // resource is specified as `projects/{project}`.
+ Resource string `protobuf:"bytes,1,opt,name=resource,proto3" json:"resource,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *GetIamPolicyRequest) Reset() { *m = GetIamPolicyRequest{} }
+func (m *GetIamPolicyRequest) String() string { return proto.CompactTextString(m) }
+func (*GetIamPolicyRequest) ProtoMessage() {}
+func (*GetIamPolicyRequest) Descriptor() ([]byte, []int) {
+ return fileDescriptor_iam_policy_58547b5cf2e9d67a, []int{1}
+}
+func (m *GetIamPolicyRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GetIamPolicyRequest.Unmarshal(m, b)
+}
+func (m *GetIamPolicyRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GetIamPolicyRequest.Marshal(b, m, deterministic)
+}
+func (dst *GetIamPolicyRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GetIamPolicyRequest.Merge(dst, src)
+}
+func (m *GetIamPolicyRequest) XXX_Size() int {
+ return xxx_messageInfo_GetIamPolicyRequest.Size(m)
+}
+func (m *GetIamPolicyRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_GetIamPolicyRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetIamPolicyRequest proto.InternalMessageInfo
+
+func (m *GetIamPolicyRequest) GetResource() string {
+ if m != nil {
+ return m.Resource
+ }
+ return ""
+}
+
+// Request message for `TestIamPermissions` method.
+type TestIamPermissionsRequest struct {
+ // REQUIRED: The resource for which the policy detail is being requested.
+ // `resource` is usually specified as a path. For example, a Project
+ // resource is specified as `projects/{project}`.
+ Resource string `protobuf:"bytes,1,opt,name=resource,proto3" json:"resource,omitempty"`
+ // The set of permissions to check for the `resource`. Permissions with
+ // wildcards (such as '*' or 'storage.*') are not allowed. For more
+ // information see
+ // [IAM Overview](https://cloud.google.com/iam/docs/overview#permissions).
+ Permissions []string `protobuf:"bytes,2,rep,name=permissions,proto3" json:"permissions,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *TestIamPermissionsRequest) Reset() { *m = TestIamPermissionsRequest{} }
+func (m *TestIamPermissionsRequest) String() string { return proto.CompactTextString(m) }
+func (*TestIamPermissionsRequest) ProtoMessage() {}
+func (*TestIamPermissionsRequest) Descriptor() ([]byte, []int) {
+ return fileDescriptor_iam_policy_58547b5cf2e9d67a, []int{2}
+}
+func (m *TestIamPermissionsRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_TestIamPermissionsRequest.Unmarshal(m, b)
+}
+func (m *TestIamPermissionsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_TestIamPermissionsRequest.Marshal(b, m, deterministic)
+}
+func (dst *TestIamPermissionsRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_TestIamPermissionsRequest.Merge(dst, src)
+}
+func (m *TestIamPermissionsRequest) XXX_Size() int {
+ return xxx_messageInfo_TestIamPermissionsRequest.Size(m)
+}
+func (m *TestIamPermissionsRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_TestIamPermissionsRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_TestIamPermissionsRequest proto.InternalMessageInfo
+
+func (m *TestIamPermissionsRequest) GetResource() string {
+ if m != nil {
+ return m.Resource
+ }
+ return ""
+}
+
+func (m *TestIamPermissionsRequest) GetPermissions() []string {
+ if m != nil {
+ return m.Permissions
+ }
+ return nil
+}
+
+// Response message for `TestIamPermissions` method.
+type TestIamPermissionsResponse struct {
+ // A subset of `TestPermissionsRequest.permissions` that the caller is
+ // allowed.
+ Permissions []string `protobuf:"bytes,1,rep,name=permissions,proto3" json:"permissions,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *TestIamPermissionsResponse) Reset() { *m = TestIamPermissionsResponse{} }
+func (m *TestIamPermissionsResponse) String() string { return proto.CompactTextString(m) }
+func (*TestIamPermissionsResponse) ProtoMessage() {}
+func (*TestIamPermissionsResponse) Descriptor() ([]byte, []int) {
+ return fileDescriptor_iam_policy_58547b5cf2e9d67a, []int{3}
+}
+func (m *TestIamPermissionsResponse) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_TestIamPermissionsResponse.Unmarshal(m, b)
+}
+func (m *TestIamPermissionsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_TestIamPermissionsResponse.Marshal(b, m, deterministic)
+}
+func (dst *TestIamPermissionsResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_TestIamPermissionsResponse.Merge(dst, src)
+}
+func (m *TestIamPermissionsResponse) XXX_Size() int {
+ return xxx_messageInfo_TestIamPermissionsResponse.Size(m)
+}
+func (m *TestIamPermissionsResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_TestIamPermissionsResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_TestIamPermissionsResponse proto.InternalMessageInfo
+
+func (m *TestIamPermissionsResponse) GetPermissions() []string {
+ if m != nil {
+ return m.Permissions
+ }
+ return nil
+}
+
+func init() {
+ proto.RegisterType((*SetIamPolicyRequest)(nil), "google.iam.v1.SetIamPolicyRequest")
+ proto.RegisterType((*GetIamPolicyRequest)(nil), "google.iam.v1.GetIamPolicyRequest")
+ proto.RegisterType((*TestIamPermissionsRequest)(nil), "google.iam.v1.TestIamPermissionsRequest")
+ proto.RegisterType((*TestIamPermissionsResponse)(nil), "google.iam.v1.TestIamPermissionsResponse")
+}
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ context.Context
+var _ grpc.ClientConn
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the grpc package it is being compiled against.
+const _ = grpc.SupportPackageIsVersion4
+
+// IAMPolicyClient is the client API for IAMPolicy service.
+//
+// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
+type IAMPolicyClient interface {
+ // Sets the access control policy on the specified resource. Replaces any
+ // existing policy.
+ SetIamPolicy(ctx context.Context, in *SetIamPolicyRequest, opts ...grpc.CallOption) (*Policy, error)
+ // Gets the access control policy for a resource.
+ // Returns an empty policy if the resource exists and does not have a policy
+ // set.
+ GetIamPolicy(ctx context.Context, in *GetIamPolicyRequest, opts ...grpc.CallOption) (*Policy, error)
+ // Returns permissions that a caller has on the specified resource.
+ // If the resource does not exist, this will return an empty set of
+ // permissions, not a NOT_FOUND error.
+ TestIamPermissions(ctx context.Context, in *TestIamPermissionsRequest, opts ...grpc.CallOption) (*TestIamPermissionsResponse, error)
+}
+
+type iAMPolicyClient struct {
+ cc *grpc.ClientConn
+}
+
+func NewIAMPolicyClient(cc *grpc.ClientConn) IAMPolicyClient {
+ return &iAMPolicyClient{cc}
+}
+
+func (c *iAMPolicyClient) SetIamPolicy(ctx context.Context, in *SetIamPolicyRequest, opts ...grpc.CallOption) (*Policy, error) {
+ out := new(Policy)
+ err := c.cc.Invoke(ctx, "/google.iam.v1.IAMPolicy/SetIamPolicy", in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *iAMPolicyClient) GetIamPolicy(ctx context.Context, in *GetIamPolicyRequest, opts ...grpc.CallOption) (*Policy, error) {
+ out := new(Policy)
+ err := c.cc.Invoke(ctx, "/google.iam.v1.IAMPolicy/GetIamPolicy", in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *iAMPolicyClient) TestIamPermissions(ctx context.Context, in *TestIamPermissionsRequest, opts ...grpc.CallOption) (*TestIamPermissionsResponse, error) {
+ out := new(TestIamPermissionsResponse)
+ err := c.cc.Invoke(ctx, "/google.iam.v1.IAMPolicy/TestIamPermissions", in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+// IAMPolicyServer is the server API for IAMPolicy service.
+type IAMPolicyServer interface {
+ // Sets the access control policy on the specified resource. Replaces any
+ // existing policy.
+ SetIamPolicy(context.Context, *SetIamPolicyRequest) (*Policy, error)
+ // Gets the access control policy for a resource.
+ // Returns an empty policy if the resource exists and does not have a policy
+ // set.
+ GetIamPolicy(context.Context, *GetIamPolicyRequest) (*Policy, error)
+ // Returns permissions that a caller has on the specified resource.
+ // If the resource does not exist, this will return an empty set of
+ // permissions, not a NOT_FOUND error.
+ TestIamPermissions(context.Context, *TestIamPermissionsRequest) (*TestIamPermissionsResponse, error)
+}
+
+func RegisterIAMPolicyServer(s *grpc.Server, srv IAMPolicyServer) {
+ s.RegisterService(&_IAMPolicy_serviceDesc, srv)
+}
+
+func _IAMPolicy_SetIamPolicy_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(SetIamPolicyRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(IAMPolicyServer).SetIamPolicy(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/google.iam.v1.IAMPolicy/SetIamPolicy",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(IAMPolicyServer).SetIamPolicy(ctx, req.(*SetIamPolicyRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _IAMPolicy_GetIamPolicy_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(GetIamPolicyRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(IAMPolicyServer).GetIamPolicy(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/google.iam.v1.IAMPolicy/GetIamPolicy",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(IAMPolicyServer).GetIamPolicy(ctx, req.(*GetIamPolicyRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _IAMPolicy_TestIamPermissions_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(TestIamPermissionsRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(IAMPolicyServer).TestIamPermissions(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/google.iam.v1.IAMPolicy/TestIamPermissions",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(IAMPolicyServer).TestIamPermissions(ctx, req.(*TestIamPermissionsRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+var _IAMPolicy_serviceDesc = grpc.ServiceDesc{
+ ServiceName: "google.iam.v1.IAMPolicy",
+ HandlerType: (*IAMPolicyServer)(nil),
+ Methods: []grpc.MethodDesc{
+ {
+ MethodName: "SetIamPolicy",
+ Handler: _IAMPolicy_SetIamPolicy_Handler,
+ },
+ {
+ MethodName: "GetIamPolicy",
+ Handler: _IAMPolicy_GetIamPolicy_Handler,
+ },
+ {
+ MethodName: "TestIamPermissions",
+ Handler: _IAMPolicy_TestIamPermissions_Handler,
+ },
+ },
+ Streams: []grpc.StreamDesc{},
+ Metadata: "google/iam/v1/iam_policy.proto",
+}
+
+func init() {
+ proto.RegisterFile("google/iam/v1/iam_policy.proto", fileDescriptor_iam_policy_58547b5cf2e9d67a)
+}
+
+var fileDescriptor_iam_policy_58547b5cf2e9d67a = []byte{
+ // 411 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4b, 0xcf, 0xcf, 0x4f,
+ 0xcf, 0x49, 0xd5, 0xcf, 0x4c, 0xcc, 0xd5, 0x2f, 0x33, 0x04, 0x51, 0xf1, 0x05, 0xf9, 0x39, 0x99,
+ 0xc9, 0x95, 0x7a, 0x05, 0x45, 0xf9, 0x25, 0xf9, 0x42, 0xbc, 0x10, 0x79, 0xbd, 0xcc, 0xc4, 0x5c,
+ 0xbd, 0x32, 0x43, 0x29, 0x19, 0xa8, 0xf2, 0xc4, 0x82, 0x4c, 0xfd, 0xc4, 0xbc, 0xbc, 0xfc, 0x92,
+ 0xc4, 0x92, 0xcc, 0xfc, 0xbc, 0x62, 0x88, 0x62, 0x29, 0x29, 0x54, 0xc3, 0x90, 0x0d, 0x52, 0x4a,
+ 0xe0, 0x12, 0x0e, 0x4e, 0x2d, 0xf1, 0x4c, 0xcc, 0x0d, 0x00, 0x8b, 0x06, 0xa5, 0x16, 0x96, 0xa6,
+ 0x16, 0x97, 0x08, 0x49, 0x71, 0x71, 0x14, 0xa5, 0x16, 0xe7, 0x97, 0x16, 0x25, 0xa7, 0x4a, 0x30,
+ 0x2a, 0x30, 0x6a, 0x70, 0x06, 0xc1, 0xf9, 0x42, 0xba, 0x5c, 0x6c, 0x10, 0x23, 0x24, 0x98, 0x14,
+ 0x18, 0x35, 0xb8, 0x8d, 0x44, 0xf5, 0x50, 0x1c, 0xa3, 0x07, 0x35, 0x09, 0xaa, 0x48, 0xc9, 0x90,
+ 0x4b, 0xd8, 0x9d, 0x34, 0x1b, 0x94, 0x22, 0xb9, 0x24, 0x43, 0x52, 0x8b, 0xc1, 0x7a, 0x52, 0x8b,
+ 0x72, 0x33, 0x8b, 0x8b, 0x41, 0x9e, 0x21, 0xc6, 0x69, 0x0a, 0x5c, 0xdc, 0x05, 0x08, 0x1d, 0x12,
+ 0x4c, 0x0a, 0xcc, 0x1a, 0x9c, 0x41, 0xc8, 0x42, 0x4a, 0x76, 0x5c, 0x52, 0xd8, 0x8c, 0x2e, 0x2e,
+ 0xc8, 0xcf, 0x2b, 0xc6, 0xd0, 0xcf, 0x88, 0xa1, 0xdf, 0x68, 0x0a, 0x33, 0x17, 0xa7, 0xa7, 0xa3,
+ 0x2f, 0xc4, 0x2f, 0x42, 0x25, 0x5c, 0x3c, 0xc8, 0xa1, 0x27, 0xa4, 0x84, 0x16, 0x14, 0x58, 0x82,
+ 0x56, 0x0a, 0x7b, 0x70, 0x29, 0x69, 0x36, 0x5d, 0x7e, 0x32, 0x99, 0x49, 0x59, 0x49, 0x0e, 0x14,
+ 0x45, 0xd5, 0x30, 0x1f, 0xd9, 0x6a, 0x69, 0xd5, 0x5a, 0x15, 0x23, 0x99, 0x62, 0xc5, 0xa8, 0x05,
+ 0xb2, 0xd5, 0x1d, 0x9f, 0xad, 0xee, 0x54, 0xb1, 0x35, 0x1d, 0xcd, 0xd6, 0x59, 0x8c, 0x5c, 0x42,
+ 0x98, 0x41, 0x27, 0xa4, 0x81, 0x66, 0x30, 0xce, 0x88, 0x93, 0xd2, 0x24, 0x42, 0x25, 0x24, 0x1e,
+ 0x94, 0xf4, 0xc1, 0xce, 0xd2, 0x54, 0x52, 0xc1, 0x74, 0x56, 0x09, 0x86, 0x2e, 0x2b, 0x46, 0x2d,
+ 0xa7, 0x36, 0x46, 0x2e, 0xc1, 0xe4, 0xfc, 0x5c, 0x54, 0x1b, 0x9c, 0xf8, 0xe0, 0x1e, 0x08, 0x00,
+ 0x25, 0xf6, 0x00, 0xc6, 0x28, 0x03, 0xa8, 0x82, 0xf4, 0xfc, 0x9c, 0xc4, 0xbc, 0x74, 0xbd, 0xfc,
+ 0xa2, 0x74, 0xfd, 0xf4, 0xd4, 0x3c, 0x70, 0x56, 0xd0, 0x87, 0x48, 0x25, 0x16, 0x64, 0x16, 0x43,
+ 0x73, 0x8a, 0x75, 0x66, 0x62, 0xee, 0x0f, 0x46, 0xc6, 0x55, 0x4c, 0xc2, 0xee, 0x10, 0x5d, 0xce,
+ 0x39, 0xf9, 0xa5, 0x29, 0x7a, 0x9e, 0x89, 0xb9, 0x7a, 0x61, 0x86, 0xa7, 0x60, 0xa2, 0x31, 0x60,
+ 0xd1, 0x18, 0xcf, 0xc4, 0xdc, 0x98, 0x30, 0xc3, 0x24, 0x36, 0xb0, 0x59, 0xc6, 0x80, 0x00, 0x00,
+ 0x00, 0xff, 0xff, 0xea, 0x62, 0x8f, 0x22, 0xc1, 0x03, 0x00, 0x00,
+}
diff --git a/vendor/google.golang.org/genproto/googleapis/iam/v1/policy.pb.go b/vendor/google.golang.org/genproto/googleapis/iam/v1/policy.pb.go
new file mode 100644
index 000000000..99dd75f26
--- /dev/null
+++ b/vendor/google.golang.org/genproto/googleapis/iam/v1/policy.pb.go
@@ -0,0 +1,366 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// source: google/iam/v1/policy.proto
+
+package iam // import "google.golang.org/genproto/googleapis/iam/v1"
+
+import proto "github.com/golang/protobuf/proto"
+import fmt "fmt"
+import math "math"
+import _ "google.golang.org/genproto/googleapis/api/annotations"
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
+
+// The type of action performed on a Binding in a policy.
+type BindingDelta_Action int32
+
+const (
+ // Unspecified.
+ BindingDelta_ACTION_UNSPECIFIED BindingDelta_Action = 0
+ // Addition of a Binding.
+ BindingDelta_ADD BindingDelta_Action = 1
+ // Removal of a Binding.
+ BindingDelta_REMOVE BindingDelta_Action = 2
+)
+
+var BindingDelta_Action_name = map[int32]string{
+ 0: "ACTION_UNSPECIFIED",
+ 1: "ADD",
+ 2: "REMOVE",
+}
+var BindingDelta_Action_value = map[string]int32{
+ "ACTION_UNSPECIFIED": 0,
+ "ADD": 1,
+ "REMOVE": 2,
+}
+
+func (x BindingDelta_Action) String() string {
+ return proto.EnumName(BindingDelta_Action_name, int32(x))
+}
+func (BindingDelta_Action) EnumDescriptor() ([]byte, []int) {
+ return fileDescriptor_policy_6ba2a3dcbcdd909c, []int{3, 0}
+}
+
+// Defines an Identity and Access Management (IAM) policy. It is used to
+// specify access control policies for Cloud Platform resources.
+//
+//
+// A `Policy` consists of a list of `bindings`. A `Binding` binds a list of
+// `members` to a `role`, where the members can be user accounts, Google groups,
+// Google domains, and service accounts. A `role` is a named list of permissions
+// defined by IAM.
+//
+// **Example**
+//
+// {
+// "bindings": [
+// {
+// "role": "roles/owner",
+// "members": [
+// "user:mike@example.com",
+// "group:admins@example.com",
+// "domain:google.com",
+// "serviceAccount:my-other-app@appspot.gserviceaccount.com",
+// ]
+// },
+// {
+// "role": "roles/viewer",
+// "members": ["user:sean@example.com"]
+// }
+// ]
+// }
+//
+// For a description of IAM and its features, see the
+// [IAM developer's guide](https://cloud.google.com/iam).
+type Policy struct {
+ // Version of the `Policy`. The default version is 0.
+ Version int32 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"`
+ // Associates a list of `members` to a `role`.
+ // Multiple `bindings` must not be specified for the same `role`.
+ // `bindings` with no members will result in an error.
+ Bindings []*Binding `protobuf:"bytes,4,rep,name=bindings,proto3" json:"bindings,omitempty"`
+ // `etag` is used for optimistic concurrency control as a way to help
+ // prevent simultaneous updates of a policy from overwriting each other.
+ // It is strongly suggested that systems make use of the `etag` in the
+ // read-modify-write cycle to perform policy updates in order to avoid race
+ // conditions: An `etag` is returned in the response to `getIamPolicy`, and
+ // systems are expected to put that etag in the request to `setIamPolicy` to
+ // ensure that their change will be applied to the same version of the policy.
+ //
+ // If no `etag` is provided in the call to `setIamPolicy`, then the existing
+ // policy is overwritten blindly.
+ Etag []byte `protobuf:"bytes,3,opt,name=etag,proto3" json:"etag,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *Policy) Reset() { *m = Policy{} }
+func (m *Policy) String() string { return proto.CompactTextString(m) }
+func (*Policy) ProtoMessage() {}
+func (*Policy) Descriptor() ([]byte, []int) {
+ return fileDescriptor_policy_6ba2a3dcbcdd909c, []int{0}
+}
+func (m *Policy) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_Policy.Unmarshal(m, b)
+}
+func (m *Policy) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_Policy.Marshal(b, m, deterministic)
+}
+func (dst *Policy) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_Policy.Merge(dst, src)
+}
+func (m *Policy) XXX_Size() int {
+ return xxx_messageInfo_Policy.Size(m)
+}
+func (m *Policy) XXX_DiscardUnknown() {
+ xxx_messageInfo_Policy.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Policy proto.InternalMessageInfo
+
+func (m *Policy) GetVersion() int32 {
+ if m != nil {
+ return m.Version
+ }
+ return 0
+}
+
+func (m *Policy) GetBindings() []*Binding {
+ if m != nil {
+ return m.Bindings
+ }
+ return nil
+}
+
+func (m *Policy) GetEtag() []byte {
+ if m != nil {
+ return m.Etag
+ }
+ return nil
+}
+
+// Associates `members` with a `role`.
+type Binding struct {
+ // Role that is assigned to `members`.
+ // For example, `roles/viewer`, `roles/editor`, or `roles/owner`.
+ // Required
+ Role string `protobuf:"bytes,1,opt,name=role,proto3" json:"role,omitempty"`
+ // Specifies the identities requesting access for a Cloud Platform resource.
+ // `members` can have the following values:
+ //
+ // * `allUsers`: A special identifier that represents anyone who is
+ // on the internet; with or without a Google account.
+ //
+ // * `allAuthenticatedUsers`: A special identifier that represents anyone
+ // who is authenticated with a Google account or a service account.
+ //
+ // * `user:{emailid}`: An email address that represents a specific Google
+ // account. For example, `alice@gmail.com` or `joe@example.com`.
+ //
+ //
+ // * `serviceAccount:{emailid}`: An email address that represents a service
+ // account. For example, `my-other-app@appspot.gserviceaccount.com`.
+ //
+ // * `group:{emailid}`: An email address that represents a Google group.
+ // For example, `admins@example.com`.
+ //
+ // * `domain:{domain}`: A Google Apps domain name that represents all the
+ // users of that domain. For example, `google.com` or `example.com`.
+ //
+ //
+ Members []string `protobuf:"bytes,2,rep,name=members,proto3" json:"members,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *Binding) Reset() { *m = Binding{} }
+func (m *Binding) String() string { return proto.CompactTextString(m) }
+func (*Binding) ProtoMessage() {}
+func (*Binding) Descriptor() ([]byte, []int) {
+ return fileDescriptor_policy_6ba2a3dcbcdd909c, []int{1}
+}
+func (m *Binding) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_Binding.Unmarshal(m, b)
+}
+func (m *Binding) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_Binding.Marshal(b, m, deterministic)
+}
+func (dst *Binding) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_Binding.Merge(dst, src)
+}
+func (m *Binding) XXX_Size() int {
+ return xxx_messageInfo_Binding.Size(m)
+}
+func (m *Binding) XXX_DiscardUnknown() {
+ xxx_messageInfo_Binding.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Binding proto.InternalMessageInfo
+
+func (m *Binding) GetRole() string {
+ if m != nil {
+ return m.Role
+ }
+ return ""
+}
+
+func (m *Binding) GetMembers() []string {
+ if m != nil {
+ return m.Members
+ }
+ return nil
+}
+
+// The difference delta between two policies.
+type PolicyDelta struct {
+ // The delta for Bindings between two policies.
+ BindingDeltas []*BindingDelta `protobuf:"bytes,1,rep,name=binding_deltas,json=bindingDeltas,proto3" json:"binding_deltas,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *PolicyDelta) Reset() { *m = PolicyDelta{} }
+func (m *PolicyDelta) String() string { return proto.CompactTextString(m) }
+func (*PolicyDelta) ProtoMessage() {}
+func (*PolicyDelta) Descriptor() ([]byte, []int) {
+ return fileDescriptor_policy_6ba2a3dcbcdd909c, []int{2}
+}
+func (m *PolicyDelta) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_PolicyDelta.Unmarshal(m, b)
+}
+func (m *PolicyDelta) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_PolicyDelta.Marshal(b, m, deterministic)
+}
+func (dst *PolicyDelta) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_PolicyDelta.Merge(dst, src)
+}
+func (m *PolicyDelta) XXX_Size() int {
+ return xxx_messageInfo_PolicyDelta.Size(m)
+}
+func (m *PolicyDelta) XXX_DiscardUnknown() {
+ xxx_messageInfo_PolicyDelta.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_PolicyDelta proto.InternalMessageInfo
+
+func (m *PolicyDelta) GetBindingDeltas() []*BindingDelta {
+ if m != nil {
+ return m.BindingDeltas
+ }
+ return nil
+}
+
+// One delta entry for Binding. Each individual change (only one member in each
+// entry) to a binding will be a separate entry.
+type BindingDelta struct {
+ // The action that was performed on a Binding.
+ // Required
+ Action BindingDelta_Action `protobuf:"varint,1,opt,name=action,proto3,enum=google.iam.v1.BindingDelta_Action" json:"action,omitempty"`
+ // Role that is assigned to `members`.
+ // For example, `roles/viewer`, `roles/editor`, or `roles/owner`.
+ // Required
+ Role string `protobuf:"bytes,2,opt,name=role,proto3" json:"role,omitempty"`
+ // A single identity requesting access for a Cloud Platform resource.
+ // Follows the same format of Binding.members.
+ // Required
+ Member string `protobuf:"bytes,3,opt,name=member,proto3" json:"member,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *BindingDelta) Reset() { *m = BindingDelta{} }
+func (m *BindingDelta) String() string { return proto.CompactTextString(m) }
+func (*BindingDelta) ProtoMessage() {}
+func (*BindingDelta) Descriptor() ([]byte, []int) {
+ return fileDescriptor_policy_6ba2a3dcbcdd909c, []int{3}
+}
+func (m *BindingDelta) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_BindingDelta.Unmarshal(m, b)
+}
+func (m *BindingDelta) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_BindingDelta.Marshal(b, m, deterministic)
+}
+func (dst *BindingDelta) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_BindingDelta.Merge(dst, src)
+}
+func (m *BindingDelta) XXX_Size() int {
+ return xxx_messageInfo_BindingDelta.Size(m)
+}
+func (m *BindingDelta) XXX_DiscardUnknown() {
+ xxx_messageInfo_BindingDelta.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_BindingDelta proto.InternalMessageInfo
+
+func (m *BindingDelta) GetAction() BindingDelta_Action {
+ if m != nil {
+ return m.Action
+ }
+ return BindingDelta_ACTION_UNSPECIFIED
+}
+
+func (m *BindingDelta) GetRole() string {
+ if m != nil {
+ return m.Role
+ }
+ return ""
+}
+
+func (m *BindingDelta) GetMember() string {
+ if m != nil {
+ return m.Member
+ }
+ return ""
+}
+
+func init() {
+ proto.RegisterType((*Policy)(nil), "google.iam.v1.Policy")
+ proto.RegisterType((*Binding)(nil), "google.iam.v1.Binding")
+ proto.RegisterType((*PolicyDelta)(nil), "google.iam.v1.PolicyDelta")
+ proto.RegisterType((*BindingDelta)(nil), "google.iam.v1.BindingDelta")
+ proto.RegisterEnum("google.iam.v1.BindingDelta_Action", BindingDelta_Action_name, BindingDelta_Action_value)
+}
+
+func init() { proto.RegisterFile("google/iam/v1/policy.proto", fileDescriptor_policy_6ba2a3dcbcdd909c) }
+
+var fileDescriptor_policy_6ba2a3dcbcdd909c = []byte{
+ // 403 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x52, 0x4d, 0xab, 0x13, 0x31,
+ 0x14, 0x35, 0xed, 0x73, 0x6a, 0xef, 0xfb, 0xa0, 0x46, 0x28, 0xc3, 0xd3, 0x45, 0x99, 0x55, 0x57,
+ 0x19, 0x5b, 0x11, 0x41, 0x57, 0xfd, 0x18, 0x65, 0x16, 0xbe, 0x37, 0x46, 0xed, 0x42, 0x0a, 0x8f,
+ 0x4c, 0x1b, 0x42, 0x64, 0x92, 0x0c, 0x33, 0x63, 0xc1, 0xb5, 0xff, 0x46, 0xf0, 0x8f, 0xf8, 0x8b,
+ 0x5c, 0xca, 0x24, 0x99, 0x47, 0x0b, 0xe2, 0x2e, 0xe7, 0x9e, 0x73, 0x72, 0xcf, 0xcd, 0x0d, 0x5c,
+ 0x0b, 0x63, 0x44, 0xc1, 0x63, 0xc9, 0x54, 0x7c, 0x98, 0xc5, 0xa5, 0x29, 0xe4, 0xee, 0x3b, 0x29,
+ 0x2b, 0xd3, 0x18, 0x7c, 0xe9, 0x38, 0x22, 0x99, 0x22, 0x87, 0xd9, 0xf5, 0x33, 0x2f, 0x65, 0xa5,
+ 0x8c, 0x99, 0xd6, 0xa6, 0x61, 0x8d, 0x34, 0xba, 0x76, 0xe2, 0xe8, 0x2b, 0x04, 0x99, 0x35, 0xe3,
+ 0x10, 0x06, 0x07, 0x5e, 0xd5, 0xd2, 0xe8, 0x10, 0x4d, 0xd0, 0xf4, 0x21, 0xed, 0x20, 0x9e, 0xc3,
+ 0xa3, 0x5c, 0xea, 0xbd, 0xd4, 0xa2, 0x0e, 0xcf, 0x26, 0xfd, 0xe9, 0xf9, 0x7c, 0x4c, 0x4e, 0x7a,
+ 0x90, 0xa5, 0xa3, 0xe9, 0xbd, 0x0e, 0x63, 0x38, 0xe3, 0x0d, 0x13, 0x61, 0x7f, 0x82, 0xa6, 0x17,
+ 0xd4, 0x9e, 0xa3, 0x57, 0x30, 0xf0, 0xc2, 0x96, 0xae, 0x4c, 0xc1, 0x6d, 0xa7, 0x21, 0xb5, 0xe7,
+ 0x36, 0x80, 0xe2, 0x2a, 0xe7, 0x55, 0x1d, 0xf6, 0x26, 0xfd, 0xe9, 0x90, 0x76, 0x30, 0xfa, 0x00,
+ 0xe7, 0x2e, 0xe4, 0x9a, 0x17, 0x0d, 0xc3, 0x4b, 0xb8, 0xf2, 0x7d, 0xee, 0xf6, 0x6d, 0xa1, 0x0e,
+ 0x91, 0x4d, 0xf5, 0xf4, 0xdf, 0xa9, 0xac, 0x89, 0x5e, 0xe6, 0x47, 0xa8, 0x8e, 0x7e, 0x21, 0xb8,
+ 0x38, 0xe6, 0xf1, 0x6b, 0x08, 0xd8, 0xae, 0xe9, 0xa6, 0xbf, 0x9a, 0x47, 0xff, 0xb9, 0x8c, 0x2c,
+ 0xac, 0x92, 0x7a, 0xc7, 0xfd, 0x34, 0xbd, 0xa3, 0x69, 0xc6, 0x10, 0xb8, 0xf8, 0xf6, 0x09, 0x86,
+ 0xd4, 0xa3, 0xe8, 0x25, 0x04, 0xce, 0x8d, 0xc7, 0x80, 0x17, 0xab, 0x4f, 0xe9, 0xed, 0xcd, 0xdd,
+ 0xe7, 0x9b, 0x8f, 0x59, 0xb2, 0x4a, 0xdf, 0xa6, 0xc9, 0x7a, 0xf4, 0x00, 0x0f, 0xa0, 0xbf, 0x58,
+ 0xaf, 0x47, 0x08, 0x03, 0x04, 0x34, 0x79, 0x7f, 0xbb, 0x49, 0x46, 0xbd, 0xe5, 0x0f, 0x04, 0x8f,
+ 0x77, 0x46, 0x9d, 0x86, 0x5a, 0xfa, 0x67, 0xc9, 0xda, 0x55, 0x66, 0xe8, 0xcb, 0x73, 0xcf, 0x0a,
+ 0x53, 0x30, 0x2d, 0x88, 0xa9, 0x44, 0x2c, 0xb8, 0xb6, 0x8b, 0x8e, 0x1d, 0xc5, 0x4a, 0x59, 0xfb,
+ 0x4f, 0xf3, 0x46, 0x32, 0xf5, 0x07, 0xa1, 0x9f, 0xbd, 0x27, 0xef, 0x9c, 0x6b, 0x55, 0x98, 0x6f,
+ 0x7b, 0x92, 0x32, 0x45, 0x36, 0xb3, 0xdf, 0x5d, 0x75, 0x6b, 0xab, 0xdb, 0x94, 0xa9, 0xed, 0x66,
+ 0x96, 0x07, 0xf6, 0xae, 0x17, 0x7f, 0x03, 0x00, 0x00, 0xff, 0xff, 0xfc, 0x18, 0xca, 0xaa, 0x7f,
+ 0x02, 0x00, 0x00,
+}
diff --git a/vendor/google.golang.org/genproto/googleapis/rpc/code/code.pb.go b/vendor/google.golang.org/genproto/googleapis/rpc/code/code.pb.go
new file mode 100644
index 000000000..410e374c8
--- /dev/null
+++ b/vendor/google.golang.org/genproto/googleapis/rpc/code/code.pb.go
@@ -0,0 +1,246 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// source: google/rpc/code.proto
+
+package code // import "google.golang.org/genproto/googleapis/rpc/code"
+
+import proto "github.com/golang/protobuf/proto"
+import fmt "fmt"
+import math "math"
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
+
+// The canonical error codes for Google APIs.
+//
+//
+// Sometimes multiple error codes may apply. Services should return
+// the most specific error code that applies. For example, prefer
+// `OUT_OF_RANGE` over `FAILED_PRECONDITION` if both codes apply.
+// Similarly prefer `NOT_FOUND` or `ALREADY_EXISTS` over `FAILED_PRECONDITION`.
+type Code int32
+
+const (
+ // Not an error; returned on success
+ //
+ // HTTP Mapping: 200 OK
+ Code_OK Code = 0
+ // The operation was cancelled, typically by the caller.
+ //
+ // HTTP Mapping: 499 Client Closed Request
+ Code_CANCELLED Code = 1
+ // Unknown error. For example, this error may be returned when
+ // a `Status` value received from another address space belongs to
+ // an error space that is not known in this address space. Also
+ // errors raised by APIs that do not return enough error information
+ // may be converted to this error.
+ //
+ // HTTP Mapping: 500 Internal Server Error
+ Code_UNKNOWN Code = 2
+ // The client specified an invalid argument. Note that this differs
+ // from `FAILED_PRECONDITION`. `INVALID_ARGUMENT` indicates arguments
+ // that are problematic regardless of the state of the system
+ // (e.g., a malformed file name).
+ //
+ // HTTP Mapping: 400 Bad Request
+ Code_INVALID_ARGUMENT Code = 3
+ // The deadline expired before the operation could complete. For operations
+ // that change the state of the system, this error may be returned
+ // even if the operation has completed successfully. For example, a
+ // successful response from a server could have been delayed long
+ // enough for the deadline to expire.
+ //
+ // HTTP Mapping: 504 Gateway Timeout
+ Code_DEADLINE_EXCEEDED Code = 4
+ // Some requested entity (e.g., file or directory) was not found.
+ //
+ // Note to server developers: if a request is denied for an entire class
+ // of users, such as gradual feature rollout or undocumented whitelist,
+ // `NOT_FOUND` may be used. If a request is denied for some users within
+ // a class of users, such as user-based access control, `PERMISSION_DENIED`
+ // must be used.
+ //
+ // HTTP Mapping: 404 Not Found
+ Code_NOT_FOUND Code = 5
+ // The entity that a client attempted to create (e.g., file or directory)
+ // already exists.
+ //
+ // HTTP Mapping: 409 Conflict
+ Code_ALREADY_EXISTS Code = 6
+ // The caller does not have permission to execute the specified
+ // operation. `PERMISSION_DENIED` must not be used for rejections
+ // caused by exhausting some resource (use `RESOURCE_EXHAUSTED`
+ // instead for those errors). `PERMISSION_DENIED` must not be
+ // used if the caller can not be identified (use `UNAUTHENTICATED`
+ // instead for those errors). This error code does not imply the
+ // request is valid or the requested entity exists or satisfies
+ // other pre-conditions.
+ //
+ // HTTP Mapping: 403 Forbidden
+ Code_PERMISSION_DENIED Code = 7
+ // The request does not have valid authentication credentials for the
+ // operation.
+ //
+ // HTTP Mapping: 401 Unauthorized
+ Code_UNAUTHENTICATED Code = 16
+ // Some resource has been exhausted, perhaps a per-user quota, or
+ // perhaps the entire file system is out of space.
+ //
+ // HTTP Mapping: 429 Too Many Requests
+ Code_RESOURCE_EXHAUSTED Code = 8
+ // The operation was rejected because the system is not in a state
+ // required for the operation's execution. For example, the directory
+ // to be deleted is non-empty, an rmdir operation is applied to
+ // a non-directory, etc.
+ //
+ // Service implementors can use the following guidelines to decide
+ // between `FAILED_PRECONDITION`, `ABORTED`, and `UNAVAILABLE`:
+ // (a) Use `UNAVAILABLE` if the client can retry just the failing call.
+ // (b) Use `ABORTED` if the client should retry at a higher level
+ // (e.g., when a client-specified test-and-set fails, indicating the
+ // client should restart a read-modify-write sequence).
+ // (c) Use `FAILED_PRECONDITION` if the client should not retry until
+ // the system state has been explicitly fixed. E.g., if an "rmdir"
+ // fails because the directory is non-empty, `FAILED_PRECONDITION`
+ // should be returned since the client should not retry unless
+ // the files are deleted from the directory.
+ //
+ // HTTP Mapping: 400 Bad Request
+ Code_FAILED_PRECONDITION Code = 9
+ // The operation was aborted, typically due to a concurrency issue such as
+ // a sequencer check failure or transaction abort.
+ //
+ // See the guidelines above for deciding between `FAILED_PRECONDITION`,
+ // `ABORTED`, and `UNAVAILABLE`.
+ //
+ // HTTP Mapping: 409 Conflict
+ Code_ABORTED Code = 10
+ // The operation was attempted past the valid range. E.g., seeking or
+ // reading past end-of-file.
+ //
+ // Unlike `INVALID_ARGUMENT`, this error indicates a problem that may
+ // be fixed if the system state changes. For example, a 32-bit file
+ // system will generate `INVALID_ARGUMENT` if asked to read at an
+ // offset that is not in the range [0,2^32-1], but it will generate
+ // `OUT_OF_RANGE` if asked to read from an offset past the current
+ // file size.
+ //
+ // There is a fair bit of overlap between `FAILED_PRECONDITION` and
+ // `OUT_OF_RANGE`. We recommend using `OUT_OF_RANGE` (the more specific
+ // error) when it applies so that callers who are iterating through
+ // a space can easily look for an `OUT_OF_RANGE` error to detect when
+ // they are done.
+ //
+ // HTTP Mapping: 400 Bad Request
+ Code_OUT_OF_RANGE Code = 11
+ // The operation is not implemented or is not supported/enabled in this
+ // service.
+ //
+ // HTTP Mapping: 501 Not Implemented
+ Code_UNIMPLEMENTED Code = 12
+ // Internal errors. This means that some invariants expected by the
+ // underlying system have been broken. This error code is reserved
+ // for serious errors.
+ //
+ // HTTP Mapping: 500 Internal Server Error
+ Code_INTERNAL Code = 13
+ // The service is currently unavailable. This is most likely a
+ // transient condition, which can be corrected by retrying with
+ // a backoff.
+ //
+ // See the guidelines above for deciding between `FAILED_PRECONDITION`,
+ // `ABORTED`, and `UNAVAILABLE`.
+ //
+ // HTTP Mapping: 503 Service Unavailable
+ Code_UNAVAILABLE Code = 14
+ // Unrecoverable data loss or corruption.
+ //
+ // HTTP Mapping: 500 Internal Server Error
+ Code_DATA_LOSS Code = 15
+)
+
+var Code_name = map[int32]string{
+ 0: "OK",
+ 1: "CANCELLED",
+ 2: "UNKNOWN",
+ 3: "INVALID_ARGUMENT",
+ 4: "DEADLINE_EXCEEDED",
+ 5: "NOT_FOUND",
+ 6: "ALREADY_EXISTS",
+ 7: "PERMISSION_DENIED",
+ 16: "UNAUTHENTICATED",
+ 8: "RESOURCE_EXHAUSTED",
+ 9: "FAILED_PRECONDITION",
+ 10: "ABORTED",
+ 11: "OUT_OF_RANGE",
+ 12: "UNIMPLEMENTED",
+ 13: "INTERNAL",
+ 14: "UNAVAILABLE",
+ 15: "DATA_LOSS",
+}
+var Code_value = map[string]int32{
+ "OK": 0,
+ "CANCELLED": 1,
+ "UNKNOWN": 2,
+ "INVALID_ARGUMENT": 3,
+ "DEADLINE_EXCEEDED": 4,
+ "NOT_FOUND": 5,
+ "ALREADY_EXISTS": 6,
+ "PERMISSION_DENIED": 7,
+ "UNAUTHENTICATED": 16,
+ "RESOURCE_EXHAUSTED": 8,
+ "FAILED_PRECONDITION": 9,
+ "ABORTED": 10,
+ "OUT_OF_RANGE": 11,
+ "UNIMPLEMENTED": 12,
+ "INTERNAL": 13,
+ "UNAVAILABLE": 14,
+ "DATA_LOSS": 15,
+}
+
+func (x Code) String() string {
+ return proto.EnumName(Code_name, int32(x))
+}
+func (Code) EnumDescriptor() ([]byte, []int) {
+ return fileDescriptor_code_932ba152e0df0902, []int{0}
+}
+
+func init() {
+ proto.RegisterEnum("google.rpc.Code", Code_name, Code_value)
+}
+
+func init() { proto.RegisterFile("google/rpc/code.proto", fileDescriptor_code_932ba152e0df0902) }
+
+var fileDescriptor_code_932ba152e0df0902 = []byte{
+ // 362 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x44, 0x51, 0xcd, 0x6e, 0x93, 0x31,
+ 0x10, 0xa4, 0x69, 0x49, 0x9b, 0xcd, 0xdf, 0xd6, 0xa5, 0xf0, 0x0e, 0x1c, 0x92, 0x43, 0x8f, 0x9c,
+ 0x36, 0x9f, 0x37, 0xad, 0x55, 0x67, 0xfd, 0xc9, 0x3f, 0x25, 0x70, 0xb1, 0x4a, 0x1a, 0x7d, 0x42,
+ 0x2a, 0x75, 0xf4, 0xc1, 0x13, 0xf1, 0x12, 0xbc, 0x1e, 0x72, 0x8b, 0xe8, 0xc5, 0x87, 0x99, 0xf1,
+ 0xee, 0xce, 0x0c, 0x5c, 0x76, 0xa5, 0x74, 0x8f, 0xfb, 0x65, 0x7f, 0xd8, 0x2d, 0x77, 0xe5, 0x61,
+ 0xbf, 0x38, 0xf4, 0xe5, 0x57, 0x51, 0xf0, 0x02, 0x2f, 0xfa, 0xc3, 0xee, 0xe3, 0x9f, 0x01, 0x9c,
+ 0x34, 0xe5, 0x61, 0xaf, 0x86, 0x30, 0x70, 0xb7, 0xf8, 0x46, 0x4d, 0x61, 0xd4, 0x90, 0x34, 0x6c,
+ 0x2d, 0x6b, 0x3c, 0x52, 0x63, 0x38, 0x4d, 0x72, 0x2b, 0xee, 0xb3, 0xe0, 0x40, 0xbd, 0x03, 0x34,
+ 0x72, 0x47, 0xd6, 0xe8, 0x4c, 0xfe, 0x3a, 0x6d, 0x58, 0x22, 0x1e, 0xab, 0x4b, 0x38, 0xd7, 0x4c,
+ 0xda, 0x1a, 0xe1, 0xcc, 0xdb, 0x86, 0x59, 0xb3, 0xc6, 0x93, 0x3a, 0x48, 0x5c, 0xcc, 0x6b, 0x97,
+ 0x44, 0xe3, 0x5b, 0xa5, 0x60, 0x46, 0xd6, 0x33, 0xe9, 0x2f, 0x99, 0xb7, 0x26, 0xc4, 0x80, 0xc3,
+ 0xfa, 0xb3, 0x65, 0xbf, 0x31, 0x21, 0x18, 0x27, 0x59, 0xb3, 0x18, 0xd6, 0x78, 0xaa, 0x2e, 0x60,
+ 0x9e, 0x84, 0x52, 0xbc, 0x61, 0x89, 0xa6, 0xa1, 0xc8, 0x1a, 0x51, 0xbd, 0x07, 0xe5, 0x39, 0xb8,
+ 0xe4, 0x9b, 0xba, 0xe5, 0x86, 0x52, 0xa8, 0xf8, 0x99, 0xfa, 0x00, 0x17, 0x6b, 0x32, 0x96, 0x75,
+ 0x6e, 0x3d, 0x37, 0x4e, 0xb4, 0x89, 0xc6, 0x09, 0x8e, 0xea, 0xe5, 0xb4, 0x72, 0xbe, 0xaa, 0x40,
+ 0x21, 0x4c, 0x5c, 0x8a, 0xd9, 0xad, 0xb3, 0x27, 0xb9, 0x66, 0x1c, 0xab, 0x73, 0x98, 0x26, 0x31,
+ 0x9b, 0xd6, 0x72, 0xb5, 0xc1, 0x1a, 0x27, 0x6a, 0x02, 0x67, 0x46, 0x22, 0x7b, 0x21, 0x8b, 0x53,
+ 0x35, 0x87, 0x71, 0x12, 0xba, 0x23, 0x63, 0x69, 0x65, 0x19, 0x67, 0xd5, 0x90, 0xa6, 0x48, 0xd9,
+ 0xba, 0x10, 0x70, 0xbe, 0xda, 0xc2, 0x6c, 0x57, 0x7e, 0x2c, 0x5e, 0xb3, 0x5c, 0x8d, 0x6a, 0x90,
+ 0x6d, 0x8d, 0xb8, 0x3d, 0xfa, 0x7a, 0xf5, 0x8f, 0xe8, 0xca, 0xe3, 0xfd, 0x53, 0xb7, 0x28, 0x7d,
+ 0xb7, 0xec, 0xf6, 0x4f, 0xcf, 0x05, 0x2c, 0x5f, 0xa8, 0xfb, 0xc3, 0xf7, 0x9f, 0xff, 0xab, 0xf9,
+ 0x54, 0x9f, 0xdf, 0x83, 0x63, 0xdf, 0x36, 0xdf, 0x86, 0xcf, 0xaa, 0xab, 0xbf, 0x01, 0x00, 0x00,
+ 0xff, 0xff, 0x8e, 0x97, 0x77, 0xc2, 0xbf, 0x01, 0x00, 0x00,
+}
diff --git a/vendor/google.golang.org/genproto/googleapis/rpc/status/status.pb.go b/vendor/google.golang.org/genproto/googleapis/rpc/status/status.pb.go
new file mode 100644
index 000000000..7bfe37a3d
--- /dev/null
+++ b/vendor/google.golang.org/genproto/googleapis/rpc/status/status.pb.go
@@ -0,0 +1,156 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// source: google/rpc/status.proto
+
+package status // import "google.golang.org/genproto/googleapis/rpc/status"
+
+import proto "github.com/golang/protobuf/proto"
+import fmt "fmt"
+import math "math"
+import any "github.com/golang/protobuf/ptypes/any"
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
+
+// The `Status` type defines a logical error model that is suitable for different
+// programming environments, including REST APIs and RPC APIs. It is used by
+// [gRPC](https://github.com/grpc). The error model is designed to be:
+//
+// - Simple to use and understand for most users
+// - Flexible enough to meet unexpected needs
+//
+// # Overview
+//
+// The `Status` message contains three pieces of data: error code, error message,
+// and error details. The error code should be an enum value of
+// [google.rpc.Code][google.rpc.Code], but it may accept additional error codes if needed. The
+// error message should be a developer-facing English message that helps
+// developers *understand* and *resolve* the error. If a localized user-facing
+// error message is needed, put the localized message in the error details or
+// localize it in the client. The optional error details may contain arbitrary
+// information about the error. There is a predefined set of error detail types
+// in the package `google.rpc` that can be used for common error conditions.
+//
+// # Language mapping
+//
+// The `Status` message is the logical representation of the error model, but it
+// is not necessarily the actual wire format. When the `Status` message is
+// exposed in different client libraries and different wire protocols, it can be
+// mapped differently. For example, it will likely be mapped to some exceptions
+// in Java, but more likely mapped to some error codes in C.
+//
+// # Other uses
+//
+// The error model and the `Status` message can be used in a variety of
+// environments, either with or without APIs, to provide a
+// consistent developer experience across different environments.
+//
+// Example uses of this error model include:
+//
+// - Partial errors. If a service needs to return partial errors to the client,
+// it may embed the `Status` in the normal response to indicate the partial
+// errors.
+//
+// - Workflow errors. A typical workflow has multiple steps. Each step may
+// have a `Status` message for error reporting.
+//
+// - Batch operations. If a client uses batch request and batch response, the
+// `Status` message should be used directly inside batch response, one for
+// each error sub-response.
+//
+// - Asynchronous operations. If an API call embeds asynchronous operation
+// results in its response, the status of those operations should be
+// represented directly using the `Status` message.
+//
+// - Logging. If some API errors are stored in logs, the message `Status` could
+// be used directly after any stripping needed for security/privacy reasons.
+type Status struct {
+ // The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code].
+ Code int32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"`
+ // A developer-facing error message, which should be in English. Any
+ // user-facing error message should be localized and sent in the
+ // [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client.
+ Message string `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"`
+ // A list of messages that carry the error details. There is a common set of
+ // message types for APIs to use.
+ Details []*any.Any `protobuf:"bytes,3,rep,name=details,proto3" json:"details,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *Status) Reset() { *m = Status{} }
+func (m *Status) String() string { return proto.CompactTextString(m) }
+func (*Status) ProtoMessage() {}
+func (*Status) Descriptor() ([]byte, []int) {
+ return fileDescriptor_status_c6e4de62dcdf2edf, []int{0}
+}
+func (m *Status) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_Status.Unmarshal(m, b)
+}
+func (m *Status) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_Status.Marshal(b, m, deterministic)
+}
+func (dst *Status) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_Status.Merge(dst, src)
+}
+func (m *Status) XXX_Size() int {
+ return xxx_messageInfo_Status.Size(m)
+}
+func (m *Status) XXX_DiscardUnknown() {
+ xxx_messageInfo_Status.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Status proto.InternalMessageInfo
+
+func (m *Status) GetCode() int32 {
+ if m != nil {
+ return m.Code
+ }
+ return 0
+}
+
+func (m *Status) GetMessage() string {
+ if m != nil {
+ return m.Message
+ }
+ return ""
+}
+
+func (m *Status) GetDetails() []*any.Any {
+ if m != nil {
+ return m.Details
+ }
+ return nil
+}
+
+func init() {
+ proto.RegisterType((*Status)(nil), "google.rpc.Status")
+}
+
+func init() { proto.RegisterFile("google/rpc/status.proto", fileDescriptor_status_c6e4de62dcdf2edf) }
+
+var fileDescriptor_status_c6e4de62dcdf2edf = []byte{
+ // 209 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x4f, 0xcf, 0xcf, 0x4f,
+ 0xcf, 0x49, 0xd5, 0x2f, 0x2a, 0x48, 0xd6, 0x2f, 0x2e, 0x49, 0x2c, 0x29, 0x2d, 0xd6, 0x2b, 0x28,
+ 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x82, 0x48, 0xe8, 0x15, 0x15, 0x24, 0x4b, 0x49, 0x42, 0x15, 0x81,
+ 0x65, 0x92, 0x4a, 0xd3, 0xf4, 0x13, 0xf3, 0x2a, 0x21, 0xca, 0x94, 0xd2, 0xb8, 0xd8, 0x82, 0xc1,
+ 0xda, 0x84, 0x84, 0xb8, 0x58, 0x92, 0xf3, 0x53, 0x52, 0x25, 0x18, 0x15, 0x18, 0x35, 0x58, 0x83,
+ 0xc0, 0x6c, 0x21, 0x09, 0x2e, 0xf6, 0xdc, 0xd4, 0xe2, 0xe2, 0xc4, 0xf4, 0x54, 0x09, 0x26, 0x05,
+ 0x46, 0x0d, 0xce, 0x20, 0x18, 0x57, 0x48, 0x8f, 0x8b, 0x3d, 0x25, 0xb5, 0x24, 0x31, 0x33, 0xa7,
+ 0x58, 0x82, 0x59, 0x81, 0x59, 0x83, 0xdb, 0x48, 0x44, 0x0f, 0x6a, 0x21, 0xcc, 0x12, 0x3d, 0xc7,
+ 0xbc, 0xca, 0x20, 0x98, 0x22, 0xa7, 0x38, 0x2e, 0xbe, 0xe4, 0xfc, 0x5c, 0x3d, 0x84, 0xa3, 0x9c,
+ 0xb8, 0x21, 0xf6, 0x06, 0x80, 0x94, 0x07, 0x30, 0x46, 0x99, 0x43, 0xa5, 0xd2, 0xf3, 0x73, 0x12,
+ 0xf3, 0xd2, 0xf5, 0xf2, 0x8b, 0xd2, 0xf5, 0xd3, 0x53, 0xf3, 0xc0, 0x86, 0xe9, 0x43, 0xa4, 0x12,
+ 0x0b, 0x32, 0x8b, 0x91, 0xfc, 0x69, 0x0d, 0xa1, 0x16, 0x31, 0x31, 0x07, 0x05, 0x38, 0x27, 0xb1,
+ 0x81, 0x55, 0x1a, 0x03, 0x02, 0x00, 0x00, 0xff, 0xff, 0xa4, 0x53, 0xf0, 0x7c, 0x10, 0x01, 0x00,
+ 0x00,
+}
diff --git a/vendor/google.golang.org/grpc/AUTHORS b/vendor/google.golang.org/grpc/AUTHORS
new file mode 100644
index 000000000..e491a9e7f
--- /dev/null
+++ b/vendor/google.golang.org/grpc/AUTHORS
@@ -0,0 +1 @@
+Google Inc.
diff --git a/vendor/google.golang.org/grpc/CONTRIBUTING.md b/vendor/google.golang.org/grpc/CONTRIBUTING.md
new file mode 100644
index 000000000..0863eb26b
--- /dev/null
+++ b/vendor/google.golang.org/grpc/CONTRIBUTING.md
@@ -0,0 +1,36 @@
+# How to contribute
+
+We definitely welcome your patches and contributions to gRPC!
+
+If you are new to github, please start by reading [Pull Request howto](https://help.github.com/articles/about-pull-requests/)
+
+## Legal requirements
+
+In order to protect both you and ourselves, you will need to sign the
+[Contributor License Agreement](https://identity.linuxfoundation.org/projects/cncf).
+
+## Guidelines for Pull Requests
+How to get your contributions merged smoothly and quickly.
+
+- Create **small PRs** that are narrowly focused on **addressing a single concern**. We often times receive PRs that are trying to fix several things at a time, but only one fix is considered acceptable, nothing gets merged and both author's & review's time is wasted. Create more PRs to address different concerns and everyone will be happy.
+
+- For speculative changes, consider opening an issue and discussing it first. If you are suggesting a behavioral or API change, consider starting with a [gRFC proposal](https://github.com/grpc/proposal).
+
+- Provide a good **PR description** as a record of **what** change is being made and **why** it was made. Link to a github issue if it exists.
+
+- Don't fix code style and formatting unless you are already changing that line to address an issue. PRs with irrelevant changes won't be merged. If you do want to fix formatting or style, do that in a separate PR.
+
+- Unless your PR is trivial, you should expect there will be reviewer comments that you'll need to address before merging. We expect you to be reasonably responsive to those comments, otherwise the PR will be closed after 2-3 weeks of inactivity.
+
+- Maintain **clean commit history** and use **meaningful commit messages**. PRs with messy commit history are difficult to review and won't be merged. Use `rebase -i upstream/master` to curate your commit history and/or to bring in latest changes from master (but avoid rebasing in the middle of a code review).
+
+- Keep your PR up to date with upstream/master (if there are merge conflicts, we can't really merge your change).
+
+- **All tests need to be passing** before your change can be merged. We recommend you **run tests locally** before creating your PR to catch breakages early on.
+ - `make all` to test everything, OR
+ - `make vet` to catch vet errors
+ - `make test` to run the tests
+ - `make testrace` to run tests in race mode
+
+- Exceptions to the rules can be made if there's a compelling reason for doing so.
+
diff --git a/vendor/google.golang.org/grpc/LICENSE b/vendor/google.golang.org/grpc/LICENSE
new file mode 100644
index 000000000..d64569567
--- /dev/null
+++ b/vendor/google.golang.org/grpc/LICENSE
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/vendor/google.golang.org/grpc/Makefile b/vendor/google.golang.org/grpc/Makefile
new file mode 100644
index 000000000..41a754f97
--- /dev/null
+++ b/vendor/google.golang.org/grpc/Makefile
@@ -0,0 +1,60 @@
+all: vet test testrace testappengine
+
+build: deps
+ go build google.golang.org/grpc/...
+
+clean:
+ go clean -i google.golang.org/grpc/...
+
+deps:
+ go get -d -v google.golang.org/grpc/...
+
+proto:
+ @ if ! which protoc > /dev/null; then \
+ echo "error: protoc not installed" >&2; \
+ exit 1; \
+ fi
+ go generate google.golang.org/grpc/...
+
+test: testdeps
+ go test -cpu 1,4 -timeout 7m google.golang.org/grpc/...
+
+testappengine: testappenginedeps
+ goapp test -cpu 1,4 -timeout 7m google.golang.org/grpc/...
+
+testappenginedeps:
+ goapp get -d -v -t -tags 'appengine appenginevm' google.golang.org/grpc/...
+
+testdeps:
+ go get -d -v -t google.golang.org/grpc/...
+
+testrace: testdeps
+ go test -race -cpu 1,4 -timeout 7m google.golang.org/grpc/...
+
+updatedeps:
+ go get -d -v -u -f google.golang.org/grpc/...
+
+updatetestdeps:
+ go get -d -v -t -u -f google.golang.org/grpc/...
+
+vet: vetdeps
+ ./vet.sh
+
+vetdeps:
+ ./vet.sh -install
+
+.PHONY: \
+ all \
+ build \
+ clean \
+ deps \
+ proto \
+ test \
+ testappengine \
+ testappenginedeps \
+ testdeps \
+ testrace \
+ updatedeps \
+ updatetestdeps \
+ vet \
+ vetdeps
diff --git a/vendor/google.golang.org/grpc/README.md b/vendor/google.golang.org/grpc/README.md
new file mode 100644
index 000000000..e3fb3c75a
--- /dev/null
+++ b/vendor/google.golang.org/grpc/README.md
@@ -0,0 +1,67 @@
+# gRPC-Go
+
+[![Build Status](https://travis-ci.org/grpc/grpc-go.svg)](https://travis-ci.org/grpc/grpc-go) [![GoDoc](https://godoc.org/google.golang.org/grpc?status.svg)](https://godoc.org/google.golang.org/grpc) [![GoReportCard](https://goreportcard.com/badge/grpc/grpc-go)](https://goreportcard.com/report/github.com/grpc/grpc-go)
+
+The Go implementation of [gRPC](https://grpc.io/): A high performance, open source, general RPC framework that puts mobile and HTTP/2 first. For more information see the [gRPC Quick Start: Go](https://grpc.io/docs/quickstart/go.html) guide.
+
+Installation
+------------
+
+To install this package, you need to install Go and setup your Go workspace on your computer. The simplest way to install the library is to run:
+
+```
+$ go get -u google.golang.org/grpc
+```
+
+Prerequisites
+-------------
+
+gRPC-Go requires Go 1.9 or later.
+
+Constraints
+-----------
+The grpc package should only depend on standard Go packages and a small number of exceptions. If your contribution introduces new dependencies which are NOT in the [list](http://godoc.org/google.golang.org/grpc?imports), you need a discussion with gRPC-Go authors and consultants.
+
+Documentation
+-------------
+See [API documentation](https://godoc.org/google.golang.org/grpc) for package and API descriptions and find examples in the [examples directory](examples/).
+
+Performance
+-----------
+See the current benchmarks for some of the languages supported in [this dashboard](https://performance-dot-grpc-testing.appspot.com/explore?dashboard=5652536396611584&widget=490377658&container=1286539696).
+
+Status
+------
+General Availability [Google Cloud Platform Launch Stages](https://cloud.google.com/terms/launch-stages).
+
+FAQ
+---
+
+#### Compiling error, undefined: grpc.SupportPackageIsVersion
+
+Please update proto package, gRPC package and rebuild the proto files:
+ - `go get -u github.com/golang/protobuf/{proto,protoc-gen-go}`
+ - `go get -u google.golang.org/grpc`
+ - `protoc --go_out=plugins=grpc:. *.proto`
+
+#### How to turn on logging
+
+The default logger is controlled by the environment variables. Turn everything
+on by setting:
+
+```
+GRPC_GO_LOG_VERBOSITY_LEVEL=99 GRPC_GO_LOG_SEVERITY_LEVEL=info
+```
+
+#### The RPC failed with error `"code = Unavailable desc = transport is closing"`
+
+This error means the connection the RPC is using was closed, and there are many
+possible reasons, including:
+ 1. mis-configured transport credentials, connection failed on handshaking
+ 1. bytes disrupted, possibly by a proxy in between
+ 1. server shutdown
+
+It can be tricky to debug this because the error happens on the client side but
+the root cause of the connection being closed is on the server side. Turn on
+logging on __both client and server__, and see if there are any transport
+errors.
diff --git a/vendor/google.golang.org/grpc/backoff.go b/vendor/google.golang.org/grpc/backoff.go
new file mode 100644
index 000000000..fa31565fd
--- /dev/null
+++ b/vendor/google.golang.org/grpc/backoff.go
@@ -0,0 +1,38 @@
+/*
+ *
+ * Copyright 2017 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// See internal/backoff package for the backoff implementation. This file is
+// kept for the exported types and API backward compatility.
+
+package grpc
+
+import (
+ "time"
+)
+
+// DefaultBackoffConfig uses values specified for backoff in
+// https://github.com/grpc/grpc/blob/master/doc/connection-backoff.md.
+var DefaultBackoffConfig = BackoffConfig{
+ MaxDelay: 120 * time.Second,
+}
+
+// BackoffConfig defines the parameters for the default gRPC backoff strategy.
+type BackoffConfig struct {
+ // MaxDelay is the upper bound of backoff delay.
+ MaxDelay time.Duration
+}
diff --git a/vendor/google.golang.org/grpc/balancer.go b/vendor/google.golang.org/grpc/balancer.go
new file mode 100644
index 000000000..a78e702ba
--- /dev/null
+++ b/vendor/google.golang.org/grpc/balancer.go
@@ -0,0 +1,391 @@
+/*
+ *
+ * Copyright 2016 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package grpc
+
+import (
+ "context"
+ "net"
+ "sync"
+
+ "google.golang.org/grpc/codes"
+ "google.golang.org/grpc/credentials"
+ "google.golang.org/grpc/grpclog"
+ "google.golang.org/grpc/naming"
+ "google.golang.org/grpc/status"
+)
+
+// Address represents a server the client connects to.
+//
+// Deprecated: please use package balancer.
+type Address struct {
+ // Addr is the server address on which a connection will be established.
+ Addr string
+ // Metadata is the information associated with Addr, which may be used
+ // to make load balancing decision.
+ Metadata interface{}
+}
+
+// BalancerConfig specifies the configurations for Balancer.
+//
+// Deprecated: please use package balancer.
+type BalancerConfig struct {
+ // DialCreds is the transport credential the Balancer implementation can
+ // use to dial to a remote load balancer server. The Balancer implementations
+ // can ignore this if it does not need to talk to another party securely.
+ DialCreds credentials.TransportCredentials
+ // Dialer is the custom dialer the Balancer implementation can use to dial
+ // to a remote load balancer server. The Balancer implementations
+ // can ignore this if it doesn't need to talk to remote balancer.
+ Dialer func(context.Context, string) (net.Conn, error)
+}
+
+// BalancerGetOptions configures a Get call.
+//
+// Deprecated: please use package balancer.
+type BalancerGetOptions struct {
+ // BlockingWait specifies whether Get should block when there is no
+ // connected address.
+ BlockingWait bool
+}
+
+// Balancer chooses network addresses for RPCs.
+//
+// Deprecated: please use package balancer.
+type Balancer interface {
+ // Start does the initialization work to bootstrap a Balancer. For example,
+ // this function may start the name resolution and watch the updates. It will
+ // be called when dialing.
+ Start(target string, config BalancerConfig) error
+ // Up informs the Balancer that gRPC has a connection to the server at
+ // addr. It returns down which is called once the connection to addr gets
+ // lost or closed.
+ // TODO: It is not clear how to construct and take advantage of the meaningful error
+ // parameter for down. Need realistic demands to guide.
+ Up(addr Address) (down func(error))
+ // Get gets the address of a server for the RPC corresponding to ctx.
+ // i) If it returns a connected address, gRPC internals issues the RPC on the
+ // connection to this address;
+ // ii) If it returns an address on which the connection is under construction
+ // (initiated by Notify(...)) but not connected, gRPC internals
+ // * fails RPC if the RPC is fail-fast and connection is in the TransientFailure or
+ // Shutdown state;
+ // or
+ // * issues RPC on the connection otherwise.
+ // iii) If it returns an address on which the connection does not exist, gRPC
+ // internals treats it as an error and will fail the corresponding RPC.
+ //
+ // Therefore, the following is the recommended rule when writing a custom Balancer.
+ // If opts.BlockingWait is true, it should return a connected address or
+ // block if there is no connected address. It should respect the timeout or
+ // cancellation of ctx when blocking. If opts.BlockingWait is false (for fail-fast
+ // RPCs), it should return an address it has notified via Notify(...) immediately
+ // instead of blocking.
+ //
+ // The function returns put which is called once the rpc has completed or failed.
+ // put can collect and report RPC stats to a remote load balancer.
+ //
+ // This function should only return the errors Balancer cannot recover by itself.
+ // gRPC internals will fail the RPC if an error is returned.
+ Get(ctx context.Context, opts BalancerGetOptions) (addr Address, put func(), err error)
+ // Notify returns a channel that is used by gRPC internals to watch the addresses
+ // gRPC needs to connect. The addresses might be from a name resolver or remote
+ // load balancer. gRPC internals will compare it with the existing connected
+ // addresses. If the address Balancer notified is not in the existing connected
+ // addresses, gRPC starts to connect the address. If an address in the existing
+ // connected addresses is not in the notification list, the corresponding connection
+ // is shutdown gracefully. Otherwise, there are no operations to take. Note that
+ // the Address slice must be the full list of the Addresses which should be connected.
+ // It is NOT delta.
+ Notify() <-chan []Address
+ // Close shuts down the balancer.
+ Close() error
+}
+
+// RoundRobin returns a Balancer that selects addresses round-robin. It uses r to watch
+// the name resolution updates and updates the addresses available correspondingly.
+//
+// Deprecated: please use package balancer/roundrobin.
+func RoundRobin(r naming.Resolver) Balancer {
+ return &roundRobin{r: r}
+}
+
+type addrInfo struct {
+ addr Address
+ connected bool
+}
+
+type roundRobin struct {
+ r naming.Resolver
+ w naming.Watcher
+ addrs []*addrInfo // all the addresses the client should potentially connect
+ mu sync.Mutex
+ addrCh chan []Address // the channel to notify gRPC internals the list of addresses the client should connect to.
+ next int // index of the next address to return for Get()
+ waitCh chan struct{} // the channel to block when there is no connected address available
+ done bool // The Balancer is closed.
+}
+
+func (rr *roundRobin) watchAddrUpdates() error {
+ updates, err := rr.w.Next()
+ if err != nil {
+ grpclog.Warningf("grpc: the naming watcher stops working due to %v.", err)
+ return err
+ }
+ rr.mu.Lock()
+ defer rr.mu.Unlock()
+ for _, update := range updates {
+ addr := Address{
+ Addr: update.Addr,
+ Metadata: update.Metadata,
+ }
+ switch update.Op {
+ case naming.Add:
+ var exist bool
+ for _, v := range rr.addrs {
+ if addr == v.addr {
+ exist = true
+ grpclog.Infoln("grpc: The name resolver wanted to add an existing address: ", addr)
+ break
+ }
+ }
+ if exist {
+ continue
+ }
+ rr.addrs = append(rr.addrs, &addrInfo{addr: addr})
+ case naming.Delete:
+ for i, v := range rr.addrs {
+ if addr == v.addr {
+ copy(rr.addrs[i:], rr.addrs[i+1:])
+ rr.addrs = rr.addrs[:len(rr.addrs)-1]
+ break
+ }
+ }
+ default:
+ grpclog.Errorln("Unknown update.Op ", update.Op)
+ }
+ }
+ // Make a copy of rr.addrs and write it onto rr.addrCh so that gRPC internals gets notified.
+ open := make([]Address, len(rr.addrs))
+ for i, v := range rr.addrs {
+ open[i] = v.addr
+ }
+ if rr.done {
+ return ErrClientConnClosing
+ }
+ select {
+ case <-rr.addrCh:
+ default:
+ }
+ rr.addrCh <- open
+ return nil
+}
+
+func (rr *roundRobin) Start(target string, config BalancerConfig) error {
+ rr.mu.Lock()
+ defer rr.mu.Unlock()
+ if rr.done {
+ return ErrClientConnClosing
+ }
+ if rr.r == nil {
+ // If there is no name resolver installed, it is not needed to
+ // do name resolution. In this case, target is added into rr.addrs
+ // as the only address available and rr.addrCh stays nil.
+ rr.addrs = append(rr.addrs, &addrInfo{addr: Address{Addr: target}})
+ return nil
+ }
+ w, err := rr.r.Resolve(target)
+ if err != nil {
+ return err
+ }
+ rr.w = w
+ rr.addrCh = make(chan []Address, 1)
+ go func() {
+ for {
+ if err := rr.watchAddrUpdates(); err != nil {
+ return
+ }
+ }
+ }()
+ return nil
+}
+
+// Up sets the connected state of addr and sends notification if there are pending
+// Get() calls.
+func (rr *roundRobin) Up(addr Address) func(error) {
+ rr.mu.Lock()
+ defer rr.mu.Unlock()
+ var cnt int
+ for _, a := range rr.addrs {
+ if a.addr == addr {
+ if a.connected {
+ return nil
+ }
+ a.connected = true
+ }
+ if a.connected {
+ cnt++
+ }
+ }
+ // addr is only one which is connected. Notify the Get() callers who are blocking.
+ if cnt == 1 && rr.waitCh != nil {
+ close(rr.waitCh)
+ rr.waitCh = nil
+ }
+ return func(err error) {
+ rr.down(addr, err)
+ }
+}
+
+// down unsets the connected state of addr.
+func (rr *roundRobin) down(addr Address, err error) {
+ rr.mu.Lock()
+ defer rr.mu.Unlock()
+ for _, a := range rr.addrs {
+ if addr == a.addr {
+ a.connected = false
+ break
+ }
+ }
+}
+
+// Get returns the next addr in the rotation.
+func (rr *roundRobin) Get(ctx context.Context, opts BalancerGetOptions) (addr Address, put func(), err error) {
+ var ch chan struct{}
+ rr.mu.Lock()
+ if rr.done {
+ rr.mu.Unlock()
+ err = ErrClientConnClosing
+ return
+ }
+
+ if len(rr.addrs) > 0 {
+ if rr.next >= len(rr.addrs) {
+ rr.next = 0
+ }
+ next := rr.next
+ for {
+ a := rr.addrs[next]
+ next = (next + 1) % len(rr.addrs)
+ if a.connected {
+ addr = a.addr
+ rr.next = next
+ rr.mu.Unlock()
+ return
+ }
+ if next == rr.next {
+ // Has iterated all the possible address but none is connected.
+ break
+ }
+ }
+ }
+ if !opts.BlockingWait {
+ if len(rr.addrs) == 0 {
+ rr.mu.Unlock()
+ err = status.Errorf(codes.Unavailable, "there is no address available")
+ return
+ }
+ // Returns the next addr on rr.addrs for failfast RPCs.
+ addr = rr.addrs[rr.next].addr
+ rr.next++
+ rr.mu.Unlock()
+ return
+ }
+ // Wait on rr.waitCh for non-failfast RPCs.
+ if rr.waitCh == nil {
+ ch = make(chan struct{})
+ rr.waitCh = ch
+ } else {
+ ch = rr.waitCh
+ }
+ rr.mu.Unlock()
+ for {
+ select {
+ case <-ctx.Done():
+ err = ctx.Err()
+ return
+ case <-ch:
+ rr.mu.Lock()
+ if rr.done {
+ rr.mu.Unlock()
+ err = ErrClientConnClosing
+ return
+ }
+
+ if len(rr.addrs) > 0 {
+ if rr.next >= len(rr.addrs) {
+ rr.next = 0
+ }
+ next := rr.next
+ for {
+ a := rr.addrs[next]
+ next = (next + 1) % len(rr.addrs)
+ if a.connected {
+ addr = a.addr
+ rr.next = next
+ rr.mu.Unlock()
+ return
+ }
+ if next == rr.next {
+ // Has iterated all the possible address but none is connected.
+ break
+ }
+ }
+ }
+ // The newly added addr got removed by Down() again.
+ if rr.waitCh == nil {
+ ch = make(chan struct{})
+ rr.waitCh = ch
+ } else {
+ ch = rr.waitCh
+ }
+ rr.mu.Unlock()
+ }
+ }
+}
+
+func (rr *roundRobin) Notify() <-chan []Address {
+ return rr.addrCh
+}
+
+func (rr *roundRobin) Close() error {
+ rr.mu.Lock()
+ defer rr.mu.Unlock()
+ if rr.done {
+ return errBalancerClosed
+ }
+ rr.done = true
+ if rr.w != nil {
+ rr.w.Close()
+ }
+ if rr.waitCh != nil {
+ close(rr.waitCh)
+ rr.waitCh = nil
+ }
+ if rr.addrCh != nil {
+ close(rr.addrCh)
+ }
+ return nil
+}
+
+// pickFirst is used to test multi-addresses in one addrConn in which all addresses share the same addrConn.
+// It is a wrapper around roundRobin balancer. The logic of all methods works fine because balancer.Get()
+// returns the only address Up by resetTransport().
+type pickFirst struct {
+ *roundRobin
+}
diff --git a/vendor/google.golang.org/grpc/balancer/balancer.go b/vendor/google.golang.org/grpc/balancer/balancer.go
new file mode 100644
index 000000000..1bf46aafe
--- /dev/null
+++ b/vendor/google.golang.org/grpc/balancer/balancer.go
@@ -0,0 +1,290 @@
+/*
+ *
+ * Copyright 2017 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// Package balancer defines APIs for load balancing in gRPC.
+// All APIs in this package are experimental.
+package balancer
+
+import (
+ "context"
+ "errors"
+ "net"
+ "strings"
+
+ "google.golang.org/grpc/connectivity"
+ "google.golang.org/grpc/credentials"
+ "google.golang.org/grpc/metadata"
+ "google.golang.org/grpc/resolver"
+)
+
+var (
+ // m is a map from name to balancer builder.
+ m = make(map[string]Builder)
+)
+
+// Register registers the balancer builder to the balancer map. b.Name
+// (lowercased) will be used as the name registered with this builder.
+//
+// NOTE: this function must only be called during initialization time (i.e. in
+// an init() function), and is not thread-safe. If multiple Balancers are
+// registered with the same name, the one registered last will take effect.
+func Register(b Builder) {
+ m[strings.ToLower(b.Name())] = b
+}
+
+// Get returns the resolver builder registered with the given name.
+// Note that the compare is done in a case-insenstive fashion.
+// If no builder is register with the name, nil will be returned.
+func Get(name string) Builder {
+ if b, ok := m[strings.ToLower(name)]; ok {
+ return b
+ }
+ return nil
+}
+
+// SubConn represents a gRPC sub connection.
+// Each sub connection contains a list of addresses. gRPC will
+// try to connect to them (in sequence), and stop trying the
+// remainder once one connection is successful.
+//
+// The reconnect backoff will be applied on the list, not a single address.
+// For example, try_on_all_addresses -> backoff -> try_on_all_addresses.
+//
+// All SubConns start in IDLE, and will not try to connect. To trigger
+// the connecting, Balancers must call Connect.
+// When the connection encounters an error, it will reconnect immediately.
+// When the connection becomes IDLE, it will not reconnect unless Connect is
+// called.
+//
+// This interface is to be implemented by gRPC. Users should not need a
+// brand new implementation of this interface. For the situations like
+// testing, the new implementation should embed this interface. This allows
+// gRPC to add new methods to this interface.
+type SubConn interface {
+ // UpdateAddresses updates the addresses used in this SubConn.
+ // gRPC checks if currently-connected address is still in the new list.
+ // If it's in the list, the connection will be kept.
+ // If it's not in the list, the connection will gracefully closed, and
+ // a new connection will be created.
+ //
+ // This will trigger a state transition for the SubConn.
+ UpdateAddresses([]resolver.Address)
+ // Connect starts the connecting for this SubConn.
+ Connect()
+}
+
+// NewSubConnOptions contains options to create new SubConn.
+type NewSubConnOptions struct {
+ // CredsBundle is the credentials bundle that will be used in the created
+ // SubConn. If it's nil, the original creds from grpc DialOptions will be
+ // used.
+ CredsBundle credentials.Bundle
+ // HealthCheckEnabled indicates whether health check service should be
+ // enabled on this SubConn
+ HealthCheckEnabled bool
+}
+
+// ClientConn represents a gRPC ClientConn.
+//
+// This interface is to be implemented by gRPC. Users should not need a
+// brand new implementation of this interface. For the situations like
+// testing, the new implementation should embed this interface. This allows
+// gRPC to add new methods to this interface.
+type ClientConn interface {
+ // NewSubConn is called by balancer to create a new SubConn.
+ // It doesn't block and wait for the connections to be established.
+ // Behaviors of the SubConn can be controlled by options.
+ NewSubConn([]resolver.Address, NewSubConnOptions) (SubConn, error)
+ // RemoveSubConn removes the SubConn from ClientConn.
+ // The SubConn will be shutdown.
+ RemoveSubConn(SubConn)
+
+ // UpdateBalancerState is called by balancer to nofity gRPC that some internal
+ // state in balancer has changed.
+ //
+ // gRPC will update the connectivity state of the ClientConn, and will call pick
+ // on the new picker to pick new SubConn.
+ UpdateBalancerState(s connectivity.State, p Picker)
+
+ // ResolveNow is called by balancer to notify gRPC to do a name resolving.
+ ResolveNow(resolver.ResolveNowOption)
+
+ // Target returns the dial target for this ClientConn.
+ Target() string
+}
+
+// BuildOptions contains additional information for Build.
+type BuildOptions struct {
+ // DialCreds is the transport credential the Balancer implementation can
+ // use to dial to a remote load balancer server. The Balancer implementations
+ // can ignore this if it does not need to talk to another party securely.
+ DialCreds credentials.TransportCredentials
+ // CredsBundle is the credentials bundle that the Balancer can use.
+ CredsBundle credentials.Bundle
+ // Dialer is the custom dialer the Balancer implementation can use to dial
+ // to a remote load balancer server. The Balancer implementations
+ // can ignore this if it doesn't need to talk to remote balancer.
+ Dialer func(context.Context, string) (net.Conn, error)
+ // ChannelzParentID is the entity parent's channelz unique identification number.
+ ChannelzParentID int64
+}
+
+// Builder creates a balancer.
+type Builder interface {
+ // Build creates a new balancer with the ClientConn.
+ Build(cc ClientConn, opts BuildOptions) Balancer
+ // Name returns the name of balancers built by this builder.
+ // It will be used to pick balancers (for example in service config).
+ Name() string
+}
+
+// PickOptions contains addition information for the Pick operation.
+type PickOptions struct {
+ // FullMethodName is the method name that NewClientStream() is called
+ // with. The canonical format is /service/Method.
+ FullMethodName string
+ // Header contains the metadata from the RPC's client header. The metadata
+ // should not be modified; make a copy first if needed.
+ Header metadata.MD
+}
+
+// DoneInfo contains additional information for done.
+type DoneInfo struct {
+ // Err is the rpc error the RPC finished with. It could be nil.
+ Err error
+ // Trailer contains the metadata from the RPC's trailer, if present.
+ Trailer metadata.MD
+ // BytesSent indicates if any bytes have been sent to the server.
+ BytesSent bool
+ // BytesReceived indicates if any byte has been received from the server.
+ BytesReceived bool
+}
+
+var (
+ // ErrNoSubConnAvailable indicates no SubConn is available for pick().
+ // gRPC will block the RPC until a new picker is available via UpdateBalancerState().
+ ErrNoSubConnAvailable = errors.New("no SubConn is available")
+ // ErrTransientFailure indicates all SubConns are in TransientFailure.
+ // WaitForReady RPCs will block, non-WaitForReady RPCs will fail.
+ ErrTransientFailure = errors.New("all SubConns are in TransientFailure")
+)
+
+// Picker is used by gRPC to pick a SubConn to send an RPC.
+// Balancer is expected to generate a new picker from its snapshot every time its
+// internal state has changed.
+//
+// The pickers used by gRPC can be updated by ClientConn.UpdateBalancerState().
+type Picker interface {
+ // Pick returns the SubConn to be used to send the RPC.
+ // The returned SubConn must be one returned by NewSubConn().
+ //
+ // This functions is expected to return:
+ // - a SubConn that is known to be READY;
+ // - ErrNoSubConnAvailable if no SubConn is available, but progress is being
+ // made (for example, some SubConn is in CONNECTING mode);
+ // - other errors if no active connecting is happening (for example, all SubConn
+ // are in TRANSIENT_FAILURE mode).
+ //
+ // If a SubConn is returned:
+ // - If it is READY, gRPC will send the RPC on it;
+ // - If it is not ready, or becomes not ready after it's returned, gRPC will block
+ // until UpdateBalancerState() is called and will call pick on the new picker.
+ //
+ // If the returned error is not nil:
+ // - If the error is ErrNoSubConnAvailable, gRPC will block until UpdateBalancerState()
+ // - If the error is ErrTransientFailure:
+ // - If the RPC is wait-for-ready, gRPC will block until UpdateBalancerState()
+ // is called to pick again;
+ // - Otherwise, RPC will fail with unavailable error.
+ // - Else (error is other non-nil error):
+ // - The RPC will fail with unavailable error.
+ //
+ // The returned done() function will be called once the rpc has finished, with the
+ // final status of that RPC.
+ // done may be nil if balancer doesn't care about the RPC status.
+ Pick(ctx context.Context, opts PickOptions) (conn SubConn, done func(DoneInfo), err error)
+}
+
+// Balancer takes input from gRPC, manages SubConns, and collects and aggregates
+// the connectivity states.
+//
+// It also generates and updates the Picker used by gRPC to pick SubConns for RPCs.
+//
+// HandleSubConnectionStateChange, HandleResolvedAddrs and Close are guaranteed
+// to be called synchronously from the same goroutine.
+// There's no guarantee on picker.Pick, it may be called anytime.
+type Balancer interface {
+ // HandleSubConnStateChange is called by gRPC when the connectivity state
+ // of sc has changed.
+ // Balancer is expected to aggregate all the state of SubConn and report
+ // that back to gRPC.
+ // Balancer should also generate and update Pickers when its internal state has
+ // been changed by the new state.
+ HandleSubConnStateChange(sc SubConn, state connectivity.State)
+ // HandleResolvedAddrs is called by gRPC to send updated resolved addresses to
+ // balancers.
+ // Balancer can create new SubConn or remove SubConn with the addresses.
+ // An empty address slice and a non-nil error will be passed if the resolver returns
+ // non-nil error to gRPC.
+ HandleResolvedAddrs([]resolver.Address, error)
+ // Close closes the balancer. The balancer is not required to call
+ // ClientConn.RemoveSubConn for its existing SubConns.
+ Close()
+}
+
+// ConnectivityStateEvaluator takes the connectivity states of multiple SubConns
+// and returns one aggregated connectivity state.
+//
+// It's not thread safe.
+type ConnectivityStateEvaluator struct {
+ numReady uint64 // Number of addrConns in ready state.
+ numConnecting uint64 // Number of addrConns in connecting state.
+ numTransientFailure uint64 // Number of addrConns in transientFailure.
+}
+
+// RecordTransition records state change happening in subConn and based on that
+// it evaluates what aggregated state should be.
+//
+// - If at least one SubConn in Ready, the aggregated state is Ready;
+// - Else if at least one SubConn in Connecting, the aggregated state is Connecting;
+// - Else the aggregated state is TransientFailure.
+//
+// Idle and Shutdown are not considered.
+func (cse *ConnectivityStateEvaluator) RecordTransition(oldState, newState connectivity.State) connectivity.State {
+ // Update counters.
+ for idx, state := range []connectivity.State{oldState, newState} {
+ updateVal := 2*uint64(idx) - 1 // -1 for oldState and +1 for new.
+ switch state {
+ case connectivity.Ready:
+ cse.numReady += updateVal
+ case connectivity.Connecting:
+ cse.numConnecting += updateVal
+ case connectivity.TransientFailure:
+ cse.numTransientFailure += updateVal
+ }
+ }
+
+ // Evaluate.
+ if cse.numReady > 0 {
+ return connectivity.Ready
+ }
+ if cse.numConnecting > 0 {
+ return connectivity.Connecting
+ }
+ return connectivity.TransientFailure
+}
diff --git a/vendor/google.golang.org/grpc/balancer/base/balancer.go b/vendor/google.golang.org/grpc/balancer/base/balancer.go
new file mode 100644
index 000000000..5f55b274f
--- /dev/null
+++ b/vendor/google.golang.org/grpc/balancer/base/balancer.go
@@ -0,0 +1,212 @@
+/*
+ *
+ * Copyright 2017 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package base
+
+import (
+ "context"
+
+ "google.golang.org/grpc/balancer"
+ "google.golang.org/grpc/connectivity"
+ "google.golang.org/grpc/grpclog"
+ "google.golang.org/grpc/resolver"
+)
+
+type baseBuilder struct {
+ name string
+ pickerBuilder PickerBuilder
+ config Config
+}
+
+func (bb *baseBuilder) Build(cc balancer.ClientConn, opt balancer.BuildOptions) balancer.Balancer {
+ return &baseBalancer{
+ cc: cc,
+ pickerBuilder: bb.pickerBuilder,
+
+ subConns: make(map[resolver.Address]balancer.SubConn),
+ scStates: make(map[balancer.SubConn]connectivity.State),
+ csEvltr: &connectivityStateEvaluator{},
+ // Initialize picker to a picker that always return
+ // ErrNoSubConnAvailable, because when state of a SubConn changes, we
+ // may call UpdateBalancerState with this picker.
+ picker: NewErrPicker(balancer.ErrNoSubConnAvailable),
+ config: bb.config,
+ }
+}
+
+func (bb *baseBuilder) Name() string {
+ return bb.name
+}
+
+type baseBalancer struct {
+ cc balancer.ClientConn
+ pickerBuilder PickerBuilder
+
+ csEvltr *connectivityStateEvaluator
+ state connectivity.State
+
+ subConns map[resolver.Address]balancer.SubConn
+ scStates map[balancer.SubConn]connectivity.State
+ picker balancer.Picker
+ config Config
+}
+
+func (b *baseBalancer) HandleResolvedAddrs(addrs []resolver.Address, err error) {
+ if err != nil {
+ grpclog.Infof("base.baseBalancer: HandleResolvedAddrs called with error %v", err)
+ return
+ }
+ grpclog.Infoln("base.baseBalancer: got new resolved addresses: ", addrs)
+ // addrsSet is the set converted from addrs, it's used for quick lookup of an address.
+ addrsSet := make(map[resolver.Address]struct{})
+ for _, a := range addrs {
+ addrsSet[a] = struct{}{}
+ if _, ok := b.subConns[a]; !ok {
+ // a is a new address (not existing in b.subConns).
+ sc, err := b.cc.NewSubConn([]resolver.Address{a}, balancer.NewSubConnOptions{HealthCheckEnabled: b.config.HealthCheck})
+ if err != nil {
+ grpclog.Warningf("base.baseBalancer: failed to create new SubConn: %v", err)
+ continue
+ }
+ b.subConns[a] = sc
+ b.scStates[sc] = connectivity.Idle
+ sc.Connect()
+ }
+ }
+ for a, sc := range b.subConns {
+ // a was removed by resolver.
+ if _, ok := addrsSet[a]; !ok {
+ b.cc.RemoveSubConn(sc)
+ delete(b.subConns, a)
+ // Keep the state of this sc in b.scStates until sc's state becomes Shutdown.
+ // The entry will be deleted in HandleSubConnStateChange.
+ }
+ }
+}
+
+// regeneratePicker takes a snapshot of the balancer, and generates a picker
+// from it. The picker is
+// - errPicker with ErrTransientFailure if the balancer is in TransientFailure,
+// - built by the pickerBuilder with all READY SubConns otherwise.
+func (b *baseBalancer) regeneratePicker() {
+ if b.state == connectivity.TransientFailure {
+ b.picker = NewErrPicker(balancer.ErrTransientFailure)
+ return
+ }
+ readySCs := make(map[resolver.Address]balancer.SubConn)
+
+ // Filter out all ready SCs from full subConn map.
+ for addr, sc := range b.subConns {
+ if st, ok := b.scStates[sc]; ok && st == connectivity.Ready {
+ readySCs[addr] = sc
+ }
+ }
+ b.picker = b.pickerBuilder.Build(readySCs)
+}
+
+func (b *baseBalancer) HandleSubConnStateChange(sc balancer.SubConn, s connectivity.State) {
+ grpclog.Infof("base.baseBalancer: handle SubConn state change: %p, %v", sc, s)
+ oldS, ok := b.scStates[sc]
+ if !ok {
+ grpclog.Infof("base.baseBalancer: got state changes for an unknown SubConn: %p, %v", sc, s)
+ return
+ }
+ b.scStates[sc] = s
+ switch s {
+ case connectivity.Idle:
+ sc.Connect()
+ case connectivity.Shutdown:
+ // When an address was removed by resolver, b called RemoveSubConn but
+ // kept the sc's state in scStates. Remove state for this sc here.
+ delete(b.scStates, sc)
+ }
+
+ oldAggrState := b.state
+ b.state = b.csEvltr.recordTransition(oldS, s)
+
+ // Regenerate picker when one of the following happens:
+ // - this sc became ready from not-ready
+ // - this sc became not-ready from ready
+ // - the aggregated state of balancer became TransientFailure from non-TransientFailure
+ // - the aggregated state of balancer became non-TransientFailure from TransientFailure
+ if (s == connectivity.Ready) != (oldS == connectivity.Ready) ||
+ (b.state == connectivity.TransientFailure) != (oldAggrState == connectivity.TransientFailure) {
+ b.regeneratePicker()
+ }
+
+ b.cc.UpdateBalancerState(b.state, b.picker)
+}
+
+// Close is a nop because base balancer doesn't have internal state to clean up,
+// and it doesn't need to call RemoveSubConn for the SubConns.
+func (b *baseBalancer) Close() {
+}
+
+// NewErrPicker returns a picker that always returns err on Pick().
+func NewErrPicker(err error) balancer.Picker {
+ return &errPicker{err: err}
+}
+
+type errPicker struct {
+ err error // Pick() always returns this err.
+}
+
+func (p *errPicker) Pick(ctx context.Context, opts balancer.PickOptions) (balancer.SubConn, func(balancer.DoneInfo), error) {
+ return nil, nil, p.err
+}
+
+// connectivityStateEvaluator gets updated by addrConns when their
+// states transition, based on which it evaluates the state of
+// ClientConn.
+type connectivityStateEvaluator struct {
+ numReady uint64 // Number of addrConns in ready state.
+ numConnecting uint64 // Number of addrConns in connecting state.
+ numTransientFailure uint64 // Number of addrConns in transientFailure.
+}
+
+// recordTransition records state change happening in every subConn and based on
+// that it evaluates what aggregated state should be.
+// It can only transition between Ready, Connecting and TransientFailure. Other states,
+// Idle and Shutdown are transitioned into by ClientConn; in the beginning of the connection
+// before any subConn is created ClientConn is in idle state. In the end when ClientConn
+// closes it is in Shutdown state.
+//
+// recordTransition should only be called synchronously from the same goroutine.
+func (cse *connectivityStateEvaluator) recordTransition(oldState, newState connectivity.State) connectivity.State {
+ // Update counters.
+ for idx, state := range []connectivity.State{oldState, newState} {
+ updateVal := 2*uint64(idx) - 1 // -1 for oldState and +1 for new.
+ switch state {
+ case connectivity.Ready:
+ cse.numReady += updateVal
+ case connectivity.Connecting:
+ cse.numConnecting += updateVal
+ case connectivity.TransientFailure:
+ cse.numTransientFailure += updateVal
+ }
+ }
+
+ // Evaluate.
+ if cse.numReady > 0 {
+ return connectivity.Ready
+ }
+ if cse.numConnecting > 0 {
+ return connectivity.Connecting
+ }
+ return connectivity.TransientFailure
+}
diff --git a/vendor/google.golang.org/grpc/balancer/base/base.go b/vendor/google.golang.org/grpc/balancer/base/base.go
new file mode 100644
index 000000000..34b1f2994
--- /dev/null
+++ b/vendor/google.golang.org/grpc/balancer/base/base.go
@@ -0,0 +1,64 @@
+/*
+ *
+ * Copyright 2017 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// Package base defines a balancer base that can be used to build balancers with
+// different picking algorithms.
+//
+// The base balancer creates a new SubConn for each resolved address. The
+// provided picker will only be notified about READY SubConns.
+//
+// This package is the base of round_robin balancer, its purpose is to be used
+// to build round_robin like balancers with complex picking algorithms.
+// Balancers with more complicated logic should try to implement a balancer
+// builder from scratch.
+//
+// All APIs in this package are experimental.
+package base
+
+import (
+ "google.golang.org/grpc/balancer"
+ "google.golang.org/grpc/resolver"
+)
+
+// PickerBuilder creates balancer.Picker.
+type PickerBuilder interface {
+ // Build takes a slice of ready SubConns, and returns a picker that will be
+ // used by gRPC to pick a SubConn.
+ Build(readySCs map[resolver.Address]balancer.SubConn) balancer.Picker
+}
+
+// NewBalancerBuilder returns a balancer builder. The balancers
+// built by this builder will use the picker builder to build pickers.
+func NewBalancerBuilder(name string, pb PickerBuilder) balancer.Builder {
+ return NewBalancerBuilderWithConfig(name, pb, Config{})
+}
+
+// Config contains the config info about the base balancer builder.
+type Config struct {
+ // HealthCheck indicates whether health checking should be enabled for this specific balancer.
+ HealthCheck bool
+}
+
+// NewBalancerBuilderWithConfig returns a base balancer builder configured by the provided config.
+func NewBalancerBuilderWithConfig(name string, pb PickerBuilder, config Config) balancer.Builder {
+ return &baseBuilder{
+ name: name,
+ pickerBuilder: pb,
+ config: config,
+ }
+}
diff --git a/vendor/google.golang.org/grpc/balancer/roundrobin/roundrobin.go b/vendor/google.golang.org/grpc/balancer/roundrobin/roundrobin.go
new file mode 100644
index 000000000..57aea9fb4
--- /dev/null
+++ b/vendor/google.golang.org/grpc/balancer/roundrobin/roundrobin.go
@@ -0,0 +1,79 @@
+/*
+ *
+ * Copyright 2017 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// Package roundrobin defines a roundrobin balancer. Roundrobin balancer is
+// installed as one of the default balancers in gRPC, users don't need to
+// explicitly install this balancer.
+package roundrobin
+
+import (
+ "context"
+ "sync"
+
+ "google.golang.org/grpc/balancer"
+ "google.golang.org/grpc/balancer/base"
+ "google.golang.org/grpc/grpclog"
+ "google.golang.org/grpc/resolver"
+)
+
+// Name is the name of round_robin balancer.
+const Name = "round_robin"
+
+// newBuilder creates a new roundrobin balancer builder.
+func newBuilder() balancer.Builder {
+ return base.NewBalancerBuilderWithConfig(Name, &rrPickerBuilder{}, base.Config{HealthCheck: true})
+}
+
+func init() {
+ balancer.Register(newBuilder())
+}
+
+type rrPickerBuilder struct{}
+
+func (*rrPickerBuilder) Build(readySCs map[resolver.Address]balancer.SubConn) balancer.Picker {
+ grpclog.Infof("roundrobinPicker: newPicker called with readySCs: %v", readySCs)
+ var scs []balancer.SubConn
+ for _, sc := range readySCs {
+ scs = append(scs, sc)
+ }
+ return &rrPicker{
+ subConns: scs,
+ }
+}
+
+type rrPicker struct {
+ // subConns is the snapshot of the roundrobin balancer when this picker was
+ // created. The slice is immutable. Each Get() will do a round robin
+ // selection from it and return the selected SubConn.
+ subConns []balancer.SubConn
+
+ mu sync.Mutex
+ next int
+}
+
+func (p *rrPicker) Pick(ctx context.Context, opts balancer.PickOptions) (balancer.SubConn, func(balancer.DoneInfo), error) {
+ if len(p.subConns) <= 0 {
+ return nil, nil, balancer.ErrNoSubConnAvailable
+ }
+
+ p.mu.Lock()
+ sc := p.subConns[p.next]
+ p.next = (p.next + 1) % len(p.subConns)
+ p.mu.Unlock()
+ return sc, nil, nil
+}
diff --git a/vendor/google.golang.org/grpc/balancer_conn_wrappers.go b/vendor/google.golang.org/grpc/balancer_conn_wrappers.go
new file mode 100644
index 000000000..77b684775
--- /dev/null
+++ b/vendor/google.golang.org/grpc/balancer_conn_wrappers.go
@@ -0,0 +1,306 @@
+/*
+ *
+ * Copyright 2017 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package grpc
+
+import (
+ "fmt"
+ "sync"
+
+ "google.golang.org/grpc/balancer"
+ "google.golang.org/grpc/connectivity"
+ "google.golang.org/grpc/grpclog"
+ "google.golang.org/grpc/resolver"
+)
+
+// scStateUpdate contains the subConn and the new state it changed to.
+type scStateUpdate struct {
+ sc balancer.SubConn
+ state connectivity.State
+}
+
+// scStateUpdateBuffer is an unbounded channel for scStateChangeTuple.
+// TODO make a general purpose buffer that uses interface{}.
+type scStateUpdateBuffer struct {
+ c chan *scStateUpdate
+ mu sync.Mutex
+ backlog []*scStateUpdate
+}
+
+func newSCStateUpdateBuffer() *scStateUpdateBuffer {
+ return &scStateUpdateBuffer{
+ c: make(chan *scStateUpdate, 1),
+ }
+}
+
+func (b *scStateUpdateBuffer) put(t *scStateUpdate) {
+ b.mu.Lock()
+ defer b.mu.Unlock()
+ if len(b.backlog) == 0 {
+ select {
+ case b.c <- t:
+ return
+ default:
+ }
+ }
+ b.backlog = append(b.backlog, t)
+}
+
+func (b *scStateUpdateBuffer) load() {
+ b.mu.Lock()
+ defer b.mu.Unlock()
+ if len(b.backlog) > 0 {
+ select {
+ case b.c <- b.backlog[0]:
+ b.backlog[0] = nil
+ b.backlog = b.backlog[1:]
+ default:
+ }
+ }
+}
+
+// get returns the channel that the scStateUpdate will be sent to.
+//
+// Upon receiving, the caller should call load to send another
+// scStateChangeTuple onto the channel if there is any.
+func (b *scStateUpdateBuffer) get() <-chan *scStateUpdate {
+ return b.c
+}
+
+// resolverUpdate contains the new resolved addresses or error if there's
+// any.
+type resolverUpdate struct {
+ addrs []resolver.Address
+ err error
+}
+
+// ccBalancerWrapper is a wrapper on top of cc for balancers.
+// It implements balancer.ClientConn interface.
+type ccBalancerWrapper struct {
+ cc *ClientConn
+ balancer balancer.Balancer
+ stateChangeQueue *scStateUpdateBuffer
+ resolverUpdateCh chan *resolverUpdate
+ done chan struct{}
+
+ mu sync.Mutex
+ subConns map[*acBalancerWrapper]struct{}
+}
+
+func newCCBalancerWrapper(cc *ClientConn, b balancer.Builder, bopts balancer.BuildOptions) *ccBalancerWrapper {
+ ccb := &ccBalancerWrapper{
+ cc: cc,
+ stateChangeQueue: newSCStateUpdateBuffer(),
+ resolverUpdateCh: make(chan *resolverUpdate, 1),
+ done: make(chan struct{}),
+ subConns: make(map[*acBalancerWrapper]struct{}),
+ }
+ go ccb.watcher()
+ ccb.balancer = b.Build(ccb, bopts)
+ return ccb
+}
+
+// watcher balancer functions sequentially, so the balancer can be implemented
+// lock-free.
+func (ccb *ccBalancerWrapper) watcher() {
+ for {
+ select {
+ case t := <-ccb.stateChangeQueue.get():
+ ccb.stateChangeQueue.load()
+ select {
+ case <-ccb.done:
+ ccb.balancer.Close()
+ return
+ default:
+ }
+ ccb.balancer.HandleSubConnStateChange(t.sc, t.state)
+ case t := <-ccb.resolverUpdateCh:
+ select {
+ case <-ccb.done:
+ ccb.balancer.Close()
+ return
+ default:
+ }
+ ccb.balancer.HandleResolvedAddrs(t.addrs, t.err)
+ case <-ccb.done:
+ }
+
+ select {
+ case <-ccb.done:
+ ccb.balancer.Close()
+ ccb.mu.Lock()
+ scs := ccb.subConns
+ ccb.subConns = nil
+ ccb.mu.Unlock()
+ for acbw := range scs {
+ ccb.cc.removeAddrConn(acbw.getAddrConn(), errConnDrain)
+ }
+ return
+ default:
+ }
+ }
+}
+
+func (ccb *ccBalancerWrapper) close() {
+ close(ccb.done)
+}
+
+func (ccb *ccBalancerWrapper) handleSubConnStateChange(sc balancer.SubConn, s connectivity.State) {
+ // When updating addresses for a SubConn, if the address in use is not in
+ // the new addresses, the old ac will be tearDown() and a new ac will be
+ // created. tearDown() generates a state change with Shutdown state, we
+ // don't want the balancer to receive this state change. So before
+ // tearDown() on the old ac, ac.acbw (acWrapper) will be set to nil, and
+ // this function will be called with (nil, Shutdown). We don't need to call
+ // balancer method in this case.
+ if sc == nil {
+ return
+ }
+ ccb.stateChangeQueue.put(&scStateUpdate{
+ sc: sc,
+ state: s,
+ })
+}
+
+func (ccb *ccBalancerWrapper) handleResolvedAddrs(addrs []resolver.Address, err error) {
+ select {
+ case <-ccb.resolverUpdateCh:
+ default:
+ }
+ ccb.resolverUpdateCh <- &resolverUpdate{
+ addrs: addrs,
+ err: err,
+ }
+}
+
+func (ccb *ccBalancerWrapper) NewSubConn(addrs []resolver.Address, opts balancer.NewSubConnOptions) (balancer.SubConn, error) {
+ if len(addrs) <= 0 {
+ return nil, fmt.Errorf("grpc: cannot create SubConn with empty address list")
+ }
+ ccb.mu.Lock()
+ defer ccb.mu.Unlock()
+ if ccb.subConns == nil {
+ return nil, fmt.Errorf("grpc: ClientConn balancer wrapper was closed")
+ }
+ ac, err := ccb.cc.newAddrConn(addrs, opts)
+ if err != nil {
+ return nil, err
+ }
+ acbw := &acBalancerWrapper{ac: ac}
+ acbw.ac.mu.Lock()
+ ac.acbw = acbw
+ acbw.ac.mu.Unlock()
+ ccb.subConns[acbw] = struct{}{}
+ return acbw, nil
+}
+
+func (ccb *ccBalancerWrapper) RemoveSubConn(sc balancer.SubConn) {
+ acbw, ok := sc.(*acBalancerWrapper)
+ if !ok {
+ return
+ }
+ ccb.mu.Lock()
+ defer ccb.mu.Unlock()
+ if ccb.subConns == nil {
+ return
+ }
+ delete(ccb.subConns, acbw)
+ ccb.cc.removeAddrConn(acbw.getAddrConn(), errConnDrain)
+}
+
+func (ccb *ccBalancerWrapper) UpdateBalancerState(s connectivity.State, p balancer.Picker) {
+ ccb.mu.Lock()
+ defer ccb.mu.Unlock()
+ if ccb.subConns == nil {
+ return
+ }
+ // Update picker before updating state. Even though the ordering here does
+ // not matter, it can lead to multiple calls of Pick in the common start-up
+ // case where we wait for ready and then perform an RPC. If the picker is
+ // updated later, we could call the "connecting" picker when the state is
+ // updated, and then call the "ready" picker after the picker gets updated.
+ ccb.cc.blockingpicker.updatePicker(p)
+ ccb.cc.csMgr.updateState(s)
+}
+
+func (ccb *ccBalancerWrapper) ResolveNow(o resolver.ResolveNowOption) {
+ ccb.cc.resolveNow(o)
+}
+
+func (ccb *ccBalancerWrapper) Target() string {
+ return ccb.cc.target
+}
+
+// acBalancerWrapper is a wrapper on top of ac for balancers.
+// It implements balancer.SubConn interface.
+type acBalancerWrapper struct {
+ mu sync.Mutex
+ ac *addrConn
+}
+
+func (acbw *acBalancerWrapper) UpdateAddresses(addrs []resolver.Address) {
+ acbw.mu.Lock()
+ defer acbw.mu.Unlock()
+ if len(addrs) <= 0 {
+ acbw.ac.tearDown(errConnDrain)
+ return
+ }
+ if !acbw.ac.tryUpdateAddrs(addrs) {
+ cc := acbw.ac.cc
+ opts := acbw.ac.scopts
+ acbw.ac.mu.Lock()
+ // Set old ac.acbw to nil so the Shutdown state update will be ignored
+ // by balancer.
+ //
+ // TODO(bar) the state transition could be wrong when tearDown() old ac
+ // and creating new ac, fix the transition.
+ acbw.ac.acbw = nil
+ acbw.ac.mu.Unlock()
+ acState := acbw.ac.getState()
+ acbw.ac.tearDown(errConnDrain)
+
+ if acState == connectivity.Shutdown {
+ return
+ }
+
+ ac, err := cc.newAddrConn(addrs, opts)
+ if err != nil {
+ grpclog.Warningf("acBalancerWrapper: UpdateAddresses: failed to newAddrConn: %v", err)
+ return
+ }
+ acbw.ac = ac
+ ac.mu.Lock()
+ ac.acbw = acbw
+ ac.mu.Unlock()
+ if acState != connectivity.Idle {
+ ac.connect()
+ }
+ }
+}
+
+func (acbw *acBalancerWrapper) Connect() {
+ acbw.mu.Lock()
+ defer acbw.mu.Unlock()
+ acbw.ac.connect()
+}
+
+func (acbw *acBalancerWrapper) getAddrConn() *addrConn {
+ acbw.mu.Lock()
+ defer acbw.mu.Unlock()
+ return acbw.ac
+}
diff --git a/vendor/google.golang.org/grpc/balancer_v1_wrapper.go b/vendor/google.golang.org/grpc/balancer_v1_wrapper.go
new file mode 100644
index 000000000..ca07c154b
--- /dev/null
+++ b/vendor/google.golang.org/grpc/balancer_v1_wrapper.go
@@ -0,0 +1,328 @@
+/*
+ *
+ * Copyright 2017 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package grpc
+
+import (
+ "context"
+ "strings"
+ "sync"
+
+ "google.golang.org/grpc/balancer"
+ "google.golang.org/grpc/codes"
+ "google.golang.org/grpc/connectivity"
+ "google.golang.org/grpc/grpclog"
+ "google.golang.org/grpc/resolver"
+ "google.golang.org/grpc/status"
+)
+
+type balancerWrapperBuilder struct {
+ b Balancer // The v1 balancer.
+}
+
+func (bwb *balancerWrapperBuilder) Build(cc balancer.ClientConn, opts balancer.BuildOptions) balancer.Balancer {
+ targetAddr := cc.Target()
+ targetSplitted := strings.Split(targetAddr, ":///")
+ if len(targetSplitted) >= 2 {
+ targetAddr = targetSplitted[1]
+ }
+
+ bwb.b.Start(targetAddr, BalancerConfig{
+ DialCreds: opts.DialCreds,
+ Dialer: opts.Dialer,
+ })
+ _, pickfirst := bwb.b.(*pickFirst)
+ bw := &balancerWrapper{
+ balancer: bwb.b,
+ pickfirst: pickfirst,
+ cc: cc,
+ targetAddr: targetAddr,
+ startCh: make(chan struct{}),
+ conns: make(map[resolver.Address]balancer.SubConn),
+ connSt: make(map[balancer.SubConn]*scState),
+ csEvltr: &balancer.ConnectivityStateEvaluator{},
+ state: connectivity.Idle,
+ }
+ cc.UpdateBalancerState(connectivity.Idle, bw)
+ go bw.lbWatcher()
+ return bw
+}
+
+func (bwb *balancerWrapperBuilder) Name() string {
+ return "wrapper"
+}
+
+type scState struct {
+ addr Address // The v1 address type.
+ s connectivity.State
+ down func(error)
+}
+
+type balancerWrapper struct {
+ balancer Balancer // The v1 balancer.
+ pickfirst bool
+
+ cc balancer.ClientConn
+ targetAddr string // Target without the scheme.
+
+ mu sync.Mutex
+ conns map[resolver.Address]balancer.SubConn
+ connSt map[balancer.SubConn]*scState
+ // This channel is closed when handling the first resolver result.
+ // lbWatcher blocks until this is closed, to avoid race between
+ // - NewSubConn is created, cc wants to notify balancer of state changes;
+ // - Build hasn't return, cc doesn't have access to balancer.
+ startCh chan struct{}
+
+ // To aggregate the connectivity state.
+ csEvltr *balancer.ConnectivityStateEvaluator
+ state connectivity.State
+}
+
+// lbWatcher watches the Notify channel of the balancer and manages
+// connections accordingly.
+func (bw *balancerWrapper) lbWatcher() {
+ <-bw.startCh
+ notifyCh := bw.balancer.Notify()
+ if notifyCh == nil {
+ // There's no resolver in the balancer. Connect directly.
+ a := resolver.Address{
+ Addr: bw.targetAddr,
+ Type: resolver.Backend,
+ }
+ sc, err := bw.cc.NewSubConn([]resolver.Address{a}, balancer.NewSubConnOptions{})
+ if err != nil {
+ grpclog.Warningf("Error creating connection to %v. Err: %v", a, err)
+ } else {
+ bw.mu.Lock()
+ bw.conns[a] = sc
+ bw.connSt[sc] = &scState{
+ addr: Address{Addr: bw.targetAddr},
+ s: connectivity.Idle,
+ }
+ bw.mu.Unlock()
+ sc.Connect()
+ }
+ return
+ }
+
+ for addrs := range notifyCh {
+ grpclog.Infof("balancerWrapper: got update addr from Notify: %v\n", addrs)
+ if bw.pickfirst {
+ var (
+ oldA resolver.Address
+ oldSC balancer.SubConn
+ )
+ bw.mu.Lock()
+ for oldA, oldSC = range bw.conns {
+ break
+ }
+ bw.mu.Unlock()
+ if len(addrs) <= 0 {
+ if oldSC != nil {
+ // Teardown old sc.
+ bw.mu.Lock()
+ delete(bw.conns, oldA)
+ delete(bw.connSt, oldSC)
+ bw.mu.Unlock()
+ bw.cc.RemoveSubConn(oldSC)
+ }
+ continue
+ }
+
+ var newAddrs []resolver.Address
+ for _, a := range addrs {
+ newAddr := resolver.Address{
+ Addr: a.Addr,
+ Type: resolver.Backend, // All addresses from balancer are all backends.
+ ServerName: "",
+ Metadata: a.Metadata,
+ }
+ newAddrs = append(newAddrs, newAddr)
+ }
+ if oldSC == nil {
+ // Create new sc.
+ sc, err := bw.cc.NewSubConn(newAddrs, balancer.NewSubConnOptions{})
+ if err != nil {
+ grpclog.Warningf("Error creating connection to %v. Err: %v", newAddrs, err)
+ } else {
+ bw.mu.Lock()
+ // For pickfirst, there should be only one SubConn, so the
+ // address doesn't matter. All states updating (up and down)
+ // and picking should all happen on that only SubConn.
+ bw.conns[resolver.Address{}] = sc
+ bw.connSt[sc] = &scState{
+ addr: addrs[0], // Use the first address.
+ s: connectivity.Idle,
+ }
+ bw.mu.Unlock()
+ sc.Connect()
+ }
+ } else {
+ bw.mu.Lock()
+ bw.connSt[oldSC].addr = addrs[0]
+ bw.mu.Unlock()
+ oldSC.UpdateAddresses(newAddrs)
+ }
+ } else {
+ var (
+ add []resolver.Address // Addresses need to setup connections.
+ del []balancer.SubConn // Connections need to tear down.
+ )
+ resAddrs := make(map[resolver.Address]Address)
+ for _, a := range addrs {
+ resAddrs[resolver.Address{
+ Addr: a.Addr,
+ Type: resolver.Backend, // All addresses from balancer are all backends.
+ ServerName: "",
+ Metadata: a.Metadata,
+ }] = a
+ }
+ bw.mu.Lock()
+ for a := range resAddrs {
+ if _, ok := bw.conns[a]; !ok {
+ add = append(add, a)
+ }
+ }
+ for a, c := range bw.conns {
+ if _, ok := resAddrs[a]; !ok {
+ del = append(del, c)
+ delete(bw.conns, a)
+ // Keep the state of this sc in bw.connSt until its state becomes Shutdown.
+ }
+ }
+ bw.mu.Unlock()
+ for _, a := range add {
+ sc, err := bw.cc.NewSubConn([]resolver.Address{a}, balancer.NewSubConnOptions{})
+ if err != nil {
+ grpclog.Warningf("Error creating connection to %v. Err: %v", a, err)
+ } else {
+ bw.mu.Lock()
+ bw.conns[a] = sc
+ bw.connSt[sc] = &scState{
+ addr: resAddrs[a],
+ s: connectivity.Idle,
+ }
+ bw.mu.Unlock()
+ sc.Connect()
+ }
+ }
+ for _, c := range del {
+ bw.cc.RemoveSubConn(c)
+ }
+ }
+ }
+}
+
+func (bw *balancerWrapper) HandleSubConnStateChange(sc balancer.SubConn, s connectivity.State) {
+ bw.mu.Lock()
+ defer bw.mu.Unlock()
+ scSt, ok := bw.connSt[sc]
+ if !ok {
+ return
+ }
+ if s == connectivity.Idle {
+ sc.Connect()
+ }
+ oldS := scSt.s
+ scSt.s = s
+ if oldS != connectivity.Ready && s == connectivity.Ready {
+ scSt.down = bw.balancer.Up(scSt.addr)
+ } else if oldS == connectivity.Ready && s != connectivity.Ready {
+ if scSt.down != nil {
+ scSt.down(errConnClosing)
+ }
+ }
+ sa := bw.csEvltr.RecordTransition(oldS, s)
+ if bw.state != sa {
+ bw.state = sa
+ }
+ bw.cc.UpdateBalancerState(bw.state, bw)
+ if s == connectivity.Shutdown {
+ // Remove state for this sc.
+ delete(bw.connSt, sc)
+ }
+}
+
+func (bw *balancerWrapper) HandleResolvedAddrs([]resolver.Address, error) {
+ bw.mu.Lock()
+ defer bw.mu.Unlock()
+ select {
+ case <-bw.startCh:
+ default:
+ close(bw.startCh)
+ }
+ // There should be a resolver inside the balancer.
+ // All updates here, if any, are ignored.
+}
+
+func (bw *balancerWrapper) Close() {
+ bw.mu.Lock()
+ defer bw.mu.Unlock()
+ select {
+ case <-bw.startCh:
+ default:
+ close(bw.startCh)
+ }
+ bw.balancer.Close()
+}
+
+// The picker is the balancerWrapper itself.
+// Pick should never return ErrNoSubConnAvailable.
+// It either blocks or returns error, consistent with v1 balancer Get().
+func (bw *balancerWrapper) Pick(ctx context.Context, opts balancer.PickOptions) (balancer.SubConn, func(balancer.DoneInfo), error) {
+ failfast := true // Default failfast is true.
+ if ss, ok := rpcInfoFromContext(ctx); ok {
+ failfast = ss.failfast
+ }
+ a, p, err := bw.balancer.Get(ctx, BalancerGetOptions{BlockingWait: !failfast})
+ if err != nil {
+ return nil, nil, err
+ }
+ var done func(balancer.DoneInfo)
+ if p != nil {
+ done = func(i balancer.DoneInfo) { p() }
+ }
+ var sc balancer.SubConn
+ bw.mu.Lock()
+ defer bw.mu.Unlock()
+ if bw.pickfirst {
+ // Get the first sc in conns.
+ for _, sc = range bw.conns {
+ break
+ }
+ } else {
+ var ok bool
+ sc, ok = bw.conns[resolver.Address{
+ Addr: a.Addr,
+ Type: resolver.Backend,
+ ServerName: "",
+ Metadata: a.Metadata,
+ }]
+ if !ok && failfast {
+ return nil, nil, status.Errorf(codes.Unavailable, "there is no connection available")
+ }
+ if s, ok := bw.connSt[sc]; failfast && (!ok || s.s != connectivity.Ready) {
+ // If the returned sc is not ready and RPC is failfast,
+ // return error, and this RPC will fail.
+ return nil, nil, status.Errorf(codes.Unavailable, "there is no connection available")
+ }
+ }
+
+ return sc, done, nil
+}
diff --git a/vendor/google.golang.org/grpc/binarylog/grpc_binarylog_v1/binarylog.pb.go b/vendor/google.golang.org/grpc/binarylog/grpc_binarylog_v1/binarylog.pb.go
new file mode 100644
index 000000000..f393bb661
--- /dev/null
+++ b/vendor/google.golang.org/grpc/binarylog/grpc_binarylog_v1/binarylog.pb.go
@@ -0,0 +1,900 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// source: grpc/binarylog/grpc_binarylog_v1/binarylog.proto
+
+package grpc_binarylog_v1 // import "google.golang.org/grpc/binarylog/grpc_binarylog_v1"
+
+import proto "github.com/golang/protobuf/proto"
+import fmt "fmt"
+import math "math"
+import duration "github.com/golang/protobuf/ptypes/duration"
+import timestamp "github.com/golang/protobuf/ptypes/timestamp"
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
+
+// Enumerates the type of event
+// Note the terminology is different from the RPC semantics
+// definition, but the same meaning is expressed here.
+type GrpcLogEntry_EventType int32
+
+const (
+ GrpcLogEntry_EVENT_TYPE_UNKNOWN GrpcLogEntry_EventType = 0
+ // Header sent from client to server
+ GrpcLogEntry_EVENT_TYPE_CLIENT_HEADER GrpcLogEntry_EventType = 1
+ // Header sent from server to client
+ GrpcLogEntry_EVENT_TYPE_SERVER_HEADER GrpcLogEntry_EventType = 2
+ // Message sent from client to server
+ GrpcLogEntry_EVENT_TYPE_CLIENT_MESSAGE GrpcLogEntry_EventType = 3
+ // Message sent from server to client
+ GrpcLogEntry_EVENT_TYPE_SERVER_MESSAGE GrpcLogEntry_EventType = 4
+ // A signal that client is done sending
+ GrpcLogEntry_EVENT_TYPE_CLIENT_HALF_CLOSE GrpcLogEntry_EventType = 5
+ // Trailer indicates the end of the RPC.
+ // On client side, this event means a trailer was either received
+ // from the network or the gRPC library locally generated a status
+ // to inform the application about a failure.
+ // On server side, this event means the server application requested
+ // to send a trailer. Note: EVENT_TYPE_CANCEL may still arrive after
+ // this due to races on server side.
+ GrpcLogEntry_EVENT_TYPE_SERVER_TRAILER GrpcLogEntry_EventType = 6
+ // A signal that the RPC is cancelled. On client side, this
+ // indicates the client application requests a cancellation.
+ // On server side, this indicates that cancellation was detected.
+ // Note: This marks the end of the RPC. Events may arrive after
+ // this due to races. For example, on client side a trailer
+ // may arrive even though the application requested to cancel the RPC.
+ GrpcLogEntry_EVENT_TYPE_CANCEL GrpcLogEntry_EventType = 7
+)
+
+var GrpcLogEntry_EventType_name = map[int32]string{
+ 0: "EVENT_TYPE_UNKNOWN",
+ 1: "EVENT_TYPE_CLIENT_HEADER",
+ 2: "EVENT_TYPE_SERVER_HEADER",
+ 3: "EVENT_TYPE_CLIENT_MESSAGE",
+ 4: "EVENT_TYPE_SERVER_MESSAGE",
+ 5: "EVENT_TYPE_CLIENT_HALF_CLOSE",
+ 6: "EVENT_TYPE_SERVER_TRAILER",
+ 7: "EVENT_TYPE_CANCEL",
+}
+var GrpcLogEntry_EventType_value = map[string]int32{
+ "EVENT_TYPE_UNKNOWN": 0,
+ "EVENT_TYPE_CLIENT_HEADER": 1,
+ "EVENT_TYPE_SERVER_HEADER": 2,
+ "EVENT_TYPE_CLIENT_MESSAGE": 3,
+ "EVENT_TYPE_SERVER_MESSAGE": 4,
+ "EVENT_TYPE_CLIENT_HALF_CLOSE": 5,
+ "EVENT_TYPE_SERVER_TRAILER": 6,
+ "EVENT_TYPE_CANCEL": 7,
+}
+
+func (x GrpcLogEntry_EventType) String() string {
+ return proto.EnumName(GrpcLogEntry_EventType_name, int32(x))
+}
+func (GrpcLogEntry_EventType) EnumDescriptor() ([]byte, []int) {
+ return fileDescriptor_binarylog_264c8c9c551ce911, []int{0, 0}
+}
+
+// Enumerates the entity that generates the log entry
+type GrpcLogEntry_Logger int32
+
+const (
+ GrpcLogEntry_LOGGER_UNKNOWN GrpcLogEntry_Logger = 0
+ GrpcLogEntry_LOGGER_CLIENT GrpcLogEntry_Logger = 1
+ GrpcLogEntry_LOGGER_SERVER GrpcLogEntry_Logger = 2
+)
+
+var GrpcLogEntry_Logger_name = map[int32]string{
+ 0: "LOGGER_UNKNOWN",
+ 1: "LOGGER_CLIENT",
+ 2: "LOGGER_SERVER",
+}
+var GrpcLogEntry_Logger_value = map[string]int32{
+ "LOGGER_UNKNOWN": 0,
+ "LOGGER_CLIENT": 1,
+ "LOGGER_SERVER": 2,
+}
+
+func (x GrpcLogEntry_Logger) String() string {
+ return proto.EnumName(GrpcLogEntry_Logger_name, int32(x))
+}
+func (GrpcLogEntry_Logger) EnumDescriptor() ([]byte, []int) {
+ return fileDescriptor_binarylog_264c8c9c551ce911, []int{0, 1}
+}
+
+type Address_Type int32
+
+const (
+ Address_TYPE_UNKNOWN Address_Type = 0
+ // address is in 1.2.3.4 form
+ Address_TYPE_IPV4 Address_Type = 1
+ // address is in IPv6 canonical form (RFC5952 section 4)
+ // The scope is NOT included in the address string.
+ Address_TYPE_IPV6 Address_Type = 2
+ // address is UDS string
+ Address_TYPE_UNIX Address_Type = 3
+)
+
+var Address_Type_name = map[int32]string{
+ 0: "TYPE_UNKNOWN",
+ 1: "TYPE_IPV4",
+ 2: "TYPE_IPV6",
+ 3: "TYPE_UNIX",
+}
+var Address_Type_value = map[string]int32{
+ "TYPE_UNKNOWN": 0,
+ "TYPE_IPV4": 1,
+ "TYPE_IPV6": 2,
+ "TYPE_UNIX": 3,
+}
+
+func (x Address_Type) String() string {
+ return proto.EnumName(Address_Type_name, int32(x))
+}
+func (Address_Type) EnumDescriptor() ([]byte, []int) {
+ return fileDescriptor_binarylog_264c8c9c551ce911, []int{7, 0}
+}
+
+// Log entry we store in binary logs
+type GrpcLogEntry struct {
+ // The timestamp of the binary log message
+ Timestamp *timestamp.Timestamp `protobuf:"bytes,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
+ // Uniquely identifies a call. The value must not be 0 in order to disambiguate
+ // from an unset value.
+ // Each call may have several log entries, they will all have the same call_id.
+ // Nothing is guaranteed about their value other than they are unique across
+ // different RPCs in the same gRPC process.
+ CallId uint64 `protobuf:"varint,2,opt,name=call_id,json=callId,proto3" json:"call_id,omitempty"`
+ // The entry sequence id for this call. The first GrpcLogEntry has a
+ // value of 1, to disambiguate from an unset value. The purpose of
+ // this field is to detect missing entries in environments where
+ // durability or ordering is not guaranteed.
+ SequenceIdWithinCall uint64 `protobuf:"varint,3,opt,name=sequence_id_within_call,json=sequenceIdWithinCall,proto3" json:"sequence_id_within_call,omitempty"`
+ Type GrpcLogEntry_EventType `protobuf:"varint,4,opt,name=type,proto3,enum=grpc.binarylog.v1.GrpcLogEntry_EventType" json:"type,omitempty"`
+ Logger GrpcLogEntry_Logger `protobuf:"varint,5,opt,name=logger,proto3,enum=grpc.binarylog.v1.GrpcLogEntry_Logger" json:"logger,omitempty"`
+ // The logger uses one of the following fields to record the payload,
+ // according to the type of the log entry.
+ //
+ // Types that are valid to be assigned to Payload:
+ // *GrpcLogEntry_ClientHeader
+ // *GrpcLogEntry_ServerHeader
+ // *GrpcLogEntry_Message
+ // *GrpcLogEntry_Trailer
+ Payload isGrpcLogEntry_Payload `protobuf_oneof:"payload"`
+ // true if payload does not represent the full message or metadata.
+ PayloadTruncated bool `protobuf:"varint,10,opt,name=payload_truncated,json=payloadTruncated,proto3" json:"payload_truncated,omitempty"`
+ // Peer address information, will only be recorded on the first
+ // incoming event. On client side, peer is logged on
+ // EVENT_TYPE_SERVER_HEADER normally or EVENT_TYPE_SERVER_TRAILER in
+ // the case of trailers-only. On server side, peer is always
+ // logged on EVENT_TYPE_CLIENT_HEADER.
+ Peer *Address `protobuf:"bytes,11,opt,name=peer,proto3" json:"peer,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *GrpcLogEntry) Reset() { *m = GrpcLogEntry{} }
+func (m *GrpcLogEntry) String() string { return proto.CompactTextString(m) }
+func (*GrpcLogEntry) ProtoMessage() {}
+func (*GrpcLogEntry) Descriptor() ([]byte, []int) {
+ return fileDescriptor_binarylog_264c8c9c551ce911, []int{0}
+}
+func (m *GrpcLogEntry) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GrpcLogEntry.Unmarshal(m, b)
+}
+func (m *GrpcLogEntry) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GrpcLogEntry.Marshal(b, m, deterministic)
+}
+func (dst *GrpcLogEntry) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GrpcLogEntry.Merge(dst, src)
+}
+func (m *GrpcLogEntry) XXX_Size() int {
+ return xxx_messageInfo_GrpcLogEntry.Size(m)
+}
+func (m *GrpcLogEntry) XXX_DiscardUnknown() {
+ xxx_messageInfo_GrpcLogEntry.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GrpcLogEntry proto.InternalMessageInfo
+
+func (m *GrpcLogEntry) GetTimestamp() *timestamp.Timestamp {
+ if m != nil {
+ return m.Timestamp
+ }
+ return nil
+}
+
+func (m *GrpcLogEntry) GetCallId() uint64 {
+ if m != nil {
+ return m.CallId
+ }
+ return 0
+}
+
+func (m *GrpcLogEntry) GetSequenceIdWithinCall() uint64 {
+ if m != nil {
+ return m.SequenceIdWithinCall
+ }
+ return 0
+}
+
+func (m *GrpcLogEntry) GetType() GrpcLogEntry_EventType {
+ if m != nil {
+ return m.Type
+ }
+ return GrpcLogEntry_EVENT_TYPE_UNKNOWN
+}
+
+func (m *GrpcLogEntry) GetLogger() GrpcLogEntry_Logger {
+ if m != nil {
+ return m.Logger
+ }
+ return GrpcLogEntry_LOGGER_UNKNOWN
+}
+
+type isGrpcLogEntry_Payload interface {
+ isGrpcLogEntry_Payload()
+}
+
+type GrpcLogEntry_ClientHeader struct {
+ ClientHeader *ClientHeader `protobuf:"bytes,6,opt,name=client_header,json=clientHeader,proto3,oneof"`
+}
+
+type GrpcLogEntry_ServerHeader struct {
+ ServerHeader *ServerHeader `protobuf:"bytes,7,opt,name=server_header,json=serverHeader,proto3,oneof"`
+}
+
+type GrpcLogEntry_Message struct {
+ Message *Message `protobuf:"bytes,8,opt,name=message,proto3,oneof"`
+}
+
+type GrpcLogEntry_Trailer struct {
+ Trailer *Trailer `protobuf:"bytes,9,opt,name=trailer,proto3,oneof"`
+}
+
+func (*GrpcLogEntry_ClientHeader) isGrpcLogEntry_Payload() {}
+
+func (*GrpcLogEntry_ServerHeader) isGrpcLogEntry_Payload() {}
+
+func (*GrpcLogEntry_Message) isGrpcLogEntry_Payload() {}
+
+func (*GrpcLogEntry_Trailer) isGrpcLogEntry_Payload() {}
+
+func (m *GrpcLogEntry) GetPayload() isGrpcLogEntry_Payload {
+ if m != nil {
+ return m.Payload
+ }
+ return nil
+}
+
+func (m *GrpcLogEntry) GetClientHeader() *ClientHeader {
+ if x, ok := m.GetPayload().(*GrpcLogEntry_ClientHeader); ok {
+ return x.ClientHeader
+ }
+ return nil
+}
+
+func (m *GrpcLogEntry) GetServerHeader() *ServerHeader {
+ if x, ok := m.GetPayload().(*GrpcLogEntry_ServerHeader); ok {
+ return x.ServerHeader
+ }
+ return nil
+}
+
+func (m *GrpcLogEntry) GetMessage() *Message {
+ if x, ok := m.GetPayload().(*GrpcLogEntry_Message); ok {
+ return x.Message
+ }
+ return nil
+}
+
+func (m *GrpcLogEntry) GetTrailer() *Trailer {
+ if x, ok := m.GetPayload().(*GrpcLogEntry_Trailer); ok {
+ return x.Trailer
+ }
+ return nil
+}
+
+func (m *GrpcLogEntry) GetPayloadTruncated() bool {
+ if m != nil {
+ return m.PayloadTruncated
+ }
+ return false
+}
+
+func (m *GrpcLogEntry) GetPeer() *Address {
+ if m != nil {
+ return m.Peer
+ }
+ return nil
+}
+
+// XXX_OneofFuncs is for the internal use of the proto package.
+func (*GrpcLogEntry) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) {
+ return _GrpcLogEntry_OneofMarshaler, _GrpcLogEntry_OneofUnmarshaler, _GrpcLogEntry_OneofSizer, []interface{}{
+ (*GrpcLogEntry_ClientHeader)(nil),
+ (*GrpcLogEntry_ServerHeader)(nil),
+ (*GrpcLogEntry_Message)(nil),
+ (*GrpcLogEntry_Trailer)(nil),
+ }
+}
+
+func _GrpcLogEntry_OneofMarshaler(msg proto.Message, b *proto.Buffer) error {
+ m := msg.(*GrpcLogEntry)
+ // payload
+ switch x := m.Payload.(type) {
+ case *GrpcLogEntry_ClientHeader:
+ b.EncodeVarint(6<<3 | proto.WireBytes)
+ if err := b.EncodeMessage(x.ClientHeader); err != nil {
+ return err
+ }
+ case *GrpcLogEntry_ServerHeader:
+ b.EncodeVarint(7<<3 | proto.WireBytes)
+ if err := b.EncodeMessage(x.ServerHeader); err != nil {
+ return err
+ }
+ case *GrpcLogEntry_Message:
+ b.EncodeVarint(8<<3 | proto.WireBytes)
+ if err := b.EncodeMessage(x.Message); err != nil {
+ return err
+ }
+ case *GrpcLogEntry_Trailer:
+ b.EncodeVarint(9<<3 | proto.WireBytes)
+ if err := b.EncodeMessage(x.Trailer); err != nil {
+ return err
+ }
+ case nil:
+ default:
+ return fmt.Errorf("GrpcLogEntry.Payload has unexpected type %T", x)
+ }
+ return nil
+}
+
+func _GrpcLogEntry_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) {
+ m := msg.(*GrpcLogEntry)
+ switch tag {
+ case 6: // payload.client_header
+ if wire != proto.WireBytes {
+ return true, proto.ErrInternalBadWireType
+ }
+ msg := new(ClientHeader)
+ err := b.DecodeMessage(msg)
+ m.Payload = &GrpcLogEntry_ClientHeader{msg}
+ return true, err
+ case 7: // payload.server_header
+ if wire != proto.WireBytes {
+ return true, proto.ErrInternalBadWireType
+ }
+ msg := new(ServerHeader)
+ err := b.DecodeMessage(msg)
+ m.Payload = &GrpcLogEntry_ServerHeader{msg}
+ return true, err
+ case 8: // payload.message
+ if wire != proto.WireBytes {
+ return true, proto.ErrInternalBadWireType
+ }
+ msg := new(Message)
+ err := b.DecodeMessage(msg)
+ m.Payload = &GrpcLogEntry_Message{msg}
+ return true, err
+ case 9: // payload.trailer
+ if wire != proto.WireBytes {
+ return true, proto.ErrInternalBadWireType
+ }
+ msg := new(Trailer)
+ err := b.DecodeMessage(msg)
+ m.Payload = &GrpcLogEntry_Trailer{msg}
+ return true, err
+ default:
+ return false, nil
+ }
+}
+
+func _GrpcLogEntry_OneofSizer(msg proto.Message) (n int) {
+ m := msg.(*GrpcLogEntry)
+ // payload
+ switch x := m.Payload.(type) {
+ case *GrpcLogEntry_ClientHeader:
+ s := proto.Size(x.ClientHeader)
+ n += 1 // tag and wire
+ n += proto.SizeVarint(uint64(s))
+ n += s
+ case *GrpcLogEntry_ServerHeader:
+ s := proto.Size(x.ServerHeader)
+ n += 1 // tag and wire
+ n += proto.SizeVarint(uint64(s))
+ n += s
+ case *GrpcLogEntry_Message:
+ s := proto.Size(x.Message)
+ n += 1 // tag and wire
+ n += proto.SizeVarint(uint64(s))
+ n += s
+ case *GrpcLogEntry_Trailer:
+ s := proto.Size(x.Trailer)
+ n += 1 // tag and wire
+ n += proto.SizeVarint(uint64(s))
+ n += s
+ case nil:
+ default:
+ panic(fmt.Sprintf("proto: unexpected type %T in oneof", x))
+ }
+ return n
+}
+
+type ClientHeader struct {
+ // This contains only the metadata from the application.
+ Metadata *Metadata `protobuf:"bytes,1,opt,name=metadata,proto3" json:"metadata,omitempty"`
+ // The name of the RPC method, which looks something like:
+ // /<service>/<method>
+ // Note the leading "/" character.
+ MethodName string `protobuf:"bytes,2,opt,name=method_name,json=methodName,proto3" json:"method_name,omitempty"`
+ // A single process may be used to run multiple virtual
+ // servers with different identities.
+ // The authority is the name of such a server identitiy.
+ // It is typically a portion of the URI in the form of
+ // <host> or <host>:<port> .
+ Authority string `protobuf:"bytes,3,opt,name=authority,proto3" json:"authority,omitempty"`
+ // the RPC timeout
+ Timeout *duration.Duration `protobuf:"bytes,4,opt,name=timeout,proto3" json:"timeout,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *ClientHeader) Reset() { *m = ClientHeader{} }
+func (m *ClientHeader) String() string { return proto.CompactTextString(m) }
+func (*ClientHeader) ProtoMessage() {}
+func (*ClientHeader) Descriptor() ([]byte, []int) {
+ return fileDescriptor_binarylog_264c8c9c551ce911, []int{1}
+}
+func (m *ClientHeader) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_ClientHeader.Unmarshal(m, b)
+}
+func (m *ClientHeader) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_ClientHeader.Marshal(b, m, deterministic)
+}
+func (dst *ClientHeader) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_ClientHeader.Merge(dst, src)
+}
+func (m *ClientHeader) XXX_Size() int {
+ return xxx_messageInfo_ClientHeader.Size(m)
+}
+func (m *ClientHeader) XXX_DiscardUnknown() {
+ xxx_messageInfo_ClientHeader.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_ClientHeader proto.InternalMessageInfo
+
+func (m *ClientHeader) GetMetadata() *Metadata {
+ if m != nil {
+ return m.Metadata
+ }
+ return nil
+}
+
+func (m *ClientHeader) GetMethodName() string {
+ if m != nil {
+ return m.MethodName
+ }
+ return ""
+}
+
+func (m *ClientHeader) GetAuthority() string {
+ if m != nil {
+ return m.Authority
+ }
+ return ""
+}
+
+func (m *ClientHeader) GetTimeout() *duration.Duration {
+ if m != nil {
+ return m.Timeout
+ }
+ return nil
+}
+
+type ServerHeader struct {
+ // This contains only the metadata from the application.
+ Metadata *Metadata `protobuf:"bytes,1,opt,name=metadata,proto3" json:"metadata,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *ServerHeader) Reset() { *m = ServerHeader{} }
+func (m *ServerHeader) String() string { return proto.CompactTextString(m) }
+func (*ServerHeader) ProtoMessage() {}
+func (*ServerHeader) Descriptor() ([]byte, []int) {
+ return fileDescriptor_binarylog_264c8c9c551ce911, []int{2}
+}
+func (m *ServerHeader) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_ServerHeader.Unmarshal(m, b)
+}
+func (m *ServerHeader) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_ServerHeader.Marshal(b, m, deterministic)
+}
+func (dst *ServerHeader) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_ServerHeader.Merge(dst, src)
+}
+func (m *ServerHeader) XXX_Size() int {
+ return xxx_messageInfo_ServerHeader.Size(m)
+}
+func (m *ServerHeader) XXX_DiscardUnknown() {
+ xxx_messageInfo_ServerHeader.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_ServerHeader proto.InternalMessageInfo
+
+func (m *ServerHeader) GetMetadata() *Metadata {
+ if m != nil {
+ return m.Metadata
+ }
+ return nil
+}
+
+type Trailer struct {
+ // This contains only the metadata from the application.
+ Metadata *Metadata `protobuf:"bytes,1,opt,name=metadata,proto3" json:"metadata,omitempty"`
+ // The gRPC status code.
+ StatusCode uint32 `protobuf:"varint,2,opt,name=status_code,json=statusCode,proto3" json:"status_code,omitempty"`
+ // An original status message before any transport specific
+ // encoding.
+ StatusMessage string `protobuf:"bytes,3,opt,name=status_message,json=statusMessage,proto3" json:"status_message,omitempty"`
+ // The value of the 'grpc-status-details-bin' metadata key. If
+ // present, this is always an encoded 'google.rpc.Status' message.
+ StatusDetails []byte `protobuf:"bytes,4,opt,name=status_details,json=statusDetails,proto3" json:"status_details,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *Trailer) Reset() { *m = Trailer{} }
+func (m *Trailer) String() string { return proto.CompactTextString(m) }
+func (*Trailer) ProtoMessage() {}
+func (*Trailer) Descriptor() ([]byte, []int) {
+ return fileDescriptor_binarylog_264c8c9c551ce911, []int{3}
+}
+func (m *Trailer) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_Trailer.Unmarshal(m, b)
+}
+func (m *Trailer) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_Trailer.Marshal(b, m, deterministic)
+}
+func (dst *Trailer) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_Trailer.Merge(dst, src)
+}
+func (m *Trailer) XXX_Size() int {
+ return xxx_messageInfo_Trailer.Size(m)
+}
+func (m *Trailer) XXX_DiscardUnknown() {
+ xxx_messageInfo_Trailer.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Trailer proto.InternalMessageInfo
+
+func (m *Trailer) GetMetadata() *Metadata {
+ if m != nil {
+ return m.Metadata
+ }
+ return nil
+}
+
+func (m *Trailer) GetStatusCode() uint32 {
+ if m != nil {
+ return m.StatusCode
+ }
+ return 0
+}
+
+func (m *Trailer) GetStatusMessage() string {
+ if m != nil {
+ return m.StatusMessage
+ }
+ return ""
+}
+
+func (m *Trailer) GetStatusDetails() []byte {
+ if m != nil {
+ return m.StatusDetails
+ }
+ return nil
+}
+
+// Message payload, used by CLIENT_MESSAGE and SERVER_MESSAGE
+type Message struct {
+ // Length of the message. It may not be the same as the length of the
+ // data field, as the logging payload can be truncated or omitted.
+ Length uint32 `protobuf:"varint,1,opt,name=length,proto3" json:"length,omitempty"`
+ // May be truncated or omitted.
+ Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *Message) Reset() { *m = Message{} }
+func (m *Message) String() string { return proto.CompactTextString(m) }
+func (*Message) ProtoMessage() {}
+func (*Message) Descriptor() ([]byte, []int) {
+ return fileDescriptor_binarylog_264c8c9c551ce911, []int{4}
+}
+func (m *Message) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_Message.Unmarshal(m, b)
+}
+func (m *Message) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_Message.Marshal(b, m, deterministic)
+}
+func (dst *Message) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_Message.Merge(dst, src)
+}
+func (m *Message) XXX_Size() int {
+ return xxx_messageInfo_Message.Size(m)
+}
+func (m *Message) XXX_DiscardUnknown() {
+ xxx_messageInfo_Message.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Message proto.InternalMessageInfo
+
+func (m *Message) GetLength() uint32 {
+ if m != nil {
+ return m.Length
+ }
+ return 0
+}
+
+func (m *Message) GetData() []byte {
+ if m != nil {
+ return m.Data
+ }
+ return nil
+}
+
+// A list of metadata pairs, used in the payload of client header,
+// server header, and server trailer.
+// Implementations may omit some entries to honor the header limits
+// of GRPC_BINARY_LOG_CONFIG.
+//
+// Header keys added by gRPC are omitted. To be more specific,
+// implementations will not log the following entries, and this is
+// not to be treated as a truncation:
+// - entries handled by grpc that are not user visible, such as those
+// that begin with 'grpc-' (with exception of grpc-trace-bin)
+// or keys like 'lb-token'
+// - transport specific entries, including but not limited to:
+// ':path', ':authority', 'content-encoding', 'user-agent', 'te', etc
+// - entries added for call credentials
+//
+// Implementations must always log grpc-trace-bin if it is present.
+// Practically speaking it will only be visible on server side because
+// grpc-trace-bin is managed by low level client side mechanisms
+// inaccessible from the application level. On server side, the
+// header is just a normal metadata key.
+// The pair will not count towards the size limit.
+type Metadata struct {
+ Entry []*MetadataEntry `protobuf:"bytes,1,rep,name=entry,proto3" json:"entry,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *Metadata) Reset() { *m = Metadata{} }
+func (m *Metadata) String() string { return proto.CompactTextString(m) }
+func (*Metadata) ProtoMessage() {}
+func (*Metadata) Descriptor() ([]byte, []int) {
+ return fileDescriptor_binarylog_264c8c9c551ce911, []int{5}
+}
+func (m *Metadata) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_Metadata.Unmarshal(m, b)
+}
+func (m *Metadata) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_Metadata.Marshal(b, m, deterministic)
+}
+func (dst *Metadata) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_Metadata.Merge(dst, src)
+}
+func (m *Metadata) XXX_Size() int {
+ return xxx_messageInfo_Metadata.Size(m)
+}
+func (m *Metadata) XXX_DiscardUnknown() {
+ xxx_messageInfo_Metadata.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Metadata proto.InternalMessageInfo
+
+func (m *Metadata) GetEntry() []*MetadataEntry {
+ if m != nil {
+ return m.Entry
+ }
+ return nil
+}
+
+// A metadata key value pair
+type MetadataEntry struct {
+ Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
+ Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *MetadataEntry) Reset() { *m = MetadataEntry{} }
+func (m *MetadataEntry) String() string { return proto.CompactTextString(m) }
+func (*MetadataEntry) ProtoMessage() {}
+func (*MetadataEntry) Descriptor() ([]byte, []int) {
+ return fileDescriptor_binarylog_264c8c9c551ce911, []int{6}
+}
+func (m *MetadataEntry) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_MetadataEntry.Unmarshal(m, b)
+}
+func (m *MetadataEntry) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_MetadataEntry.Marshal(b, m, deterministic)
+}
+func (dst *MetadataEntry) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_MetadataEntry.Merge(dst, src)
+}
+func (m *MetadataEntry) XXX_Size() int {
+ return xxx_messageInfo_MetadataEntry.Size(m)
+}
+func (m *MetadataEntry) XXX_DiscardUnknown() {
+ xxx_messageInfo_MetadataEntry.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_MetadataEntry proto.InternalMessageInfo
+
+func (m *MetadataEntry) GetKey() string {
+ if m != nil {
+ return m.Key
+ }
+ return ""
+}
+
+func (m *MetadataEntry) GetValue() []byte {
+ if m != nil {
+ return m.Value
+ }
+ return nil
+}
+
+// Address information
+type Address struct {
+ Type Address_Type `protobuf:"varint,1,opt,name=type,proto3,enum=grpc.binarylog.v1.Address_Type" json:"type,omitempty"`
+ Address string `protobuf:"bytes,2,opt,name=address,proto3" json:"address,omitempty"`
+ // only for TYPE_IPV4 and TYPE_IPV6
+ IpPort uint32 `protobuf:"varint,3,opt,name=ip_port,json=ipPort,proto3" json:"ip_port,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *Address) Reset() { *m = Address{} }
+func (m *Address) String() string { return proto.CompactTextString(m) }
+func (*Address) ProtoMessage() {}
+func (*Address) Descriptor() ([]byte, []int) {
+ return fileDescriptor_binarylog_264c8c9c551ce911, []int{7}
+}
+func (m *Address) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_Address.Unmarshal(m, b)
+}
+func (m *Address) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_Address.Marshal(b, m, deterministic)
+}
+func (dst *Address) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_Address.Merge(dst, src)
+}
+func (m *Address) XXX_Size() int {
+ return xxx_messageInfo_Address.Size(m)
+}
+func (m *Address) XXX_DiscardUnknown() {
+ xxx_messageInfo_Address.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Address proto.InternalMessageInfo
+
+func (m *Address) GetType() Address_Type {
+ if m != nil {
+ return m.Type
+ }
+ return Address_TYPE_UNKNOWN
+}
+
+func (m *Address) GetAddress() string {
+ if m != nil {
+ return m.Address
+ }
+ return ""
+}
+
+func (m *Address) GetIpPort() uint32 {
+ if m != nil {
+ return m.IpPort
+ }
+ return 0
+}
+
+func init() {
+ proto.RegisterType((*GrpcLogEntry)(nil), "grpc.binarylog.v1.GrpcLogEntry")
+ proto.RegisterType((*ClientHeader)(nil), "grpc.binarylog.v1.ClientHeader")
+ proto.RegisterType((*ServerHeader)(nil), "grpc.binarylog.v1.ServerHeader")
+ proto.RegisterType((*Trailer)(nil), "grpc.binarylog.v1.Trailer")
+ proto.RegisterType((*Message)(nil), "grpc.binarylog.v1.Message")
+ proto.RegisterType((*Metadata)(nil), "grpc.binarylog.v1.Metadata")
+ proto.RegisterType((*MetadataEntry)(nil), "grpc.binarylog.v1.MetadataEntry")
+ proto.RegisterType((*Address)(nil), "grpc.binarylog.v1.Address")
+ proto.RegisterEnum("grpc.binarylog.v1.GrpcLogEntry_EventType", GrpcLogEntry_EventType_name, GrpcLogEntry_EventType_value)
+ proto.RegisterEnum("grpc.binarylog.v1.GrpcLogEntry_Logger", GrpcLogEntry_Logger_name, GrpcLogEntry_Logger_value)
+ proto.RegisterEnum("grpc.binarylog.v1.Address_Type", Address_Type_name, Address_Type_value)
+}
+
+func init() {
+ proto.RegisterFile("grpc/binarylog/grpc_binarylog_v1/binarylog.proto", fileDescriptor_binarylog_264c8c9c551ce911)
+}
+
+var fileDescriptor_binarylog_264c8c9c551ce911 = []byte{
+ // 900 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x55, 0x51, 0x6f, 0xe3, 0x44,
+ 0x10, 0x3e, 0x37, 0x69, 0xdc, 0x4c, 0x92, 0xca, 0x5d, 0x95, 0x3b, 0x5f, 0x29, 0x34, 0xb2, 0x04,
+ 0x0a, 0x42, 0x72, 0xb9, 0x94, 0xeb, 0xf1, 0x02, 0x52, 0x92, 0xfa, 0xd2, 0x88, 0x5c, 0x1a, 0x6d,
+ 0x72, 0x3d, 0x40, 0x48, 0xd6, 0x36, 0x5e, 0x1c, 0x0b, 0xc7, 0x6b, 0xd6, 0x9b, 0xa0, 0xfc, 0x2c,
+ 0xde, 0x90, 0xee, 0x77, 0xf1, 0x8e, 0xbc, 0x6b, 0x27, 0xa6, 0x69, 0x0f, 0x09, 0xde, 0x3c, 0xdf,
+ 0x7c, 0xf3, 0xcd, 0xee, 0x78, 0x66, 0x16, 0xbe, 0xf2, 0x79, 0x3c, 0x3b, 0xbf, 0x0b, 0x22, 0xc2,
+ 0xd7, 0x21, 0xf3, 0xcf, 0x53, 0xd3, 0xdd, 0x98, 0xee, 0xea, 0xc5, 0xd6, 0x67, 0xc7, 0x9c, 0x09,
+ 0x86, 0x8e, 0x52, 0x8a, 0xbd, 0x45, 0x57, 0x2f, 0x4e, 0x3e, 0xf5, 0x19, 0xf3, 0x43, 0x7a, 0x2e,
+ 0x09, 0x77, 0xcb, 0x5f, 0xce, 0xbd, 0x25, 0x27, 0x22, 0x60, 0x91, 0x0a, 0x39, 0x39, 0xbb, 0xef,
+ 0x17, 0xc1, 0x82, 0x26, 0x82, 0x2c, 0x62, 0x45, 0xb0, 0xde, 0xeb, 0x50, 0xef, 0xf3, 0x78, 0x36,
+ 0x64, 0xbe, 0x13, 0x09, 0xbe, 0x46, 0xdf, 0x40, 0x75, 0xc3, 0x31, 0xb5, 0xa6, 0xd6, 0xaa, 0xb5,
+ 0x4f, 0x6c, 0xa5, 0x62, 0xe7, 0x2a, 0xf6, 0x34, 0x67, 0xe0, 0x2d, 0x19, 0x3d, 0x03, 0x7d, 0x46,
+ 0xc2, 0xd0, 0x0d, 0x3c, 0x73, 0xaf, 0xa9, 0xb5, 0xca, 0xb8, 0x92, 0x9a, 0x03, 0x0f, 0xbd, 0x84,
+ 0x67, 0x09, 0xfd, 0x6d, 0x49, 0xa3, 0x19, 0x75, 0x03, 0xcf, 0xfd, 0x3d, 0x10, 0xf3, 0x20, 0x72,
+ 0x53, 0xa7, 0x59, 0x92, 0xc4, 0xe3, 0xdc, 0x3d, 0xf0, 0xde, 0x49, 0x67, 0x8f, 0x84, 0x21, 0xfa,
+ 0x16, 0xca, 0x62, 0x1d, 0x53, 0xb3, 0xdc, 0xd4, 0x5a, 0x87, 0xed, 0x2f, 0xec, 0x9d, 0xdb, 0xdb,
+ 0xc5, 0x83, 0xdb, 0xce, 0x8a, 0x46, 0x62, 0xba, 0x8e, 0x29, 0x96, 0x61, 0xe8, 0x3b, 0xa8, 0x84,
+ 0xcc, 0xf7, 0x29, 0x37, 0xf7, 0xa5, 0xc0, 0xe7, 0xff, 0x26, 0x30, 0x94, 0x6c, 0x9c, 0x45, 0xa1,
+ 0xd7, 0xd0, 0x98, 0x85, 0x01, 0x8d, 0x84, 0x3b, 0xa7, 0xc4, 0xa3, 0xdc, 0xac, 0xc8, 0x62, 0x9c,
+ 0x3d, 0x20, 0xd3, 0x93, 0xbc, 0x6b, 0x49, 0xbb, 0x7e, 0x82, 0xeb, 0xb3, 0x82, 0x9d, 0xea, 0x24,
+ 0x94, 0xaf, 0x28, 0xcf, 0x75, 0xf4, 0x47, 0x75, 0x26, 0x92, 0xb7, 0xd5, 0x49, 0x0a, 0x36, 0xba,
+ 0x04, 0x7d, 0x41, 0x93, 0x84, 0xf8, 0xd4, 0x3c, 0xc8, 0x7f, 0xcb, 0x8e, 0xc2, 0x1b, 0xc5, 0xb8,
+ 0x7e, 0x82, 0x73, 0x72, 0x1a, 0x27, 0x38, 0x09, 0x42, 0xca, 0xcd, 0xea, 0xa3, 0x71, 0x53, 0xc5,
+ 0x48, 0xe3, 0x32, 0x32, 0xfa, 0x12, 0x8e, 0x62, 0xb2, 0x0e, 0x19, 0xf1, 0x5c, 0xc1, 0x97, 0xd1,
+ 0x8c, 0x08, 0xea, 0x99, 0xd0, 0xd4, 0x5a, 0x07, 0xd8, 0xc8, 0x1c, 0xd3, 0x1c, 0x47, 0x36, 0x94,
+ 0x63, 0x4a, 0xb9, 0x59, 0x7b, 0x34, 0x43, 0xc7, 0xf3, 0x38, 0x4d, 0x12, 0x2c, 0x79, 0xd6, 0x5f,
+ 0x1a, 0x54, 0x37, 0x3f, 0x0c, 0x3d, 0x05, 0xe4, 0xdc, 0x3a, 0xa3, 0xa9, 0x3b, 0xfd, 0x71, 0xec,
+ 0xb8, 0x6f, 0x47, 0xdf, 0x8f, 0x6e, 0xde, 0x8d, 0x8c, 0x27, 0xe8, 0x14, 0xcc, 0x02, 0xde, 0x1b,
+ 0x0e, 0xd2, 0xef, 0x6b, 0xa7, 0x73, 0xe5, 0x60, 0x43, 0xbb, 0xe7, 0x9d, 0x38, 0xf8, 0xd6, 0xc1,
+ 0xb9, 0x77, 0x0f, 0x7d, 0x02, 0xcf, 0x77, 0x63, 0xdf, 0x38, 0x93, 0x49, 0xa7, 0xef, 0x18, 0xa5,
+ 0x7b, 0xee, 0x2c, 0x38, 0x77, 0x97, 0x51, 0x13, 0x4e, 0x1f, 0xc8, 0xdc, 0x19, 0xbe, 0x76, 0x7b,
+ 0xc3, 0x9b, 0x89, 0x63, 0xec, 0x3f, 0x2c, 0x30, 0xc5, 0x9d, 0xc1, 0xd0, 0xc1, 0x46, 0x05, 0x7d,
+ 0x04, 0x47, 0x45, 0x81, 0xce, 0xa8, 0xe7, 0x0c, 0x0d, 0xdd, 0xea, 0x42, 0x45, 0xb5, 0x19, 0x42,
+ 0x70, 0x38, 0xbc, 0xe9, 0xf7, 0x1d, 0x5c, 0xb8, 0xef, 0x11, 0x34, 0x32, 0x4c, 0x65, 0x34, 0xb4,
+ 0x02, 0xa4, 0x52, 0x18, 0x7b, 0xdd, 0x2a, 0xe8, 0x59, 0xfd, 0xad, 0xf7, 0x1a, 0xd4, 0x8b, 0xcd,
+ 0x87, 0x5e, 0xc1, 0xc1, 0x82, 0x0a, 0xe2, 0x11, 0x41, 0xb2, 0xe1, 0xfd, 0xf8, 0xc1, 0x2e, 0x51,
+ 0x14, 0xbc, 0x21, 0xa3, 0x33, 0xa8, 0x2d, 0xa8, 0x98, 0x33, 0xcf, 0x8d, 0xc8, 0x82, 0xca, 0x01,
+ 0xae, 0x62, 0x50, 0xd0, 0x88, 0x2c, 0x28, 0x3a, 0x85, 0x2a, 0x59, 0x8a, 0x39, 0xe3, 0x81, 0x58,
+ 0xcb, 0xb1, 0xad, 0xe2, 0x2d, 0x80, 0x2e, 0x40, 0x4f, 0x17, 0x01, 0x5b, 0x0a, 0x39, 0xae, 0xb5,
+ 0xf6, 0xf3, 0x9d, 0x9d, 0x71, 0x95, 0x6d, 0x26, 0x9c, 0x33, 0xad, 0x3e, 0xd4, 0x8b, 0x1d, 0xff,
+ 0x9f, 0x0f, 0x6f, 0xfd, 0xa1, 0x81, 0x9e, 0x75, 0xf0, 0xff, 0xaa, 0x40, 0x22, 0x88, 0x58, 0x26,
+ 0xee, 0x8c, 0x79, 0xaa, 0x02, 0x0d, 0x0c, 0x0a, 0xea, 0x31, 0x8f, 0xa2, 0xcf, 0xe0, 0x30, 0x23,
+ 0xe4, 0x73, 0xa8, 0xca, 0xd0, 0x50, 0x68, 0x36, 0x7a, 0x05, 0x9a, 0x47, 0x05, 0x09, 0xc2, 0x44,
+ 0x56, 0xa4, 0x9e, 0xd3, 0xae, 0x14, 0x68, 0xbd, 0x04, 0x3d, 0x8f, 0x78, 0x0a, 0x95, 0x90, 0x46,
+ 0xbe, 0x98, 0xcb, 0x03, 0x37, 0x70, 0x66, 0x21, 0x04, 0x65, 0x79, 0x8d, 0x3d, 0x19, 0x2f, 0xbf,
+ 0xad, 0x2e, 0x1c, 0xe4, 0x67, 0x47, 0x97, 0xb0, 0x4f, 0xd3, 0xcd, 0x65, 0x6a, 0xcd, 0x52, 0xab,
+ 0xd6, 0x6e, 0x7e, 0xe0, 0x9e, 0x72, 0xc3, 0x61, 0x45, 0xb7, 0x5e, 0x41, 0xe3, 0x1f, 0x38, 0x32,
+ 0xa0, 0xf4, 0x2b, 0x5d, 0xcb, 0xec, 0x55, 0x9c, 0x7e, 0xa2, 0x63, 0xd8, 0x5f, 0x91, 0x70, 0x49,
+ 0xb3, 0xdc, 0xca, 0xb0, 0xfe, 0xd4, 0x40, 0xcf, 0xe6, 0x18, 0x5d, 0x64, 0xdb, 0x59, 0x93, 0xcb,
+ 0xf5, 0xec, 0xf1, 0x89, 0xb7, 0x0b, 0x3b, 0xd9, 0x04, 0x9d, 0x28, 0x34, 0xeb, 0xb0, 0xdc, 0x4c,
+ 0x1f, 0x8f, 0x20, 0x76, 0x63, 0xc6, 0x85, 0xac, 0x6a, 0x03, 0x57, 0x82, 0x78, 0xcc, 0xb8, 0xb0,
+ 0x1c, 0x28, 0xcb, 0x1d, 0x61, 0x40, 0xfd, 0xde, 0x76, 0x68, 0x40, 0x55, 0x22, 0x83, 0xf1, 0xed,
+ 0xd7, 0x86, 0x56, 0x34, 0x2f, 0x8d, 0xbd, 0x8d, 0xf9, 0x76, 0x34, 0xf8, 0xc1, 0x28, 0x75, 0x7f,
+ 0x86, 0xe3, 0x80, 0xed, 0x1e, 0xb2, 0x7b, 0xd8, 0x95, 0xd6, 0x90, 0xf9, 0xe3, 0xb4, 0x51, 0xc7,
+ 0xda, 0x4f, 0xed, 0xac, 0x71, 0x7d, 0x16, 0x92, 0xc8, 0xb7, 0x19, 0x57, 0x4f, 0xf3, 0x87, 0x5e,
+ 0xea, 0xbb, 0x8a, 0xec, 0xf2, 0x8b, 0xbf, 0x03, 0x00, 0x00, 0xff, 0xff, 0xe7, 0xf6, 0x4b, 0x50,
+ 0xd4, 0x07, 0x00, 0x00,
+}
diff --git a/vendor/google.golang.org/grpc/call.go b/vendor/google.golang.org/grpc/call.go
new file mode 100644
index 000000000..100f05dc7
--- /dev/null
+++ b/vendor/google.golang.org/grpc/call.go
@@ -0,0 +1,74 @@
+/*
+ *
+ * Copyright 2014 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package grpc
+
+import (
+ "context"
+)
+
+// Invoke sends the RPC request on the wire and returns after response is
+// received. This is typically called by generated code.
+//
+// All errors returned by Invoke are compatible with the status package.
+func (cc *ClientConn) Invoke(ctx context.Context, method string, args, reply interface{}, opts ...CallOption) error {
+ // allow interceptor to see all applicable call options, which means those
+ // configured as defaults from dial option as well as per-call options
+ opts = combine(cc.dopts.callOptions, opts)
+
+ if cc.dopts.unaryInt != nil {
+ return cc.dopts.unaryInt(ctx, method, args, reply, cc, invoke, opts...)
+ }
+ return invoke(ctx, method, args, reply, cc, opts...)
+}
+
+func combine(o1 []CallOption, o2 []CallOption) []CallOption {
+ // we don't use append because o1 could have extra capacity whose
+ // elements would be overwritten, which could cause inadvertent
+ // sharing (and race connditions) between concurrent calls
+ if len(o1) == 0 {
+ return o2
+ } else if len(o2) == 0 {
+ return o1
+ }
+ ret := make([]CallOption, len(o1)+len(o2))
+ copy(ret, o1)
+ copy(ret[len(o1):], o2)
+ return ret
+}
+
+// Invoke sends the RPC request on the wire and returns after response is
+// received. This is typically called by generated code.
+//
+// DEPRECATED: Use ClientConn.Invoke instead.
+func Invoke(ctx context.Context, method string, args, reply interface{}, cc *ClientConn, opts ...CallOption) error {
+ return cc.Invoke(ctx, method, args, reply, opts...)
+}
+
+var unaryStreamDesc = &StreamDesc{ServerStreams: false, ClientStreams: false}
+
+func invoke(ctx context.Context, method string, req, reply interface{}, cc *ClientConn, opts ...CallOption) error {
+ cs, err := newClientStream(ctx, unaryStreamDesc, cc, method, opts...)
+ if err != nil {
+ return err
+ }
+ if err := cs.SendMsg(req); err != nil {
+ return err
+ }
+ return cs.RecvMsg(reply)
+}
diff --git a/vendor/google.golang.org/grpc/clientconn.go b/vendor/google.golang.org/grpc/clientconn.go
new file mode 100644
index 000000000..84b6dbe3e
--- /dev/null
+++ b/vendor/google.golang.org/grpc/clientconn.go
@@ -0,0 +1,1508 @@
+/*
+ *
+ * Copyright 2014 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package grpc
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "math"
+ "net"
+ "reflect"
+ "strings"
+ "sync"
+ "sync/atomic"
+ "time"
+
+ "google.golang.org/grpc/balancer"
+ _ "google.golang.org/grpc/balancer/roundrobin" // To register roundrobin.
+ "google.golang.org/grpc/codes"
+ "google.golang.org/grpc/connectivity"
+ "google.golang.org/grpc/credentials"
+ "google.golang.org/grpc/grpclog"
+ "google.golang.org/grpc/internal"
+ "google.golang.org/grpc/internal/backoff"
+ "google.golang.org/grpc/internal/channelz"
+ "google.golang.org/grpc/internal/envconfig"
+ "google.golang.org/grpc/internal/grpcsync"
+ "google.golang.org/grpc/internal/transport"
+ "google.golang.org/grpc/keepalive"
+ "google.golang.org/grpc/metadata"
+ "google.golang.org/grpc/resolver"
+ _ "google.golang.org/grpc/resolver/dns" // To register dns resolver.
+ _ "google.golang.org/grpc/resolver/passthrough" // To register passthrough resolver.
+ "google.golang.org/grpc/status"
+)
+
+const (
+ // minimum time to give a connection to complete
+ minConnectTimeout = 20 * time.Second
+ // must match grpclbName in grpclb/grpclb.go
+ grpclbName = "grpclb"
+)
+
+var (
+ // ErrClientConnClosing indicates that the operation is illegal because
+ // the ClientConn is closing.
+ //
+ // Deprecated: this error should not be relied upon by users; use the status
+ // code of Canceled instead.
+ ErrClientConnClosing = status.Error(codes.Canceled, "grpc: the client connection is closing")
+ // errConnDrain indicates that the connection starts to be drained and does not accept any new RPCs.
+ errConnDrain = errors.New("grpc: the connection is drained")
+ // errConnClosing indicates that the connection is closing.
+ errConnClosing = errors.New("grpc: the connection is closing")
+ // errBalancerClosed indicates that the balancer is closed.
+ errBalancerClosed = errors.New("grpc: balancer is closed")
+ // We use an accessor so that minConnectTimeout can be
+ // atomically read and updated while testing.
+ getMinConnectTimeout = func() time.Duration {
+ return minConnectTimeout
+ }
+)
+
+// The following errors are returned from Dial and DialContext
+var (
+ // errNoTransportSecurity indicates that there is no transport security
+ // being set for ClientConn. Users should either set one or explicitly
+ // call WithInsecure DialOption to disable security.
+ errNoTransportSecurity = errors.New("grpc: no transport security set (use grpc.WithInsecure() explicitly or set credentials)")
+ // errTransportCredsAndBundle indicates that creds bundle is used together
+ // with other individual Transport Credentials.
+ errTransportCredsAndBundle = errors.New("grpc: credentials.Bundle may not be used with individual TransportCredentials")
+ // errTransportCredentialsMissing indicates that users want to transmit security
+ // information (e.g., oauth2 token) which requires secure connection on an insecure
+ // connection.
+ errTransportCredentialsMissing = errors.New("grpc: the credentials require transport level security (use grpc.WithTransportCredentials() to set)")
+ // errCredentialsConflict indicates that grpc.WithTransportCredentials()
+ // and grpc.WithInsecure() are both called for a connection.
+ errCredentialsConflict = errors.New("grpc: transport credentials are set for an insecure connection (grpc.WithTransportCredentials() and grpc.WithInsecure() are both called)")
+)
+
+const (
+ defaultClientMaxReceiveMessageSize = 1024 * 1024 * 4
+ defaultClientMaxSendMessageSize = math.MaxInt32
+ // http2IOBufSize specifies the buffer size for sending frames.
+ defaultWriteBufSize = 32 * 1024
+ defaultReadBufSize = 32 * 1024
+)
+
+// Dial creates a client connection to the given target.
+func Dial(target string, opts ...DialOption) (*ClientConn, error) {
+ return DialContext(context.Background(), target, opts...)
+}
+
+// DialContext creates a client connection to the given target. By default, it's
+// a non-blocking dial (the function won't wait for connections to be
+// established, and connecting happens in the background). To make it a blocking
+// dial, use WithBlock() dial option.
+//
+// In the non-blocking case, the ctx does not act against the connection. It
+// only controls the setup steps.
+//
+// In the blocking case, ctx can be used to cancel or expire the pending
+// connection. Once this function returns, the cancellation and expiration of
+// ctx will be noop. Users should call ClientConn.Close to terminate all the
+// pending operations after this function returns.
+//
+// The target name syntax is defined in
+// https://github.com/grpc/grpc/blob/master/doc/naming.md.
+// e.g. to use dns resolver, a "dns:///" prefix should be applied to the target.
+func DialContext(ctx context.Context, target string, opts ...DialOption) (conn *ClientConn, err error) {
+ cc := &ClientConn{
+ target: target,
+ csMgr: &connectivityStateManager{},
+ conns: make(map[*addrConn]struct{}),
+ dopts: defaultDialOptions(),
+ blockingpicker: newPickerWrapper(),
+ czData: new(channelzData),
+ firstResolveEvent: grpcsync.NewEvent(),
+ }
+ cc.retryThrottler.Store((*retryThrottler)(nil))
+ cc.ctx, cc.cancel = context.WithCancel(context.Background())
+
+ for _, opt := range opts {
+ opt.apply(&cc.dopts)
+ }
+
+ if channelz.IsOn() {
+ if cc.dopts.channelzParentID != 0 {
+ cc.channelzID = channelz.RegisterChannel(&channelzChannel{cc}, cc.dopts.channelzParentID, target)
+ channelz.AddTraceEvent(cc.channelzID, &channelz.TraceEventDesc{
+ Desc: "Channel Created",
+ Severity: channelz.CtINFO,
+ Parent: &channelz.TraceEventDesc{
+ Desc: fmt.Sprintf("Nested Channel(id:%d) created", cc.channelzID),
+ Severity: channelz.CtINFO,
+ },
+ })
+ } else {
+ cc.channelzID = channelz.RegisterChannel(&channelzChannel{cc}, 0, target)
+ channelz.AddTraceEvent(cc.channelzID, &channelz.TraceEventDesc{
+ Desc: "Channel Created",
+ Severity: channelz.CtINFO,
+ })
+ }
+ cc.csMgr.channelzID = cc.channelzID
+ }
+
+ if !cc.dopts.insecure {
+ if cc.dopts.copts.TransportCredentials == nil && cc.dopts.copts.CredsBundle == nil {
+ return nil, errNoTransportSecurity
+ }
+ if cc.dopts.copts.TransportCredentials != nil && cc.dopts.copts.CredsBundle != nil {
+ return nil, errTransportCredsAndBundle
+ }
+ } else {
+ if cc.dopts.copts.TransportCredentials != nil || cc.dopts.copts.CredsBundle != nil {
+ return nil, errCredentialsConflict
+ }
+ for _, cd := range cc.dopts.copts.PerRPCCredentials {
+ if cd.RequireTransportSecurity() {
+ return nil, errTransportCredentialsMissing
+ }
+ }
+ }
+
+ cc.mkp = cc.dopts.copts.KeepaliveParams
+
+ if cc.dopts.copts.Dialer == nil {
+ cc.dopts.copts.Dialer = newProxyDialer(
+ func(ctx context.Context, addr string) (net.Conn, error) {
+ network, addr := parseDialTarget(addr)
+ return (&net.Dialer{}).DialContext(ctx, network, addr)
+ },
+ )
+ }
+
+ if cc.dopts.copts.UserAgent != "" {
+ cc.dopts.copts.UserAgent += " " + grpcUA
+ } else {
+ cc.dopts.copts.UserAgent = grpcUA
+ }
+
+ if cc.dopts.timeout > 0 {
+ var cancel context.CancelFunc
+ ctx, cancel = context.WithTimeout(ctx, cc.dopts.timeout)
+ defer cancel()
+ }
+
+ defer func() {
+ select {
+ case <-ctx.Done():
+ conn, err = nil, ctx.Err()
+ default:
+ }
+
+ if err != nil {
+ cc.Close()
+ }
+ }()
+
+ scSet := false
+ if cc.dopts.scChan != nil {
+ // Try to get an initial service config.
+ select {
+ case sc, ok := <-cc.dopts.scChan:
+ if ok {
+ cc.sc = sc
+ scSet = true
+ }
+ default:
+ }
+ }
+ if cc.dopts.bs == nil {
+ cc.dopts.bs = backoff.Exponential{
+ MaxDelay: DefaultBackoffConfig.MaxDelay,
+ }
+ }
+ if cc.dopts.resolverBuilder == nil {
+ // Only try to parse target when resolver builder is not already set.
+ cc.parsedTarget = parseTarget(cc.target)
+ grpclog.Infof("parsed scheme: %q", cc.parsedTarget.Scheme)
+ cc.dopts.resolverBuilder = resolver.Get(cc.parsedTarget.Scheme)
+ if cc.dopts.resolverBuilder == nil {
+ // If resolver builder is still nil, the parse target's scheme is
+ // not registered. Fallback to default resolver and set Endpoint to
+ // the original unparsed target.
+ grpclog.Infof("scheme %q not registered, fallback to default scheme", cc.parsedTarget.Scheme)
+ cc.parsedTarget = resolver.Target{
+ Scheme: resolver.GetDefaultScheme(),
+ Endpoint: target,
+ }
+ cc.dopts.resolverBuilder = resolver.Get(cc.parsedTarget.Scheme)
+ }
+ } else {
+ cc.parsedTarget = resolver.Target{Endpoint: target}
+ }
+ creds := cc.dopts.copts.TransportCredentials
+ if creds != nil && creds.Info().ServerName != "" {
+ cc.authority = creds.Info().ServerName
+ } else if cc.dopts.insecure && cc.dopts.authority != "" {
+ cc.authority = cc.dopts.authority
+ } else {
+ // Use endpoint from "scheme://authority/endpoint" as the default
+ // authority for ClientConn.
+ cc.authority = cc.parsedTarget.Endpoint
+ }
+
+ if cc.dopts.scChan != nil && !scSet {
+ // Blocking wait for the initial service config.
+ select {
+ case sc, ok := <-cc.dopts.scChan:
+ if ok {
+ cc.sc = sc
+ }
+ case <-ctx.Done():
+ return nil, ctx.Err()
+ }
+ }
+ if cc.dopts.scChan != nil {
+ go cc.scWatcher()
+ }
+
+ var credsClone credentials.TransportCredentials
+ if creds := cc.dopts.copts.TransportCredentials; creds != nil {
+ credsClone = creds.Clone()
+ }
+ cc.balancerBuildOpts = balancer.BuildOptions{
+ DialCreds: credsClone,
+ CredsBundle: cc.dopts.copts.CredsBundle,
+ Dialer: cc.dopts.copts.Dialer,
+ ChannelzParentID: cc.channelzID,
+ }
+
+ // Build the resolver.
+ rWrapper, err := newCCResolverWrapper(cc)
+ if err != nil {
+ return nil, fmt.Errorf("failed to build resolver: %v", err)
+ }
+
+ cc.mu.Lock()
+ cc.resolverWrapper = rWrapper
+ cc.mu.Unlock()
+ // A blocking dial blocks until the clientConn is ready.
+ if cc.dopts.block {
+ for {
+ s := cc.GetState()
+ if s == connectivity.Ready {
+ break
+ } else if cc.dopts.copts.FailOnNonTempDialError && s == connectivity.TransientFailure {
+ if err = cc.blockingpicker.connectionError(); err != nil {
+ terr, ok := err.(interface {
+ Temporary() bool
+ })
+ if ok && !terr.Temporary() {
+ return nil, err
+ }
+ }
+ }
+ if !cc.WaitForStateChange(ctx, s) {
+ // ctx got timeout or canceled.
+ return nil, ctx.Err()
+ }
+ }
+ }
+
+ return cc, nil
+}
+
+// connectivityStateManager keeps the connectivity.State of ClientConn.
+// This struct will eventually be exported so the balancers can access it.
+type connectivityStateManager struct {
+ mu sync.Mutex
+ state connectivity.State
+ notifyChan chan struct{}
+ channelzID int64
+}
+
+// updateState updates the connectivity.State of ClientConn.
+// If there's a change it notifies goroutines waiting on state change to
+// happen.
+func (csm *connectivityStateManager) updateState(state connectivity.State) {
+ csm.mu.Lock()
+ defer csm.mu.Unlock()
+ if csm.state == connectivity.Shutdown {
+ return
+ }
+ if csm.state == state {
+ return
+ }
+ csm.state = state
+ if channelz.IsOn() {
+ channelz.AddTraceEvent(csm.channelzID, &channelz.TraceEventDesc{
+ Desc: fmt.Sprintf("Channel Connectivity change to %v", state),
+ Severity: channelz.CtINFO,
+ })
+ }
+ if csm.notifyChan != nil {
+ // There are other goroutines waiting on this channel.
+ close(csm.notifyChan)
+ csm.notifyChan = nil
+ }
+}
+
+func (csm *connectivityStateManager) getState() connectivity.State {
+ csm.mu.Lock()
+ defer csm.mu.Unlock()
+ return csm.state
+}
+
+func (csm *connectivityStateManager) getNotifyChan() <-chan struct{} {
+ csm.mu.Lock()
+ defer csm.mu.Unlock()
+ if csm.notifyChan == nil {
+ csm.notifyChan = make(chan struct{})
+ }
+ return csm.notifyChan
+}
+
+// ClientConn represents a client connection to an RPC server.
+type ClientConn struct {
+ ctx context.Context
+ cancel context.CancelFunc
+
+ target string
+ parsedTarget resolver.Target
+ authority string
+ dopts dialOptions
+ csMgr *connectivityStateManager
+
+ balancerBuildOpts balancer.BuildOptions
+ blockingpicker *pickerWrapper
+
+ mu sync.RWMutex
+ resolverWrapper *ccResolverWrapper
+ sc ServiceConfig
+ scRaw string
+ conns map[*addrConn]struct{}
+ // Keepalive parameter can be updated if a GoAway is received.
+ mkp keepalive.ClientParameters
+ curBalancerName string
+ preBalancerName string // previous balancer name.
+ curAddresses []resolver.Address
+ balancerWrapper *ccBalancerWrapper
+ retryThrottler atomic.Value
+
+ firstResolveEvent *grpcsync.Event
+
+ channelzID int64 // channelz unique identification number
+ czData *channelzData
+}
+
+// WaitForStateChange waits until the connectivity.State of ClientConn changes from sourceState or
+// ctx expires. A true value is returned in former case and false in latter.
+// This is an EXPERIMENTAL API.
+func (cc *ClientConn) WaitForStateChange(ctx context.Context, sourceState connectivity.State) bool {
+ ch := cc.csMgr.getNotifyChan()
+ if cc.csMgr.getState() != sourceState {
+ return true
+ }
+ select {
+ case <-ctx.Done():
+ return false
+ case <-ch:
+ return true
+ }
+}
+
+// GetState returns the connectivity.State of ClientConn.
+// This is an EXPERIMENTAL API.
+func (cc *ClientConn) GetState() connectivity.State {
+ return cc.csMgr.getState()
+}
+
+func (cc *ClientConn) scWatcher() {
+ for {
+ select {
+ case sc, ok := <-cc.dopts.scChan:
+ if !ok {
+ return
+ }
+ cc.mu.Lock()
+ // TODO: load balance policy runtime change is ignored.
+ // We may revist this decision in the future.
+ cc.sc = sc
+ cc.scRaw = ""
+ cc.mu.Unlock()
+ case <-cc.ctx.Done():
+ return
+ }
+ }
+}
+
+// waitForResolvedAddrs blocks until the resolver has provided addresses or the
+// context expires. Returns nil unless the context expires first; otherwise
+// returns a status error based on the context.
+func (cc *ClientConn) waitForResolvedAddrs(ctx context.Context) error {
+ // This is on the RPC path, so we use a fast path to avoid the
+ // more-expensive "select" below after the resolver has returned once.
+ if cc.firstResolveEvent.HasFired() {
+ return nil
+ }
+ select {
+ case <-cc.firstResolveEvent.Done():
+ return nil
+ case <-ctx.Done():
+ return status.FromContextError(ctx.Err()).Err()
+ case <-cc.ctx.Done():
+ return ErrClientConnClosing
+ }
+}
+
+func (cc *ClientConn) handleResolvedAddrs(addrs []resolver.Address, err error) {
+ cc.mu.Lock()
+ defer cc.mu.Unlock()
+ if cc.conns == nil {
+ // cc was closed.
+ return
+ }
+
+ if reflect.DeepEqual(cc.curAddresses, addrs) {
+ return
+ }
+
+ cc.curAddresses = addrs
+ cc.firstResolveEvent.Fire()
+
+ if cc.dopts.balancerBuilder == nil {
+ // Only look at balancer types and switch balancer if balancer dial
+ // option is not set.
+ var isGRPCLB bool
+ for _, a := range addrs {
+ if a.Type == resolver.GRPCLB {
+ isGRPCLB = true
+ break
+ }
+ }
+ var newBalancerName string
+ if isGRPCLB {
+ newBalancerName = grpclbName
+ } else {
+ // Address list doesn't contain grpclb address. Try to pick a
+ // non-grpclb balancer.
+ newBalancerName = cc.curBalancerName
+ // If current balancer is grpclb, switch to the previous one.
+ if newBalancerName == grpclbName {
+ newBalancerName = cc.preBalancerName
+ }
+ // The following could be true in two cases:
+ // - the first time handling resolved addresses
+ // (curBalancerName="")
+ // - the first time handling non-grpclb addresses
+ // (curBalancerName="grpclb", preBalancerName="")
+ if newBalancerName == "" {
+ newBalancerName = PickFirstBalancerName
+ }
+ }
+ cc.switchBalancer(newBalancerName)
+ } else if cc.balancerWrapper == nil {
+ // Balancer dial option was set, and this is the first time handling
+ // resolved addresses. Build a balancer with dopts.balancerBuilder.
+ cc.balancerWrapper = newCCBalancerWrapper(cc, cc.dopts.balancerBuilder, cc.balancerBuildOpts)
+ }
+
+ cc.balancerWrapper.handleResolvedAddrs(addrs, nil)
+}
+
+// switchBalancer starts the switching from current balancer to the balancer
+// with the given name.
+//
+// It will NOT send the current address list to the new balancer. If needed,
+// caller of this function should send address list to the new balancer after
+// this function returns.
+//
+// Caller must hold cc.mu.
+func (cc *ClientConn) switchBalancer(name string) {
+ if cc.conns == nil {
+ return
+ }
+
+ if strings.ToLower(cc.curBalancerName) == strings.ToLower(name) {
+ return
+ }
+
+ grpclog.Infof("ClientConn switching balancer to %q", name)
+ if cc.dopts.balancerBuilder != nil {
+ grpclog.Infoln("ignoring balancer switching: Balancer DialOption used instead")
+ return
+ }
+ // TODO(bar switching) change this to two steps: drain and close.
+ // Keep track of sc in wrapper.
+ if cc.balancerWrapper != nil {
+ cc.balancerWrapper.close()
+ }
+
+ builder := balancer.Get(name)
+ // TODO(yuxuanli): If user send a service config that does not contain a valid balancer name, should
+ // we reuse previous one?
+ if channelz.IsOn() {
+ if builder == nil {
+ channelz.AddTraceEvent(cc.channelzID, &channelz.TraceEventDesc{
+ Desc: fmt.Sprintf("Channel switches to new LB policy %q due to fallback from invalid balancer name", PickFirstBalancerName),
+ Severity: channelz.CtWarning,
+ })
+ } else {
+ channelz.AddTraceEvent(cc.channelzID, &channelz.TraceEventDesc{
+ Desc: fmt.Sprintf("Channel switches to new LB policy %q", name),
+ Severity: channelz.CtINFO,
+ })
+ }
+ }
+ if builder == nil {
+ grpclog.Infof("failed to get balancer builder for: %v, using pick_first instead", name)
+ builder = newPickfirstBuilder()
+ }
+
+ cc.preBalancerName = cc.curBalancerName
+ cc.curBalancerName = builder.Name()
+ cc.balancerWrapper = newCCBalancerWrapper(cc, builder, cc.balancerBuildOpts)
+}
+
+func (cc *ClientConn) handleSubConnStateChange(sc balancer.SubConn, s connectivity.State) {
+ cc.mu.Lock()
+ if cc.conns == nil {
+ cc.mu.Unlock()
+ return
+ }
+ // TODO(bar switching) send updates to all balancer wrappers when balancer
+ // gracefully switching is supported.
+ cc.balancerWrapper.handleSubConnStateChange(sc, s)
+ cc.mu.Unlock()
+}
+
+// newAddrConn creates an addrConn for addrs and adds it to cc.conns.
+//
+// Caller needs to make sure len(addrs) > 0.
+func (cc *ClientConn) newAddrConn(addrs []resolver.Address, opts balancer.NewSubConnOptions) (*addrConn, error) {
+ ac := &addrConn{
+ cc: cc,
+ addrs: addrs,
+ scopts: opts,
+ dopts: cc.dopts,
+ czData: new(channelzData),
+ successfulHandshake: true, // make the first nextAddr() call _not_ move addrIdx up by 1
+ resetBackoff: make(chan struct{}),
+ }
+ ac.ctx, ac.cancel = context.WithCancel(cc.ctx)
+ // Track ac in cc. This needs to be done before any getTransport(...) is called.
+ cc.mu.Lock()
+ if cc.conns == nil {
+ cc.mu.Unlock()
+ return nil, ErrClientConnClosing
+ }
+ if channelz.IsOn() {
+ ac.channelzID = channelz.RegisterSubChannel(ac, cc.channelzID, "")
+ channelz.AddTraceEvent(ac.channelzID, &channelz.TraceEventDesc{
+ Desc: "Subchannel Created",
+ Severity: channelz.CtINFO,
+ Parent: &channelz.TraceEventDesc{
+ Desc: fmt.Sprintf("Subchannel(id:%d) created", ac.channelzID),
+ Severity: channelz.CtINFO,
+ },
+ })
+ }
+ cc.conns[ac] = struct{}{}
+ cc.mu.Unlock()
+ return ac, nil
+}
+
+// removeAddrConn removes the addrConn in the subConn from clientConn.
+// It also tears down the ac with the given error.
+func (cc *ClientConn) removeAddrConn(ac *addrConn, err error) {
+ cc.mu.Lock()
+ if cc.conns == nil {
+ cc.mu.Unlock()
+ return
+ }
+ delete(cc.conns, ac)
+ cc.mu.Unlock()
+ ac.tearDown(err)
+}
+
+func (cc *ClientConn) channelzMetric() *channelz.ChannelInternalMetric {
+ return &channelz.ChannelInternalMetric{
+ State: cc.GetState(),
+ Target: cc.target,
+ CallsStarted: atomic.LoadInt64(&cc.czData.callsStarted),
+ CallsSucceeded: atomic.LoadInt64(&cc.czData.callsSucceeded),
+ CallsFailed: atomic.LoadInt64(&cc.czData.callsFailed),
+ LastCallStartedTimestamp: time.Unix(0, atomic.LoadInt64(&cc.czData.lastCallStartedTime)),
+ }
+}
+
+// Target returns the target string of the ClientConn.
+// This is an EXPERIMENTAL API.
+func (cc *ClientConn) Target() string {
+ return cc.target
+}
+
+func (cc *ClientConn) incrCallsStarted() {
+ atomic.AddInt64(&cc.czData.callsStarted, 1)
+ atomic.StoreInt64(&cc.czData.lastCallStartedTime, time.Now().UnixNano())
+}
+
+func (cc *ClientConn) incrCallsSucceeded() {
+ atomic.AddInt64(&cc.czData.callsSucceeded, 1)
+}
+
+func (cc *ClientConn) incrCallsFailed() {
+ atomic.AddInt64(&cc.czData.callsFailed, 1)
+}
+
+// connect starts creating a transport.
+// It does nothing if the ac is not IDLE.
+// TODO(bar) Move this to the addrConn section.
+func (ac *addrConn) connect() error {
+ ac.mu.Lock()
+ if ac.state == connectivity.Shutdown {
+ ac.mu.Unlock()
+ return errConnClosing
+ }
+ if ac.state != connectivity.Idle {
+ ac.mu.Unlock()
+ return nil
+ }
+ ac.updateConnectivityState(connectivity.Connecting)
+ ac.cc.handleSubConnStateChange(ac.acbw, ac.state)
+ ac.mu.Unlock()
+
+ // Start a goroutine connecting to the server asynchronously.
+ go ac.resetTransport(false)
+ return nil
+}
+
+// tryUpdateAddrs tries to update ac.addrs with the new addresses list.
+//
+// It checks whether current connected address of ac is in the new addrs list.
+// - If true, it updates ac.addrs and returns true. The ac will keep using
+// the existing connection.
+// - If false, it does nothing and returns false.
+func (ac *addrConn) tryUpdateAddrs(addrs []resolver.Address) bool {
+ ac.mu.Lock()
+ defer ac.mu.Unlock()
+ grpclog.Infof("addrConn: tryUpdateAddrs curAddr: %v, addrs: %v", ac.curAddr, addrs)
+ if ac.state == connectivity.Shutdown {
+ ac.addrs = addrs
+ return true
+ }
+
+ var curAddrFound bool
+ for _, a := range addrs {
+ if reflect.DeepEqual(ac.curAddr, a) {
+ curAddrFound = true
+ break
+ }
+ }
+ grpclog.Infof("addrConn: tryUpdateAddrs curAddrFound: %v", curAddrFound)
+ if curAddrFound {
+ ac.addrs = addrs
+ ac.addrIdx = 0 // Start reconnecting from beginning in the new list.
+ }
+
+ return curAddrFound
+}
+
+// GetMethodConfig gets the method config of the input method.
+// If there's an exact match for input method (i.e. /service/method), we return
+// the corresponding MethodConfig.
+// If there isn't an exact match for the input method, we look for the default config
+// under the service (i.e /service/). If there is a default MethodConfig for
+// the service, we return it.
+// Otherwise, we return an empty MethodConfig.
+func (cc *ClientConn) GetMethodConfig(method string) MethodConfig {
+ // TODO: Avoid the locking here.
+ cc.mu.RLock()
+ defer cc.mu.RUnlock()
+ m, ok := cc.sc.Methods[method]
+ if !ok {
+ i := strings.LastIndex(method, "/")
+ m = cc.sc.Methods[method[:i+1]]
+ }
+ return m
+}
+
+func (cc *ClientConn) healthCheckConfig() *healthCheckConfig {
+ cc.mu.RLock()
+ defer cc.mu.RUnlock()
+ return cc.sc.healthCheckConfig
+}
+
+func (cc *ClientConn) getTransport(ctx context.Context, failfast bool, method string) (transport.ClientTransport, func(balancer.DoneInfo), error) {
+ hdr, _ := metadata.FromOutgoingContext(ctx)
+ t, done, err := cc.blockingpicker.pick(ctx, failfast, balancer.PickOptions{
+ FullMethodName: method,
+ Header: hdr,
+ })
+ if err != nil {
+ return nil, nil, toRPCErr(err)
+ }
+ return t, done, nil
+}
+
+// handleServiceConfig parses the service config string in JSON format to Go native
+// struct ServiceConfig, and store both the struct and the JSON string in ClientConn.
+func (cc *ClientConn) handleServiceConfig(js string) error {
+ if cc.dopts.disableServiceConfig {
+ return nil
+ }
+ if cc.scRaw == js {
+ return nil
+ }
+ if channelz.IsOn() {
+ channelz.AddTraceEvent(cc.channelzID, &channelz.TraceEventDesc{
+ // The special formatting of \"%s\" instead of %q is to provide nice printing of service config
+ // for human consumption.
+ Desc: fmt.Sprintf("Channel has a new service config \"%s\"", js),
+ Severity: channelz.CtINFO,
+ })
+ }
+ sc, err := parseServiceConfig(js)
+ if err != nil {
+ return err
+ }
+ cc.mu.Lock()
+ // Check if the ClientConn is already closed. Some fields (e.g.
+ // balancerWrapper) are set to nil when closing the ClientConn, and could
+ // cause nil pointer panic if we don't have this check.
+ if cc.conns == nil {
+ cc.mu.Unlock()
+ return nil
+ }
+ cc.scRaw = js
+ cc.sc = sc
+
+ if sc.retryThrottling != nil {
+ newThrottler := &retryThrottler{
+ tokens: sc.retryThrottling.MaxTokens,
+ max: sc.retryThrottling.MaxTokens,
+ thresh: sc.retryThrottling.MaxTokens / 2,
+ ratio: sc.retryThrottling.TokenRatio,
+ }
+ cc.retryThrottler.Store(newThrottler)
+ } else {
+ cc.retryThrottler.Store((*retryThrottler)(nil))
+ }
+
+ if sc.LB != nil && *sc.LB != grpclbName { // "grpclb" is not a valid balancer option in service config.
+ if cc.curBalancerName == grpclbName {
+ // If current balancer is grpclb, there's at least one grpclb
+ // balancer address in the resolved list. Don't switch the balancer,
+ // but change the previous balancer name, so if a new resolved
+ // address list doesn't contain grpclb address, balancer will be
+ // switched to *sc.LB.
+ cc.preBalancerName = *sc.LB
+ } else {
+ cc.switchBalancer(*sc.LB)
+ cc.balancerWrapper.handleResolvedAddrs(cc.curAddresses, nil)
+ }
+ }
+
+ cc.mu.Unlock()
+ return nil
+}
+
+func (cc *ClientConn) resolveNow(o resolver.ResolveNowOption) {
+ cc.mu.RLock()
+ r := cc.resolverWrapper
+ cc.mu.RUnlock()
+ if r == nil {
+ return
+ }
+ go r.resolveNow(o)
+}
+
+// ResetConnectBackoff wakes up all subchannels in transient failure and causes
+// them to attempt another connection immediately. It also resets the backoff
+// times used for subsequent attempts regardless of the current state.
+//
+// In general, this function should not be used. Typical service or network
+// outages result in a reasonable client reconnection strategy by default.
+// However, if a previously unavailable network becomes available, this may be
+// used to trigger an immediate reconnect.
+//
+// This API is EXPERIMENTAL.
+func (cc *ClientConn) ResetConnectBackoff() {
+ cc.mu.Lock()
+ defer cc.mu.Unlock()
+ for ac := range cc.conns {
+ ac.resetConnectBackoff()
+ }
+}
+
+// Close tears down the ClientConn and all underlying connections.
+func (cc *ClientConn) Close() error {
+ defer cc.cancel()
+
+ cc.mu.Lock()
+ if cc.conns == nil {
+ cc.mu.Unlock()
+ return ErrClientConnClosing
+ }
+ conns := cc.conns
+ cc.conns = nil
+ cc.csMgr.updateState(connectivity.Shutdown)
+
+ rWrapper := cc.resolverWrapper
+ cc.resolverWrapper = nil
+ bWrapper := cc.balancerWrapper
+ cc.balancerWrapper = nil
+ cc.mu.Unlock()
+
+ cc.blockingpicker.close()
+
+ if rWrapper != nil {
+ rWrapper.close()
+ }
+ if bWrapper != nil {
+ bWrapper.close()
+ }
+
+ for ac := range conns {
+ ac.tearDown(ErrClientConnClosing)
+ }
+ if channelz.IsOn() {
+ ted := &channelz.TraceEventDesc{
+ Desc: "Channel Deleted",
+ Severity: channelz.CtINFO,
+ }
+ if cc.dopts.channelzParentID != 0 {
+ ted.Parent = &channelz.TraceEventDesc{
+ Desc: fmt.Sprintf("Nested channel(id:%d) deleted", cc.channelzID),
+ Severity: channelz.CtINFO,
+ }
+ }
+ channelz.AddTraceEvent(cc.channelzID, ted)
+ // TraceEvent needs to be called before RemoveEntry, as TraceEvent may add trace reference to
+ // the entity beng deleted, and thus prevent it from being deleted right away.
+ channelz.RemoveEntry(cc.channelzID)
+ }
+ return nil
+}
+
+// addrConn is a network connection to a given address.
+type addrConn struct {
+ ctx context.Context
+ cancel context.CancelFunc
+
+ cc *ClientConn
+ dopts dialOptions
+ acbw balancer.SubConn
+ scopts balancer.NewSubConnOptions
+
+ // transport is set when there's a viable transport (note: ac state may not be READY as LB channel
+ // health checking may require server to report healthy to set ac to READY), and is reset
+ // to nil when the current transport should no longer be used to create a stream (e.g. after GoAway
+ // is received, transport is closed, ac has been torn down).
+ transport transport.ClientTransport // The current transport.
+
+ mu sync.Mutex
+ addrIdx int // The index in addrs list to start reconnecting from.
+ curAddr resolver.Address // The current address.
+ addrs []resolver.Address // All addresses that the resolver resolved to.
+
+ // Use updateConnectivityState for updating addrConn's connectivity state.
+ state connectivity.State
+
+ tearDownErr error // The reason this addrConn is torn down.
+
+ backoffIdx int
+ // backoffDeadline is the time until which resetTransport needs to
+ // wait before increasing backoffIdx count.
+ backoffDeadline time.Time
+ // connectDeadline is the time by which all connection
+ // negotiations must complete.
+ connectDeadline time.Time
+
+ resetBackoff chan struct{}
+
+ channelzID int64 // channelz unique identification number
+ czData *channelzData
+
+ successfulHandshake bool
+
+ healthCheckEnabled bool
+}
+
+// Note: this requires a lock on ac.mu.
+func (ac *addrConn) updateConnectivityState(s connectivity.State) {
+ ac.state = s
+ if channelz.IsOn() {
+ channelz.AddTraceEvent(ac.channelzID, &channelz.TraceEventDesc{
+ Desc: fmt.Sprintf("Subchannel Connectivity change to %v", s),
+ Severity: channelz.CtINFO,
+ })
+ }
+}
+
+// adjustParams updates parameters used to create transports upon
+// receiving a GoAway.
+func (ac *addrConn) adjustParams(r transport.GoAwayReason) {
+ switch r {
+ case transport.GoAwayTooManyPings:
+ v := 2 * ac.dopts.copts.KeepaliveParams.Time
+ ac.cc.mu.Lock()
+ if v > ac.cc.mkp.Time {
+ ac.cc.mkp.Time = v
+ }
+ ac.cc.mu.Unlock()
+ }
+}
+
+// resetTransport makes sure that a healthy ac.transport exists.
+//
+// The transport will close itself when it encounters an error, or on GOAWAY, or on deadline waiting for handshake, or
+// when the clientconn is closed. Each iteration creating a new transport will try a different address that the balancer
+// assigned to the addrConn, until it has tried all addresses. Once it has tried all addresses, it will re-resolve to
+// get a new address list. If an error is received, the list is re-resolved and the next reset attempt will try from the
+// beginning. This method has backoff built in. The backoff amount starts at 0 and increases each time resolution occurs
+// (addresses are exhausted). The backoff amount is reset to 0 each time a handshake is received.
+//
+// If the DialOption WithWaitForHandshake was set, resetTransport returns successfully only after handshake is received.
+func (ac *addrConn) resetTransport(resolveNow bool) {
+ for {
+ // If this is the first in a line of resets, we want to resolve immediately. The only other time we
+ // want to reset is if we have tried all the addresses handed to us.
+ if resolveNow {
+ ac.mu.Lock()
+ ac.cc.resolveNow(resolver.ResolveNowOption{})
+ ac.mu.Unlock()
+ }
+
+ ac.mu.Lock()
+ if ac.state == connectivity.Shutdown {
+ ac.mu.Unlock()
+ return
+ }
+
+ // The transport that was used before is no longer viable.
+ ac.transport = nil
+ // If the connection is READY, a failure must have occurred.
+ // Otherwise, we'll consider this is a transient failure when:
+ // We've exhausted all addresses
+ // We're in CONNECTING
+ // And it's not the very first addr to try TODO(deklerk) find a better way to do this than checking ac.successfulHandshake
+ if ac.state == connectivity.Ready || (ac.addrIdx == len(ac.addrs)-1 && ac.state == connectivity.Connecting && !ac.successfulHandshake) {
+ ac.updateConnectivityState(connectivity.TransientFailure)
+ ac.cc.handleSubConnStateChange(ac.acbw, ac.state)
+ }
+ ac.transport = nil
+ ac.mu.Unlock()
+
+ if err := ac.nextAddr(); err != nil {
+ return
+ }
+
+ ac.mu.Lock()
+ if ac.state == connectivity.Shutdown {
+ ac.mu.Unlock()
+ return
+ }
+
+ backoffIdx := ac.backoffIdx
+ backoffFor := ac.dopts.bs.Backoff(backoffIdx)
+
+ // This will be the duration that dial gets to finish.
+ dialDuration := getMinConnectTimeout()
+ if backoffFor > dialDuration {
+ // Give dial more time as we keep failing to connect.
+ dialDuration = backoffFor
+ }
+ start := time.Now()
+ connectDeadline := start.Add(dialDuration)
+ ac.backoffDeadline = start.Add(backoffFor)
+ ac.connectDeadline = connectDeadline
+
+ ac.mu.Unlock()
+
+ ac.cc.mu.RLock()
+ ac.dopts.copts.KeepaliveParams = ac.cc.mkp
+ ac.cc.mu.RUnlock()
+
+ ac.mu.Lock()
+
+ if ac.state == connectivity.Shutdown {
+ ac.mu.Unlock()
+ return
+ }
+
+ if ac.state != connectivity.Connecting {
+ ac.updateConnectivityState(connectivity.Connecting)
+ ac.cc.handleSubConnStateChange(ac.acbw, ac.state)
+ }
+
+ addr := ac.addrs[ac.addrIdx]
+ copts := ac.dopts.copts
+ if ac.scopts.CredsBundle != nil {
+ copts.CredsBundle = ac.scopts.CredsBundle
+ }
+ ac.mu.Unlock()
+
+ if channelz.IsOn() {
+ channelz.AddTraceEvent(ac.channelzID, &channelz.TraceEventDesc{
+ Desc: fmt.Sprintf("Subchannel picks a new address %q to connect", addr.Addr),
+ Severity: channelz.CtINFO,
+ })
+ }
+
+ if err := ac.createTransport(backoffIdx, addr, copts, connectDeadline); err != nil {
+ continue
+ }
+
+ return
+ }
+}
+
+// createTransport creates a connection to one of the backends in addrs.
+func (ac *addrConn) createTransport(backoffNum int, addr resolver.Address, copts transport.ConnectOptions, connectDeadline time.Time) error {
+ oneReset := sync.Once{}
+ skipReset := make(chan struct{})
+ allowedToReset := make(chan struct{})
+ prefaceReceived := make(chan struct{})
+ onCloseCalled := make(chan struct{})
+
+ var prefaceMu sync.Mutex
+ var serverPrefaceReceived bool
+ var clientPrefaceWrote bool
+
+ hcCtx, hcCancel := context.WithCancel(ac.ctx)
+
+ onGoAway := func(r transport.GoAwayReason) {
+ hcCancel()
+ ac.mu.Lock()
+ ac.adjustParams(r)
+ ac.mu.Unlock()
+ select {
+ case <-skipReset: // The outer resetTransport loop will handle reconnection.
+ return
+ case <-allowedToReset: // We're in the clear to reset.
+ go oneReset.Do(func() { ac.resetTransport(false) })
+ }
+ }
+
+ prefaceTimer := time.NewTimer(connectDeadline.Sub(time.Now()))
+
+ onClose := func() {
+ hcCancel()
+ close(onCloseCalled)
+ prefaceTimer.Stop()
+
+ select {
+ case <-skipReset: // The outer resetTransport loop will handle reconnection.
+ return
+ case <-allowedToReset: // We're in the clear to reset.
+ oneReset.Do(func() { ac.resetTransport(false) })
+ }
+ }
+
+ target := transport.TargetInfo{
+ Addr: addr.Addr,
+ Metadata: addr.Metadata,
+ Authority: ac.cc.authority,
+ }
+
+ onPrefaceReceipt := func() {
+ close(prefaceReceived)
+ prefaceTimer.Stop()
+
+ // TODO(deklerk): optimization; does anyone else actually use this lock? maybe we can just remove it for this scope
+ ac.mu.Lock()
+
+ prefaceMu.Lock()
+ serverPrefaceReceived = true
+ if clientPrefaceWrote {
+ ac.successfulHandshake = true
+ }
+ prefaceMu.Unlock()
+
+ ac.mu.Unlock()
+ }
+
+ connectCtx, cancel := context.WithDeadline(ac.ctx, connectDeadline)
+ defer cancel()
+ if channelz.IsOn() {
+ copts.ChannelzParentID = ac.channelzID
+ }
+
+ newTr, err := transport.NewClientTransport(connectCtx, ac.cc.ctx, target, copts, onPrefaceReceipt, onGoAway, onClose)
+
+ if err == nil {
+ prefaceMu.Lock()
+ clientPrefaceWrote = true
+ if serverPrefaceReceived || ac.dopts.reqHandshake == envconfig.RequireHandshakeOff {
+ ac.successfulHandshake = true
+ }
+ prefaceMu.Unlock()
+
+ if ac.dopts.reqHandshake == envconfig.RequireHandshakeOn {
+ select {
+ case <-prefaceTimer.C:
+ // We didn't get the preface in time.
+ newTr.Close()
+ err = errors.New("timed out waiting for server handshake")
+ case <-prefaceReceived:
+ // We got the preface - huzzah! things are good.
+ case <-onCloseCalled:
+ // The transport has already closed - noop.
+ close(allowedToReset)
+ return nil
+ }
+ } else if ac.dopts.reqHandshake == envconfig.RequireHandshakeHybrid {
+ go func() {
+ select {
+ case <-prefaceTimer.C:
+ // We didn't get the preface in time.
+ newTr.Close()
+ case <-prefaceReceived:
+ // We got the preface just in the nick of time - huzzah!
+ case <-onCloseCalled:
+ // The transport has already closed - noop.
+ }
+ }()
+ }
+ }
+
+ if err != nil {
+ // newTr is either nil, or closed.
+ ac.cc.blockingpicker.updateConnectionError(err)
+ ac.mu.Lock()
+ if ac.state == connectivity.Shutdown {
+ // ac.tearDown(...) has been invoked.
+ ac.mu.Unlock()
+
+ // We don't want to reset during this close because we prefer to kick out of this function and let the loop
+ // in resetTransport take care of reconnecting.
+ close(skipReset)
+
+ return errConnClosing
+ }
+ ac.mu.Unlock()
+ grpclog.Warningf("grpc: addrConn.createTransport failed to connect to %v. Err :%v. Reconnecting...", addr, err)
+
+ // We don't want to reset during this close because we prefer to kick out of this function and let the loop
+ // in resetTransport take care of reconnecting.
+ close(skipReset)
+
+ return err
+ }
+
+ // Now there is a viable transport to be use, so set ac.transport to reflect the new viable transport.
+ ac.mu.Lock()
+ if ac.state == connectivity.Shutdown {
+ ac.mu.Unlock()
+ close(skipReset)
+ newTr.Close()
+ return nil
+ }
+ ac.transport = newTr
+ ac.mu.Unlock()
+
+ healthCheckConfig := ac.cc.healthCheckConfig()
+ // LB channel health checking is only enabled when all the four requirements below are met:
+ // 1. it is not disabled by the user with the WithDisableHealthCheck DialOption,
+ // 2. the internal.HealthCheckFunc is set by importing the grpc/healthcheck package,
+ // 3. a service config with non-empty healthCheckConfig field is provided,
+ // 4. the current load balancer allows it.
+ if !ac.cc.dopts.disableHealthCheck && healthCheckConfig != nil && ac.scopts.HealthCheckEnabled {
+ if internal.HealthCheckFunc != nil {
+ go ac.startHealthCheck(hcCtx, newTr, addr, healthCheckConfig.ServiceName)
+ close(allowedToReset)
+ return nil
+ }
+ // TODO: add a link to the health check doc in the error message.
+ grpclog.Error("the client side LB channel health check function has not been set.")
+ }
+
+ // No LB channel health check case
+ ac.mu.Lock()
+
+ if ac.state == connectivity.Shutdown {
+ ac.mu.Unlock()
+
+ // unblock onGoAway/onClose callback.
+ close(skipReset)
+ return errConnClosing
+ }
+
+ ac.updateConnectivityState(connectivity.Ready)
+ ac.cc.handleSubConnStateChange(ac.acbw, ac.state)
+ ac.curAddr = addr
+
+ ac.mu.Unlock()
+
+ // Ok, _now_ we will finally let the transport reset if it encounters a closable error. Without this, the reader
+ // goroutine failing races with all the code in this method that sets the connection to "ready".
+ close(allowedToReset)
+ return nil
+}
+
+func (ac *addrConn) startHealthCheck(ctx context.Context, newTr transport.ClientTransport, addr resolver.Address, serviceName string) {
+ // Set up the health check helper functions
+ newStream := func() (interface{}, error) {
+ return ac.newClientStream(ctx, &StreamDesc{ServerStreams: true}, "/grpc.health.v1.Health/Watch", newTr)
+ }
+ firstReady := true
+ reportHealth := func(ok bool) {
+ ac.mu.Lock()
+ defer ac.mu.Unlock()
+ if ac.transport != newTr {
+ return
+ }
+ if ok {
+ if firstReady {
+ firstReady = false
+ ac.curAddr = addr
+ }
+ if ac.state != connectivity.Ready {
+ ac.updateConnectivityState(connectivity.Ready)
+ ac.cc.handleSubConnStateChange(ac.acbw, ac.state)
+ }
+ } else {
+ if ac.state != connectivity.TransientFailure {
+ ac.updateConnectivityState(connectivity.TransientFailure)
+ ac.cc.handleSubConnStateChange(ac.acbw, ac.state)
+ }
+ }
+ }
+
+ err := internal.HealthCheckFunc(ctx, newStream, reportHealth, serviceName)
+ if err != nil {
+ if status.Code(err) == codes.Unimplemented {
+ if channelz.IsOn() {
+ channelz.AddTraceEvent(ac.channelzID, &channelz.TraceEventDesc{
+ Desc: "Subchannel health check is unimplemented at server side, thus health check is disabled",
+ Severity: channelz.CtError,
+ })
+ }
+ grpclog.Error("Subchannel health check is unimplemented at server side, thus health check is disabled")
+ } else {
+ grpclog.Errorf("HealthCheckFunc exits with unexpected error %v", err)
+ }
+ }
+}
+
+// nextAddr increments the addrIdx if there are more addresses to try. If
+// there are no more addrs to try it will re-resolve, set addrIdx to 0, and
+// increment the backoffIdx.
+//
+// nextAddr must be called without ac.mu being held.
+func (ac *addrConn) nextAddr() error {
+ ac.mu.Lock()
+
+ // If a handshake has been observed, we want the next usage to start at
+ // index 0 immediately.
+ if ac.successfulHandshake {
+ ac.successfulHandshake = false
+ ac.backoffDeadline = time.Time{}
+ ac.connectDeadline = time.Time{}
+ ac.addrIdx = 0
+ ac.backoffIdx = 0
+ ac.mu.Unlock()
+ return nil
+ }
+
+ if ac.addrIdx < len(ac.addrs)-1 {
+ ac.addrIdx++
+ ac.mu.Unlock()
+ return nil
+ }
+
+ ac.addrIdx = 0
+ ac.backoffIdx++
+
+ if ac.state == connectivity.Shutdown {
+ ac.mu.Unlock()
+ return errConnClosing
+ }
+ ac.cc.resolveNow(resolver.ResolveNowOption{})
+ backoffDeadline := ac.backoffDeadline
+ b := ac.resetBackoff
+ ac.mu.Unlock()
+ timer := time.NewTimer(backoffDeadline.Sub(time.Now()))
+ select {
+ case <-timer.C:
+ case <-b:
+ timer.Stop()
+ case <-ac.ctx.Done():
+ timer.Stop()
+ return ac.ctx.Err()
+ }
+ return nil
+}
+
+func (ac *addrConn) resetConnectBackoff() {
+ ac.mu.Lock()
+ close(ac.resetBackoff)
+ ac.backoffIdx = 0
+ ac.resetBackoff = make(chan struct{})
+ ac.mu.Unlock()
+}
+
+// getReadyTransport returns the transport if ac's state is READY.
+// Otherwise it returns nil, false.
+// If ac's state is IDLE, it will trigger ac to connect.
+func (ac *addrConn) getReadyTransport() (transport.ClientTransport, bool) {
+ ac.mu.Lock()
+ if ac.state == connectivity.Ready && ac.transport != nil {
+ t := ac.transport
+ ac.mu.Unlock()
+ return t, true
+ }
+ var idle bool
+ if ac.state == connectivity.Idle {
+ idle = true
+ }
+ ac.mu.Unlock()
+ // Trigger idle ac to connect.
+ if idle {
+ ac.connect()
+ }
+ return nil, false
+}
+
+// tearDown starts to tear down the addrConn.
+// TODO(zhaoq): Make this synchronous to avoid unbounded memory consumption in
+// some edge cases (e.g., the caller opens and closes many addrConn's in a
+// tight loop.
+// tearDown doesn't remove ac from ac.cc.conns.
+func (ac *addrConn) tearDown(err error) {
+ ac.mu.Lock()
+ if ac.state == connectivity.Shutdown {
+ ac.mu.Unlock()
+ return
+ }
+ curTr := ac.transport
+ ac.transport = nil
+ // We have to set the state to Shutdown before anything else to prevent races
+ // between setting the state and logic that waits on context cancelation / etc.
+ ac.updateConnectivityState(connectivity.Shutdown)
+ ac.cancel()
+ ac.tearDownErr = err
+ ac.cc.handleSubConnStateChange(ac.acbw, ac.state)
+ ac.curAddr = resolver.Address{}
+ if err == errConnDrain && curTr != nil {
+ // GracefulClose(...) may be executed multiple times when
+ // i) receiving multiple GoAway frames from the server; or
+ // ii) there are concurrent name resolver/Balancer triggered
+ // address removal and GoAway.
+ // We have to unlock and re-lock here because GracefulClose => Close => onClose, which requires locking ac.mu.
+ ac.mu.Unlock()
+ curTr.GracefulClose()
+ ac.mu.Lock()
+ }
+ if channelz.IsOn() {
+ channelz.AddTraceEvent(ac.channelzID, &channelz.TraceEventDesc{
+ Desc: "Subchannel Deleted",
+ Severity: channelz.CtINFO,
+ Parent: &channelz.TraceEventDesc{
+ Desc: fmt.Sprintf("Subchanel(id:%d) deleted", ac.channelzID),
+ Severity: channelz.CtINFO,
+ },
+ })
+ // TraceEvent needs to be called before RemoveEntry, as TraceEvent may add trace reference to
+ // the entity beng deleted, and thus prevent it from being deleted right away.
+ channelz.RemoveEntry(ac.channelzID)
+ }
+ ac.mu.Unlock()
+}
+
+func (ac *addrConn) getState() connectivity.State {
+ ac.mu.Lock()
+ defer ac.mu.Unlock()
+ return ac.state
+}
+
+func (ac *addrConn) ChannelzMetric() *channelz.ChannelInternalMetric {
+ ac.mu.Lock()
+ addr := ac.curAddr.Addr
+ ac.mu.Unlock()
+ return &channelz.ChannelInternalMetric{
+ State: ac.getState(),
+ Target: addr,
+ CallsStarted: atomic.LoadInt64(&ac.czData.callsStarted),
+ CallsSucceeded: atomic.LoadInt64(&ac.czData.callsSucceeded),
+ CallsFailed: atomic.LoadInt64(&ac.czData.callsFailed),
+ LastCallStartedTimestamp: time.Unix(0, atomic.LoadInt64(&ac.czData.lastCallStartedTime)),
+ }
+}
+
+func (ac *addrConn) incrCallsStarted() {
+ atomic.AddInt64(&ac.czData.callsStarted, 1)
+ atomic.StoreInt64(&ac.czData.lastCallStartedTime, time.Now().UnixNano())
+}
+
+func (ac *addrConn) incrCallsSucceeded() {
+ atomic.AddInt64(&ac.czData.callsSucceeded, 1)
+}
+
+func (ac *addrConn) incrCallsFailed() {
+ atomic.AddInt64(&ac.czData.callsFailed, 1)
+}
+
+type retryThrottler struct {
+ max float64
+ thresh float64
+ ratio float64
+
+ mu sync.Mutex
+ tokens float64 // TODO(dfawley): replace with atomic and remove lock.
+}
+
+// throttle subtracts a retry token from the pool and returns whether a retry
+// should be throttled (disallowed) based upon the retry throttling policy in
+// the service config.
+func (rt *retryThrottler) throttle() bool {
+ if rt == nil {
+ return false
+ }
+ rt.mu.Lock()
+ defer rt.mu.Unlock()
+ rt.tokens--
+ if rt.tokens < 0 {
+ rt.tokens = 0
+ }
+ return rt.tokens <= rt.thresh
+}
+
+func (rt *retryThrottler) successfulRPC() {
+ if rt == nil {
+ return
+ }
+ rt.mu.Lock()
+ defer rt.mu.Unlock()
+ rt.tokens += rt.ratio
+ if rt.tokens > rt.max {
+ rt.tokens = rt.max
+ }
+}
+
+type channelzChannel struct {
+ cc *ClientConn
+}
+
+func (c *channelzChannel) ChannelzMetric() *channelz.ChannelInternalMetric {
+ return c.cc.channelzMetric()
+}
+
+// ErrClientConnTimeout indicates that the ClientConn cannot establish the
+// underlying connections within the specified timeout.
+//
+// Deprecated: This error is never returned by grpc and should not be
+// referenced by users.
+var ErrClientConnTimeout = errors.New("grpc: timed out when dialing")
diff --git a/vendor/google.golang.org/grpc/codec.go b/vendor/google.golang.org/grpc/codec.go
new file mode 100644
index 000000000..129776547
--- /dev/null
+++ b/vendor/google.golang.org/grpc/codec.go
@@ -0,0 +1,50 @@
+/*
+ *
+ * Copyright 2014 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package grpc
+
+import (
+ "google.golang.org/grpc/encoding"
+ _ "google.golang.org/grpc/encoding/proto" // to register the Codec for "proto"
+)
+
+// baseCodec contains the functionality of both Codec and encoding.Codec, but
+// omits the name/string, which vary between the two and are not needed for
+// anything besides the registry in the encoding package.
+type baseCodec interface {
+ Marshal(v interface{}) ([]byte, error)
+ Unmarshal(data []byte, v interface{}) error
+}
+
+var _ baseCodec = Codec(nil)
+var _ baseCodec = encoding.Codec(nil)
+
+// Codec defines the interface gRPC uses to encode and decode messages.
+// Note that implementations of this interface must be thread safe;
+// a Codec's methods can be called from concurrent goroutines.
+//
+// Deprecated: use encoding.Codec instead.
+type Codec interface {
+ // Marshal returns the wire format of v.
+ Marshal(v interface{}) ([]byte, error)
+ // Unmarshal parses the wire format into v.
+ Unmarshal(data []byte, v interface{}) error
+ // String returns the name of the Codec implementation. This is unused by
+ // gRPC.
+ String() string
+}
diff --git a/vendor/google.golang.org/grpc/codegen.sh b/vendor/google.golang.org/grpc/codegen.sh
new file mode 100755
index 000000000..4cdc6ba7c
--- /dev/null
+++ b/vendor/google.golang.org/grpc/codegen.sh
@@ -0,0 +1,17 @@
+#!/usr/bin/env bash
+
+# This script serves as an example to demonstrate how to generate the gRPC-Go
+# interface and the related messages from .proto file.
+#
+# It assumes the installation of i) Google proto buffer compiler at
+# https://github.com/google/protobuf (after v2.6.1) and ii) the Go codegen
+# plugin at https://github.com/golang/protobuf (after 2015-02-20). If you have
+# not, please install them first.
+#
+# We recommend running this script at $GOPATH/src.
+#
+# If this is not what you need, feel free to make your own scripts. Again, this
+# script is for demonstration purpose.
+#
+proto=$1
+protoc --go_out=plugins=grpc:. $proto
diff --git a/vendor/google.golang.org/grpc/codes/code_string.go b/vendor/google.golang.org/grpc/codes/code_string.go
new file mode 100644
index 000000000..0b206a578
--- /dev/null
+++ b/vendor/google.golang.org/grpc/codes/code_string.go
@@ -0,0 +1,62 @@
+/*
+ *
+ * Copyright 2017 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package codes
+
+import "strconv"
+
+func (c Code) String() string {
+ switch c {
+ case OK:
+ return "OK"
+ case Canceled:
+ return "Canceled"
+ case Unknown:
+ return "Unknown"
+ case InvalidArgument:
+ return "InvalidArgument"
+ case DeadlineExceeded:
+ return "DeadlineExceeded"
+ case NotFound:
+ return "NotFound"
+ case AlreadyExists:
+ return "AlreadyExists"
+ case PermissionDenied:
+ return "PermissionDenied"
+ case ResourceExhausted:
+ return "ResourceExhausted"
+ case FailedPrecondition:
+ return "FailedPrecondition"
+ case Aborted:
+ return "Aborted"
+ case OutOfRange:
+ return "OutOfRange"
+ case Unimplemented:
+ return "Unimplemented"
+ case Internal:
+ return "Internal"
+ case Unavailable:
+ return "Unavailable"
+ case DataLoss:
+ return "DataLoss"
+ case Unauthenticated:
+ return "Unauthenticated"
+ default:
+ return "Code(" + strconv.FormatInt(int64(c), 10) + ")"
+ }
+}
diff --git a/vendor/google.golang.org/grpc/codes/codes.go b/vendor/google.golang.org/grpc/codes/codes.go
new file mode 100644
index 000000000..d9b9d5782
--- /dev/null
+++ b/vendor/google.golang.org/grpc/codes/codes.go
@@ -0,0 +1,197 @@
+/*
+ *
+ * Copyright 2014 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// Package codes defines the canonical error codes used by gRPC. It is
+// consistent across various languages.
+package codes // import "google.golang.org/grpc/codes"
+
+import (
+ "fmt"
+ "strconv"
+)
+
+// A Code is an unsigned 32-bit error code as defined in the gRPC spec.
+type Code uint32
+
+const (
+ // OK is returned on success.
+ OK Code = 0
+
+ // Canceled indicates the operation was canceled (typically by the caller).
+ Canceled Code = 1
+
+ // Unknown error. An example of where this error may be returned is
+ // if a Status value received from another address space belongs to
+ // an error-space that is not known in this address space. Also
+ // errors raised by APIs that do not return enough error information
+ // may be converted to this error.
+ Unknown Code = 2
+
+ // InvalidArgument indicates client specified an invalid argument.
+ // Note that this differs from FailedPrecondition. It indicates arguments
+ // that are problematic regardless of the state of the system
+ // (e.g., a malformed file name).
+ InvalidArgument Code = 3
+
+ // DeadlineExceeded means operation expired before completion.
+ // For operations that change the state of the system, this error may be
+ // returned even if the operation has completed successfully. For
+ // example, a successful response from a server could have been delayed
+ // long enough for the deadline to expire.
+ DeadlineExceeded Code = 4
+
+ // NotFound means some requested entity (e.g., file or directory) was
+ // not found.
+ NotFound Code = 5
+
+ // AlreadyExists means an attempt to create an entity failed because one
+ // already exists.
+ AlreadyExists Code = 6
+
+ // PermissionDenied indicates the caller does not have permission to
+ // execute the specified operation. It must not be used for rejections
+ // caused by exhausting some resource (use ResourceExhausted
+ // instead for those errors). It must not be
+ // used if the caller cannot be identified (use Unauthenticated
+ // instead for those errors).
+ PermissionDenied Code = 7
+
+ // ResourceExhausted indicates some resource has been exhausted, perhaps
+ // a per-user quota, or perhaps the entire file system is out of space.
+ ResourceExhausted Code = 8
+
+ // FailedPrecondition indicates operation was rejected because the
+ // system is not in a state required for the operation's execution.
+ // For example, directory to be deleted may be non-empty, an rmdir
+ // operation is applied to a non-directory, etc.
+ //
+ // A litmus test that may help a service implementor in deciding
+ // between FailedPrecondition, Aborted, and Unavailable:
+ // (a) Use Unavailable if the client can retry just the failing call.
+ // (b) Use Aborted if the client should retry at a higher-level
+ // (e.g., restarting a read-modify-write sequence).
+ // (c) Use FailedPrecondition if the client should not retry until
+ // the system state has been explicitly fixed. E.g., if an "rmdir"
+ // fails because the directory is non-empty, FailedPrecondition
+ // should be returned since the client should not retry unless
+ // they have first fixed up the directory by deleting files from it.
+ // (d) Use FailedPrecondition if the client performs conditional
+ // REST Get/Update/Delete on a resource and the resource on the
+ // server does not match the condition. E.g., conflicting
+ // read-modify-write on the same resource.
+ FailedPrecondition Code = 9
+
+ // Aborted indicates the operation was aborted, typically due to a
+ // concurrency issue like sequencer check failures, transaction aborts,
+ // etc.
+ //
+ // See litmus test above for deciding between FailedPrecondition,
+ // Aborted, and Unavailable.
+ Aborted Code = 10
+
+ // OutOfRange means operation was attempted past the valid range.
+ // E.g., seeking or reading past end of file.
+ //
+ // Unlike InvalidArgument, this error indicates a problem that may
+ // be fixed if the system state changes. For example, a 32-bit file
+ // system will generate InvalidArgument if asked to read at an
+ // offset that is not in the range [0,2^32-1], but it will generate
+ // OutOfRange if asked to read from an offset past the current
+ // file size.
+ //
+ // There is a fair bit of overlap between FailedPrecondition and
+ // OutOfRange. We recommend using OutOfRange (the more specific
+ // error) when it applies so that callers who are iterating through
+ // a space can easily look for an OutOfRange error to detect when
+ // they are done.
+ OutOfRange Code = 11
+
+ // Unimplemented indicates operation is not implemented or not
+ // supported/enabled in this service.
+ Unimplemented Code = 12
+
+ // Internal errors. Means some invariants expected by underlying
+ // system has been broken. If you see one of these errors,
+ // something is very broken.
+ Internal Code = 13
+
+ // Unavailable indicates the service is currently unavailable.
+ // This is a most likely a transient condition and may be corrected
+ // by retrying with a backoff.
+ //
+ // See litmus test above for deciding between FailedPrecondition,
+ // Aborted, and Unavailable.
+ Unavailable Code = 14
+
+ // DataLoss indicates unrecoverable data loss or corruption.
+ DataLoss Code = 15
+
+ // Unauthenticated indicates the request does not have valid
+ // authentication credentials for the operation.
+ Unauthenticated Code = 16
+
+ _maxCode = 17
+)
+
+var strToCode = map[string]Code{
+ `"OK"`: OK,
+ `"CANCELLED"`:/* [sic] */ Canceled,
+ `"UNKNOWN"`: Unknown,
+ `"INVALID_ARGUMENT"`: InvalidArgument,
+ `"DEADLINE_EXCEEDED"`: DeadlineExceeded,
+ `"NOT_FOUND"`: NotFound,
+ `"ALREADY_EXISTS"`: AlreadyExists,
+ `"PERMISSION_DENIED"`: PermissionDenied,
+ `"RESOURCE_EXHAUSTED"`: ResourceExhausted,
+ `"FAILED_PRECONDITION"`: FailedPrecondition,
+ `"ABORTED"`: Aborted,
+ `"OUT_OF_RANGE"`: OutOfRange,
+ `"UNIMPLEMENTED"`: Unimplemented,
+ `"INTERNAL"`: Internal,
+ `"UNAVAILABLE"`: Unavailable,
+ `"DATA_LOSS"`: DataLoss,
+ `"UNAUTHENTICATED"`: Unauthenticated,
+}
+
+// UnmarshalJSON unmarshals b into the Code.
+func (c *Code) UnmarshalJSON(b []byte) error {
+ // From json.Unmarshaler: By convention, to approximate the behavior of
+ // Unmarshal itself, Unmarshalers implement UnmarshalJSON([]byte("null")) as
+ // a no-op.
+ if string(b) == "null" {
+ return nil
+ }
+ if c == nil {
+ return fmt.Errorf("nil receiver passed to UnmarshalJSON")
+ }
+
+ if ci, err := strconv.ParseUint(string(b), 10, 32); err == nil {
+ if ci >= _maxCode {
+ return fmt.Errorf("invalid code: %q", ci)
+ }
+
+ *c = Code(ci)
+ return nil
+ }
+
+ if jc, ok := strToCode[string(b)]; ok {
+ *c = jc
+ return nil
+ }
+ return fmt.Errorf("invalid code: %q", string(b))
+}
diff --git a/vendor/google.golang.org/grpc/connectivity/connectivity.go b/vendor/google.golang.org/grpc/connectivity/connectivity.go
new file mode 100644
index 000000000..b1d7dbc54
--- /dev/null
+++ b/vendor/google.golang.org/grpc/connectivity/connectivity.go
@@ -0,0 +1,73 @@
+/*
+ *
+ * Copyright 2017 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// Package connectivity defines connectivity semantics.
+// For details, see https://github.com/grpc/grpc/blob/master/doc/connectivity-semantics-and-api.md.
+// All APIs in this package are experimental.
+package connectivity
+
+import (
+ "context"
+
+ "google.golang.org/grpc/grpclog"
+)
+
+// State indicates the state of connectivity.
+// It can be the state of a ClientConn or SubConn.
+type State int
+
+func (s State) String() string {
+ switch s {
+ case Idle:
+ return "IDLE"
+ case Connecting:
+ return "CONNECTING"
+ case Ready:
+ return "READY"
+ case TransientFailure:
+ return "TRANSIENT_FAILURE"
+ case Shutdown:
+ return "SHUTDOWN"
+ default:
+ grpclog.Errorf("unknown connectivity state: %d", s)
+ return "Invalid-State"
+ }
+}
+
+const (
+ // Idle indicates the ClientConn is idle.
+ Idle State = iota
+ // Connecting indicates the ClienConn is connecting.
+ Connecting
+ // Ready indicates the ClientConn is ready for work.
+ Ready
+ // TransientFailure indicates the ClientConn has seen a failure but expects to recover.
+ TransientFailure
+ // Shutdown indicates the ClientConn has started shutting down.
+ Shutdown
+)
+
+// Reporter reports the connectivity states.
+type Reporter interface {
+ // CurrentState returns the current state of the reporter.
+ CurrentState() State
+ // WaitForStateChange blocks until the reporter's state is different from the given state,
+ // and returns true.
+ // It returns false if <-ctx.Done() can proceed (ctx got timeout or got canceled).
+ WaitForStateChange(context.Context, State) bool
+}
diff --git a/vendor/google.golang.org/grpc/credentials/credentials.go b/vendor/google.golang.org/grpc/credentials/credentials.go
new file mode 100644
index 000000000..a85156045
--- /dev/null
+++ b/vendor/google.golang.org/grpc/credentials/credentials.go
@@ -0,0 +1,328 @@
+/*
+ *
+ * Copyright 2014 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// Package credentials implements various credentials supported by gRPC library,
+// which encapsulate all the state needed by a client to authenticate with a
+// server and make various assertions, e.g., about the client's identity, role,
+// or whether it is authorized to make a particular call.
+package credentials // import "google.golang.org/grpc/credentials"
+
+import (
+ "context"
+ "crypto/tls"
+ "crypto/x509"
+ "errors"
+ "fmt"
+ "io/ioutil"
+ "net"
+ "strings"
+
+ "github.com/golang/protobuf/proto"
+ "google.golang.org/grpc/credentials/internal"
+)
+
+// alpnProtoStr are the specified application level protocols for gRPC.
+var alpnProtoStr = []string{"h2"}
+
+// PerRPCCredentials defines the common interface for the credentials which need to
+// attach security information to every RPC (e.g., oauth2).
+type PerRPCCredentials interface {
+ // GetRequestMetadata gets the current request metadata, refreshing
+ // tokens if required. This should be called by the transport layer on
+ // each request, and the data should be populated in headers or other
+ // context. If a status code is returned, it will be used as the status
+ // for the RPC. uri is the URI of the entry point for the request.
+ // When supported by the underlying implementation, ctx can be used for
+ // timeout and cancellation.
+ // TODO(zhaoq): Define the set of the qualified keys instead of leaving
+ // it as an arbitrary string.
+ GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error)
+ // RequireTransportSecurity indicates whether the credentials requires
+ // transport security.
+ RequireTransportSecurity() bool
+}
+
+// ProtocolInfo provides information regarding the gRPC wire protocol version,
+// security protocol, security protocol version in use, server name, etc.
+type ProtocolInfo struct {
+ // ProtocolVersion is the gRPC wire protocol version.
+ ProtocolVersion string
+ // SecurityProtocol is the security protocol in use.
+ SecurityProtocol string
+ // SecurityVersion is the security protocol version.
+ SecurityVersion string
+ // ServerName is the user-configured server name.
+ ServerName string
+}
+
+// AuthInfo defines the common interface for the auth information the users are interested in.
+type AuthInfo interface {
+ AuthType() string
+}
+
+// ErrConnDispatched indicates that rawConn has been dispatched out of gRPC
+// and the caller should not close rawConn.
+var ErrConnDispatched = errors.New("credentials: rawConn is dispatched out of gRPC")
+
+// TransportCredentials defines the common interface for all the live gRPC wire
+// protocols and supported transport security protocols (e.g., TLS, SSL).
+type TransportCredentials interface {
+ // ClientHandshake does the authentication handshake specified by the corresponding
+ // authentication protocol on rawConn for clients. It returns the authenticated
+ // connection and the corresponding auth information about the connection.
+ // Implementations must use the provided context to implement timely cancellation.
+ // gRPC will try to reconnect if the error returned is a temporary error
+ // (io.EOF, context.DeadlineExceeded or err.Temporary() == true).
+ // If the returned error is a wrapper error, implementations should make sure that
+ // the error implements Temporary() to have the correct retry behaviors.
+ //
+ // If the returned net.Conn is closed, it MUST close the net.Conn provided.
+ ClientHandshake(context.Context, string, net.Conn) (net.Conn, AuthInfo, error)
+ // ServerHandshake does the authentication handshake for servers. It returns
+ // the authenticated connection and the corresponding auth information about
+ // the connection.
+ //
+ // If the returned net.Conn is closed, it MUST close the net.Conn provided.
+ ServerHandshake(net.Conn) (net.Conn, AuthInfo, error)
+ // Info provides the ProtocolInfo of this TransportCredentials.
+ Info() ProtocolInfo
+ // Clone makes a copy of this TransportCredentials.
+ Clone() TransportCredentials
+ // OverrideServerName overrides the server name used to verify the hostname on the returned certificates from the server.
+ // gRPC internals also use it to override the virtual hosting name if it is set.
+ // It must be called before dialing. Currently, this is only used by grpclb.
+ OverrideServerName(string) error
+}
+
+// Bundle is a combination of TransportCredentials and PerRPCCredentials.
+//
+// It also contains a mode switching method, so it can be used as a combination
+// of different credential policies.
+//
+// Bundle cannot be used together with individual TransportCredentials.
+// PerRPCCredentials from Bundle will be appended to other PerRPCCredentials.
+//
+// This API is experimental.
+type Bundle interface {
+ TransportCredentials() TransportCredentials
+ PerRPCCredentials() PerRPCCredentials
+ // NewWithMode should make a copy of Bundle, and switch mode. Modifying the
+ // existing Bundle may cause races.
+ //
+ // NewWithMode returns nil if the requested mode is not supported.
+ NewWithMode(mode string) (Bundle, error)
+}
+
+// TLSInfo contains the auth information for a TLS authenticated connection.
+// It implements the AuthInfo interface.
+type TLSInfo struct {
+ State tls.ConnectionState
+}
+
+// AuthType returns the type of TLSInfo as a string.
+func (t TLSInfo) AuthType() string {
+ return "tls"
+}
+
+// GetSecurityValue returns security info requested by channelz.
+func (t TLSInfo) GetSecurityValue() ChannelzSecurityValue {
+ v := &TLSChannelzSecurityValue{
+ StandardName: cipherSuiteLookup[t.State.CipherSuite],
+ }
+ // Currently there's no way to get LocalCertificate info from tls package.
+ if len(t.State.PeerCertificates) > 0 {
+ v.RemoteCertificate = t.State.PeerCertificates[0].Raw
+ }
+ return v
+}
+
+// tlsCreds is the credentials required for authenticating a connection using TLS.
+type tlsCreds struct {
+ // TLS configuration
+ config *tls.Config
+}
+
+func (c tlsCreds) Info() ProtocolInfo {
+ return ProtocolInfo{
+ SecurityProtocol: "tls",
+ SecurityVersion: "1.2",
+ ServerName: c.config.ServerName,
+ }
+}
+
+func (c *tlsCreds) ClientHandshake(ctx context.Context, authority string, rawConn net.Conn) (_ net.Conn, _ AuthInfo, err error) {
+ // use local cfg to avoid clobbering ServerName if using multiple endpoints
+ cfg := cloneTLSConfig(c.config)
+ if cfg.ServerName == "" {
+ colonPos := strings.LastIndex(authority, ":")
+ if colonPos == -1 {
+ colonPos = len(authority)
+ }
+ cfg.ServerName = authority[:colonPos]
+ }
+ conn := tls.Client(rawConn, cfg)
+ errChannel := make(chan error, 1)
+ go func() {
+ errChannel <- conn.Handshake()
+ }()
+ select {
+ case err := <-errChannel:
+ if err != nil {
+ return nil, nil, err
+ }
+ case <-ctx.Done():
+ return nil, nil, ctx.Err()
+ }
+ return internal.WrapSyscallConn(rawConn, conn), TLSInfo{conn.ConnectionState()}, nil
+}
+
+func (c *tlsCreds) ServerHandshake(rawConn net.Conn) (net.Conn, AuthInfo, error) {
+ conn := tls.Server(rawConn, c.config)
+ if err := conn.Handshake(); err != nil {
+ return nil, nil, err
+ }
+ return internal.WrapSyscallConn(rawConn, conn), TLSInfo{conn.ConnectionState()}, nil
+}
+
+func (c *tlsCreds) Clone() TransportCredentials {
+ return NewTLS(c.config)
+}
+
+func (c *tlsCreds) OverrideServerName(serverNameOverride string) error {
+ c.config.ServerName = serverNameOverride
+ return nil
+}
+
+// NewTLS uses c to construct a TransportCredentials based on TLS.
+func NewTLS(c *tls.Config) TransportCredentials {
+ tc := &tlsCreds{cloneTLSConfig(c)}
+ tc.config.NextProtos = alpnProtoStr
+ return tc
+}
+
+// NewClientTLSFromCert constructs TLS credentials from the input certificate for client.
+// serverNameOverride is for testing only. If set to a non empty string,
+// it will override the virtual host name of authority (e.g. :authority header field) in requests.
+func NewClientTLSFromCert(cp *x509.CertPool, serverNameOverride string) TransportCredentials {
+ return NewTLS(&tls.Config{ServerName: serverNameOverride, RootCAs: cp})
+}
+
+// NewClientTLSFromFile constructs TLS credentials from the input certificate file for client.
+// serverNameOverride is for testing only. If set to a non empty string,
+// it will override the virtual host name of authority (e.g. :authority header field) in requests.
+func NewClientTLSFromFile(certFile, serverNameOverride string) (TransportCredentials, error) {
+ b, err := ioutil.ReadFile(certFile)
+ if err != nil {
+ return nil, err
+ }
+ cp := x509.NewCertPool()
+ if !cp.AppendCertsFromPEM(b) {
+ return nil, fmt.Errorf("credentials: failed to append certificates")
+ }
+ return NewTLS(&tls.Config{ServerName: serverNameOverride, RootCAs: cp}), nil
+}
+
+// NewServerTLSFromCert constructs TLS credentials from the input certificate for server.
+func NewServerTLSFromCert(cert *tls.Certificate) TransportCredentials {
+ return NewTLS(&tls.Config{Certificates: []tls.Certificate{*cert}})
+}
+
+// NewServerTLSFromFile constructs TLS credentials from the input certificate file and key
+// file for server.
+func NewServerTLSFromFile(certFile, keyFile string) (TransportCredentials, error) {
+ cert, err := tls.LoadX509KeyPair(certFile, keyFile)
+ if err != nil {
+ return nil, err
+ }
+ return NewTLS(&tls.Config{Certificates: []tls.Certificate{cert}}), nil
+}
+
+// ChannelzSecurityInfo defines the interface that security protocols should implement
+// in order to provide security info to channelz.
+type ChannelzSecurityInfo interface {
+ GetSecurityValue() ChannelzSecurityValue
+}
+
+// ChannelzSecurityValue defines the interface that GetSecurityValue() return value
+// should satisfy. This interface should only be satisfied by *TLSChannelzSecurityValue
+// and *OtherChannelzSecurityValue.
+type ChannelzSecurityValue interface {
+ isChannelzSecurityValue()
+}
+
+// TLSChannelzSecurityValue defines the struct that TLS protocol should return
+// from GetSecurityValue(), containing security info like cipher and certificate used.
+type TLSChannelzSecurityValue struct {
+ StandardName string
+ LocalCertificate []byte
+ RemoteCertificate []byte
+}
+
+func (*TLSChannelzSecurityValue) isChannelzSecurityValue() {}
+
+// OtherChannelzSecurityValue defines the struct that non-TLS protocol should return
+// from GetSecurityValue(), which contains protocol specific security info. Note
+// the Value field will be sent to users of channelz requesting channel info, and
+// thus sensitive info should better be avoided.
+type OtherChannelzSecurityValue struct {
+ Name string
+ Value proto.Message
+}
+
+func (*OtherChannelzSecurityValue) isChannelzSecurityValue() {}
+
+var cipherSuiteLookup = map[uint16]string{
+ tls.TLS_RSA_WITH_RC4_128_SHA: "TLS_RSA_WITH_RC4_128_SHA",
+ tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA: "TLS_RSA_WITH_3DES_EDE_CBC_SHA",
+ tls.TLS_RSA_WITH_AES_128_CBC_SHA: "TLS_RSA_WITH_AES_128_CBC_SHA",
+ tls.TLS_RSA_WITH_AES_256_CBC_SHA: "TLS_RSA_WITH_AES_256_CBC_SHA",
+ tls.TLS_RSA_WITH_AES_128_GCM_SHA256: "TLS_RSA_WITH_AES_128_GCM_SHA256",
+ tls.TLS_RSA_WITH_AES_256_GCM_SHA384: "TLS_RSA_WITH_AES_256_GCM_SHA384",
+ tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA: "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA",
+ tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
+ tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
+ tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA: "TLS_ECDHE_RSA_WITH_RC4_128_SHA",
+ tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",
+ tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
+ tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
+ tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
+ tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
+ tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
+ tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
+ tls.TLS_FALLBACK_SCSV: "TLS_FALLBACK_SCSV",
+ tls.TLS_RSA_WITH_AES_128_CBC_SHA256: "TLS_RSA_WITH_AES_128_CBC_SHA256",
+ tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256: "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
+ tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
+ tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305: "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305",
+ tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305: "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305",
+}
+
+// cloneTLSConfig returns a shallow clone of the exported
+// fields of cfg, ignoring the unexported sync.Once, which
+// contains a mutex and must not be copied.
+//
+// If cfg is nil, a new zero tls.Config is returned.
+//
+// TODO: inline this function if possible.
+func cloneTLSConfig(cfg *tls.Config) *tls.Config {
+ if cfg == nil {
+ return &tls.Config{}
+ }
+
+ return cfg.Clone()
+}
diff --git a/vendor/google.golang.org/grpc/credentials/internal/syscallconn.go b/vendor/google.golang.org/grpc/credentials/internal/syscallconn.go
new file mode 100644
index 000000000..2f4472bec
--- /dev/null
+++ b/vendor/google.golang.org/grpc/credentials/internal/syscallconn.go
@@ -0,0 +1,61 @@
+// +build !appengine
+
+/*
+ *
+ * Copyright 2018 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// Package internal contains credentials-internal code.
+package internal
+
+import (
+ "net"
+ "syscall"
+)
+
+type sysConn = syscall.Conn
+
+// syscallConn keeps reference of rawConn to support syscall.Conn for channelz.
+// SyscallConn() (the method in interface syscall.Conn) is explicitly
+// implemented on this type,
+//
+// Interface syscall.Conn is implemented by most net.Conn implementations (e.g.
+// TCPConn, UnixConn), but is not part of net.Conn interface. So wrapper conns
+// that embed net.Conn don't implement syscall.Conn. (Side note: tls.Conn
+// doesn't embed net.Conn, so even if syscall.Conn is part of net.Conn, it won't
+// help here).
+type syscallConn struct {
+ net.Conn
+ // sysConn is a type alias of syscall.Conn. It's necessary because the name
+ // `Conn` collides with `net.Conn`.
+ sysConn
+}
+
+// WrapSyscallConn tries to wrap rawConn and newConn into a net.Conn that
+// implements syscall.Conn. rawConn will be used to support syscall, and newConn
+// will be used for read/write.
+//
+// This function returns newConn if rawConn doesn't implement syscall.Conn.
+func WrapSyscallConn(rawConn, newConn net.Conn) net.Conn {
+ sysConn, ok := rawConn.(syscall.Conn)
+ if !ok {
+ return newConn
+ }
+ return &syscallConn{
+ Conn: newConn,
+ sysConn: sysConn,
+ }
+}
diff --git a/vendor/google.golang.org/grpc/credentials/internal/syscallconn_appengine.go b/vendor/google.golang.org/grpc/credentials/internal/syscallconn_appengine.go
new file mode 100644
index 000000000..d4346e9ea
--- /dev/null
+++ b/vendor/google.golang.org/grpc/credentials/internal/syscallconn_appengine.go
@@ -0,0 +1,30 @@
+// +build appengine
+
+/*
+ *
+ * Copyright 2018 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package internal
+
+import (
+ "net"
+)
+
+// WrapSyscallConn returns newConn on appengine.
+func WrapSyscallConn(rawConn, newConn net.Conn) net.Conn {
+ return newConn
+}
diff --git a/vendor/google.golang.org/grpc/dialoptions.go b/vendor/google.golang.org/grpc/dialoptions.go
new file mode 100644
index 000000000..fe00a254d
--- /dev/null
+++ b/vendor/google.golang.org/grpc/dialoptions.go
@@ -0,0 +1,480 @@
+/*
+ *
+ * Copyright 2018 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package grpc
+
+import (
+ "context"
+ "fmt"
+ "net"
+ "time"
+
+ "google.golang.org/grpc/balancer"
+ "google.golang.org/grpc/credentials"
+ "google.golang.org/grpc/internal"
+ "google.golang.org/grpc/internal/backoff"
+ "google.golang.org/grpc/internal/envconfig"
+ "google.golang.org/grpc/internal/transport"
+ "google.golang.org/grpc/keepalive"
+ "google.golang.org/grpc/resolver"
+ "google.golang.org/grpc/stats"
+)
+
+// dialOptions configure a Dial call. dialOptions are set by the DialOption
+// values passed to Dial.
+type dialOptions struct {
+ unaryInt UnaryClientInterceptor
+ streamInt StreamClientInterceptor
+ cp Compressor
+ dc Decompressor
+ bs backoff.Strategy
+ block bool
+ insecure bool
+ timeout time.Duration
+ scChan <-chan ServiceConfig
+ authority string
+ copts transport.ConnectOptions
+ callOptions []CallOption
+ // This is used by v1 balancer dial option WithBalancer to support v1
+ // balancer, and also by WithBalancerName dial option.
+ balancerBuilder balancer.Builder
+ // This is to support grpclb.
+ resolverBuilder resolver.Builder
+ reqHandshake envconfig.RequireHandshakeSetting
+ channelzParentID int64
+ disableServiceConfig bool
+ disableRetry bool
+ disableHealthCheck bool
+}
+
+// DialOption configures how we set up the connection.
+type DialOption interface {
+ apply(*dialOptions)
+}
+
+// EmptyDialOption does not alter the dial configuration. It can be embedded in
+// another structure to build custom dial options.
+//
+// This API is EXPERIMENTAL.
+type EmptyDialOption struct{}
+
+func (EmptyDialOption) apply(*dialOptions) {}
+
+// funcDialOption wraps a function that modifies dialOptions into an
+// implementation of the DialOption interface.
+type funcDialOption struct {
+ f func(*dialOptions)
+}
+
+func (fdo *funcDialOption) apply(do *dialOptions) {
+ fdo.f(do)
+}
+
+func newFuncDialOption(f func(*dialOptions)) *funcDialOption {
+ return &funcDialOption{
+ f: f,
+ }
+}
+
+// WithWaitForHandshake blocks until the initial settings frame is received from
+// the server before assigning RPCs to the connection.
+//
+// Deprecated: this will become the default behavior in the 1.17 release, and
+// will be removed after the 1.18 release. To override the default behavior in
+// the 1.17 release, either use this dial option or set the environment
+// variable GRPC_GO_READY_BEFORE_HANDSHAKE=on.
+func WithWaitForHandshake() DialOption {
+ return newFuncDialOption(func(o *dialOptions) {
+ o.reqHandshake = envconfig.RequireHandshakeOn
+ })
+}
+
+// WithWriteBufferSize determines how much data can be batched before doing a
+// write on the wire. The corresponding memory allocation for this buffer will
+// be twice the size to keep syscalls low. The default value for this buffer is
+// 32KB.
+//
+// Zero will disable the write buffer such that each write will be on underlying
+// connection. Note: A Send call may not directly translate to a write.
+func WithWriteBufferSize(s int) DialOption {
+ return newFuncDialOption(func(o *dialOptions) {
+ o.copts.WriteBufferSize = s
+ })
+}
+
+// WithReadBufferSize lets you set the size of read buffer, this determines how
+// much data can be read at most for each read syscall.
+//
+// The default value for this buffer is 32KB. Zero will disable read buffer for
+// a connection so data framer can access the underlying conn directly.
+func WithReadBufferSize(s int) DialOption {
+ return newFuncDialOption(func(o *dialOptions) {
+ o.copts.ReadBufferSize = s
+ })
+}
+
+// WithInitialWindowSize returns a DialOption which sets the value for initial
+// window size on a stream. The lower bound for window size is 64K and any value
+// smaller than that will be ignored.
+func WithInitialWindowSize(s int32) DialOption {
+ return newFuncDialOption(func(o *dialOptions) {
+ o.copts.InitialWindowSize = s
+ })
+}
+
+// WithInitialConnWindowSize returns a DialOption which sets the value for
+// initial window size on a connection. The lower bound for window size is 64K
+// and any value smaller than that will be ignored.
+func WithInitialConnWindowSize(s int32) DialOption {
+ return newFuncDialOption(func(o *dialOptions) {
+ o.copts.InitialConnWindowSize = s
+ })
+}
+
+// WithMaxMsgSize returns a DialOption which sets the maximum message size the
+// client can receive.
+//
+// Deprecated: use WithDefaultCallOptions(MaxCallRecvMsgSize(s)) instead.
+func WithMaxMsgSize(s int) DialOption {
+ return WithDefaultCallOptions(MaxCallRecvMsgSize(s))
+}
+
+// WithDefaultCallOptions returns a DialOption which sets the default
+// CallOptions for calls over the connection.
+func WithDefaultCallOptions(cos ...CallOption) DialOption {
+ return newFuncDialOption(func(o *dialOptions) {
+ o.callOptions = append(o.callOptions, cos...)
+ })
+}
+
+// WithCodec returns a DialOption which sets a codec for message marshaling and
+// unmarshaling.
+//
+// Deprecated: use WithDefaultCallOptions(CallCustomCodec(c)) instead.
+func WithCodec(c Codec) DialOption {
+ return WithDefaultCallOptions(CallCustomCodec(c))
+}
+
+// WithCompressor returns a DialOption which sets a Compressor to use for
+// message compression. It has lower priority than the compressor set by the
+// UseCompressor CallOption.
+//
+// Deprecated: use UseCompressor instead.
+func WithCompressor(cp Compressor) DialOption {
+ return newFuncDialOption(func(o *dialOptions) {
+ o.cp = cp
+ })
+}
+
+// WithDecompressor returns a DialOption which sets a Decompressor to use for
+// incoming message decompression. If incoming response messages are encoded
+// using the decompressor's Type(), it will be used. Otherwise, the message
+// encoding will be used to look up the compressor registered via
+// encoding.RegisterCompressor, which will then be used to decompress the
+// message. If no compressor is registered for the encoding, an Unimplemented
+// status error will be returned.
+//
+// Deprecated: use encoding.RegisterCompressor instead.
+func WithDecompressor(dc Decompressor) DialOption {
+ return newFuncDialOption(func(o *dialOptions) {
+ o.dc = dc
+ })
+}
+
+// WithBalancer returns a DialOption which sets a load balancer with the v1 API.
+// Name resolver will be ignored if this DialOption is specified.
+//
+// Deprecated: use the new balancer APIs in balancer package and
+// WithBalancerName.
+func WithBalancer(b Balancer) DialOption {
+ return newFuncDialOption(func(o *dialOptions) {
+ o.balancerBuilder = &balancerWrapperBuilder{
+ b: b,
+ }
+ })
+}
+
+// WithBalancerName sets the balancer that the ClientConn will be initialized
+// with. Balancer registered with balancerName will be used. This function
+// panics if no balancer was registered by balancerName.
+//
+// The balancer cannot be overridden by balancer option specified by service
+// config.
+//
+// This is an EXPERIMENTAL API.
+func WithBalancerName(balancerName string) DialOption {
+ builder := balancer.Get(balancerName)
+ if builder == nil {
+ panic(fmt.Sprintf("grpc.WithBalancerName: no balancer is registered for name %v", balancerName))
+ }
+ return newFuncDialOption(func(o *dialOptions) {
+ o.balancerBuilder = builder
+ })
+}
+
+// withResolverBuilder is only for grpclb.
+func withResolverBuilder(b resolver.Builder) DialOption {
+ return newFuncDialOption(func(o *dialOptions) {
+ o.resolverBuilder = b
+ })
+}
+
+// WithServiceConfig returns a DialOption which has a channel to read the
+// service configuration.
+//
+// Deprecated: service config should be received through name resolver, as
+// specified here.
+// https://github.com/grpc/grpc/blob/master/doc/service_config.md
+func WithServiceConfig(c <-chan ServiceConfig) DialOption {
+ return newFuncDialOption(func(o *dialOptions) {
+ o.scChan = c
+ })
+}
+
+// WithBackoffMaxDelay configures the dialer to use the provided maximum delay
+// when backing off after failed connection attempts.
+func WithBackoffMaxDelay(md time.Duration) DialOption {
+ return WithBackoffConfig(BackoffConfig{MaxDelay: md})
+}
+
+// WithBackoffConfig configures the dialer to use the provided backoff
+// parameters after connection failures.
+//
+// Use WithBackoffMaxDelay until more parameters on BackoffConfig are opened up
+// for use.
+func WithBackoffConfig(b BackoffConfig) DialOption {
+ return withBackoff(backoff.Exponential{
+ MaxDelay: b.MaxDelay,
+ })
+}
+
+// withBackoff sets the backoff strategy used for connectRetryNum after a failed
+// connection attempt.
+//
+// This can be exported if arbitrary backoff strategies are allowed by gRPC.
+func withBackoff(bs backoff.Strategy) DialOption {
+ return newFuncDialOption(func(o *dialOptions) {
+ o.bs = bs
+ })
+}
+
+// WithBlock returns a DialOption which makes caller of Dial blocks until the
+// underlying connection is up. Without this, Dial returns immediately and
+// connecting the server happens in background.
+func WithBlock() DialOption {
+ return newFuncDialOption(func(o *dialOptions) {
+ o.block = true
+ })
+}
+
+// WithInsecure returns a DialOption which disables transport security for this
+// ClientConn. Note that transport security is required unless WithInsecure is
+// set.
+func WithInsecure() DialOption {
+ return newFuncDialOption(func(o *dialOptions) {
+ o.insecure = true
+ })
+}
+
+// WithTransportCredentials returns a DialOption which configures a connection
+// level security credentials (e.g., TLS/SSL). This should not be used together
+// with WithCredentialsBundle.
+func WithTransportCredentials(creds credentials.TransportCredentials) DialOption {
+ return newFuncDialOption(func(o *dialOptions) {
+ o.copts.TransportCredentials = creds
+ })
+}
+
+// WithPerRPCCredentials returns a DialOption which sets credentials and places
+// auth state on each outbound RPC.
+func WithPerRPCCredentials(creds credentials.PerRPCCredentials) DialOption {
+ return newFuncDialOption(func(o *dialOptions) {
+ o.copts.PerRPCCredentials = append(o.copts.PerRPCCredentials, creds)
+ })
+}
+
+// WithCredentialsBundle returns a DialOption to set a credentials bundle for
+// the ClientConn.WithCreds. This should not be used together with
+// WithTransportCredentials.
+//
+// This API is experimental.
+func WithCredentialsBundle(b credentials.Bundle) DialOption {
+ return newFuncDialOption(func(o *dialOptions) {
+ o.copts.CredsBundle = b
+ })
+}
+
+// WithTimeout returns a DialOption that configures a timeout for dialing a
+// ClientConn initially. This is valid if and only if WithBlock() is present.
+//
+// Deprecated: use DialContext and context.WithTimeout instead.
+func WithTimeout(d time.Duration) DialOption {
+ return newFuncDialOption(func(o *dialOptions) {
+ o.timeout = d
+ })
+}
+
+func withContextDialer(f func(context.Context, string) (net.Conn, error)) DialOption {
+ return newFuncDialOption(func(o *dialOptions) {
+ o.copts.Dialer = f
+ })
+}
+
+func init() {
+ internal.WithContextDialer = withContextDialer
+ internal.WithResolverBuilder = withResolverBuilder
+}
+
+// WithDialer returns a DialOption that specifies a function to use for dialing
+// network addresses. If FailOnNonTempDialError() is set to true, and an error
+// is returned by f, gRPC checks the error's Temporary() method to decide if it
+// should try to reconnect to the network address.
+func WithDialer(f func(string, time.Duration) (net.Conn, error)) DialOption {
+ return withContextDialer(
+ func(ctx context.Context, addr string) (net.Conn, error) {
+ if deadline, ok := ctx.Deadline(); ok {
+ return f(addr, deadline.Sub(time.Now()))
+ }
+ return f(addr, 0)
+ })
+}
+
+// WithStatsHandler returns a DialOption that specifies the stats handler for
+// all the RPCs and underlying network connections in this ClientConn.
+func WithStatsHandler(h stats.Handler) DialOption {
+ return newFuncDialOption(func(o *dialOptions) {
+ o.copts.StatsHandler = h
+ })
+}
+
+// FailOnNonTempDialError returns a DialOption that specifies if gRPC fails on
+// non-temporary dial errors. If f is true, and dialer returns a non-temporary
+// error, gRPC will fail the connection to the network address and won't try to
+// reconnect. The default value of FailOnNonTempDialError is false.
+//
+// FailOnNonTempDialError only affects the initial dial, and does not do
+// anything useful unless you are also using WithBlock().
+//
+// This is an EXPERIMENTAL API.
+func FailOnNonTempDialError(f bool) DialOption {
+ return newFuncDialOption(func(o *dialOptions) {
+ o.copts.FailOnNonTempDialError = f
+ })
+}
+
+// WithUserAgent returns a DialOption that specifies a user agent string for all
+// the RPCs.
+func WithUserAgent(s string) DialOption {
+ return newFuncDialOption(func(o *dialOptions) {
+ o.copts.UserAgent = s
+ })
+}
+
+// WithKeepaliveParams returns a DialOption that specifies keepalive parameters
+// for the client transport.
+func WithKeepaliveParams(kp keepalive.ClientParameters) DialOption {
+ return newFuncDialOption(func(o *dialOptions) {
+ o.copts.KeepaliveParams = kp
+ })
+}
+
+// WithUnaryInterceptor returns a DialOption that specifies the interceptor for
+// unary RPCs.
+func WithUnaryInterceptor(f UnaryClientInterceptor) DialOption {
+ return newFuncDialOption(func(o *dialOptions) {
+ o.unaryInt = f
+ })
+}
+
+// WithStreamInterceptor returns a DialOption that specifies the interceptor for
+// streaming RPCs.
+func WithStreamInterceptor(f StreamClientInterceptor) DialOption {
+ return newFuncDialOption(func(o *dialOptions) {
+ o.streamInt = f
+ })
+}
+
+// WithAuthority returns a DialOption that specifies the value to be used as the
+// :authority pseudo-header. This value only works with WithInsecure and has no
+// effect if TransportCredentials are present.
+func WithAuthority(a string) DialOption {
+ return newFuncDialOption(func(o *dialOptions) {
+ o.authority = a
+ })
+}
+
+// WithChannelzParentID returns a DialOption that specifies the channelz ID of
+// current ClientConn's parent. This function is used in nested channel creation
+// (e.g. grpclb dial).
+func WithChannelzParentID(id int64) DialOption {
+ return newFuncDialOption(func(o *dialOptions) {
+ o.channelzParentID = id
+ })
+}
+
+// WithDisableServiceConfig returns a DialOption that causes grpc to ignore any
+// service config provided by the resolver and provides a hint to the resolver
+// to not fetch service configs.
+func WithDisableServiceConfig() DialOption {
+ return newFuncDialOption(func(o *dialOptions) {
+ o.disableServiceConfig = true
+ })
+}
+
+// WithDisableRetry returns a DialOption that disables retries, even if the
+// service config enables them. This does not impact transparent retries, which
+// will happen automatically if no data is written to the wire or if the RPC is
+// unprocessed by the remote server.
+//
+// Retry support is currently disabled by default, but will be enabled by
+// default in the future. Until then, it may be enabled by setting the
+// environment variable "GRPC_GO_RETRY" to "on".
+//
+// This API is EXPERIMENTAL.
+func WithDisableRetry() DialOption {
+ return newFuncDialOption(func(o *dialOptions) {
+ o.disableRetry = true
+ })
+}
+
+// WithMaxHeaderListSize returns a DialOption that specifies the maximum
+// (uncompressed) size of header list that the client is prepared to accept.
+func WithMaxHeaderListSize(s uint32) DialOption {
+ return newFuncDialOption(func(o *dialOptions) {
+ o.copts.MaxHeaderListSize = &s
+ })
+}
+
+// WithDisableHealthCheck disables the LB channel health checking for all SubConns of this ClientConn.
+//
+// This API is EXPERIMENTAL.
+func WithDisableHealthCheck() DialOption {
+ return newFuncDialOption(func(o *dialOptions) {
+ o.disableHealthCheck = true
+ })
+}
+func defaultDialOptions() dialOptions {
+ return dialOptions{
+ disableRetry: !envconfig.Retry,
+ reqHandshake: envconfig.RequireHandshake,
+ copts: transport.ConnectOptions{
+ WriteBufferSize: defaultWriteBufSize,
+ ReadBufferSize: defaultReadBufSize,
+ },
+ }
+}
diff --git a/vendor/google.golang.org/grpc/doc.go b/vendor/google.golang.org/grpc/doc.go
new file mode 100644
index 000000000..187adbb11
--- /dev/null
+++ b/vendor/google.golang.org/grpc/doc.go
@@ -0,0 +1,24 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/*
+Package grpc implements an RPC system called gRPC.
+
+See grpc.io for more information about gRPC.
+*/
+package grpc // import "google.golang.org/grpc"
diff --git a/vendor/google.golang.org/grpc/encoding/encoding.go b/vendor/google.golang.org/grpc/encoding/encoding.go
new file mode 100644
index 000000000..ade8b7cec
--- /dev/null
+++ b/vendor/google.golang.org/grpc/encoding/encoding.go
@@ -0,0 +1,118 @@
+/*
+ *
+ * Copyright 2017 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// Package encoding defines the interface for the compressor and codec, and
+// functions to register and retrieve compressors and codecs.
+//
+// This package is EXPERIMENTAL.
+package encoding
+
+import (
+ "io"
+ "strings"
+)
+
+// Identity specifies the optional encoding for uncompressed streams.
+// It is intended for grpc internal use only.
+const Identity = "identity"
+
+// Compressor is used for compressing and decompressing when sending or
+// receiving messages.
+type Compressor interface {
+ // Compress writes the data written to wc to w after compressing it. If an
+ // error occurs while initializing the compressor, that error is returned
+ // instead.
+ Compress(w io.Writer) (io.WriteCloser, error)
+ // Decompress reads data from r, decompresses it, and provides the
+ // uncompressed data via the returned io.Reader. If an error occurs while
+ // initializing the decompressor, that error is returned instead.
+ Decompress(r io.Reader) (io.Reader, error)
+ // Name is the name of the compression codec and is used to set the content
+ // coding header. The result must be static; the result cannot change
+ // between calls.
+ Name() string
+}
+
+var registeredCompressor = make(map[string]Compressor)
+
+// RegisterCompressor registers the compressor with gRPC by its name. It can
+// be activated when sending an RPC via grpc.UseCompressor(). It will be
+// automatically accessed when receiving a message based on the content coding
+// header. Servers also use it to send a response with the same encoding as
+// the request.
+//
+// NOTE: this function must only be called during initialization time (i.e. in
+// an init() function), and is not thread-safe. If multiple Compressors are
+// registered with the same name, the one registered last will take effect.
+func RegisterCompressor(c Compressor) {
+ registeredCompressor[c.Name()] = c
+}
+
+// GetCompressor returns Compressor for the given compressor name.
+func GetCompressor(name string) Compressor {
+ return registeredCompressor[name]
+}
+
+// Codec defines the interface gRPC uses to encode and decode messages. Note
+// that implementations of this interface must be thread safe; a Codec's
+// methods can be called from concurrent goroutines.
+type Codec interface {
+ // Marshal returns the wire format of v.
+ Marshal(v interface{}) ([]byte, error)
+ // Unmarshal parses the wire format into v.
+ Unmarshal(data []byte, v interface{}) error
+ // Name returns the name of the Codec implementation. The returned string
+ // will be used as part of content type in transmission. The result must be
+ // static; the result cannot change between calls.
+ Name() string
+}
+
+var registeredCodecs = make(map[string]Codec)
+
+// RegisterCodec registers the provided Codec for use with all gRPC clients and
+// servers.
+//
+// The Codec will be stored and looked up by result of its Name() method, which
+// should match the content-subtype of the encoding handled by the Codec. This
+// is case-insensitive, and is stored and looked up as lowercase. If the
+// result of calling Name() is an empty string, RegisterCodec will panic. See
+// Content-Type on
+// https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md#requests for
+// more details.
+//
+// NOTE: this function must only be called during initialization time (i.e. in
+// an init() function), and is not thread-safe. If multiple Compressors are
+// registered with the same name, the one registered last will take effect.
+func RegisterCodec(codec Codec) {
+ if codec == nil {
+ panic("cannot register a nil Codec")
+ }
+ contentSubtype := strings.ToLower(codec.Name())
+ if contentSubtype == "" {
+ panic("cannot register Codec with empty string result for String()")
+ }
+ registeredCodecs[contentSubtype] = codec
+}
+
+// GetCodec gets a registered Codec by content-subtype, or nil if no Codec is
+// registered for the content-subtype.
+//
+// The content-subtype is expected to be lowercase.
+func GetCodec(contentSubtype string) Codec {
+ return registeredCodecs[contentSubtype]
+}
diff --git a/vendor/google.golang.org/grpc/encoding/proto/proto.go b/vendor/google.golang.org/grpc/encoding/proto/proto.go
new file mode 100644
index 000000000..66b97a6f6
--- /dev/null
+++ b/vendor/google.golang.org/grpc/encoding/proto/proto.go
@@ -0,0 +1,110 @@
+/*
+ *
+ * Copyright 2018 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// Package proto defines the protobuf codec. Importing this package will
+// register the codec.
+package proto
+
+import (
+ "math"
+ "sync"
+
+ "github.com/golang/protobuf/proto"
+ "google.golang.org/grpc/encoding"
+)
+
+// Name is the name registered for the proto compressor.
+const Name = "proto"
+
+func init() {
+ encoding.RegisterCodec(codec{})
+}
+
+// codec is a Codec implementation with protobuf. It is the default codec for gRPC.
+type codec struct{}
+
+type cachedProtoBuffer struct {
+ lastMarshaledSize uint32
+ proto.Buffer
+}
+
+func capToMaxInt32(val int) uint32 {
+ if val > math.MaxInt32 {
+ return uint32(math.MaxInt32)
+ }
+ return uint32(val)
+}
+
+func marshal(v interface{}, cb *cachedProtoBuffer) ([]byte, error) {
+ protoMsg := v.(proto.Message)
+ newSlice := make([]byte, 0, cb.lastMarshaledSize)
+
+ cb.SetBuf(newSlice)
+ cb.Reset()
+ if err := cb.Marshal(protoMsg); err != nil {
+ return nil, err
+ }
+ out := cb.Bytes()
+ cb.lastMarshaledSize = capToMaxInt32(len(out))
+ return out, nil
+}
+
+func (codec) Marshal(v interface{}) ([]byte, error) {
+ if pm, ok := v.(proto.Marshaler); ok {
+ // object can marshal itself, no need for buffer
+ return pm.Marshal()
+ }
+
+ cb := protoBufferPool.Get().(*cachedProtoBuffer)
+ out, err := marshal(v, cb)
+
+ // put back buffer and lose the ref to the slice
+ cb.SetBuf(nil)
+ protoBufferPool.Put(cb)
+ return out, err
+}
+
+func (codec) Unmarshal(data []byte, v interface{}) error {
+ protoMsg := v.(proto.Message)
+ protoMsg.Reset()
+
+ if pu, ok := protoMsg.(proto.Unmarshaler); ok {
+ // object can unmarshal itself, no need for buffer
+ return pu.Unmarshal(data)
+ }
+
+ cb := protoBufferPool.Get().(*cachedProtoBuffer)
+ cb.SetBuf(data)
+ err := cb.Unmarshal(protoMsg)
+ cb.SetBuf(nil)
+ protoBufferPool.Put(cb)
+ return err
+}
+
+func (codec) Name() string {
+ return Name
+}
+
+var protoBufferPool = &sync.Pool{
+ New: func() interface{} {
+ return &cachedProtoBuffer{
+ Buffer: proto.Buffer{},
+ lastMarshaledSize: 16,
+ }
+ },
+}
diff --git a/vendor/google.golang.org/grpc/go.mod b/vendor/google.golang.org/grpc/go.mod
new file mode 100644
index 000000000..f296dcf4e
--- /dev/null
+++ b/vendor/google.golang.org/grpc/go.mod
@@ -0,0 +1,20 @@
+module google.golang.org/grpc
+
+require (
+ cloud.google.com/go v0.26.0 // indirect
+ github.com/client9/misspell v0.3.4
+ github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b
+ github.com/golang/mock v1.1.1
+ github.com/golang/protobuf v1.2.0
+ github.com/kisielk/gotool v1.0.0 // indirect
+ golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3
+ golang.org/x/net v0.0.0-20180826012351-8a410e7b638d
+ golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be
+ golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f // indirect
+ golang.org/x/sys v0.0.0-20180830151530-49385e6e1522
+ golang.org/x/text v0.3.0 // indirect
+ golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52
+ google.golang.org/appengine v1.1.0 // indirect
+ google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8
+ honnef.co/go/tools v0.0.0-20180728063816-88497007e858
+)
diff --git a/vendor/google.golang.org/grpc/go.sum b/vendor/google.golang.org/grpc/go.sum
new file mode 100644
index 000000000..bfb6bb7c0
--- /dev/null
+++ b/vendor/google.golang.org/grpc/go.sum
@@ -0,0 +1,32 @@
+cloud.google.com/go v0.26.0 h1:e0WKqKTd5BnrG8aKH3J3h+QvEIQtSUcf2n5UZ5ZgLtQ=
+cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+github.com/client9/misspell v0.3.4 h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJI=
+github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
+github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
+github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
+github.com/golang/mock v1.1.1 h1:G5FRp8JnTd7RQH5kemVNlMeyXQAztQ3mOWV95KxsXH8=
+github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
+github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
+github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg=
+github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
+golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3 h1:x/bBzNauLQAlE3fLku/xy92Y8QwKX5HZymrMz2IiKFc=
+golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
+golang.org/x/net v0.0.0-20180826012351-8a410e7b638d h1:g9qWBGx4puODJTMVyoPrpoxPFgVGd+z1DZwjfRu4d0I=
+golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be h1:vEDujvNQGv4jgYKudGeI/+DAX4Jffq6hpD55MmoEvKs=
+golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
+golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA=
+golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20180830151530-49385e6e1522 h1:Ve1ORMCxvRmSXBwJK+t3Oy+V2vRW2OetUQBq4rJIkZE=
+golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52 h1:JG/0uqcGdTNgq7FdU+61l5Pdmb8putNZlXb65bJBROs=
+golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+google.golang.org/appengine v1.1.0 h1:igQkv0AAhEIvTEpD5LIpAfav2eeVO9HBTjvKHVJPRSs=
+google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
+google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0NQvRW8DG4Yk3Q6T9cu9RcFQDu1tc=
+google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
+honnef.co/go/tools v0.0.0-20180728063816-88497007e858 h1:wN+eVZ7U+gqdqkec6C6VXR1OFf9a5Ul9ETzeYsYv20g=
+honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
diff --git a/vendor/google.golang.org/grpc/grpclog/grpclog.go b/vendor/google.golang.org/grpc/grpclog/grpclog.go
new file mode 100644
index 000000000..1fabb11e1
--- /dev/null
+++ b/vendor/google.golang.org/grpc/grpclog/grpclog.go
@@ -0,0 +1,126 @@
+/*
+ *
+ * Copyright 2017 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// Package grpclog defines logging for grpc.
+//
+// All logs in transport package only go to verbose level 2.
+// All logs in other packages in grpc are logged in spite of the verbosity level.
+//
+// In the default logger,
+// severity level can be set by environment variable GRPC_GO_LOG_SEVERITY_LEVEL,
+// verbosity level can be set by GRPC_GO_LOG_VERBOSITY_LEVEL.
+package grpclog // import "google.golang.org/grpc/grpclog"
+
+import "os"
+
+var logger = newLoggerV2()
+
+// V reports whether verbosity level l is at least the requested verbose level.
+func V(l int) bool {
+ return logger.V(l)
+}
+
+// Info logs to the INFO log.
+func Info(args ...interface{}) {
+ logger.Info(args...)
+}
+
+// Infof logs to the INFO log. Arguments are handled in the manner of fmt.Printf.
+func Infof(format string, args ...interface{}) {
+ logger.Infof(format, args...)
+}
+
+// Infoln logs to the INFO log. Arguments are handled in the manner of fmt.Println.
+func Infoln(args ...interface{}) {
+ logger.Infoln(args...)
+}
+
+// Warning logs to the WARNING log.
+func Warning(args ...interface{}) {
+ logger.Warning(args...)
+}
+
+// Warningf logs to the WARNING log. Arguments are handled in the manner of fmt.Printf.
+func Warningf(format string, args ...interface{}) {
+ logger.Warningf(format, args...)
+}
+
+// Warningln logs to the WARNING log. Arguments are handled in the manner of fmt.Println.
+func Warningln(args ...interface{}) {
+ logger.Warningln(args...)
+}
+
+// Error logs to the ERROR log.
+func Error(args ...interface{}) {
+ logger.Error(args...)
+}
+
+// Errorf logs to the ERROR log. Arguments are handled in the manner of fmt.Printf.
+func Errorf(format string, args ...interface{}) {
+ logger.Errorf(format, args...)
+}
+
+// Errorln logs to the ERROR log. Arguments are handled in the manner of fmt.Println.
+func Errorln(args ...interface{}) {
+ logger.Errorln(args...)
+}
+
+// Fatal logs to the FATAL log. Arguments are handled in the manner of fmt.Print.
+// It calls os.Exit() with exit code 1.
+func Fatal(args ...interface{}) {
+ logger.Fatal(args...)
+ // Make sure fatal logs will exit.
+ os.Exit(1)
+}
+
+// Fatalf logs to the FATAL log. Arguments are handled in the manner of fmt.Printf.
+// It calles os.Exit() with exit code 1.
+func Fatalf(format string, args ...interface{}) {
+ logger.Fatalf(format, args...)
+ // Make sure fatal logs will exit.
+ os.Exit(1)
+}
+
+// Fatalln logs to the FATAL log. Arguments are handled in the manner of fmt.Println.
+// It calle os.Exit()) with exit code 1.
+func Fatalln(args ...interface{}) {
+ logger.Fatalln(args...)
+ // Make sure fatal logs will exit.
+ os.Exit(1)
+}
+
+// Print prints to the logger. Arguments are handled in the manner of fmt.Print.
+//
+// Deprecated: use Info.
+func Print(args ...interface{}) {
+ logger.Info(args...)
+}
+
+// Printf prints to the logger. Arguments are handled in the manner of fmt.Printf.
+//
+// Deprecated: use Infof.
+func Printf(format string, args ...interface{}) {
+ logger.Infof(format, args...)
+}
+
+// Println prints to the logger. Arguments are handled in the manner of fmt.Println.
+//
+// Deprecated: use Infoln.
+func Println(args ...interface{}) {
+ logger.Infoln(args...)
+}
diff --git a/vendor/google.golang.org/grpc/grpclog/logger.go b/vendor/google.golang.org/grpc/grpclog/logger.go
new file mode 100644
index 000000000..097494f71
--- /dev/null
+++ b/vendor/google.golang.org/grpc/grpclog/logger.go
@@ -0,0 +1,85 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package grpclog
+
+// Logger mimics golang's standard Logger as an interface.
+//
+// Deprecated: use LoggerV2.
+type Logger interface {
+ Fatal(args ...interface{})
+ Fatalf(format string, args ...interface{})
+ Fatalln(args ...interface{})
+ Print(args ...interface{})
+ Printf(format string, args ...interface{})
+ Println(args ...interface{})
+}
+
+// SetLogger sets the logger that is used in grpc. Call only from
+// init() functions.
+//
+// Deprecated: use SetLoggerV2.
+func SetLogger(l Logger) {
+ logger = &loggerWrapper{Logger: l}
+}
+
+// loggerWrapper wraps Logger into a LoggerV2.
+type loggerWrapper struct {
+ Logger
+}
+
+func (g *loggerWrapper) Info(args ...interface{}) {
+ g.Logger.Print(args...)
+}
+
+func (g *loggerWrapper) Infoln(args ...interface{}) {
+ g.Logger.Println(args...)
+}
+
+func (g *loggerWrapper) Infof(format string, args ...interface{}) {
+ g.Logger.Printf(format, args...)
+}
+
+func (g *loggerWrapper) Warning(args ...interface{}) {
+ g.Logger.Print(args...)
+}
+
+func (g *loggerWrapper) Warningln(args ...interface{}) {
+ g.Logger.Println(args...)
+}
+
+func (g *loggerWrapper) Warningf(format string, args ...interface{}) {
+ g.Logger.Printf(format, args...)
+}
+
+func (g *loggerWrapper) Error(args ...interface{}) {
+ g.Logger.Print(args...)
+}
+
+func (g *loggerWrapper) Errorln(args ...interface{}) {
+ g.Logger.Println(args...)
+}
+
+func (g *loggerWrapper) Errorf(format string, args ...interface{}) {
+ g.Logger.Printf(format, args...)
+}
+
+func (g *loggerWrapper) V(l int) bool {
+ // Returns true for all verbose level.
+ return true
+}
diff --git a/vendor/google.golang.org/grpc/grpclog/loggerv2.go b/vendor/google.golang.org/grpc/grpclog/loggerv2.go
new file mode 100644
index 000000000..d49325776
--- /dev/null
+++ b/vendor/google.golang.org/grpc/grpclog/loggerv2.go
@@ -0,0 +1,195 @@
+/*
+ *
+ * Copyright 2017 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package grpclog
+
+import (
+ "io"
+ "io/ioutil"
+ "log"
+ "os"
+ "strconv"
+)
+
+// LoggerV2 does underlying logging work for grpclog.
+type LoggerV2 interface {
+ // Info logs to INFO log. Arguments are handled in the manner of fmt.Print.
+ Info(args ...interface{})
+ // Infoln logs to INFO log. Arguments are handled in the manner of fmt.Println.
+ Infoln(args ...interface{})
+ // Infof logs to INFO log. Arguments are handled in the manner of fmt.Printf.
+ Infof(format string, args ...interface{})
+ // Warning logs to WARNING log. Arguments are handled in the manner of fmt.Print.
+ Warning(args ...interface{})
+ // Warningln logs to WARNING log. Arguments are handled in the manner of fmt.Println.
+ Warningln(args ...interface{})
+ // Warningf logs to WARNING log. Arguments are handled in the manner of fmt.Printf.
+ Warningf(format string, args ...interface{})
+ // Error logs to ERROR log. Arguments are handled in the manner of fmt.Print.
+ Error(args ...interface{})
+ // Errorln logs to ERROR log. Arguments are handled in the manner of fmt.Println.
+ Errorln(args ...interface{})
+ // Errorf logs to ERROR log. Arguments are handled in the manner of fmt.Printf.
+ Errorf(format string, args ...interface{})
+ // Fatal logs to ERROR log. Arguments are handled in the manner of fmt.Print.
+ // gRPC ensures that all Fatal logs will exit with os.Exit(1).
+ // Implementations may also call os.Exit() with a non-zero exit code.
+ Fatal(args ...interface{})
+ // Fatalln logs to ERROR log. Arguments are handled in the manner of fmt.Println.
+ // gRPC ensures that all Fatal logs will exit with os.Exit(1).
+ // Implementations may also call os.Exit() with a non-zero exit code.
+ Fatalln(args ...interface{})
+ // Fatalf logs to ERROR log. Arguments are handled in the manner of fmt.Printf.
+ // gRPC ensures that all Fatal logs will exit with os.Exit(1).
+ // Implementations may also call os.Exit() with a non-zero exit code.
+ Fatalf(format string, args ...interface{})
+ // V reports whether verbosity level l is at least the requested verbose level.
+ V(l int) bool
+}
+
+// SetLoggerV2 sets logger that is used in grpc to a V2 logger.
+// Not mutex-protected, should be called before any gRPC functions.
+func SetLoggerV2(l LoggerV2) {
+ logger = l
+}
+
+const (
+ // infoLog indicates Info severity.
+ infoLog int = iota
+ // warningLog indicates Warning severity.
+ warningLog
+ // errorLog indicates Error severity.
+ errorLog
+ // fatalLog indicates Fatal severity.
+ fatalLog
+)
+
+// severityName contains the string representation of each severity.
+var severityName = []string{
+ infoLog: "INFO",
+ warningLog: "WARNING",
+ errorLog: "ERROR",
+ fatalLog: "FATAL",
+}
+
+// loggerT is the default logger used by grpclog.
+type loggerT struct {
+ m []*log.Logger
+ v int
+}
+
+// NewLoggerV2 creates a loggerV2 with the provided writers.
+// Fatal logs will be written to errorW, warningW, infoW, followed by exit(1).
+// Error logs will be written to errorW, warningW and infoW.
+// Warning logs will be written to warningW and infoW.
+// Info logs will be written to infoW.
+func NewLoggerV2(infoW, warningW, errorW io.Writer) LoggerV2 {
+ return NewLoggerV2WithVerbosity(infoW, warningW, errorW, 0)
+}
+
+// NewLoggerV2WithVerbosity creates a loggerV2 with the provided writers and
+// verbosity level.
+func NewLoggerV2WithVerbosity(infoW, warningW, errorW io.Writer, v int) LoggerV2 {
+ var m []*log.Logger
+ m = append(m, log.New(infoW, severityName[infoLog]+": ", log.LstdFlags))
+ m = append(m, log.New(io.MultiWriter(infoW, warningW), severityName[warningLog]+": ", log.LstdFlags))
+ ew := io.MultiWriter(infoW, warningW, errorW) // ew will be used for error and fatal.
+ m = append(m, log.New(ew, severityName[errorLog]+": ", log.LstdFlags))
+ m = append(m, log.New(ew, severityName[fatalLog]+": ", log.LstdFlags))
+ return &loggerT{m: m, v: v}
+}
+
+// newLoggerV2 creates a loggerV2 to be used as default logger.
+// All logs are written to stderr.
+func newLoggerV2() LoggerV2 {
+ errorW := ioutil.Discard
+ warningW := ioutil.Discard
+ infoW := ioutil.Discard
+
+ logLevel := os.Getenv("GRPC_GO_LOG_SEVERITY_LEVEL")
+ switch logLevel {
+ case "", "ERROR", "error": // If env is unset, set level to ERROR.
+ errorW = os.Stderr
+ case "WARNING", "warning":
+ warningW = os.Stderr
+ case "INFO", "info":
+ infoW = os.Stderr
+ }
+
+ var v int
+ vLevel := os.Getenv("GRPC_GO_LOG_VERBOSITY_LEVEL")
+ if vl, err := strconv.Atoi(vLevel); err == nil {
+ v = vl
+ }
+ return NewLoggerV2WithVerbosity(infoW, warningW, errorW, v)
+}
+
+func (g *loggerT) Info(args ...interface{}) {
+ g.m[infoLog].Print(args...)
+}
+
+func (g *loggerT) Infoln(args ...interface{}) {
+ g.m[infoLog].Println(args...)
+}
+
+func (g *loggerT) Infof(format string, args ...interface{}) {
+ g.m[infoLog].Printf(format, args...)
+}
+
+func (g *loggerT) Warning(args ...interface{}) {
+ g.m[warningLog].Print(args...)
+}
+
+func (g *loggerT) Warningln(args ...interface{}) {
+ g.m[warningLog].Println(args...)
+}
+
+func (g *loggerT) Warningf(format string, args ...interface{}) {
+ g.m[warningLog].Printf(format, args...)
+}
+
+func (g *loggerT) Error(args ...interface{}) {
+ g.m[errorLog].Print(args...)
+}
+
+func (g *loggerT) Errorln(args ...interface{}) {
+ g.m[errorLog].Println(args...)
+}
+
+func (g *loggerT) Errorf(format string, args ...interface{}) {
+ g.m[errorLog].Printf(format, args...)
+}
+
+func (g *loggerT) Fatal(args ...interface{}) {
+ g.m[fatalLog].Fatal(args...)
+ // No need to call os.Exit() again because log.Logger.Fatal() calls os.Exit().
+}
+
+func (g *loggerT) Fatalln(args ...interface{}) {
+ g.m[fatalLog].Fatalln(args...)
+ // No need to call os.Exit() again because log.Logger.Fatal() calls os.Exit().
+}
+
+func (g *loggerT) Fatalf(format string, args ...interface{}) {
+ g.m[fatalLog].Fatalf(format, args...)
+ // No need to call os.Exit() again because log.Logger.Fatal() calls os.Exit().
+}
+
+func (g *loggerT) V(l int) bool {
+ return l <= g.v
+}
diff --git a/vendor/google.golang.org/grpc/install_gae.sh b/vendor/google.golang.org/grpc/install_gae.sh
new file mode 100755
index 000000000..7c7bcada5
--- /dev/null
+++ b/vendor/google.golang.org/grpc/install_gae.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+
+TMP=$(mktemp -d /tmp/sdk.XXX) \
+&& curl -o $TMP.zip "https://storage.googleapis.com/appengine-sdks/featured/go_appengine_sdk_linux_amd64-1.9.68.zip" \
+&& unzip -q $TMP.zip -d $TMP \
+&& export PATH="$PATH:$TMP/go_appengine"
diff --git a/vendor/google.golang.org/grpc/interceptor.go b/vendor/google.golang.org/grpc/interceptor.go
new file mode 100644
index 000000000..8b7350022
--- /dev/null
+++ b/vendor/google.golang.org/grpc/interceptor.go
@@ -0,0 +1,77 @@
+/*
+ *
+ * Copyright 2016 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package grpc
+
+import (
+ "context"
+)
+
+// UnaryInvoker is called by UnaryClientInterceptor to complete RPCs.
+type UnaryInvoker func(ctx context.Context, method string, req, reply interface{}, cc *ClientConn, opts ...CallOption) error
+
+// UnaryClientInterceptor intercepts the execution of a unary RPC on the client. invoker is the handler to complete the RPC
+// and it is the responsibility of the interceptor to call it.
+// This is an EXPERIMENTAL API.
+type UnaryClientInterceptor func(ctx context.Context, method string, req, reply interface{}, cc *ClientConn, invoker UnaryInvoker, opts ...CallOption) error
+
+// Streamer is called by StreamClientInterceptor to create a ClientStream.
+type Streamer func(ctx context.Context, desc *StreamDesc, cc *ClientConn, method string, opts ...CallOption) (ClientStream, error)
+
+// StreamClientInterceptor intercepts the creation of ClientStream. It may return a custom ClientStream to intercept all I/O
+// operations. streamer is the handler to create a ClientStream and it is the responsibility of the interceptor to call it.
+// This is an EXPERIMENTAL API.
+type StreamClientInterceptor func(ctx context.Context, desc *StreamDesc, cc *ClientConn, method string, streamer Streamer, opts ...CallOption) (ClientStream, error)
+
+// UnaryServerInfo consists of various information about a unary RPC on
+// server side. All per-rpc information may be mutated by the interceptor.
+type UnaryServerInfo struct {
+ // Server is the service implementation the user provides. This is read-only.
+ Server interface{}
+ // FullMethod is the full RPC method string, i.e., /package.service/method.
+ FullMethod string
+}
+
+// UnaryHandler defines the handler invoked by UnaryServerInterceptor to complete the normal
+// execution of a unary RPC. If a UnaryHandler returns an error, it should be produced by the
+// status package, or else gRPC will use codes.Unknown as the status code and err.Error() as
+// the status message of the RPC.
+type UnaryHandler func(ctx context.Context, req interface{}) (interface{}, error)
+
+// UnaryServerInterceptor provides a hook to intercept the execution of a unary RPC on the server. info
+// contains all the information of this RPC the interceptor can operate on. And handler is the wrapper
+// of the service method implementation. It is the responsibility of the interceptor to invoke handler
+// to complete the RPC.
+type UnaryServerInterceptor func(ctx context.Context, req interface{}, info *UnaryServerInfo, handler UnaryHandler) (resp interface{}, err error)
+
+// StreamServerInfo consists of various information about a streaming RPC on
+// server side. All per-rpc information may be mutated by the interceptor.
+type StreamServerInfo struct {
+ // FullMethod is the full RPC method string, i.e., /package.service/method.
+ FullMethod string
+ // IsClientStream indicates whether the RPC is a client streaming RPC.
+ IsClientStream bool
+ // IsServerStream indicates whether the RPC is a server streaming RPC.
+ IsServerStream bool
+}
+
+// StreamServerInterceptor provides a hook to intercept the execution of a streaming RPC on the server.
+// info contains all the information of this RPC the interceptor can operate on. And handler is the
+// service method implementation. It is the responsibility of the interceptor to invoke handler to
+// complete the RPC.
+type StreamServerInterceptor func(srv interface{}, ss ServerStream, info *StreamServerInfo, handler StreamHandler) error
diff --git a/vendor/google.golang.org/grpc/internal/backoff/backoff.go b/vendor/google.golang.org/grpc/internal/backoff/backoff.go
new file mode 100644
index 000000000..1bd0cce5a
--- /dev/null
+++ b/vendor/google.golang.org/grpc/internal/backoff/backoff.go
@@ -0,0 +1,78 @@
+/*
+ *
+ * Copyright 2017 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// Package backoff implement the backoff strategy for gRPC.
+//
+// This is kept in internal until the gRPC project decides whether or not to
+// allow alternative backoff strategies.
+package backoff
+
+import (
+ "time"
+
+ "google.golang.org/grpc/internal/grpcrand"
+)
+
+// Strategy defines the methodology for backing off after a grpc connection
+// failure.
+//
+type Strategy interface {
+ // Backoff returns the amount of time to wait before the next retry given
+ // the number of consecutive failures.
+ Backoff(retries int) time.Duration
+}
+
+const (
+ // baseDelay is the amount of time to wait before retrying after the first
+ // failure.
+ baseDelay = 1.0 * time.Second
+ // factor is applied to the backoff after each retry.
+ factor = 1.6
+ // jitter provides a range to randomize backoff delays.
+ jitter = 0.2
+)
+
+// Exponential implements exponential backoff algorithm as defined in
+// https://github.com/grpc/grpc/blob/master/doc/connection-backoff.md.
+type Exponential struct {
+ // MaxDelay is the upper bound of backoff delay.
+ MaxDelay time.Duration
+}
+
+// Backoff returns the amount of time to wait before the next retry given the
+// number of retries.
+func (bc Exponential) Backoff(retries int) time.Duration {
+ if retries == 0 {
+ return baseDelay
+ }
+ backoff, max := float64(baseDelay), float64(bc.MaxDelay)
+ for backoff < max && retries > 0 {
+ backoff *= factor
+ retries--
+ }
+ if backoff > max {
+ backoff = max
+ }
+ // Randomize backoff delays so that if a cluster of requests start at
+ // the same time, they won't operate in lockstep.
+ backoff *= 1 + jitter*(grpcrand.Float64()*2-1)
+ if backoff < 0 {
+ return 0
+ }
+ return time.Duration(backoff)
+}
diff --git a/vendor/google.golang.org/grpc/internal/binarylog/binarylog.go b/vendor/google.golang.org/grpc/internal/binarylog/binarylog.go
new file mode 100644
index 000000000..fee6aecd0
--- /dev/null
+++ b/vendor/google.golang.org/grpc/internal/binarylog/binarylog.go
@@ -0,0 +1,167 @@
+/*
+ *
+ * Copyright 2018 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// Package binarylog implementation binary logging as defined in
+// https://github.com/grpc/proposal/blob/master/A16-binary-logging.md.
+package binarylog
+
+import (
+ "fmt"
+ "os"
+
+ "google.golang.org/grpc/grpclog"
+)
+
+// Logger is the global binary logger. It can be used to get binary logger for
+// each method.
+type Logger interface {
+ getMethodLogger(methodName string) *MethodLogger
+}
+
+// binLogger is the global binary logger for the binary. One of this should be
+// built at init time from the configuration (environment varialbe or flags).
+//
+// It is used to get a methodLogger for each individual method.
+var binLogger Logger
+
+// SetLogger sets the binarg logger.
+//
+// Only call this at init time.
+func SetLogger(l Logger) {
+ binLogger = l
+}
+
+// GetMethodLogger returns the methodLogger for the given methodName.
+//
+// methodName should be in the format of "/service/method".
+//
+// Each methodLogger returned by this method is a new instance. This is to
+// generate sequence id within the call.
+func GetMethodLogger(methodName string) *MethodLogger {
+ if binLogger == nil {
+ return nil
+ }
+ return binLogger.getMethodLogger(methodName)
+}
+
+func init() {
+ const envStr = "GRPC_BINARY_LOG_FILTER"
+ configStr := os.Getenv(envStr)
+ binLogger = NewLoggerFromConfigString(configStr)
+}
+
+type methodLoggerConfig struct {
+ // Max length of header and message.
+ hdr, msg uint64
+}
+
+type logger struct {
+ all *methodLoggerConfig
+ services map[string]*methodLoggerConfig
+ methods map[string]*methodLoggerConfig
+
+ blacklist map[string]struct{}
+}
+
+// newEmptyLogger creates an empty logger. The map fields need to be filled in
+// using the set* functions.
+func newEmptyLogger() *logger {
+ return &logger{}
+}
+
+// Set method logger for "*".
+func (l *logger) setDefaultMethodLogger(ml *methodLoggerConfig) error {
+ if l.all != nil {
+ return fmt.Errorf("conflicting global rules found")
+ }
+ l.all = ml
+ return nil
+}
+
+// Set method logger for "service/*".
+//
+// New methodLogger with same service overrides the old one.
+func (l *logger) setServiceMethodLogger(service string, ml *methodLoggerConfig) error {
+ if _, ok := l.services[service]; ok {
+ return fmt.Errorf("conflicting rules for service %v found", service)
+ }
+ if l.services == nil {
+ l.services = make(map[string]*methodLoggerConfig)
+ }
+ l.services[service] = ml
+ return nil
+}
+
+// Set method logger for "service/method".
+//
+// New methodLogger with same method overrides the old one.
+func (l *logger) setMethodMethodLogger(method string, ml *methodLoggerConfig) error {
+ if _, ok := l.blacklist[method]; ok {
+ return fmt.Errorf("conflicting rules for method %v found", method)
+ }
+ if _, ok := l.methods[method]; ok {
+ return fmt.Errorf("conflicting rules for method %v found", method)
+ }
+ if l.methods == nil {
+ l.methods = make(map[string]*methodLoggerConfig)
+ }
+ l.methods[method] = ml
+ return nil
+}
+
+// Set blacklist method for "-service/method".
+func (l *logger) setBlacklist(method string) error {
+ if _, ok := l.blacklist[method]; ok {
+ return fmt.Errorf("conflicting rules for method %v found", method)
+ }
+ if _, ok := l.methods[method]; ok {
+ return fmt.Errorf("conflicting rules for method %v found", method)
+ }
+ if l.blacklist == nil {
+ l.blacklist = make(map[string]struct{})
+ }
+ l.blacklist[method] = struct{}{}
+ return nil
+}
+
+// getMethodLogger returns the methodLogger for the given methodName.
+//
+// methodName should be in the format of "/service/method".
+//
+// Each methodLogger returned by this method is a new instance. This is to
+// generate sequence id within the call.
+func (l *logger) getMethodLogger(methodName string) *MethodLogger {
+ s, m, err := parseMethodName(methodName)
+ if err != nil {
+ grpclog.Infof("binarylogging: failed to parse %q: %v", methodName, err)
+ return nil
+ }
+ if ml, ok := l.methods[s+"/"+m]; ok {
+ return newMethodLogger(ml.hdr, ml.msg)
+ }
+ if _, ok := l.blacklist[s+"/"+m]; ok {
+ return nil
+ }
+ if ml, ok := l.services[s]; ok {
+ return newMethodLogger(ml.hdr, ml.msg)
+ }
+ if l.all == nil {
+ return nil
+ }
+ return newMethodLogger(l.all.hdr, l.all.msg)
+}
diff --git a/vendor/google.golang.org/grpc/internal/binarylog/binarylog_testutil.go b/vendor/google.golang.org/grpc/internal/binarylog/binarylog_testutil.go
new file mode 100644
index 000000000..1ee00a39a
--- /dev/null
+++ b/vendor/google.golang.org/grpc/internal/binarylog/binarylog_testutil.go
@@ -0,0 +1,42 @@
+/*
+ *
+ * Copyright 2018 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// This file contains exported variables/functions that are exported for testing
+// only.
+//
+// An ideal way for this would be to put those in a *_test.go but in binarylog
+// package. But this doesn't work with staticcheck with go module. Error was:
+// "MdToMetadataProto not declared by package binarylog". This could be caused
+// by the way staticcheck looks for files for a certain package, which doesn't
+// support *_test.go files.
+//
+// Move those to binary_test.go when staticcheck is fixed.
+
+package binarylog
+
+var (
+ // AllLogger is a logger that logs all headers/messages for all RPCs. It's
+ // for testing only.
+ AllLogger = NewLoggerFromConfigString("*")
+ // MdToMetadataProto converts metadata to a binary logging proto message.
+ // It's for testing only.
+ MdToMetadataProto = mdToMetadataProto
+ // AddrToProto converts an address to a binary logging proto message. It's
+ // for testing only.
+ AddrToProto = addrToProto
+)
diff --git a/vendor/google.golang.org/grpc/internal/binarylog/env_config.go b/vendor/google.golang.org/grpc/internal/binarylog/env_config.go
new file mode 100644
index 000000000..eb188eae5
--- /dev/null
+++ b/vendor/google.golang.org/grpc/internal/binarylog/env_config.go
@@ -0,0 +1,210 @@
+/*
+ *
+ * Copyright 2018 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package binarylog
+
+import (
+ "errors"
+ "fmt"
+ "regexp"
+ "strconv"
+ "strings"
+
+ "google.golang.org/grpc/grpclog"
+)
+
+// NewLoggerFromConfigString reads the string and build a logger. It can be used
+// to build a new logger and assign it to binarylog.Logger.
+//
+// Example filter config strings:
+// - "" Nothing will be logged
+// - "*" All headers and messages will be fully logged.
+// - "*{h}" Only headers will be logged.
+// - "*{m:256}" Only the first 256 bytes of each message will be logged.
+// - "Foo/*" Logs every method in service Foo
+// - "Foo/*,-Foo/Bar" Logs every method in service Foo except method /Foo/Bar
+// - "Foo/*,Foo/Bar{m:256}" Logs the first 256 bytes of each message in method
+// /Foo/Bar, logs all headers and messages in every other method in service
+// Foo.
+//
+// If two configs exist for one certain method or service, the one specified
+// later overrides the privous config.
+func NewLoggerFromConfigString(s string) Logger {
+ if s == "" {
+ return nil
+ }
+ l := newEmptyLogger()
+ methods := strings.Split(s, ",")
+ for _, method := range methods {
+ if err := l.fillMethodLoggerWithConfigString(method); err != nil {
+ grpclog.Warningf("failed to parse binary log config: %v", err)
+ return nil
+ }
+ }
+ return l
+}
+
+// fillMethodLoggerWithConfigString parses config, creates methodLogger and adds
+// it to the right map in the logger.
+func (l *logger) fillMethodLoggerWithConfigString(config string) error {
+ // "" is invalid.
+ if config == "" {
+ return errors.New("empty string is not a valid method binary logging config")
+ }
+
+ // "-service/method", blacklist, no * or {} allowed.
+ if config[0] == '-' {
+ s, m, suffix, err := parseMethodConfigAndSuffix(config[1:])
+ if err != nil {
+ return fmt.Errorf("invalid config: %q, %v", config, err)
+ }
+ if m == "*" {
+ return fmt.Errorf("invalid config: %q, %v", config, "* not allowd in blacklist config")
+ }
+ if suffix != "" {
+ return fmt.Errorf("invalid config: %q, %v", config, "header/message limit not allowed in blacklist config")
+ }
+ if err := l.setBlacklist(s + "/" + m); err != nil {
+ return fmt.Errorf("invalid config: %v", err)
+ }
+ return nil
+ }
+
+ // "*{h:256;m:256}"
+ if config[0] == '*' {
+ hdr, msg, err := parseHeaderMessageLengthConfig(config[1:])
+ if err != nil {
+ return fmt.Errorf("invalid config: %q, %v", config, err)
+ }
+ if err := l.setDefaultMethodLogger(&methodLoggerConfig{hdr: hdr, msg: msg}); err != nil {
+ return fmt.Errorf("invalid config: %v", err)
+ }
+ return nil
+ }
+
+ s, m, suffix, err := parseMethodConfigAndSuffix(config)
+ if err != nil {
+ return fmt.Errorf("invalid config: %q, %v", config, err)
+ }
+ hdr, msg, err := parseHeaderMessageLengthConfig(suffix)
+ if err != nil {
+ return fmt.Errorf("invalid header/message length config: %q, %v", suffix, err)
+ }
+ if m == "*" {
+ if err := l.setServiceMethodLogger(s, &methodLoggerConfig{hdr: hdr, msg: msg}); err != nil {
+ return fmt.Errorf("invalid config: %v", err)
+ }
+ } else {
+ if err := l.setMethodMethodLogger(s+"/"+m, &methodLoggerConfig{hdr: hdr, msg: msg}); err != nil {
+ return fmt.Errorf("invalid config: %v", err)
+ }
+ }
+ return nil
+}
+
+const (
+ // TODO: this const is only used by env_config now. But could be useful for
+ // other config. Move to binarylog.go if necessary.
+ maxUInt = ^uint64(0)
+
+ // For "p.s/m" plus any suffix. Suffix will be parsed again. See test for
+ // expected output.
+ longMethodConfigRegexpStr = `^([\w./]+)/((?:\w+)|[*])(.+)?$`
+
+ // For suffix from above, "{h:123,m:123}". See test for expected output.
+ optionalLengthRegexpStr = `(?::(\d+))?` // Optional ":123".
+ headerConfigRegexpStr = `^{h` + optionalLengthRegexpStr + `}$`
+ messageConfigRegexpStr = `^{m` + optionalLengthRegexpStr + `}$`
+ headerMessageConfigRegexpStr = `^{h` + optionalLengthRegexpStr + `;m` + optionalLengthRegexpStr + `}$`
+)
+
+var (
+ longMethodConfigRegexp = regexp.MustCompile(longMethodConfigRegexpStr)
+ headerConfigRegexp = regexp.MustCompile(headerConfigRegexpStr)
+ messageConfigRegexp = regexp.MustCompile(messageConfigRegexpStr)
+ headerMessageConfigRegexp = regexp.MustCompile(headerMessageConfigRegexpStr)
+)
+
+// Turn "service/method{h;m}" into "service", "method", "{h;m}".
+func parseMethodConfigAndSuffix(c string) (service, method, suffix string, _ error) {
+ // Regexp result:
+ //
+ // in: "p.s/m{h:123,m:123}",
+ // out: []string{"p.s/m{h:123,m:123}", "p.s", "m", "{h:123,m:123}"},
+ match := longMethodConfigRegexp.FindStringSubmatch(c)
+ if match == nil {
+ return "", "", "", fmt.Errorf("%q contains invalid substring", c)
+ }
+ service = match[1]
+ method = match[2]
+ suffix = match[3]
+ return
+}
+
+// Turn "{h:123;m:345}" into 123, 345.
+//
+// Return maxUInt if length is unspecified.
+func parseHeaderMessageLengthConfig(c string) (hdrLenStr, msgLenStr uint64, err error) {
+ if c == "" {
+ return maxUInt, maxUInt, nil
+ }
+ // Header config only.
+ if match := headerConfigRegexp.FindStringSubmatch(c); match != nil {
+ if s := match[1]; s != "" {
+ hdrLenStr, err = strconv.ParseUint(s, 10, 64)
+ if err != nil {
+ return 0, 0, fmt.Errorf("failed to convert %q to uint", s)
+ }
+ return hdrLenStr, 0, nil
+ }
+ return maxUInt, 0, nil
+ }
+
+ // Message config only.
+ if match := messageConfigRegexp.FindStringSubmatch(c); match != nil {
+ if s := match[1]; s != "" {
+ msgLenStr, err = strconv.ParseUint(s, 10, 64)
+ if err != nil {
+ return 0, 0, fmt.Errorf("Failed to convert %q to uint", s)
+ }
+ return 0, msgLenStr, nil
+ }
+ return 0, maxUInt, nil
+ }
+
+ // Header and message config both.
+ if match := headerMessageConfigRegexp.FindStringSubmatch(c); match != nil {
+ // Both hdr and msg are specified, but one or two of them might be empty.
+ hdrLenStr = maxUInt
+ msgLenStr = maxUInt
+ if s := match[1]; s != "" {
+ hdrLenStr, err = strconv.ParseUint(s, 10, 64)
+ if err != nil {
+ return 0, 0, fmt.Errorf("Failed to convert %q to uint", s)
+ }
+ }
+ if s := match[2]; s != "" {
+ msgLenStr, err = strconv.ParseUint(s, 10, 64)
+ if err != nil {
+ return 0, 0, fmt.Errorf("Failed to convert %q to uint", s)
+ }
+ }
+ return hdrLenStr, msgLenStr, nil
+ }
+ return 0, 0, fmt.Errorf("%q contains invalid substring", c)
+}
diff --git a/vendor/google.golang.org/grpc/internal/binarylog/method_logger.go b/vendor/google.golang.org/grpc/internal/binarylog/method_logger.go
new file mode 100644
index 000000000..b06cdd4d4
--- /dev/null
+++ b/vendor/google.golang.org/grpc/internal/binarylog/method_logger.go
@@ -0,0 +1,426 @@
+/*
+ *
+ * Copyright 2018 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package binarylog
+
+import (
+ "net"
+ "strings"
+ "sync/atomic"
+ "time"
+
+ "github.com/golang/protobuf/proto"
+ "github.com/golang/protobuf/ptypes"
+ pb "google.golang.org/grpc/binarylog/grpc_binarylog_v1"
+ "google.golang.org/grpc/grpclog"
+ "google.golang.org/grpc/metadata"
+ "google.golang.org/grpc/status"
+)
+
+type callIDGenerator struct {
+ id uint64
+}
+
+func (g *callIDGenerator) next() uint64 {
+ id := atomic.AddUint64(&g.id, 1)
+ return id
+}
+
+// reset is for testing only, and doesn't need to be thread safe.
+func (g *callIDGenerator) reset() {
+ g.id = 0
+}
+
+var idGen callIDGenerator
+
+// MethodLogger is the sub-logger for each method.
+type MethodLogger struct {
+ headerMaxLen, messageMaxLen uint64
+
+ callID uint64
+ idWithinCallGen *callIDGenerator
+
+ sink Sink // TODO(blog): make this plugable.
+}
+
+func newMethodLogger(h, m uint64) *MethodLogger {
+ return &MethodLogger{
+ headerMaxLen: h,
+ messageMaxLen: m,
+
+ callID: idGen.next(),
+ idWithinCallGen: &callIDGenerator{},
+
+ sink: defaultSink, // TODO(blog): make it plugable.
+ }
+}
+
+// Log creates a proto binary log entry, and logs it to the sink.
+func (ml *MethodLogger) Log(c LogEntryConfig) {
+ m := c.toProto()
+ timestamp, _ := ptypes.TimestampProto(time.Now())
+ m.Timestamp = timestamp
+ m.CallId = ml.callID
+ m.SequenceIdWithinCall = ml.idWithinCallGen.next()
+
+ switch pay := m.Payload.(type) {
+ case *pb.GrpcLogEntry_ClientHeader:
+ m.PayloadTruncated = ml.truncateMetadata(pay.ClientHeader.GetMetadata())
+ case *pb.GrpcLogEntry_ServerHeader:
+ m.PayloadTruncated = ml.truncateMetadata(pay.ServerHeader.GetMetadata())
+ case *pb.GrpcLogEntry_Message:
+ m.PayloadTruncated = ml.truncateMessage(pay.Message)
+ }
+
+ ml.sink.Write(m)
+}
+
+func (ml *MethodLogger) truncateMetadata(mdPb *pb.Metadata) (truncated bool) {
+ if ml.headerMaxLen == maxUInt {
+ return false
+ }
+ var (
+ bytesLimit = ml.headerMaxLen
+ index int
+ )
+ // At the end of the loop, index will be the first entry where the total
+ // size is greater than the limit:
+ //
+ // len(entry[:index]) <= ml.hdr && len(entry[:index+1]) > ml.hdr.
+ for ; index < len(mdPb.Entry); index++ {
+ entry := mdPb.Entry[index]
+ if entry.Key == "grpc-trace-bin" {
+ // "grpc-trace-bin" is a special key. It's kept in the log entry,
+ // but not counted towards the size limit.
+ continue
+ }
+ currentEntryLen := uint64(len(entry.Value))
+ if currentEntryLen > bytesLimit {
+ break
+ }
+ bytesLimit -= currentEntryLen
+ }
+ truncated = index < len(mdPb.Entry)
+ mdPb.Entry = mdPb.Entry[:index]
+ return truncated
+}
+
+func (ml *MethodLogger) truncateMessage(msgPb *pb.Message) (truncated bool) {
+ if ml.messageMaxLen == maxUInt {
+ return false
+ }
+ if ml.messageMaxLen >= uint64(len(msgPb.Data)) {
+ return false
+ }
+ msgPb.Data = msgPb.Data[:ml.messageMaxLen]
+ return true
+}
+
+// LogEntryConfig represents the configuration for binary log entry.
+type LogEntryConfig interface {
+ toProto() *pb.GrpcLogEntry
+}
+
+// ClientHeader configs the binary log entry to be a ClientHeader entry.
+type ClientHeader struct {
+ OnClientSide bool
+ Header metadata.MD
+ MethodName string
+ Authority string
+ Timeout time.Duration
+ // PeerAddr is required only when it's on server side.
+ PeerAddr net.Addr
+}
+
+func (c *ClientHeader) toProto() *pb.GrpcLogEntry {
+ // This function doesn't need to set all the fields (e.g. seq ID). The Log
+ // function will set the fields when necessary.
+ clientHeader := &pb.ClientHeader{
+ Metadata: mdToMetadataProto(c.Header),
+ MethodName: c.MethodName,
+ Authority: c.Authority,
+ }
+ if c.Timeout > 0 {
+ clientHeader.Timeout = ptypes.DurationProto(c.Timeout)
+ }
+ ret := &pb.GrpcLogEntry{
+ Type: pb.GrpcLogEntry_EVENT_TYPE_CLIENT_HEADER,
+ Payload: &pb.GrpcLogEntry_ClientHeader{
+ ClientHeader: clientHeader,
+ },
+ }
+ if c.OnClientSide {
+ ret.Logger = pb.GrpcLogEntry_LOGGER_CLIENT
+ } else {
+ ret.Logger = pb.GrpcLogEntry_LOGGER_SERVER
+ }
+ if c.PeerAddr != nil {
+ ret.Peer = addrToProto(c.PeerAddr)
+ }
+ return ret
+}
+
+// ServerHeader configs the binary log entry to be a ServerHeader entry.
+type ServerHeader struct {
+ OnClientSide bool
+ Header metadata.MD
+ // PeerAddr is required only when it's on client side.
+ PeerAddr net.Addr
+}
+
+func (c *ServerHeader) toProto() *pb.GrpcLogEntry {
+ ret := &pb.GrpcLogEntry{
+ Type: pb.GrpcLogEntry_EVENT_TYPE_SERVER_HEADER,
+ Payload: &pb.GrpcLogEntry_ServerHeader{
+ ServerHeader: &pb.ServerHeader{
+ Metadata: mdToMetadataProto(c.Header),
+ },
+ },
+ }
+ if c.OnClientSide {
+ ret.Logger = pb.GrpcLogEntry_LOGGER_CLIENT
+ } else {
+ ret.Logger = pb.GrpcLogEntry_LOGGER_SERVER
+ }
+ if c.PeerAddr != nil {
+ ret.Peer = addrToProto(c.PeerAddr)
+ }
+ return ret
+}
+
+// ClientMessage configs the binary log entry to be a ClientMessage entry.
+type ClientMessage struct {
+ OnClientSide bool
+ // Message can be a proto.Message or []byte. Other messages formats are not
+ // supported.
+ Message interface{}
+}
+
+func (c *ClientMessage) toProto() *pb.GrpcLogEntry {
+ var (
+ data []byte
+ err error
+ )
+ if m, ok := c.Message.(proto.Message); ok {
+ data, err = proto.Marshal(m)
+ if err != nil {
+ grpclog.Infof("binarylogging: failed to marshal proto message: %v", err)
+ }
+ } else if b, ok := c.Message.([]byte); ok {
+ data = b
+ } else {
+ grpclog.Infof("binarylogging: message to log is neither proto.message nor []byte")
+ }
+ ret := &pb.GrpcLogEntry{
+ Type: pb.GrpcLogEntry_EVENT_TYPE_CLIENT_MESSAGE,
+ Payload: &pb.GrpcLogEntry_Message{
+ Message: &pb.Message{
+ Length: uint32(len(data)),
+ Data: data,
+ },
+ },
+ }
+ if c.OnClientSide {
+ ret.Logger = pb.GrpcLogEntry_LOGGER_CLIENT
+ } else {
+ ret.Logger = pb.GrpcLogEntry_LOGGER_SERVER
+ }
+ return ret
+}
+
+// ServerMessage configs the binary log entry to be a ServerMessage entry.
+type ServerMessage struct {
+ OnClientSide bool
+ // Message can be a proto.Message or []byte. Other messages formats are not
+ // supported.
+ Message interface{}
+}
+
+func (c *ServerMessage) toProto() *pb.GrpcLogEntry {
+ var (
+ data []byte
+ err error
+ )
+ if m, ok := c.Message.(proto.Message); ok {
+ data, err = proto.Marshal(m)
+ if err != nil {
+ grpclog.Infof("binarylogging: failed to marshal proto message: %v", err)
+ }
+ } else if b, ok := c.Message.([]byte); ok {
+ data = b
+ } else {
+ grpclog.Infof("binarylogging: message to log is neither proto.message nor []byte")
+ }
+ ret := &pb.GrpcLogEntry{
+ Type: pb.GrpcLogEntry_EVENT_TYPE_SERVER_MESSAGE,
+ Payload: &pb.GrpcLogEntry_Message{
+ Message: &pb.Message{
+ Length: uint32(len(data)),
+ Data: data,
+ },
+ },
+ }
+ if c.OnClientSide {
+ ret.Logger = pb.GrpcLogEntry_LOGGER_CLIENT
+ } else {
+ ret.Logger = pb.GrpcLogEntry_LOGGER_SERVER
+ }
+ return ret
+}
+
+// ClientHalfClose configs the binary log entry to be a ClientHalfClose entry.
+type ClientHalfClose struct {
+ OnClientSide bool
+}
+
+func (c *ClientHalfClose) toProto() *pb.GrpcLogEntry {
+ ret := &pb.GrpcLogEntry{
+ Type: pb.GrpcLogEntry_EVENT_TYPE_CLIENT_HALF_CLOSE,
+ Payload: nil, // No payload here.
+ }
+ if c.OnClientSide {
+ ret.Logger = pb.GrpcLogEntry_LOGGER_CLIENT
+ } else {
+ ret.Logger = pb.GrpcLogEntry_LOGGER_SERVER
+ }
+ return ret
+}
+
+// ServerTrailer configs the binary log entry to be a ServerTrailer entry.
+type ServerTrailer struct {
+ OnClientSide bool
+ Trailer metadata.MD
+ // Err is the status error.
+ Err error
+ // PeerAddr is required only when it's on client side and the RPC is trailer
+ // only.
+ PeerAddr net.Addr
+}
+
+func (c *ServerTrailer) toProto() *pb.GrpcLogEntry {
+ st, ok := status.FromError(c.Err)
+ if !ok {
+ grpclog.Info("binarylogging: error in trailer is not a status error")
+ }
+ var (
+ detailsBytes []byte
+ err error
+ )
+ stProto := st.Proto()
+ if stProto != nil && len(stProto.Details) != 0 {
+ detailsBytes, err = proto.Marshal(stProto)
+ if err != nil {
+ grpclog.Infof("binarylogging: failed to marshal status proto: %v", err)
+ }
+ }
+ ret := &pb.GrpcLogEntry{
+ Type: pb.GrpcLogEntry_EVENT_TYPE_SERVER_TRAILER,
+ Payload: &pb.GrpcLogEntry_Trailer{
+ Trailer: &pb.Trailer{
+ Metadata: mdToMetadataProto(c.Trailer),
+ StatusCode: uint32(st.Code()),
+ StatusMessage: st.Message(),
+ StatusDetails: detailsBytes,
+ },
+ },
+ }
+ if c.OnClientSide {
+ ret.Logger = pb.GrpcLogEntry_LOGGER_CLIENT
+ } else {
+ ret.Logger = pb.GrpcLogEntry_LOGGER_SERVER
+ }
+ if c.PeerAddr != nil {
+ ret.Peer = addrToProto(c.PeerAddr)
+ }
+ return ret
+}
+
+// Cancel configs the binary log entry to be a Cancel entry.
+type Cancel struct {
+ OnClientSide bool
+}
+
+func (c *Cancel) toProto() *pb.GrpcLogEntry {
+ ret := &pb.GrpcLogEntry{
+ Type: pb.GrpcLogEntry_EVENT_TYPE_CANCEL,
+ Payload: nil,
+ }
+ if c.OnClientSide {
+ ret.Logger = pb.GrpcLogEntry_LOGGER_CLIENT
+ } else {
+ ret.Logger = pb.GrpcLogEntry_LOGGER_SERVER
+ }
+ return ret
+}
+
+// metadataKeyOmit returns whether the metadata entry with this key should be
+// omitted.
+func metadataKeyOmit(key string) bool {
+ switch key {
+ case "lb-token", ":path", ":authority", "content-encoding", "content-type", "user-agent", "te":
+ return true
+ case "grpc-trace-bin": // grpc-trace-bin is special because it's visiable to users.
+ return false
+ }
+ if strings.HasPrefix(key, "grpc-") {
+ return true
+ }
+ return false
+}
+
+func mdToMetadataProto(md metadata.MD) *pb.Metadata {
+ ret := &pb.Metadata{}
+ for k, vv := range md {
+ if metadataKeyOmit(k) {
+ continue
+ }
+ for _, v := range vv {
+ ret.Entry = append(ret.Entry,
+ &pb.MetadataEntry{
+ Key: k,
+ Value: []byte(v),
+ },
+ )
+ }
+ }
+ return ret
+}
+
+func addrToProto(addr net.Addr) *pb.Address {
+ ret := &pb.Address{}
+ switch a := addr.(type) {
+ case *net.TCPAddr:
+ if a.IP.To4() != nil {
+ ret.Type = pb.Address_TYPE_IPV4
+ } else if a.IP.To16() != nil {
+ ret.Type = pb.Address_TYPE_IPV6
+ } else {
+ ret.Type = pb.Address_TYPE_UNKNOWN
+ // Do not set address and port fields.
+ break
+ }
+ ret.Address = a.IP.String()
+ ret.IpPort = uint32(a.Port)
+ case *net.UnixAddr:
+ ret.Type = pb.Address_TYPE_UNIX
+ ret.Address = a.String()
+ default:
+ ret.Type = pb.Address_TYPE_UNKNOWN
+ }
+ return ret
+}
diff --git a/vendor/google.golang.org/grpc/internal/binarylog/regenerate.sh b/vendor/google.golang.org/grpc/internal/binarylog/regenerate.sh
new file mode 100755
index 000000000..113d40cbe
--- /dev/null
+++ b/vendor/google.golang.org/grpc/internal/binarylog/regenerate.sh
@@ -0,0 +1,33 @@
+#!/bin/bash
+# Copyright 2018 gRPC authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+set -eux -o pipefail
+
+TMP=$(mktemp -d)
+
+function finish {
+ rm -rf "$TMP"
+}
+trap finish EXIT
+
+pushd "$TMP"
+mkdir -p grpc/binarylog/grpc_binarylog_v1
+curl https://raw.githubusercontent.com/grpc/grpc-proto/master/grpc/binlog/v1/binarylog.proto > grpc/binarylog/grpc_binarylog_v1/binarylog.proto
+
+protoc --go_out=plugins=grpc,paths=source_relative:. -I. grpc/binarylog/grpc_binarylog_v1/*.proto
+popd
+rm -f ./grpc_binarylog_v1/*.pb.go
+cp "$TMP"/grpc/binarylog/grpc_binarylog_v1/*.pb.go ../../binarylog/grpc_binarylog_v1/
+
diff --git a/vendor/google.golang.org/grpc/internal/binarylog/sink.go b/vendor/google.golang.org/grpc/internal/binarylog/sink.go
new file mode 100644
index 000000000..20d044f0f
--- /dev/null
+++ b/vendor/google.golang.org/grpc/internal/binarylog/sink.go
@@ -0,0 +1,162 @@
+/*
+ *
+ * Copyright 2018 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package binarylog
+
+import (
+ "bufio"
+ "encoding/binary"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "sync"
+ "time"
+
+ "github.com/golang/protobuf/proto"
+ pb "google.golang.org/grpc/binarylog/grpc_binarylog_v1"
+ "google.golang.org/grpc/grpclog"
+)
+
+var (
+ defaultSink Sink = &noopSink{} // TODO(blog): change this default (file in /tmp).
+)
+
+// SetDefaultSink sets the sink where binary logs will be written to.
+//
+// Not thread safe. Only set during initialization.
+func SetDefaultSink(s Sink) {
+ if defaultSink != nil {
+ defaultSink.Close()
+ }
+ defaultSink = s
+}
+
+// Sink writes log entry into the binary log sink.
+type Sink interface {
+ // Write will be called to write the log entry into the sink.
+ //
+ // It should be thread-safe so it can be called in parallel.
+ Write(*pb.GrpcLogEntry) error
+ // Close will be called when the Sink is replaced by a new Sink.
+ Close() error
+}
+
+type noopSink struct{}
+
+func (ns *noopSink) Write(*pb.GrpcLogEntry) error { return nil }
+func (ns *noopSink) Close() error { return nil }
+
+// newWriterSink creates a binary log sink with the given writer.
+//
+// Write() marshalls the proto message and writes it to the given writer. Each
+// message is prefixed with a 4 byte big endian unsigned integer as the length.
+//
+// No buffer is done, Close() doesn't try to close the writer.
+func newWriterSink(w io.Writer) *writerSink {
+ return &writerSink{out: w}
+}
+
+type writerSink struct {
+ out io.Writer
+}
+
+func (ws *writerSink) Write(e *pb.GrpcLogEntry) error {
+ b, err := proto.Marshal(e)
+ if err != nil {
+ grpclog.Infof("binary logging: failed to marshal proto message: %v", err)
+ }
+ hdr := make([]byte, 4)
+ binary.BigEndian.PutUint32(hdr, uint32(len(b)))
+ if _, err := ws.out.Write(hdr); err != nil {
+ return err
+ }
+ if _, err := ws.out.Write(b); err != nil {
+ return err
+ }
+ return nil
+}
+
+func (ws *writerSink) Close() error { return nil }
+
+type bufWriteCloserSink struct {
+ mu sync.Mutex
+ closer io.Closer
+ out *writerSink // out is built on buf.
+ buf *bufio.Writer // buf is kept for flush.
+
+ writeStartOnce sync.Once
+ writeTicker *time.Ticker
+}
+
+func (fs *bufWriteCloserSink) Write(e *pb.GrpcLogEntry) error {
+ // Start the write loop when Write is called.
+ fs.writeStartOnce.Do(fs.startFlushGoroutine)
+ fs.mu.Lock()
+ if err := fs.out.Write(e); err != nil {
+ fs.mu.Unlock()
+ return err
+ }
+ fs.mu.Unlock()
+ return nil
+}
+
+const (
+ bufFlushDuration = 60 * time.Second
+)
+
+func (fs *bufWriteCloserSink) startFlushGoroutine() {
+ fs.writeTicker = time.NewTicker(bufFlushDuration)
+ go func() {
+ for range fs.writeTicker.C {
+ fs.mu.Lock()
+ fs.buf.Flush()
+ fs.mu.Unlock()
+ }
+ }()
+}
+
+func (fs *bufWriteCloserSink) Close() error {
+ if fs.writeTicker != nil {
+ fs.writeTicker.Stop()
+ }
+ fs.mu.Lock()
+ fs.buf.Flush()
+ fs.closer.Close()
+ fs.out.Close()
+ fs.mu.Unlock()
+ return nil
+}
+
+func newBufWriteCloserSink(o io.WriteCloser) Sink {
+ bufW := bufio.NewWriter(o)
+ return &bufWriteCloserSink{
+ closer: o,
+ out: newWriterSink(bufW),
+ buf: bufW,
+ }
+}
+
+// NewTempFileSink creates a temp file and returns a Sink that writes to this
+// file.
+func NewTempFileSink() (Sink, error) {
+ tempFile, err := ioutil.TempFile("/tmp", "grpcgo_binarylog_*.txt")
+ if err != nil {
+ return nil, fmt.Errorf("failed to create temp file: %v", err)
+ }
+ return newBufWriteCloserSink(tempFile), nil
+}
diff --git a/vendor/google.golang.org/grpc/internal/binarylog/util.go b/vendor/google.golang.org/grpc/internal/binarylog/util.go
new file mode 100644
index 000000000..15dc7803d
--- /dev/null
+++ b/vendor/google.golang.org/grpc/internal/binarylog/util.go
@@ -0,0 +1,41 @@
+/*
+ *
+ * Copyright 2018 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package binarylog
+
+import (
+ "errors"
+ "strings"
+)
+
+// parseMethodName splits service and method from the input. It expects format
+// "/service/method".
+//
+// TODO: move to internal/grpcutil.
+func parseMethodName(methodName string) (service, method string, _ error) {
+ if !strings.HasPrefix(methodName, "/") {
+ return "", "", errors.New("invalid method name: should start with /")
+ }
+ methodName = methodName[1:]
+
+ pos := strings.LastIndex(methodName, "/")
+ if pos < 0 {
+ return "", "", errors.New("invalid method name: suffix /method is missing")
+ }
+ return methodName[:pos], methodName[pos+1:], nil
+}
diff --git a/vendor/google.golang.org/grpc/internal/channelz/funcs.go b/vendor/google.golang.org/grpc/internal/channelz/funcs.go
new file mode 100644
index 000000000..3021a31a5
--- /dev/null
+++ b/vendor/google.golang.org/grpc/internal/channelz/funcs.go
@@ -0,0 +1,668 @@
+/*
+ *
+ * Copyright 2018 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// Package channelz defines APIs for enabling channelz service, entry
+// registration/deletion, and accessing channelz data. It also defines channelz
+// metric struct formats.
+//
+// All APIs in this package are experimental.
+package channelz
+
+import (
+ "sort"
+ "sync"
+ "sync/atomic"
+ "time"
+
+ "google.golang.org/grpc/grpclog"
+)
+
+const (
+ defaultMaxTraceEntry int32 = 30
+)
+
+var (
+ db dbWrapper
+ idGen idGenerator
+ // EntryPerPage defines the number of channelz entries to be shown on a web page.
+ EntryPerPage = 50
+ curState int32
+ maxTraceEntry = defaultMaxTraceEntry
+)
+
+// TurnOn turns on channelz data collection.
+func TurnOn() {
+ if !IsOn() {
+ NewChannelzStorage()
+ atomic.StoreInt32(&curState, 1)
+ }
+}
+
+// IsOn returns whether channelz data collection is on.
+func IsOn() bool {
+ return atomic.CompareAndSwapInt32(&curState, 1, 1)
+}
+
+// SetMaxTraceEntry sets maximum number of trace entry per entity (i.e. channel/subchannel).
+// Setting it to 0 will disable channel tracing.
+func SetMaxTraceEntry(i int32) {
+ atomic.StoreInt32(&maxTraceEntry, i)
+}
+
+// ResetMaxTraceEntryToDefault resets the maximum number of trace entry per entity to default.
+func ResetMaxTraceEntryToDefault() {
+ atomic.StoreInt32(&maxTraceEntry, defaultMaxTraceEntry)
+}
+
+func getMaxTraceEntry() int {
+ i := atomic.LoadInt32(&maxTraceEntry)
+ return int(i)
+}
+
+// dbWarpper wraps around a reference to internal channelz data storage, and
+// provide synchronized functionality to set and get the reference.
+type dbWrapper struct {
+ mu sync.RWMutex
+ DB *channelMap
+}
+
+func (d *dbWrapper) set(db *channelMap) {
+ d.mu.Lock()
+ d.DB = db
+ d.mu.Unlock()
+}
+
+func (d *dbWrapper) get() *channelMap {
+ d.mu.RLock()
+ defer d.mu.RUnlock()
+ return d.DB
+}
+
+// NewChannelzStorage initializes channelz data storage and id generator.
+//
+// Note: This function is exported for testing purpose only. User should not call
+// it in most cases.
+func NewChannelzStorage() {
+ db.set(&channelMap{
+ topLevelChannels: make(map[int64]struct{}),
+ channels: make(map[int64]*channel),
+ listenSockets: make(map[int64]*listenSocket),
+ normalSockets: make(map[int64]*normalSocket),
+ servers: make(map[int64]*server),
+ subChannels: make(map[int64]*subChannel),
+ })
+ idGen.reset()
+}
+
+// GetTopChannels returns a slice of top channel's ChannelMetric, along with a
+// boolean indicating whether there's more top channels to be queried for.
+//
+// The arg id specifies that only top channel with id at or above it will be included
+// in the result. The returned slice is up to a length of EntryPerPage, and is
+// sorted in ascending id order.
+func GetTopChannels(id int64) ([]*ChannelMetric, bool) {
+ return db.get().GetTopChannels(id)
+}
+
+// GetServers returns a slice of server's ServerMetric, along with a
+// boolean indicating whether there's more servers to be queried for.
+//
+// The arg id specifies that only server with id at or above it will be included
+// in the result. The returned slice is up to a length of EntryPerPage, and is
+// sorted in ascending id order.
+func GetServers(id int64) ([]*ServerMetric, bool) {
+ return db.get().GetServers(id)
+}
+
+// GetServerSockets returns a slice of server's (identified by id) normal socket's
+// SocketMetric, along with a boolean indicating whether there's more sockets to
+// be queried for.
+//
+// The arg startID specifies that only sockets with id at or above it will be
+// included in the result. The returned slice is up to a length of EntryPerPage,
+// and is sorted in ascending id order.
+func GetServerSockets(id int64, startID int64) ([]*SocketMetric, bool) {
+ return db.get().GetServerSockets(id, startID)
+}
+
+// GetChannel returns the ChannelMetric for the channel (identified by id).
+func GetChannel(id int64) *ChannelMetric {
+ return db.get().GetChannel(id)
+}
+
+// GetSubChannel returns the SubChannelMetric for the subchannel (identified by id).
+func GetSubChannel(id int64) *SubChannelMetric {
+ return db.get().GetSubChannel(id)
+}
+
+// GetSocket returns the SocketInternalMetric for the socket (identified by id).
+func GetSocket(id int64) *SocketMetric {
+ return db.get().GetSocket(id)
+}
+
+// RegisterChannel registers the given channel c in channelz database with ref
+// as its reference name, and add it to the child list of its parent (identified
+// by pid). pid = 0 means no parent. It returns the unique channelz tracking id
+// assigned to this channel.
+func RegisterChannel(c Channel, pid int64, ref string) int64 {
+ id := idGen.genID()
+ cn := &channel{
+ refName: ref,
+ c: c,
+ subChans: make(map[int64]string),
+ nestedChans: make(map[int64]string),
+ id: id,
+ pid: pid,
+ trace: &channelTrace{createdTime: time.Now(), events: make([]*TraceEvent, 0, getMaxTraceEntry())},
+ }
+ if pid == 0 {
+ db.get().addChannel(id, cn, true, pid, ref)
+ } else {
+ db.get().addChannel(id, cn, false, pid, ref)
+ }
+ return id
+}
+
+// RegisterSubChannel registers the given channel c in channelz database with ref
+// as its reference name, and add it to the child list of its parent (identified
+// by pid). It returns the unique channelz tracking id assigned to this subchannel.
+func RegisterSubChannel(c Channel, pid int64, ref string) int64 {
+ if pid == 0 {
+ grpclog.Error("a SubChannel's parent id cannot be 0")
+ return 0
+ }
+ id := idGen.genID()
+ sc := &subChannel{
+ refName: ref,
+ c: c,
+ sockets: make(map[int64]string),
+ id: id,
+ pid: pid,
+ trace: &channelTrace{createdTime: time.Now(), events: make([]*TraceEvent, 0, getMaxTraceEntry())},
+ }
+ db.get().addSubChannel(id, sc, pid, ref)
+ return id
+}
+
+// RegisterServer registers the given server s in channelz database. It returns
+// the unique channelz tracking id assigned to this server.
+func RegisterServer(s Server, ref string) int64 {
+ id := idGen.genID()
+ svr := &server{
+ refName: ref,
+ s: s,
+ sockets: make(map[int64]string),
+ listenSockets: make(map[int64]string),
+ id: id,
+ }
+ db.get().addServer(id, svr)
+ return id
+}
+
+// RegisterListenSocket registers the given listen socket s in channelz database
+// with ref as its reference name, and add it to the child list of its parent
+// (identified by pid). It returns the unique channelz tracking id assigned to
+// this listen socket.
+func RegisterListenSocket(s Socket, pid int64, ref string) int64 {
+ if pid == 0 {
+ grpclog.Error("a ListenSocket's parent id cannot be 0")
+ return 0
+ }
+ id := idGen.genID()
+ ls := &listenSocket{refName: ref, s: s, id: id, pid: pid}
+ db.get().addListenSocket(id, ls, pid, ref)
+ return id
+}
+
+// RegisterNormalSocket registers the given normal socket s in channelz database
+// with ref as its reference name, and add it to the child list of its parent
+// (identified by pid). It returns the unique channelz tracking id assigned to
+// this normal socket.
+func RegisterNormalSocket(s Socket, pid int64, ref string) int64 {
+ if pid == 0 {
+ grpclog.Error("a NormalSocket's parent id cannot be 0")
+ return 0
+ }
+ id := idGen.genID()
+ ns := &normalSocket{refName: ref, s: s, id: id, pid: pid}
+ db.get().addNormalSocket(id, ns, pid, ref)
+ return id
+}
+
+// RemoveEntry removes an entry with unique channelz trakcing id to be id from
+// channelz database.
+func RemoveEntry(id int64) {
+ db.get().removeEntry(id)
+}
+
+// TraceEventDesc is what the caller of AddTraceEvent should provide to describe the event to be added
+// to the channel trace.
+// The Parent field is optional. It is used for event that will be recorded in the entity's parent
+// trace also.
+type TraceEventDesc struct {
+ Desc string
+ Severity Severity
+ Parent *TraceEventDesc
+}
+
+// AddTraceEvent adds trace related to the entity with specified id, using the provided TraceEventDesc.
+func AddTraceEvent(id int64, desc *TraceEventDesc) {
+ if getMaxTraceEntry() == 0 {
+ return
+ }
+ db.get().traceEvent(id, desc)
+}
+
+// channelMap is the storage data structure for channelz.
+// Methods of channelMap can be divided in two two categories with respect to locking.
+// 1. Methods acquire the global lock.
+// 2. Methods that can only be called when global lock is held.
+// A second type of method need always to be called inside a first type of method.
+type channelMap struct {
+ mu sync.RWMutex
+ topLevelChannels map[int64]struct{}
+ servers map[int64]*server
+ channels map[int64]*channel
+ subChannels map[int64]*subChannel
+ listenSockets map[int64]*listenSocket
+ normalSockets map[int64]*normalSocket
+}
+
+func (c *channelMap) addServer(id int64, s *server) {
+ c.mu.Lock()
+ s.cm = c
+ c.servers[id] = s
+ c.mu.Unlock()
+}
+
+func (c *channelMap) addChannel(id int64, cn *channel, isTopChannel bool, pid int64, ref string) {
+ c.mu.Lock()
+ cn.cm = c
+ cn.trace.cm = c
+ c.channels[id] = cn
+ if isTopChannel {
+ c.topLevelChannels[id] = struct{}{}
+ } else {
+ c.findEntry(pid).addChild(id, cn)
+ }
+ c.mu.Unlock()
+}
+
+func (c *channelMap) addSubChannel(id int64, sc *subChannel, pid int64, ref string) {
+ c.mu.Lock()
+ sc.cm = c
+ sc.trace.cm = c
+ c.subChannels[id] = sc
+ c.findEntry(pid).addChild(id, sc)
+ c.mu.Unlock()
+}
+
+func (c *channelMap) addListenSocket(id int64, ls *listenSocket, pid int64, ref string) {
+ c.mu.Lock()
+ ls.cm = c
+ c.listenSockets[id] = ls
+ c.findEntry(pid).addChild(id, ls)
+ c.mu.Unlock()
+}
+
+func (c *channelMap) addNormalSocket(id int64, ns *normalSocket, pid int64, ref string) {
+ c.mu.Lock()
+ ns.cm = c
+ c.normalSockets[id] = ns
+ c.findEntry(pid).addChild(id, ns)
+ c.mu.Unlock()
+}
+
+// removeEntry triggers the removal of an entry, which may not indeed delete the entry, if it has to
+// wait on the deletion of its children and until no other entity's channel trace references it.
+// It may lead to a chain of entry deletion. For example, deleting the last socket of a gracefully
+// shutting down server will lead to the server being also deleted.
+func (c *channelMap) removeEntry(id int64) {
+ c.mu.Lock()
+ c.findEntry(id).triggerDelete()
+ c.mu.Unlock()
+}
+
+// c.mu must be held by the caller
+func (c *channelMap) decrTraceRefCount(id int64) {
+ e := c.findEntry(id)
+ if v, ok := e.(tracedChannel); ok {
+ v.decrTraceRefCount()
+ e.deleteSelfIfReady()
+ }
+}
+
+// c.mu must be held by the caller.
+func (c *channelMap) findEntry(id int64) entry {
+ var v entry
+ var ok bool
+ if v, ok = c.channels[id]; ok {
+ return v
+ }
+ if v, ok = c.subChannels[id]; ok {
+ return v
+ }
+ if v, ok = c.servers[id]; ok {
+ return v
+ }
+ if v, ok = c.listenSockets[id]; ok {
+ return v
+ }
+ if v, ok = c.normalSockets[id]; ok {
+ return v
+ }
+ return &dummyEntry{idNotFound: id}
+}
+
+// c.mu must be held by the caller
+// deleteEntry simply deletes an entry from the channelMap. Before calling this
+// method, caller must check this entry is ready to be deleted, i.e removeEntry()
+// has been called on it, and no children still exist.
+// Conditionals are ordered by the expected frequency of deletion of each entity
+// type, in order to optimize performance.
+func (c *channelMap) deleteEntry(id int64) {
+ var ok bool
+ if _, ok = c.normalSockets[id]; ok {
+ delete(c.normalSockets, id)
+ return
+ }
+ if _, ok = c.subChannels[id]; ok {
+ delete(c.subChannels, id)
+ return
+ }
+ if _, ok = c.channels[id]; ok {
+ delete(c.channels, id)
+ delete(c.topLevelChannels, id)
+ return
+ }
+ if _, ok = c.listenSockets[id]; ok {
+ delete(c.listenSockets, id)
+ return
+ }
+ if _, ok = c.servers[id]; ok {
+ delete(c.servers, id)
+ return
+ }
+}
+
+func (c *channelMap) traceEvent(id int64, desc *TraceEventDesc) {
+ c.mu.Lock()
+ child := c.findEntry(id)
+ childTC, ok := child.(tracedChannel)
+ if !ok {
+ c.mu.Unlock()
+ return
+ }
+ childTC.getChannelTrace().append(&TraceEvent{Desc: desc.Desc, Severity: desc.Severity, Timestamp: time.Now()})
+ if desc.Parent != nil {
+ parent := c.findEntry(child.getParentID())
+ var chanType RefChannelType
+ switch child.(type) {
+ case *channel:
+ chanType = RefChannel
+ case *subChannel:
+ chanType = RefSubChannel
+ }
+ if parentTC, ok := parent.(tracedChannel); ok {
+ parentTC.getChannelTrace().append(&TraceEvent{
+ Desc: desc.Parent.Desc,
+ Severity: desc.Parent.Severity,
+ Timestamp: time.Now(),
+ RefID: id,
+ RefName: childTC.getRefName(),
+ RefType: chanType,
+ })
+ childTC.incrTraceRefCount()
+ }
+ }
+ c.mu.Unlock()
+}
+
+type int64Slice []int64
+
+func (s int64Slice) Len() int { return len(s) }
+func (s int64Slice) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
+func (s int64Slice) Less(i, j int) bool { return s[i] < s[j] }
+
+func copyMap(m map[int64]string) map[int64]string {
+ n := make(map[int64]string)
+ for k, v := range m {
+ n[k] = v
+ }
+ return n
+}
+
+func min(a, b int) int {
+ if a < b {
+ return a
+ }
+ return b
+}
+
+func (c *channelMap) GetTopChannels(id int64) ([]*ChannelMetric, bool) {
+ c.mu.RLock()
+ l := len(c.topLevelChannels)
+ ids := make([]int64, 0, l)
+ cns := make([]*channel, 0, min(l, EntryPerPage))
+
+ for k := range c.topLevelChannels {
+ ids = append(ids, k)
+ }
+ sort.Sort(int64Slice(ids))
+ idx := sort.Search(len(ids), func(i int) bool { return ids[i] >= id })
+ count := 0
+ var end bool
+ var t []*ChannelMetric
+ for i, v := range ids[idx:] {
+ if count == EntryPerPage {
+ break
+ }
+ if cn, ok := c.channels[v]; ok {
+ cns = append(cns, cn)
+ t = append(t, &ChannelMetric{
+ NestedChans: copyMap(cn.nestedChans),
+ SubChans: copyMap(cn.subChans),
+ })
+ count++
+ }
+ if i == len(ids[idx:])-1 {
+ end = true
+ break
+ }
+ }
+ c.mu.RUnlock()
+ if count == 0 {
+ end = true
+ }
+
+ for i, cn := range cns {
+ t[i].ChannelData = cn.c.ChannelzMetric()
+ t[i].ID = cn.id
+ t[i].RefName = cn.refName
+ t[i].Trace = cn.trace.dumpData()
+ }
+ return t, end
+}
+
+func (c *channelMap) GetServers(id int64) ([]*ServerMetric, bool) {
+ c.mu.RLock()
+ l := len(c.servers)
+ ids := make([]int64, 0, l)
+ ss := make([]*server, 0, min(l, EntryPerPage))
+ for k := range c.servers {
+ ids = append(ids, k)
+ }
+ sort.Sort(int64Slice(ids))
+ idx := sort.Search(len(ids), func(i int) bool { return ids[i] >= id })
+ count := 0
+ var end bool
+ var s []*ServerMetric
+ for i, v := range ids[idx:] {
+ if count == EntryPerPage {
+ break
+ }
+ if svr, ok := c.servers[v]; ok {
+ ss = append(ss, svr)
+ s = append(s, &ServerMetric{
+ ListenSockets: copyMap(svr.listenSockets),
+ })
+ count++
+ }
+ if i == len(ids[idx:])-1 {
+ end = true
+ break
+ }
+ }
+ c.mu.RUnlock()
+ if count == 0 {
+ end = true
+ }
+
+ for i, svr := range ss {
+ s[i].ServerData = svr.s.ChannelzMetric()
+ s[i].ID = svr.id
+ s[i].RefName = svr.refName
+ }
+ return s, end
+}
+
+func (c *channelMap) GetServerSockets(id int64, startID int64) ([]*SocketMetric, bool) {
+ var svr *server
+ var ok bool
+ c.mu.RLock()
+ if svr, ok = c.servers[id]; !ok {
+ // server with id doesn't exist.
+ c.mu.RUnlock()
+ return nil, true
+ }
+ svrskts := svr.sockets
+ l := len(svrskts)
+ ids := make([]int64, 0, l)
+ sks := make([]*normalSocket, 0, min(l, EntryPerPage))
+ for k := range svrskts {
+ ids = append(ids, k)
+ }
+ sort.Sort(int64Slice(ids))
+ idx := sort.Search(len(ids), func(i int) bool { return ids[i] >= startID })
+ count := 0
+ var end bool
+ for i, v := range ids[idx:] {
+ if count == EntryPerPage {
+ break
+ }
+ if ns, ok := c.normalSockets[v]; ok {
+ sks = append(sks, ns)
+ count++
+ }
+ if i == len(ids[idx:])-1 {
+ end = true
+ break
+ }
+ }
+ c.mu.RUnlock()
+ if count == 0 {
+ end = true
+ }
+ var s []*SocketMetric
+ for _, ns := range sks {
+ sm := &SocketMetric{}
+ sm.SocketData = ns.s.ChannelzMetric()
+ sm.ID = ns.id
+ sm.RefName = ns.refName
+ s = append(s, sm)
+ }
+ return s, end
+}
+
+func (c *channelMap) GetChannel(id int64) *ChannelMetric {
+ cm := &ChannelMetric{}
+ var cn *channel
+ var ok bool
+ c.mu.RLock()
+ if cn, ok = c.channels[id]; !ok {
+ // channel with id doesn't exist.
+ c.mu.RUnlock()
+ return nil
+ }
+ cm.NestedChans = copyMap(cn.nestedChans)
+ cm.SubChans = copyMap(cn.subChans)
+ // cn.c can be set to &dummyChannel{} when deleteSelfFromMap is called. Save a copy of cn.c when
+ // holding the lock to prevent potential data race.
+ chanCopy := cn.c
+ c.mu.RUnlock()
+ cm.ChannelData = chanCopy.ChannelzMetric()
+ cm.ID = cn.id
+ cm.RefName = cn.refName
+ cm.Trace = cn.trace.dumpData()
+ return cm
+}
+
+func (c *channelMap) GetSubChannel(id int64) *SubChannelMetric {
+ cm := &SubChannelMetric{}
+ var sc *subChannel
+ var ok bool
+ c.mu.RLock()
+ if sc, ok = c.subChannels[id]; !ok {
+ // subchannel with id doesn't exist.
+ c.mu.RUnlock()
+ return nil
+ }
+ cm.Sockets = copyMap(sc.sockets)
+ // sc.c can be set to &dummyChannel{} when deleteSelfFromMap is called. Save a copy of sc.c when
+ // holding the lock to prevent potential data race.
+ chanCopy := sc.c
+ c.mu.RUnlock()
+ cm.ChannelData = chanCopy.ChannelzMetric()
+ cm.ID = sc.id
+ cm.RefName = sc.refName
+ cm.Trace = sc.trace.dumpData()
+ return cm
+}
+
+func (c *channelMap) GetSocket(id int64) *SocketMetric {
+ sm := &SocketMetric{}
+ c.mu.RLock()
+ if ls, ok := c.listenSockets[id]; ok {
+ c.mu.RUnlock()
+ sm.SocketData = ls.s.ChannelzMetric()
+ sm.ID = ls.id
+ sm.RefName = ls.refName
+ return sm
+ }
+ if ns, ok := c.normalSockets[id]; ok {
+ c.mu.RUnlock()
+ sm.SocketData = ns.s.ChannelzMetric()
+ sm.ID = ns.id
+ sm.RefName = ns.refName
+ return sm
+ }
+ c.mu.RUnlock()
+ return nil
+}
+
+type idGenerator struct {
+ id int64
+}
+
+func (i *idGenerator) reset() {
+ atomic.StoreInt64(&i.id, 0)
+}
+
+func (i *idGenerator) genID() int64 {
+ return atomic.AddInt64(&i.id, 1)
+}
diff --git a/vendor/google.golang.org/grpc/internal/channelz/types.go b/vendor/google.golang.org/grpc/internal/channelz/types.go
new file mode 100644
index 000000000..17c2274cb
--- /dev/null
+++ b/vendor/google.golang.org/grpc/internal/channelz/types.go
@@ -0,0 +1,702 @@
+/*
+ *
+ * Copyright 2018 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package channelz
+
+import (
+ "net"
+ "sync"
+ "sync/atomic"
+ "time"
+
+ "google.golang.org/grpc/connectivity"
+ "google.golang.org/grpc/credentials"
+ "google.golang.org/grpc/grpclog"
+)
+
+// entry represents a node in the channelz database.
+type entry interface {
+ // addChild adds a child e, whose channelz id is id to child list
+ addChild(id int64, e entry)
+ // deleteChild deletes a child with channelz id to be id from child list
+ deleteChild(id int64)
+ // triggerDelete tries to delete self from channelz database. However, if child
+ // list is not empty, then deletion from the database is on hold until the last
+ // child is deleted from database.
+ triggerDelete()
+ // deleteSelfIfReady check whether triggerDelete() has been called before, and whether child
+ // list is now empty. If both conditions are met, then delete self from database.
+ deleteSelfIfReady()
+ // getParentID returns parent ID of the entry. 0 value parent ID means no parent.
+ getParentID() int64
+}
+
+// dummyEntry is a fake entry to handle entry not found case.
+type dummyEntry struct {
+ idNotFound int64
+}
+
+func (d *dummyEntry) addChild(id int64, e entry) {
+ // Note: It is possible for a normal program to reach here under race condition.
+ // For example, there could be a race between ClientConn.Close() info being propagated
+ // to addrConn and http2Client. ClientConn.Close() cancel the context and result
+ // in http2Client to error. The error info is then caught by transport monitor
+ // and before addrConn.tearDown() is called in side ClientConn.Close(). Therefore,
+ // the addrConn will create a new transport. And when registering the new transport in
+ // channelz, its parent addrConn could have already been torn down and deleted
+ // from channelz tracking, and thus reach the code here.
+ grpclog.Infof("attempt to add child of type %T with id %d to a parent (id=%d) that doesn't currently exist", e, id, d.idNotFound)
+}
+
+func (d *dummyEntry) deleteChild(id int64) {
+ // It is possible for a normal program to reach here under race condition.
+ // Refer to the example described in addChild().
+ grpclog.Infof("attempt to delete child with id %d from a parent (id=%d) that doesn't currently exist", id, d.idNotFound)
+}
+
+func (d *dummyEntry) triggerDelete() {
+ grpclog.Warningf("attempt to delete an entry (id=%d) that doesn't currently exist", d.idNotFound)
+}
+
+func (*dummyEntry) deleteSelfIfReady() {
+ // code should not reach here. deleteSelfIfReady is always called on an existing entry.
+}
+
+func (*dummyEntry) getParentID() int64 {
+ return 0
+}
+
+// ChannelMetric defines the info channelz provides for a specific Channel, which
+// includes ChannelInternalMetric and channelz-specific data, such as channelz id,
+// child list, etc.
+type ChannelMetric struct {
+ // ID is the channelz id of this channel.
+ ID int64
+ // RefName is the human readable reference string of this channel.
+ RefName string
+ // ChannelData contains channel internal metric reported by the channel through
+ // ChannelzMetric().
+ ChannelData *ChannelInternalMetric
+ // NestedChans tracks the nested channel type children of this channel in the format of
+ // a map from nested channel channelz id to corresponding reference string.
+ NestedChans map[int64]string
+ // SubChans tracks the subchannel type children of this channel in the format of a
+ // map from subchannel channelz id to corresponding reference string.
+ SubChans map[int64]string
+ // Sockets tracks the socket type children of this channel in the format of a map
+ // from socket channelz id to corresponding reference string.
+ // Note current grpc implementation doesn't allow channel having sockets directly,
+ // therefore, this is field is unused.
+ Sockets map[int64]string
+ // Trace contains the most recent traced events.
+ Trace *ChannelTrace
+}
+
+// SubChannelMetric defines the info channelz provides for a specific SubChannel,
+// which includes ChannelInternalMetric and channelz-specific data, such as
+// channelz id, child list, etc.
+type SubChannelMetric struct {
+ // ID is the channelz id of this subchannel.
+ ID int64
+ // RefName is the human readable reference string of this subchannel.
+ RefName string
+ // ChannelData contains subchannel internal metric reported by the subchannel
+ // through ChannelzMetric().
+ ChannelData *ChannelInternalMetric
+ // NestedChans tracks the nested channel type children of this subchannel in the format of
+ // a map from nested channel channelz id to corresponding reference string.
+ // Note current grpc implementation doesn't allow subchannel to have nested channels
+ // as children, therefore, this field is unused.
+ NestedChans map[int64]string
+ // SubChans tracks the subchannel type children of this subchannel in the format of a
+ // map from subchannel channelz id to corresponding reference string.
+ // Note current grpc implementation doesn't allow subchannel to have subchannels
+ // as children, therefore, this field is unused.
+ SubChans map[int64]string
+ // Sockets tracks the socket type children of this subchannel in the format of a map
+ // from socket channelz id to corresponding reference string.
+ Sockets map[int64]string
+ // Trace contains the most recent traced events.
+ Trace *ChannelTrace
+}
+
+// ChannelInternalMetric defines the struct that the implementor of Channel interface
+// should return from ChannelzMetric().
+type ChannelInternalMetric struct {
+ // current connectivity state of the channel.
+ State connectivity.State
+ // The target this channel originally tried to connect to. May be absent
+ Target string
+ // The number of calls started on the channel.
+ CallsStarted int64
+ // The number of calls that have completed with an OK status.
+ CallsSucceeded int64
+ // The number of calls that have a completed with a non-OK status.
+ CallsFailed int64
+ // The last time a call was started on the channel.
+ LastCallStartedTimestamp time.Time
+}
+
+// ChannelTrace stores traced events on a channel/subchannel and related info.
+type ChannelTrace struct {
+ // EventNum is the number of events that ever got traced (i.e. including those that have been deleted)
+ EventNum int64
+ // CreationTime is the creation time of the trace.
+ CreationTime time.Time
+ // Events stores the most recent trace events (up to $maxTraceEntry, newer event will overwrite the
+ // oldest one)
+ Events []*TraceEvent
+}
+
+// TraceEvent represent a single trace event
+type TraceEvent struct {
+ // Desc is a simple description of the trace event.
+ Desc string
+ // Severity states the severity of this trace event.
+ Severity Severity
+ // Timestamp is the event time.
+ Timestamp time.Time
+ // RefID is the id of the entity that gets referenced in the event. RefID is 0 if no other entity is
+ // involved in this event.
+ // e.g. SubChannel (id: 4[]) Created. --> RefID = 4, RefName = "" (inside [])
+ RefID int64
+ // RefName is the reference name for the entity that gets referenced in the event.
+ RefName string
+ // RefType indicates the referenced entity type, i.e Channel or SubChannel.
+ RefType RefChannelType
+}
+
+// Channel is the interface that should be satisfied in order to be tracked by
+// channelz as Channel or SubChannel.
+type Channel interface {
+ ChannelzMetric() *ChannelInternalMetric
+}
+
+type dummyChannel struct{}
+
+func (d *dummyChannel) ChannelzMetric() *ChannelInternalMetric {
+ return &ChannelInternalMetric{}
+}
+
+type channel struct {
+ refName string
+ c Channel
+ closeCalled bool
+ nestedChans map[int64]string
+ subChans map[int64]string
+ id int64
+ pid int64
+ cm *channelMap
+ trace *channelTrace
+ // traceRefCount is the number of trace events that reference this channel.
+ // Non-zero traceRefCount means the trace of this channel cannot be deleted.
+ traceRefCount int32
+}
+
+func (c *channel) addChild(id int64, e entry) {
+ switch v := e.(type) {
+ case *subChannel:
+ c.subChans[id] = v.refName
+ case *channel:
+ c.nestedChans[id] = v.refName
+ default:
+ grpclog.Errorf("cannot add a child (id = %d) of type %T to a channel", id, e)
+ }
+}
+
+func (c *channel) deleteChild(id int64) {
+ delete(c.subChans, id)
+ delete(c.nestedChans, id)
+ c.deleteSelfIfReady()
+}
+
+func (c *channel) triggerDelete() {
+ c.closeCalled = true
+ c.deleteSelfIfReady()
+}
+
+func (c *channel) getParentID() int64 {
+ return c.pid
+}
+
+// deleteSelfFromTree tries to delete the channel from the channelz entry relation tree, which means
+// deleting the channel reference from its parent's child list.
+//
+// In order for a channel to be deleted from the tree, it must meet the criteria that, removal of the
+// corresponding grpc object has been invoked, and the channel does not have any children left.
+//
+// The returned boolean value indicates whether the channel has been successfully deleted from tree.
+func (c *channel) deleteSelfFromTree() (deleted bool) {
+ if !c.closeCalled || len(c.subChans)+len(c.nestedChans) != 0 {
+ return false
+ }
+ // not top channel
+ if c.pid != 0 {
+ c.cm.findEntry(c.pid).deleteChild(c.id)
+ }
+ return true
+}
+
+// deleteSelfFromMap checks whether it is valid to delete the channel from the map, which means
+// deleting the channel from channelz's tracking entirely. Users can no longer use id to query the
+// channel, and its memory will be garbage collected.
+//
+// The trace reference count of the channel must be 0 in order to be deleted from the map. This is
+// specified in the channel tracing gRFC that as long as some other trace has reference to an entity,
+// the trace of the referenced entity must not be deleted. In order to release the resource allocated
+// by grpc, the reference to the grpc object is reset to a dummy object.
+//
+// deleteSelfFromMap must be called after deleteSelfFromTree returns true.
+//
+// It returns a bool to indicate whether the channel can be safely deleted from map.
+func (c *channel) deleteSelfFromMap() (delete bool) {
+ if c.getTraceRefCount() != 0 {
+ c.c = &dummyChannel{}
+ return false
+ }
+ return true
+}
+
+// deleteSelfIfReady tries to delete the channel itself from the channelz database.
+// The delete process includes two steps:
+// 1. delete the channel from the entry relation tree, i.e. delete the channel reference from its
+// parent's child list.
+// 2. delete the channel from the map, i.e. delete the channel entirely from channelz. Lookup by id
+// will return entry not found error.
+func (c *channel) deleteSelfIfReady() {
+ if !c.deleteSelfFromTree() {
+ return
+ }
+ if !c.deleteSelfFromMap() {
+ return
+ }
+ c.cm.deleteEntry(c.id)
+ c.trace.clear()
+}
+
+func (c *channel) getChannelTrace() *channelTrace {
+ return c.trace
+}
+
+func (c *channel) incrTraceRefCount() {
+ atomic.AddInt32(&c.traceRefCount, 1)
+}
+
+func (c *channel) decrTraceRefCount() {
+ atomic.AddInt32(&c.traceRefCount, -1)
+}
+
+func (c *channel) getTraceRefCount() int {
+ i := atomic.LoadInt32(&c.traceRefCount)
+ return int(i)
+}
+
+func (c *channel) getRefName() string {
+ return c.refName
+}
+
+type subChannel struct {
+ refName string
+ c Channel
+ closeCalled bool
+ sockets map[int64]string
+ id int64
+ pid int64
+ cm *channelMap
+ trace *channelTrace
+ traceRefCount int32
+}
+
+func (sc *subChannel) addChild(id int64, e entry) {
+ if v, ok := e.(*normalSocket); ok {
+ sc.sockets[id] = v.refName
+ } else {
+ grpclog.Errorf("cannot add a child (id = %d) of type %T to a subChannel", id, e)
+ }
+}
+
+func (sc *subChannel) deleteChild(id int64) {
+ delete(sc.sockets, id)
+ sc.deleteSelfIfReady()
+}
+
+func (sc *subChannel) triggerDelete() {
+ sc.closeCalled = true
+ sc.deleteSelfIfReady()
+}
+
+func (sc *subChannel) getParentID() int64 {
+ return sc.pid
+}
+
+// deleteSelfFromTree tries to delete the subchannel from the channelz entry relation tree, which
+// means deleting the subchannel reference from its parent's child list.
+//
+// In order for a subchannel to be deleted from the tree, it must meet the criteria that, removal of
+// the corresponding grpc object has been invoked, and the subchannel does not have any children left.
+//
+// The returned boolean value indicates whether the channel has been successfully deleted from tree.
+func (sc *subChannel) deleteSelfFromTree() (deleted bool) {
+ if !sc.closeCalled || len(sc.sockets) != 0 {
+ return false
+ }
+ sc.cm.findEntry(sc.pid).deleteChild(sc.id)
+ return true
+}
+
+// deleteSelfFromMap checks whether it is valid to delete the subchannel from the map, which means
+// deleting the subchannel from channelz's tracking entirely. Users can no longer use id to query
+// the subchannel, and its memory will be garbage collected.
+//
+// The trace reference count of the subchannel must be 0 in order to be deleted from the map. This is
+// specified in the channel tracing gRFC that as long as some other trace has reference to an entity,
+// the trace of the referenced entity must not be deleted. In order to release the resource allocated
+// by grpc, the reference to the grpc object is reset to a dummy object.
+//
+// deleteSelfFromMap must be called after deleteSelfFromTree returns true.
+//
+// It returns a bool to indicate whether the channel can be safely deleted from map.
+func (sc *subChannel) deleteSelfFromMap() (delete bool) {
+ if sc.getTraceRefCount() != 0 {
+ // free the grpc struct (i.e. addrConn)
+ sc.c = &dummyChannel{}
+ return false
+ }
+ return true
+}
+
+// deleteSelfIfReady tries to delete the subchannel itself from the channelz database.
+// The delete process includes two steps:
+// 1. delete the subchannel from the entry relation tree, i.e. delete the subchannel reference from
+// its parent's child list.
+// 2. delete the subchannel from the map, i.e. delete the subchannel entirely from channelz. Lookup
+// by id will return entry not found error.
+func (sc *subChannel) deleteSelfIfReady() {
+ if !sc.deleteSelfFromTree() {
+ return
+ }
+ if !sc.deleteSelfFromMap() {
+ return
+ }
+ sc.cm.deleteEntry(sc.id)
+ sc.trace.clear()
+}
+
+func (sc *subChannel) getChannelTrace() *channelTrace {
+ return sc.trace
+}
+
+func (sc *subChannel) incrTraceRefCount() {
+ atomic.AddInt32(&sc.traceRefCount, 1)
+}
+
+func (sc *subChannel) decrTraceRefCount() {
+ atomic.AddInt32(&sc.traceRefCount, -1)
+}
+
+func (sc *subChannel) getTraceRefCount() int {
+ i := atomic.LoadInt32(&sc.traceRefCount)
+ return int(i)
+}
+
+func (sc *subChannel) getRefName() string {
+ return sc.refName
+}
+
+// SocketMetric defines the info channelz provides for a specific Socket, which
+// includes SocketInternalMetric and channelz-specific data, such as channelz id, etc.
+type SocketMetric struct {
+ // ID is the channelz id of this socket.
+ ID int64
+ // RefName is the human readable reference string of this socket.
+ RefName string
+ // SocketData contains socket internal metric reported by the socket through
+ // ChannelzMetric().
+ SocketData *SocketInternalMetric
+}
+
+// SocketInternalMetric defines the struct that the implementor of Socket interface
+// should return from ChannelzMetric().
+type SocketInternalMetric struct {
+ // The number of streams that have been started.
+ StreamsStarted int64
+ // The number of streams that have ended successfully:
+ // On client side, receiving frame with eos bit set.
+ // On server side, sending frame with eos bit set.
+ StreamsSucceeded int64
+ // The number of streams that have ended unsuccessfully:
+ // On client side, termination without receiving frame with eos bit set.
+ // On server side, termination without sending frame with eos bit set.
+ StreamsFailed int64
+ // The number of messages successfully sent on this socket.
+ MessagesSent int64
+ MessagesReceived int64
+ // The number of keep alives sent. This is typically implemented with HTTP/2
+ // ping messages.
+ KeepAlivesSent int64
+ // The last time a stream was created by this endpoint. Usually unset for
+ // servers.
+ LastLocalStreamCreatedTimestamp time.Time
+ // The last time a stream was created by the remote endpoint. Usually unset
+ // for clients.
+ LastRemoteStreamCreatedTimestamp time.Time
+ // The last time a message was sent by this endpoint.
+ LastMessageSentTimestamp time.Time
+ // The last time a message was received by this endpoint.
+ LastMessageReceivedTimestamp time.Time
+ // The amount of window, granted to the local endpoint by the remote endpoint.
+ // This may be slightly out of date due to network latency. This does NOT
+ // include stream level or TCP level flow control info.
+ LocalFlowControlWindow int64
+ // The amount of window, granted to the remote endpoint by the local endpoint.
+ // This may be slightly out of date due to network latency. This does NOT
+ // include stream level or TCP level flow control info.
+ RemoteFlowControlWindow int64
+ // The locally bound address.
+ LocalAddr net.Addr
+ // The remote bound address. May be absent.
+ RemoteAddr net.Addr
+ // Optional, represents the name of the remote endpoint, if different than
+ // the original target name.
+ RemoteName string
+ SocketOptions *SocketOptionData
+ Security credentials.ChannelzSecurityValue
+}
+
+// Socket is the interface that should be satisfied in order to be tracked by
+// channelz as Socket.
+type Socket interface {
+ ChannelzMetric() *SocketInternalMetric
+}
+
+type listenSocket struct {
+ refName string
+ s Socket
+ id int64
+ pid int64
+ cm *channelMap
+}
+
+func (ls *listenSocket) addChild(id int64, e entry) {
+ grpclog.Errorf("cannot add a child (id = %d) of type %T to a listen socket", id, e)
+}
+
+func (ls *listenSocket) deleteChild(id int64) {
+ grpclog.Errorf("cannot delete a child (id = %d) from a listen socket", id)
+}
+
+func (ls *listenSocket) triggerDelete() {
+ ls.cm.deleteEntry(ls.id)
+ ls.cm.findEntry(ls.pid).deleteChild(ls.id)
+}
+
+func (ls *listenSocket) deleteSelfIfReady() {
+ grpclog.Errorf("cannot call deleteSelfIfReady on a listen socket")
+}
+
+func (ls *listenSocket) getParentID() int64 {
+ return ls.pid
+}
+
+type normalSocket struct {
+ refName string
+ s Socket
+ id int64
+ pid int64
+ cm *channelMap
+}
+
+func (ns *normalSocket) addChild(id int64, e entry) {
+ grpclog.Errorf("cannot add a child (id = %d) of type %T to a normal socket", id, e)
+}
+
+func (ns *normalSocket) deleteChild(id int64) {
+ grpclog.Errorf("cannot delete a child (id = %d) from a normal socket", id)
+}
+
+func (ns *normalSocket) triggerDelete() {
+ ns.cm.deleteEntry(ns.id)
+ ns.cm.findEntry(ns.pid).deleteChild(ns.id)
+}
+
+func (ns *normalSocket) deleteSelfIfReady() {
+ grpclog.Errorf("cannot call deleteSelfIfReady on a normal socket")
+}
+
+func (ns *normalSocket) getParentID() int64 {
+ return ns.pid
+}
+
+// ServerMetric defines the info channelz provides for a specific Server, which
+// includes ServerInternalMetric and channelz-specific data, such as channelz id,
+// child list, etc.
+type ServerMetric struct {
+ // ID is the channelz id of this server.
+ ID int64
+ // RefName is the human readable reference string of this server.
+ RefName string
+ // ServerData contains server internal metric reported by the server through
+ // ChannelzMetric().
+ ServerData *ServerInternalMetric
+ // ListenSockets tracks the listener socket type children of this server in the
+ // format of a map from socket channelz id to corresponding reference string.
+ ListenSockets map[int64]string
+}
+
+// ServerInternalMetric defines the struct that the implementor of Server interface
+// should return from ChannelzMetric().
+type ServerInternalMetric struct {
+ // The number of incoming calls started on the server.
+ CallsStarted int64
+ // The number of incoming calls that have completed with an OK status.
+ CallsSucceeded int64
+ // The number of incoming calls that have a completed with a non-OK status.
+ CallsFailed int64
+ // The last time a call was started on the server.
+ LastCallStartedTimestamp time.Time
+}
+
+// Server is the interface to be satisfied in order to be tracked by channelz as
+// Server.
+type Server interface {
+ ChannelzMetric() *ServerInternalMetric
+}
+
+type server struct {
+ refName string
+ s Server
+ closeCalled bool
+ sockets map[int64]string
+ listenSockets map[int64]string
+ id int64
+ cm *channelMap
+}
+
+func (s *server) addChild(id int64, e entry) {
+ switch v := e.(type) {
+ case *normalSocket:
+ s.sockets[id] = v.refName
+ case *listenSocket:
+ s.listenSockets[id] = v.refName
+ default:
+ grpclog.Errorf("cannot add a child (id = %d) of type %T to a server", id, e)
+ }
+}
+
+func (s *server) deleteChild(id int64) {
+ delete(s.sockets, id)
+ delete(s.listenSockets, id)
+ s.deleteSelfIfReady()
+}
+
+func (s *server) triggerDelete() {
+ s.closeCalled = true
+ s.deleteSelfIfReady()
+}
+
+func (s *server) deleteSelfIfReady() {
+ if !s.closeCalled || len(s.sockets)+len(s.listenSockets) != 0 {
+ return
+ }
+ s.cm.deleteEntry(s.id)
+}
+
+func (s *server) getParentID() int64 {
+ return 0
+}
+
+type tracedChannel interface {
+ getChannelTrace() *channelTrace
+ incrTraceRefCount()
+ decrTraceRefCount()
+ getRefName() string
+}
+
+type channelTrace struct {
+ cm *channelMap
+ createdTime time.Time
+ eventCount int64
+ mu sync.Mutex
+ events []*TraceEvent
+}
+
+func (c *channelTrace) append(e *TraceEvent) {
+ c.mu.Lock()
+ if len(c.events) == getMaxTraceEntry() {
+ del := c.events[0]
+ c.events = c.events[1:]
+ if del.RefID != 0 {
+ // start recursive cleanup in a goroutine to not block the call originated from grpc.
+ go func() {
+ // need to acquire c.cm.mu lock to call the unlocked attemptCleanup func.
+ c.cm.mu.Lock()
+ c.cm.decrTraceRefCount(del.RefID)
+ c.cm.mu.Unlock()
+ }()
+ }
+ }
+ e.Timestamp = time.Now()
+ c.events = append(c.events, e)
+ c.eventCount++
+ c.mu.Unlock()
+}
+
+func (c *channelTrace) clear() {
+ c.mu.Lock()
+ for _, e := range c.events {
+ if e.RefID != 0 {
+ // caller should have already held the c.cm.mu lock.
+ c.cm.decrTraceRefCount(e.RefID)
+ }
+ }
+ c.mu.Unlock()
+}
+
+// Severity is the severity level of a trace event.
+// The canonical enumeration of all valid values is here:
+// https://github.com/grpc/grpc-proto/blob/9b13d199cc0d4703c7ea26c9c330ba695866eb23/grpc/channelz/v1/channelz.proto#L126.
+type Severity int
+
+const (
+ // CtUNKNOWN indicates unknown severity of a trace event.
+ CtUNKNOWN Severity = iota
+ // CtINFO indicates info level severity of a trace event.
+ CtINFO
+ // CtWarning indicates warning level severity of a trace event.
+ CtWarning
+ // CtError indicates error level severity of a trace event.
+ CtError
+)
+
+// RefChannelType is the type of the entity being referenced in a trace event.
+type RefChannelType int
+
+const (
+ // RefChannel indicates the referenced entity is a Channel.
+ RefChannel RefChannelType = iota
+ // RefSubChannel indicates the referenced entity is a SubChannel.
+ RefSubChannel
+)
+
+func (c *channelTrace) dumpData() *ChannelTrace {
+ c.mu.Lock()
+ ct := &ChannelTrace{EventNum: c.eventCount, CreationTime: c.createdTime}
+ ct.Events = c.events[:len(c.events)]
+ c.mu.Unlock()
+ return ct
+}
diff --git a/vendor/google.golang.org/grpc/internal/channelz/types_linux.go b/vendor/google.golang.org/grpc/internal/channelz/types_linux.go
new file mode 100644
index 000000000..692dd6181
--- /dev/null
+++ b/vendor/google.golang.org/grpc/internal/channelz/types_linux.go
@@ -0,0 +1,53 @@
+// +build !appengine
+
+/*
+ *
+ * Copyright 2018 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package channelz
+
+import (
+ "syscall"
+
+ "golang.org/x/sys/unix"
+)
+
+// SocketOptionData defines the struct to hold socket option data, and related
+// getter function to obtain info from fd.
+type SocketOptionData struct {
+ Linger *unix.Linger
+ RecvTimeout *unix.Timeval
+ SendTimeout *unix.Timeval
+ TCPInfo *unix.TCPInfo
+}
+
+// Getsockopt defines the function to get socket options requested by channelz.
+// It is to be passed to syscall.RawConn.Control().
+func (s *SocketOptionData) Getsockopt(fd uintptr) {
+ if v, err := unix.GetsockoptLinger(int(fd), syscall.SOL_SOCKET, syscall.SO_LINGER); err == nil {
+ s.Linger = v
+ }
+ if v, err := unix.GetsockoptTimeval(int(fd), syscall.SOL_SOCKET, syscall.SO_RCVTIMEO); err == nil {
+ s.RecvTimeout = v
+ }
+ if v, err := unix.GetsockoptTimeval(int(fd), syscall.SOL_SOCKET, syscall.SO_SNDTIMEO); err == nil {
+ s.SendTimeout = v
+ }
+ if v, err := unix.GetsockoptTCPInfo(int(fd), syscall.SOL_TCP, syscall.TCP_INFO); err == nil {
+ s.TCPInfo = v
+ }
+}
diff --git a/vendor/google.golang.org/grpc/internal/channelz/types_nonlinux.go b/vendor/google.golang.org/grpc/internal/channelz/types_nonlinux.go
new file mode 100644
index 000000000..79edbefc4
--- /dev/null
+++ b/vendor/google.golang.org/grpc/internal/channelz/types_nonlinux.go
@@ -0,0 +1,44 @@
+// +build !linux appengine
+
+/*
+ *
+ * Copyright 2018 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package channelz
+
+import (
+ "sync"
+
+ "google.golang.org/grpc/grpclog"
+)
+
+var once sync.Once
+
+// SocketOptionData defines the struct to hold socket option data, and related
+// getter function to obtain info from fd.
+// Windows OS doesn't support Socket Option
+type SocketOptionData struct {
+}
+
+// Getsockopt defines the function to get socket options requested by channelz.
+// It is to be passed to syscall.RawConn.Control().
+// Windows OS doesn't support Socket Option
+func (s *SocketOptionData) Getsockopt(fd uintptr) {
+ once.Do(func() {
+ grpclog.Warningln("Channelz: socket options are not supported on non-linux os and appengine.")
+ })
+}
diff --git a/vendor/google.golang.org/grpc/internal/channelz/util_linux.go b/vendor/google.golang.org/grpc/internal/channelz/util_linux.go
new file mode 100644
index 000000000..fdf409d55
--- /dev/null
+++ b/vendor/google.golang.org/grpc/internal/channelz/util_linux.go
@@ -0,0 +1,39 @@
+// +build linux,!appengine
+
+/*
+ *
+ * Copyright 2018 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package channelz
+
+import (
+ "syscall"
+)
+
+// GetSocketOption gets the socket option info of the conn.
+func GetSocketOption(socket interface{}) *SocketOptionData {
+ c, ok := socket.(syscall.Conn)
+ if !ok {
+ return nil
+ }
+ data := &SocketOptionData{}
+ if rawConn, err := c.SyscallConn(); err == nil {
+ rawConn.Control(data.Getsockopt)
+ return data
+ }
+ return nil
+}
diff --git a/vendor/google.golang.org/grpc/internal/channelz/util_nonlinux.go b/vendor/google.golang.org/grpc/internal/channelz/util_nonlinux.go
new file mode 100644
index 000000000..8864a0811
--- /dev/null
+++ b/vendor/google.golang.org/grpc/internal/channelz/util_nonlinux.go
@@ -0,0 +1,26 @@
+// +build !linux appengine
+
+/*
+ *
+ * Copyright 2018 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package channelz
+
+// GetSocketOption gets the socket option info of the conn.
+func GetSocketOption(c interface{}) *SocketOptionData {
+ return nil
+}
diff --git a/vendor/google.golang.org/grpc/internal/envconfig/envconfig.go b/vendor/google.golang.org/grpc/internal/envconfig/envconfig.go
new file mode 100644
index 000000000..a3e02b661
--- /dev/null
+++ b/vendor/google.golang.org/grpc/internal/envconfig/envconfig.go
@@ -0,0 +1,69 @@
+/*
+ *
+ * Copyright 2018 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// Package envconfig contains grpc settings configured by environment variables.
+package envconfig
+
+import (
+ "os"
+ "strings"
+)
+
+const (
+ prefix = "GRPC_GO_"
+ retryStr = prefix + "RETRY"
+ requireHandshakeStr = prefix + "REQUIRE_HANDSHAKE"
+)
+
+// RequireHandshakeSetting describes the settings for handshaking.
+type RequireHandshakeSetting int
+
+const (
+ // RequireHandshakeHybrid (default, deprecated) indicates to wait for
+ // handshake before considering a connection ready, but wait before
+ // considering successful.
+ RequireHandshakeHybrid RequireHandshakeSetting = iota
+ // RequireHandshakeOn (default after the 1.17 release) indicates to wait
+ // for handshake before considering a connection ready/successful.
+ RequireHandshakeOn
+ // RequireHandshakeOff indicates to not wait for handshake before
+ // considering a connection ready/successful.
+ RequireHandshakeOff
+)
+
+var (
+ // Retry is set if retry is explicitly enabled via "GRPC_GO_RETRY=on".
+ Retry = strings.EqualFold(os.Getenv(retryStr), "on")
+ // RequireHandshake is set based upon the GRPC_GO_REQUIRE_HANDSHAKE
+ // environment variable.
+ //
+ // Will be removed after the 1.18 release.
+ RequireHandshake RequireHandshakeSetting
+)
+
+func init() {
+ switch strings.ToLower(os.Getenv(requireHandshakeStr)) {
+ case "on":
+ RequireHandshake = RequireHandshakeOn
+ case "off":
+ RequireHandshake = RequireHandshakeOff
+ case "hybrid":
+ // Will be removed after the 1.17 release.
+ RequireHandshake = RequireHandshakeHybrid
+ }
+}
diff --git a/vendor/google.golang.org/grpc/internal/grpcrand/grpcrand.go b/vendor/google.golang.org/grpc/internal/grpcrand/grpcrand.go
new file mode 100644
index 000000000..200b115ca
--- /dev/null
+++ b/vendor/google.golang.org/grpc/internal/grpcrand/grpcrand.go
@@ -0,0 +1,56 @@
+/*
+ *
+ * Copyright 2018 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// Package grpcrand implements math/rand functions in a concurrent-safe way
+// with a global random source, independent of math/rand's global source.
+package grpcrand
+
+import (
+ "math/rand"
+ "sync"
+ "time"
+)
+
+var (
+ r = rand.New(rand.NewSource(time.Now().UnixNano()))
+ mu sync.Mutex
+)
+
+// Int63n implements rand.Int63n on the grpcrand global source.
+func Int63n(n int64) int64 {
+ mu.Lock()
+ res := r.Int63n(n)
+ mu.Unlock()
+ return res
+}
+
+// Intn implements rand.Intn on the grpcrand global source.
+func Intn(n int) int {
+ mu.Lock()
+ res := r.Intn(n)
+ mu.Unlock()
+ return res
+}
+
+// Float64 implements rand.Float64 on the grpcrand global source.
+func Float64() float64 {
+ mu.Lock()
+ res := r.Float64()
+ mu.Unlock()
+ return res
+}
diff --git a/vendor/google.golang.org/grpc/internal/grpcsync/event.go b/vendor/google.golang.org/grpc/internal/grpcsync/event.go
new file mode 100644
index 000000000..fbe697c37
--- /dev/null
+++ b/vendor/google.golang.org/grpc/internal/grpcsync/event.go
@@ -0,0 +1,61 @@
+/*
+ *
+ * Copyright 2018 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// Package grpcsync implements additional synchronization primitives built upon
+// the sync package.
+package grpcsync
+
+import (
+ "sync"
+ "sync/atomic"
+)
+
+// Event represents a one-time event that may occur in the future.
+type Event struct {
+ fired int32
+ c chan struct{}
+ o sync.Once
+}
+
+// Fire causes e to complete. It is safe to call multiple times, and
+// concurrently. It returns true iff this call to Fire caused the signaling
+// channel returned by Done to close.
+func (e *Event) Fire() bool {
+ ret := false
+ e.o.Do(func() {
+ atomic.StoreInt32(&e.fired, 1)
+ close(e.c)
+ ret = true
+ })
+ return ret
+}
+
+// Done returns a channel that will be closed when Fire is called.
+func (e *Event) Done() <-chan struct{} {
+ return e.c
+}
+
+// HasFired returns true if Fire has been called.
+func (e *Event) HasFired() bool {
+ return atomic.LoadInt32(&e.fired) == 1
+}
+
+// NewEvent returns a new, ready-to-use Event.
+func NewEvent() *Event {
+ return &Event{c: make(chan struct{})}
+}
diff --git a/vendor/google.golang.org/grpc/internal/internal.go b/vendor/google.golang.org/grpc/internal/internal.go
new file mode 100644
index 000000000..f8932b1d8
--- /dev/null
+++ b/vendor/google.golang.org/grpc/internal/internal.go
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2016 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// Package internal contains gRPC-internal code, to avoid polluting
+// the godoc of the top-level grpc package. It must not import any grpc
+// symbols to avoid circular dependencies.
+package internal
+
+import "context"
+
+var (
+ // WithContextDialer is exported by clientconn.go
+ WithContextDialer interface{} // func(context.Context, string) (net.Conn, error) grpc.DialOption
+ // WithResolverBuilder is exported by clientconn.go
+ WithResolverBuilder interface{} // func (resolver.Builder) grpc.DialOption
+ // HealthCheckFunc is used to provide client-side LB channel health checking
+ HealthCheckFunc func(ctx context.Context, newStream func() (interface{}, error), reportHealth func(bool), serviceName string) error
+)
+
+const (
+ // CredsBundleModeFallback switches GoogleDefaultCreds to fallback mode.
+ CredsBundleModeFallback = "fallback"
+ // CredsBundleModeBalancer switches GoogleDefaultCreds to grpclb balancer
+ // mode.
+ CredsBundleModeBalancer = "balancer"
+ // CredsBundleModeBackendFromBalancer switches GoogleDefaultCreds to mode
+ // that supports backend returned by grpclb balancer.
+ CredsBundleModeBackendFromBalancer = "backend-from-balancer"
+)
diff --git a/vendor/google.golang.org/grpc/internal/syscall/syscall_linux.go b/vendor/google.golang.org/grpc/internal/syscall/syscall_linux.go
new file mode 100644
index 000000000..43281a3e0
--- /dev/null
+++ b/vendor/google.golang.org/grpc/internal/syscall/syscall_linux.go
@@ -0,0 +1,114 @@
+// +build !appengine
+
+/*
+ *
+ * Copyright 2018 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// Package syscall provides functionalities that grpc uses to get low-level operating system
+// stats/info.
+package syscall
+
+import (
+ "fmt"
+ "net"
+ "syscall"
+ "time"
+
+ "golang.org/x/sys/unix"
+ "google.golang.org/grpc/grpclog"
+)
+
+// GetCPUTime returns the how much CPU time has passed since the start of this process.
+func GetCPUTime() int64 {
+ var ts unix.Timespec
+ if err := unix.ClockGettime(unix.CLOCK_PROCESS_CPUTIME_ID, &ts); err != nil {
+ grpclog.Fatal(err)
+ }
+ return ts.Nano()
+}
+
+// Rusage is an alias for syscall.Rusage under linux non-appengine environment.
+type Rusage syscall.Rusage
+
+// GetRusage returns the resource usage of current process.
+func GetRusage() (rusage *Rusage) {
+ rusage = new(Rusage)
+ syscall.Getrusage(syscall.RUSAGE_SELF, (*syscall.Rusage)(rusage))
+ return
+}
+
+// CPUTimeDiff returns the differences of user CPU time and system CPU time used
+// between two Rusage structs.
+func CPUTimeDiff(first *Rusage, latest *Rusage) (float64, float64) {
+ f := (*syscall.Rusage)(first)
+ l := (*syscall.Rusage)(latest)
+ var (
+ utimeDiffs = l.Utime.Sec - f.Utime.Sec
+ utimeDiffus = l.Utime.Usec - f.Utime.Usec
+ stimeDiffs = l.Stime.Sec - f.Stime.Sec
+ stimeDiffus = l.Stime.Usec - f.Stime.Usec
+ )
+
+ uTimeElapsed := float64(utimeDiffs) + float64(utimeDiffus)*1.0e-6
+ sTimeElapsed := float64(stimeDiffs) + float64(stimeDiffus)*1.0e-6
+
+ return uTimeElapsed, sTimeElapsed
+}
+
+// SetTCPUserTimeout sets the TCP user timeout on a connection's socket
+func SetTCPUserTimeout(conn net.Conn, timeout time.Duration) error {
+ tcpconn, ok := conn.(*net.TCPConn)
+ if !ok {
+ // not a TCP connection. exit early
+ return nil
+ }
+ rawConn, err := tcpconn.SyscallConn()
+ if err != nil {
+ return fmt.Errorf("error getting raw connection: %v", err)
+ }
+ err = rawConn.Control(func(fd uintptr) {
+ err = syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, unix.TCP_USER_TIMEOUT, int(timeout/time.Millisecond))
+ })
+ if err != nil {
+ return fmt.Errorf("error setting option on socket: %v", err)
+ }
+
+ return nil
+}
+
+// GetTCPUserTimeout gets the TCP user timeout on a connection's socket
+func GetTCPUserTimeout(conn net.Conn) (opt int, err error) {
+ tcpconn, ok := conn.(*net.TCPConn)
+ if !ok {
+ err = fmt.Errorf("conn is not *net.TCPConn. got %T", conn)
+ return
+ }
+ rawConn, err := tcpconn.SyscallConn()
+ if err != nil {
+ err = fmt.Errorf("error getting raw connection: %v", err)
+ return
+ }
+ err = rawConn.Control(func(fd uintptr) {
+ opt, err = syscall.GetsockoptInt(int(fd), syscall.IPPROTO_TCP, unix.TCP_USER_TIMEOUT)
+ })
+ if err != nil {
+ err = fmt.Errorf("error getting option on socket: %v", err)
+ return
+ }
+
+ return
+}
diff --git a/vendor/google.golang.org/grpc/internal/syscall/syscall_nonlinux.go b/vendor/google.golang.org/grpc/internal/syscall/syscall_nonlinux.go
new file mode 100644
index 000000000..61678feb0
--- /dev/null
+++ b/vendor/google.golang.org/grpc/internal/syscall/syscall_nonlinux.go
@@ -0,0 +1,63 @@
+// +build !linux appengine
+
+/*
+ *
+ * Copyright 2018 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package syscall
+
+import (
+ "net"
+ "time"
+
+ "google.golang.org/grpc/grpclog"
+)
+
+func init() {
+ grpclog.Info("CPU time info is unavailable on non-linux or appengine environment.")
+}
+
+// GetCPUTime returns the how much CPU time has passed since the start of this process.
+// It always returns 0 under non-linux or appengine environment.
+func GetCPUTime() int64 {
+ return 0
+}
+
+// Rusage is an empty struct under non-linux or appengine environment.
+type Rusage struct{}
+
+// GetRusage is a no-op function under non-linux or appengine environment.
+func GetRusage() (rusage *Rusage) {
+ return nil
+}
+
+// CPUTimeDiff returns the differences of user CPU time and system CPU time used
+// between two Rusage structs. It a no-op function for non-linux or appengine environment.
+func CPUTimeDiff(first *Rusage, latest *Rusage) (float64, float64) {
+ return 0, 0
+}
+
+// SetTCPUserTimeout is a no-op function under non-linux or appengine environments
+func SetTCPUserTimeout(conn net.Conn, timeout time.Duration) error {
+ return nil
+}
+
+// GetTCPUserTimeout is a no-op function under non-linux or appengine environments
+// a negative return value indicates the operation is not supported
+func GetTCPUserTimeout(conn net.Conn) (int, error) {
+ return -1, nil
+}
diff --git a/vendor/google.golang.org/grpc/internal/transport/bdp_estimator.go b/vendor/google.golang.org/grpc/internal/transport/bdp_estimator.go
new file mode 100644
index 000000000..070680edb
--- /dev/null
+++ b/vendor/google.golang.org/grpc/internal/transport/bdp_estimator.go
@@ -0,0 +1,141 @@
+/*
+ *
+ * Copyright 2017 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package transport
+
+import (
+ "sync"
+ "time"
+)
+
+const (
+ // bdpLimit is the maximum value the flow control windows will be increased
+ // to. TCP typically limits this to 4MB, but some systems go up to 16MB.
+ // Since this is only a limit, it is safe to make it optimistic.
+ bdpLimit = (1 << 20) * 16
+ // alpha is a constant factor used to keep a moving average
+ // of RTTs.
+ alpha = 0.9
+ // If the current bdp sample is greater than or equal to
+ // our beta * our estimated bdp and the current bandwidth
+ // sample is the maximum bandwidth observed so far, we
+ // increase our bbp estimate by a factor of gamma.
+ beta = 0.66
+ // To put our bdp to be smaller than or equal to twice the real BDP,
+ // we should multiply our current sample with 4/3, however to round things out
+ // we use 2 as the multiplication factor.
+ gamma = 2
+)
+
+// Adding arbitrary data to ping so that its ack can be identified.
+// Easter-egg: what does the ping message say?
+var bdpPing = &ping{data: [8]byte{2, 4, 16, 16, 9, 14, 7, 7}}
+
+type bdpEstimator struct {
+ // sentAt is the time when the ping was sent.
+ sentAt time.Time
+
+ mu sync.Mutex
+ // bdp is the current bdp estimate.
+ bdp uint32
+ // sample is the number of bytes received in one measurement cycle.
+ sample uint32
+ // bwMax is the maximum bandwidth noted so far (bytes/sec).
+ bwMax float64
+ // bool to keep track of the beginning of a new measurement cycle.
+ isSent bool
+ // Callback to update the window sizes.
+ updateFlowControl func(n uint32)
+ // sampleCount is the number of samples taken so far.
+ sampleCount uint64
+ // round trip time (seconds)
+ rtt float64
+}
+
+// timesnap registers the time bdp ping was sent out so that
+// network rtt can be calculated when its ack is received.
+// It is called (by controller) when the bdpPing is
+// being written on the wire.
+func (b *bdpEstimator) timesnap(d [8]byte) {
+ if bdpPing.data != d {
+ return
+ }
+ b.sentAt = time.Now()
+}
+
+// add adds bytes to the current sample for calculating bdp.
+// It returns true only if a ping must be sent. This can be used
+// by the caller (handleData) to make decision about batching
+// a window update with it.
+func (b *bdpEstimator) add(n uint32) bool {
+ b.mu.Lock()
+ defer b.mu.Unlock()
+ if b.bdp == bdpLimit {
+ return false
+ }
+ if !b.isSent {
+ b.isSent = true
+ b.sample = n
+ b.sentAt = time.Time{}
+ b.sampleCount++
+ return true
+ }
+ b.sample += n
+ return false
+}
+
+// calculate is called when an ack for a bdp ping is received.
+// Here we calculate the current bdp and bandwidth sample and
+// decide if the flow control windows should go up.
+func (b *bdpEstimator) calculate(d [8]byte) {
+ // Check if the ping acked for was the bdp ping.
+ if bdpPing.data != d {
+ return
+ }
+ b.mu.Lock()
+ rttSample := time.Since(b.sentAt).Seconds()
+ if b.sampleCount < 10 {
+ // Bootstrap rtt with an average of first 10 rtt samples.
+ b.rtt += (rttSample - b.rtt) / float64(b.sampleCount)
+ } else {
+ // Heed to the recent past more.
+ b.rtt += (rttSample - b.rtt) * float64(alpha)
+ }
+ b.isSent = false
+ // The number of bytes accumulated so far in the sample is smaller
+ // than or equal to 1.5 times the real BDP on a saturated connection.
+ bwCurrent := float64(b.sample) / (b.rtt * float64(1.5))
+ if bwCurrent > b.bwMax {
+ b.bwMax = bwCurrent
+ }
+ // If the current sample (which is smaller than or equal to the 1.5 times the real BDP) is
+ // greater than or equal to 2/3rd our perceived bdp AND this is the maximum bandwidth seen so far, we
+ // should update our perception of the network BDP.
+ if float64(b.sample) >= beta*float64(b.bdp) && bwCurrent == b.bwMax && b.bdp != bdpLimit {
+ sampleFloat := float64(b.sample)
+ b.bdp = uint32(gamma * sampleFloat)
+ if b.bdp > bdpLimit {
+ b.bdp = bdpLimit
+ }
+ bdp := b.bdp
+ b.mu.Unlock()
+ b.updateFlowControl(bdp)
+ return
+ }
+ b.mu.Unlock()
+}
diff --git a/vendor/google.golang.org/grpc/internal/transport/controlbuf.go b/vendor/google.golang.org/grpc/internal/transport/controlbuf.go
new file mode 100644
index 000000000..204ba1588
--- /dev/null
+++ b/vendor/google.golang.org/grpc/internal/transport/controlbuf.go
@@ -0,0 +1,852 @@
+/*
+ *
+ * Copyright 2014 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package transport
+
+import (
+ "bytes"
+ "fmt"
+ "runtime"
+ "sync"
+
+ "golang.org/x/net/http2"
+ "golang.org/x/net/http2/hpack"
+)
+
+var updateHeaderTblSize = func(e *hpack.Encoder, v uint32) {
+ e.SetMaxDynamicTableSizeLimit(v)
+}
+
+type itemNode struct {
+ it interface{}
+ next *itemNode
+}
+
+type itemList struct {
+ head *itemNode
+ tail *itemNode
+}
+
+func (il *itemList) enqueue(i interface{}) {
+ n := &itemNode{it: i}
+ if il.tail == nil {
+ il.head, il.tail = n, n
+ return
+ }
+ il.tail.next = n
+ il.tail = n
+}
+
+// peek returns the first item in the list without removing it from the
+// list.
+func (il *itemList) peek() interface{} {
+ return il.head.it
+}
+
+func (il *itemList) dequeue() interface{} {
+ if il.head == nil {
+ return nil
+ }
+ i := il.head.it
+ il.head = il.head.next
+ if il.head == nil {
+ il.tail = nil
+ }
+ return i
+}
+
+func (il *itemList) dequeueAll() *itemNode {
+ h := il.head
+ il.head, il.tail = nil, nil
+ return h
+}
+
+func (il *itemList) isEmpty() bool {
+ return il.head == nil
+}
+
+// The following defines various control items which could flow through
+// the control buffer of transport. They represent different aspects of
+// control tasks, e.g., flow control, settings, streaming resetting, etc.
+
+// registerStream is used to register an incoming stream with loopy writer.
+type registerStream struct {
+ streamID uint32
+ wq *writeQuota
+}
+
+// headerFrame is also used to register stream on the client-side.
+type headerFrame struct {
+ streamID uint32
+ hf []hpack.HeaderField
+ endStream bool // Valid on server side.
+ initStream func(uint32) (bool, error) // Used only on the client side.
+ onWrite func()
+ wq *writeQuota // write quota for the stream created.
+ cleanup *cleanupStream // Valid on the server side.
+ onOrphaned func(error) // Valid on client-side
+}
+
+type cleanupStream struct {
+ streamID uint32
+ rst bool
+ rstCode http2.ErrCode
+ onWrite func()
+}
+
+type dataFrame struct {
+ streamID uint32
+ endStream bool
+ h []byte
+ d []byte
+ // onEachWrite is called every time
+ // a part of d is written out.
+ onEachWrite func()
+}
+
+type incomingWindowUpdate struct {
+ streamID uint32
+ increment uint32
+}
+
+type outgoingWindowUpdate struct {
+ streamID uint32
+ increment uint32
+}
+
+type incomingSettings struct {
+ ss []http2.Setting
+}
+
+type outgoingSettings struct {
+ ss []http2.Setting
+}
+
+type incomingGoAway struct {
+}
+
+type goAway struct {
+ code http2.ErrCode
+ debugData []byte
+ headsUp bool
+ closeConn bool
+}
+
+type ping struct {
+ ack bool
+ data [8]byte
+}
+
+type outFlowControlSizeRequest struct {
+ resp chan uint32
+}
+
+type outStreamState int
+
+const (
+ active outStreamState = iota
+ empty
+ waitingOnStreamQuota
+)
+
+type outStream struct {
+ id uint32
+ state outStreamState
+ itl *itemList
+ bytesOutStanding int
+ wq *writeQuota
+
+ next *outStream
+ prev *outStream
+}
+
+func (s *outStream) deleteSelf() {
+ if s.prev != nil {
+ s.prev.next = s.next
+ }
+ if s.next != nil {
+ s.next.prev = s.prev
+ }
+ s.next, s.prev = nil, nil
+}
+
+type outStreamList struct {
+ // Following are sentinel objects that mark the
+ // beginning and end of the list. They do not
+ // contain any item lists. All valid objects are
+ // inserted in between them.
+ // This is needed so that an outStream object can
+ // deleteSelf() in O(1) time without knowing which
+ // list it belongs to.
+ head *outStream
+ tail *outStream
+}
+
+func newOutStreamList() *outStreamList {
+ head, tail := new(outStream), new(outStream)
+ head.next = tail
+ tail.prev = head
+ return &outStreamList{
+ head: head,
+ tail: tail,
+ }
+}
+
+func (l *outStreamList) enqueue(s *outStream) {
+ e := l.tail.prev
+ e.next = s
+ s.prev = e
+ s.next = l.tail
+ l.tail.prev = s
+}
+
+// remove from the beginning of the list.
+func (l *outStreamList) dequeue() *outStream {
+ b := l.head.next
+ if b == l.tail {
+ return nil
+ }
+ b.deleteSelf()
+ return b
+}
+
+// controlBuffer is a way to pass information to loopy.
+// Information is passed as specific struct types called control frames.
+// A control frame not only represents data, messages or headers to be sent out
+// but can also be used to instruct loopy to update its internal state.
+// It shouldn't be confused with an HTTP2 frame, although some of the control frames
+// like dataFrame and headerFrame do go out on wire as HTTP2 frames.
+type controlBuffer struct {
+ ch chan struct{}
+ done <-chan struct{}
+ mu sync.Mutex
+ consumerWaiting bool
+ list *itemList
+ err error
+}
+
+func newControlBuffer(done <-chan struct{}) *controlBuffer {
+ return &controlBuffer{
+ ch: make(chan struct{}, 1),
+ list: &itemList{},
+ done: done,
+ }
+}
+
+func (c *controlBuffer) put(it interface{}) error {
+ _, err := c.executeAndPut(nil, it)
+ return err
+}
+
+func (c *controlBuffer) executeAndPut(f func(it interface{}) bool, it interface{}) (bool, error) {
+ var wakeUp bool
+ c.mu.Lock()
+ if c.err != nil {
+ c.mu.Unlock()
+ return false, c.err
+ }
+ if f != nil {
+ if !f(it) { // f wasn't successful
+ c.mu.Unlock()
+ return false, nil
+ }
+ }
+ if c.consumerWaiting {
+ wakeUp = true
+ c.consumerWaiting = false
+ }
+ c.list.enqueue(it)
+ c.mu.Unlock()
+ if wakeUp {
+ select {
+ case c.ch <- struct{}{}:
+ default:
+ }
+ }
+ return true, nil
+}
+
+// Note argument f should never be nil.
+func (c *controlBuffer) execute(f func(it interface{}) bool, it interface{}) (bool, error) {
+ c.mu.Lock()
+ if c.err != nil {
+ c.mu.Unlock()
+ return false, c.err
+ }
+ if !f(it) { // f wasn't successful
+ c.mu.Unlock()
+ return false, nil
+ }
+ c.mu.Unlock()
+ return true, nil
+}
+
+func (c *controlBuffer) get(block bool) (interface{}, error) {
+ for {
+ c.mu.Lock()
+ if c.err != nil {
+ c.mu.Unlock()
+ return nil, c.err
+ }
+ if !c.list.isEmpty() {
+ h := c.list.dequeue()
+ c.mu.Unlock()
+ return h, nil
+ }
+ if !block {
+ c.mu.Unlock()
+ return nil, nil
+ }
+ c.consumerWaiting = true
+ c.mu.Unlock()
+ select {
+ case <-c.ch:
+ case <-c.done:
+ c.finish()
+ return nil, ErrConnClosing
+ }
+ }
+}
+
+func (c *controlBuffer) finish() {
+ c.mu.Lock()
+ if c.err != nil {
+ c.mu.Unlock()
+ return
+ }
+ c.err = ErrConnClosing
+ // There may be headers for streams in the control buffer.
+ // These streams need to be cleaned out since the transport
+ // is still not aware of these yet.
+ for head := c.list.dequeueAll(); head != nil; head = head.next {
+ hdr, ok := head.it.(*headerFrame)
+ if !ok {
+ continue
+ }
+ if hdr.onOrphaned != nil { // It will be nil on the server-side.
+ hdr.onOrphaned(ErrConnClosing)
+ }
+ }
+ c.mu.Unlock()
+}
+
+type side int
+
+const (
+ clientSide side = iota
+ serverSide
+)
+
+// Loopy receives frames from the control buffer.
+// Each frame is handled individually; most of the work done by loopy goes
+// into handling data frames. Loopy maintains a queue of active streams, and each
+// stream maintains a queue of data frames; as loopy receives data frames
+// it gets added to the queue of the relevant stream.
+// Loopy goes over this list of active streams by processing one node every iteration,
+// thereby closely resemebling to a round-robin scheduling over all streams. While
+// processing a stream, loopy writes out data bytes from this stream capped by the min
+// of http2MaxFrameLen, connection-level flow control and stream-level flow control.
+type loopyWriter struct {
+ side side
+ cbuf *controlBuffer
+ sendQuota uint32
+ oiws uint32 // outbound initial window size.
+ // estdStreams is map of all established streams that are not cleaned-up yet.
+ // On client-side, this is all streams whose headers were sent out.
+ // On server-side, this is all streams whose headers were received.
+ estdStreams map[uint32]*outStream // Established streams.
+ // activeStreams is a linked-list of all streams that have data to send and some
+ // stream-level flow control quota.
+ // Each of these streams internally have a list of data items(and perhaps trailers
+ // on the server-side) to be sent out.
+ activeStreams *outStreamList
+ framer *framer
+ hBuf *bytes.Buffer // The buffer for HPACK encoding.
+ hEnc *hpack.Encoder // HPACK encoder.
+ bdpEst *bdpEstimator
+ draining bool
+
+ // Side-specific handlers
+ ssGoAwayHandler func(*goAway) (bool, error)
+}
+
+func newLoopyWriter(s side, fr *framer, cbuf *controlBuffer, bdpEst *bdpEstimator) *loopyWriter {
+ var buf bytes.Buffer
+ l := &loopyWriter{
+ side: s,
+ cbuf: cbuf,
+ sendQuota: defaultWindowSize,
+ oiws: defaultWindowSize,
+ estdStreams: make(map[uint32]*outStream),
+ activeStreams: newOutStreamList(),
+ framer: fr,
+ hBuf: &buf,
+ hEnc: hpack.NewEncoder(&buf),
+ bdpEst: bdpEst,
+ }
+ return l
+}
+
+const minBatchSize = 1000
+
+// run should be run in a separate goroutine.
+// It reads control frames from controlBuf and processes them by:
+// 1. Updating loopy's internal state, or/and
+// 2. Writing out HTTP2 frames on the wire.
+//
+// Loopy keeps all active streams with data to send in a linked-list.
+// All streams in the activeStreams linked-list must have both:
+// 1. Data to send, and
+// 2. Stream level flow control quota available.
+//
+// In each iteration of run loop, other than processing the incoming control
+// frame, loopy calls processData, which processes one node from the activeStreams linked-list.
+// This results in writing of HTTP2 frames into an underlying write buffer.
+// When there's no more control frames to read from controlBuf, loopy flushes the write buffer.
+// As an optimization, to increase the batch size for each flush, loopy yields the processor, once
+// if the batch size is too low to give stream goroutines a chance to fill it up.
+func (l *loopyWriter) run() (err error) {
+ defer func() {
+ if err == ErrConnClosing {
+ // Don't log ErrConnClosing as error since it happens
+ // 1. When the connection is closed by some other known issue.
+ // 2. User closed the connection.
+ // 3. A graceful close of connection.
+ infof("transport: loopyWriter.run returning. %v", err)
+ err = nil
+ }
+ }()
+ for {
+ it, err := l.cbuf.get(true)
+ if err != nil {
+ return err
+ }
+ if err = l.handle(it); err != nil {
+ return err
+ }
+ if _, err = l.processData(); err != nil {
+ return err
+ }
+ gosched := true
+ hasdata:
+ for {
+ it, err := l.cbuf.get(false)
+ if err != nil {
+ return err
+ }
+ if it != nil {
+ if err = l.handle(it); err != nil {
+ return err
+ }
+ if _, err = l.processData(); err != nil {
+ return err
+ }
+ continue hasdata
+ }
+ isEmpty, err := l.processData()
+ if err != nil {
+ return err
+ }
+ if !isEmpty {
+ continue hasdata
+ }
+ if gosched {
+ gosched = false
+ if l.framer.writer.offset < minBatchSize {
+ runtime.Gosched()
+ continue hasdata
+ }
+ }
+ l.framer.writer.Flush()
+ break hasdata
+
+ }
+ }
+}
+
+func (l *loopyWriter) outgoingWindowUpdateHandler(w *outgoingWindowUpdate) error {
+ return l.framer.fr.WriteWindowUpdate(w.streamID, w.increment)
+}
+
+func (l *loopyWriter) incomingWindowUpdateHandler(w *incomingWindowUpdate) error {
+ // Otherwise update the quota.
+ if w.streamID == 0 {
+ l.sendQuota += w.increment
+ return nil
+ }
+ // Find the stream and update it.
+ if str, ok := l.estdStreams[w.streamID]; ok {
+ str.bytesOutStanding -= int(w.increment)
+ if strQuota := int(l.oiws) - str.bytesOutStanding; strQuota > 0 && str.state == waitingOnStreamQuota {
+ str.state = active
+ l.activeStreams.enqueue(str)
+ return nil
+ }
+ }
+ return nil
+}
+
+func (l *loopyWriter) outgoingSettingsHandler(s *outgoingSettings) error {
+ return l.framer.fr.WriteSettings(s.ss...)
+}
+
+func (l *loopyWriter) incomingSettingsHandler(s *incomingSettings) error {
+ if err := l.applySettings(s.ss); err != nil {
+ return err
+ }
+ return l.framer.fr.WriteSettingsAck()
+}
+
+func (l *loopyWriter) registerStreamHandler(h *registerStream) error {
+ str := &outStream{
+ id: h.streamID,
+ state: empty,
+ itl: &itemList{},
+ wq: h.wq,
+ }
+ l.estdStreams[h.streamID] = str
+ return nil
+}
+
+func (l *loopyWriter) headerHandler(h *headerFrame) error {
+ if l.side == serverSide {
+ str, ok := l.estdStreams[h.streamID]
+ if !ok {
+ warningf("transport: loopy doesn't recognize the stream: %d", h.streamID)
+ return nil
+ }
+ // Case 1.A: Server is responding back with headers.
+ if !h.endStream {
+ return l.writeHeader(h.streamID, h.endStream, h.hf, h.onWrite)
+ }
+ // else: Case 1.B: Server wants to close stream.
+
+ if str.state != empty { // either active or waiting on stream quota.
+ // add it str's list of items.
+ str.itl.enqueue(h)
+ return nil
+ }
+ if err := l.writeHeader(h.streamID, h.endStream, h.hf, h.onWrite); err != nil {
+ return err
+ }
+ return l.cleanupStreamHandler(h.cleanup)
+ }
+ // Case 2: Client wants to originate stream.
+ str := &outStream{
+ id: h.streamID,
+ state: empty,
+ itl: &itemList{},
+ wq: h.wq,
+ }
+ str.itl.enqueue(h)
+ return l.originateStream(str)
+}
+
+func (l *loopyWriter) originateStream(str *outStream) error {
+ hdr := str.itl.dequeue().(*headerFrame)
+ sendPing, err := hdr.initStream(str.id)
+ if err != nil {
+ if err == ErrConnClosing {
+ return err
+ }
+ // Other errors(errStreamDrain) need not close transport.
+ return nil
+ }
+ if err = l.writeHeader(str.id, hdr.endStream, hdr.hf, hdr.onWrite); err != nil {
+ return err
+ }
+ l.estdStreams[str.id] = str
+ if sendPing {
+ return l.pingHandler(&ping{data: [8]byte{}})
+ }
+ return nil
+}
+
+func (l *loopyWriter) writeHeader(streamID uint32, endStream bool, hf []hpack.HeaderField, onWrite func()) error {
+ if onWrite != nil {
+ onWrite()
+ }
+ l.hBuf.Reset()
+ for _, f := range hf {
+ if err := l.hEnc.WriteField(f); err != nil {
+ warningf("transport: loopyWriter.writeHeader encountered error while encoding headers:", err)
+ }
+ }
+ var (
+ err error
+ endHeaders, first bool
+ )
+ first = true
+ for !endHeaders {
+ size := l.hBuf.Len()
+ if size > http2MaxFrameLen {
+ size = http2MaxFrameLen
+ } else {
+ endHeaders = true
+ }
+ if first {
+ first = false
+ err = l.framer.fr.WriteHeaders(http2.HeadersFrameParam{
+ StreamID: streamID,
+ BlockFragment: l.hBuf.Next(size),
+ EndStream: endStream,
+ EndHeaders: endHeaders,
+ })
+ } else {
+ err = l.framer.fr.WriteContinuation(
+ streamID,
+ endHeaders,
+ l.hBuf.Next(size),
+ )
+ }
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func (l *loopyWriter) preprocessData(df *dataFrame) error {
+ str, ok := l.estdStreams[df.streamID]
+ if !ok {
+ return nil
+ }
+ // If we got data for a stream it means that
+ // stream was originated and the headers were sent out.
+ str.itl.enqueue(df)
+ if str.state == empty {
+ str.state = active
+ l.activeStreams.enqueue(str)
+ }
+ return nil
+}
+
+func (l *loopyWriter) pingHandler(p *ping) error {
+ if !p.ack {
+ l.bdpEst.timesnap(p.data)
+ }
+ return l.framer.fr.WritePing(p.ack, p.data)
+
+}
+
+func (l *loopyWriter) outFlowControlSizeRequestHandler(o *outFlowControlSizeRequest) error {
+ o.resp <- l.sendQuota
+ return nil
+}
+
+func (l *loopyWriter) cleanupStreamHandler(c *cleanupStream) error {
+ c.onWrite()
+ if str, ok := l.estdStreams[c.streamID]; ok {
+ // On the server side it could be a trailers-only response or
+ // a RST_STREAM before stream initialization thus the stream might
+ // not be established yet.
+ delete(l.estdStreams, c.streamID)
+ str.deleteSelf()
+ }
+ if c.rst { // If RST_STREAM needs to be sent.
+ if err := l.framer.fr.WriteRSTStream(c.streamID, c.rstCode); err != nil {
+ return err
+ }
+ }
+ if l.side == clientSide && l.draining && len(l.estdStreams) == 0 {
+ return ErrConnClosing
+ }
+ return nil
+}
+
+func (l *loopyWriter) incomingGoAwayHandler(*incomingGoAway) error {
+ if l.side == clientSide {
+ l.draining = true
+ if len(l.estdStreams) == 0 {
+ return ErrConnClosing
+ }
+ }
+ return nil
+}
+
+func (l *loopyWriter) goAwayHandler(g *goAway) error {
+ // Handling of outgoing GoAway is very specific to side.
+ if l.ssGoAwayHandler != nil {
+ draining, err := l.ssGoAwayHandler(g)
+ if err != nil {
+ return err
+ }
+ l.draining = draining
+ }
+ return nil
+}
+
+func (l *loopyWriter) handle(i interface{}) error {
+ switch i := i.(type) {
+ case *incomingWindowUpdate:
+ return l.incomingWindowUpdateHandler(i)
+ case *outgoingWindowUpdate:
+ return l.outgoingWindowUpdateHandler(i)
+ case *incomingSettings:
+ return l.incomingSettingsHandler(i)
+ case *outgoingSettings:
+ return l.outgoingSettingsHandler(i)
+ case *headerFrame:
+ return l.headerHandler(i)
+ case *registerStream:
+ return l.registerStreamHandler(i)
+ case *cleanupStream:
+ return l.cleanupStreamHandler(i)
+ case *incomingGoAway:
+ return l.incomingGoAwayHandler(i)
+ case *dataFrame:
+ return l.preprocessData(i)
+ case *ping:
+ return l.pingHandler(i)
+ case *goAway:
+ return l.goAwayHandler(i)
+ case *outFlowControlSizeRequest:
+ return l.outFlowControlSizeRequestHandler(i)
+ default:
+ return fmt.Errorf("transport: unknown control message type %T", i)
+ }
+}
+
+func (l *loopyWriter) applySettings(ss []http2.Setting) error {
+ for _, s := range ss {
+ switch s.ID {
+ case http2.SettingInitialWindowSize:
+ o := l.oiws
+ l.oiws = s.Val
+ if o < l.oiws {
+ // If the new limit is greater make all depleted streams active.
+ for _, stream := range l.estdStreams {
+ if stream.state == waitingOnStreamQuota {
+ stream.state = active
+ l.activeStreams.enqueue(stream)
+ }
+ }
+ }
+ case http2.SettingHeaderTableSize:
+ updateHeaderTblSize(l.hEnc, s.Val)
+ }
+ }
+ return nil
+}
+
+// processData removes the first stream from active streams, writes out at most 16KB
+// of its data and then puts it at the end of activeStreams if there's still more data
+// to be sent and stream has some stream-level flow control.
+func (l *loopyWriter) processData() (bool, error) {
+ if l.sendQuota == 0 {
+ return true, nil
+ }
+ str := l.activeStreams.dequeue() // Remove the first stream.
+ if str == nil {
+ return true, nil
+ }
+ dataItem := str.itl.peek().(*dataFrame) // Peek at the first data item this stream.
+ // A data item is represented by a dataFrame, since it later translates into
+ // multiple HTTP2 data frames.
+ // Every dataFrame has two buffers; h that keeps grpc-message header and d that is acutal data.
+ // As an optimization to keep wire traffic low, data from d is copied to h to make as big as the
+ // maximum possilbe HTTP2 frame size.
+
+ if len(dataItem.h) == 0 && len(dataItem.d) == 0 { // Empty data frame
+ // Client sends out empty data frame with endStream = true
+ if err := l.framer.fr.WriteData(dataItem.streamID, dataItem.endStream, nil); err != nil {
+ return false, err
+ }
+ str.itl.dequeue() // remove the empty data item from stream
+ if str.itl.isEmpty() {
+ str.state = empty
+ } else if trailer, ok := str.itl.peek().(*headerFrame); ok { // the next item is trailers.
+ if err := l.writeHeader(trailer.streamID, trailer.endStream, trailer.hf, trailer.onWrite); err != nil {
+ return false, err
+ }
+ if err := l.cleanupStreamHandler(trailer.cleanup); err != nil {
+ return false, nil
+ }
+ } else {
+ l.activeStreams.enqueue(str)
+ }
+ return false, nil
+ }
+ var (
+ idx int
+ buf []byte
+ )
+ if len(dataItem.h) != 0 { // data header has not been written out yet.
+ buf = dataItem.h
+ } else {
+ idx = 1
+ buf = dataItem.d
+ }
+ size := http2MaxFrameLen
+ if len(buf) < size {
+ size = len(buf)
+ }
+ if strQuota := int(l.oiws) - str.bytesOutStanding; strQuota <= 0 { // stream-level flow control.
+ str.state = waitingOnStreamQuota
+ return false, nil
+ } else if strQuota < size {
+ size = strQuota
+ }
+
+ if l.sendQuota < uint32(size) { // connection-level flow control.
+ size = int(l.sendQuota)
+ }
+ // Now that outgoing flow controls are checked we can replenish str's write quota
+ str.wq.replenish(size)
+ var endStream bool
+ // If this is the last data message on this stream and all of it can be written in this iteration.
+ if dataItem.endStream && size == len(buf) {
+ // buf contains either data or it contains header but data is empty.
+ if idx == 1 || len(dataItem.d) == 0 {
+ endStream = true
+ }
+ }
+ if dataItem.onEachWrite != nil {
+ dataItem.onEachWrite()
+ }
+ if err := l.framer.fr.WriteData(dataItem.streamID, endStream, buf[:size]); err != nil {
+ return false, err
+ }
+ buf = buf[size:]
+ str.bytesOutStanding += size
+ l.sendQuota -= uint32(size)
+ if idx == 0 {
+ dataItem.h = buf
+ } else {
+ dataItem.d = buf
+ }
+
+ if len(dataItem.h) == 0 && len(dataItem.d) == 0 { // All the data from that message was written out.
+ str.itl.dequeue()
+ }
+ if str.itl.isEmpty() {
+ str.state = empty
+ } else if trailer, ok := str.itl.peek().(*headerFrame); ok { // The next item is trailers.
+ if err := l.writeHeader(trailer.streamID, trailer.endStream, trailer.hf, trailer.onWrite); err != nil {
+ return false, err
+ }
+ if err := l.cleanupStreamHandler(trailer.cleanup); err != nil {
+ return false, err
+ }
+ } else if int(l.oiws)-str.bytesOutStanding <= 0 { // Ran out of stream quota.
+ str.state = waitingOnStreamQuota
+ } else { // Otherwise add it back to the list of active streams.
+ l.activeStreams.enqueue(str)
+ }
+ return false, nil
+}
diff --git a/vendor/google.golang.org/grpc/internal/transport/defaults.go b/vendor/google.golang.org/grpc/internal/transport/defaults.go
new file mode 100644
index 000000000..9fa306b2e
--- /dev/null
+++ b/vendor/google.golang.org/grpc/internal/transport/defaults.go
@@ -0,0 +1,49 @@
+/*
+ *
+ * Copyright 2018 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package transport
+
+import (
+ "math"
+ "time"
+)
+
+const (
+ // The default value of flow control window size in HTTP2 spec.
+ defaultWindowSize = 65535
+ // The initial window size for flow control.
+ initialWindowSize = defaultWindowSize // for an RPC
+ infinity = time.Duration(math.MaxInt64)
+ defaultClientKeepaliveTime = infinity
+ defaultClientKeepaliveTimeout = 20 * time.Second
+ defaultMaxStreamsClient = 100
+ defaultMaxConnectionIdle = infinity
+ defaultMaxConnectionAge = infinity
+ defaultMaxConnectionAgeGrace = infinity
+ defaultServerKeepaliveTime = 2 * time.Hour
+ defaultServerKeepaliveTimeout = 20 * time.Second
+ defaultKeepalivePolicyMinTime = 5 * time.Minute
+ // max window limit set by HTTP2 Specs.
+ maxWindowSize = math.MaxInt32
+ // defaultWriteQuota is the default value for number of data
+ // bytes that each stream can schedule before some of it being
+ // flushed out.
+ defaultWriteQuota = 64 * 1024
+ defaultClientMaxHeaderListSize = uint32(16 << 20)
+ defaultServerMaxHeaderListSize = uint32(16 << 20)
+)
diff --git a/vendor/google.golang.org/grpc/internal/transport/flowcontrol.go b/vendor/google.golang.org/grpc/internal/transport/flowcontrol.go
new file mode 100644
index 000000000..5ea997a7e
--- /dev/null
+++ b/vendor/google.golang.org/grpc/internal/transport/flowcontrol.go
@@ -0,0 +1,218 @@
+/*
+ *
+ * Copyright 2014 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package transport
+
+import (
+ "fmt"
+ "math"
+ "sync"
+ "sync/atomic"
+)
+
+// writeQuota is a soft limit on the amount of data a stream can
+// schedule before some of it is written out.
+type writeQuota struct {
+ quota int32
+ // get waits on read from when quota goes less than or equal to zero.
+ // replenish writes on it when quota goes positive again.
+ ch chan struct{}
+ // done is triggered in error case.
+ done <-chan struct{}
+ // replenish is called by loopyWriter to give quota back to.
+ // It is implemented as a field so that it can be updated
+ // by tests.
+ replenish func(n int)
+}
+
+func newWriteQuota(sz int32, done <-chan struct{}) *writeQuota {
+ w := &writeQuota{
+ quota: sz,
+ ch: make(chan struct{}, 1),
+ done: done,
+ }
+ w.replenish = w.realReplenish
+ return w
+}
+
+func (w *writeQuota) get(sz int32) error {
+ for {
+ if atomic.LoadInt32(&w.quota) > 0 {
+ atomic.AddInt32(&w.quota, -sz)
+ return nil
+ }
+ select {
+ case <-w.ch:
+ continue
+ case <-w.done:
+ return errStreamDone
+ }
+ }
+}
+
+func (w *writeQuota) realReplenish(n int) {
+ sz := int32(n)
+ a := atomic.AddInt32(&w.quota, sz)
+ b := a - sz
+ if b <= 0 && a > 0 {
+ select {
+ case w.ch <- struct{}{}:
+ default:
+ }
+ }
+}
+
+type trInFlow struct {
+ limit uint32
+ unacked uint32
+ effectiveWindowSize uint32
+}
+
+func (f *trInFlow) newLimit(n uint32) uint32 {
+ d := n - f.limit
+ f.limit = n
+ f.updateEffectiveWindowSize()
+ return d
+}
+
+func (f *trInFlow) onData(n uint32) uint32 {
+ f.unacked += n
+ if f.unacked >= f.limit/4 {
+ w := f.unacked
+ f.unacked = 0
+ f.updateEffectiveWindowSize()
+ return w
+ }
+ f.updateEffectiveWindowSize()
+ return 0
+}
+
+func (f *trInFlow) reset() uint32 {
+ w := f.unacked
+ f.unacked = 0
+ f.updateEffectiveWindowSize()
+ return w
+}
+
+func (f *trInFlow) updateEffectiveWindowSize() {
+ atomic.StoreUint32(&f.effectiveWindowSize, f.limit-f.unacked)
+}
+
+func (f *trInFlow) getSize() uint32 {
+ return atomic.LoadUint32(&f.effectiveWindowSize)
+}
+
+// TODO(mmukhi): Simplify this code.
+// inFlow deals with inbound flow control
+type inFlow struct {
+ mu sync.Mutex
+ // The inbound flow control limit for pending data.
+ limit uint32
+ // pendingData is the overall data which have been received but not been
+ // consumed by applications.
+ pendingData uint32
+ // The amount of data the application has consumed but grpc has not sent
+ // window update for them. Used to reduce window update frequency.
+ pendingUpdate uint32
+ // delta is the extra window update given by receiver when an application
+ // is reading data bigger in size than the inFlow limit.
+ delta uint32
+}
+
+// newLimit updates the inflow window to a new value n.
+// It assumes that n is always greater than the old limit.
+func (f *inFlow) newLimit(n uint32) uint32 {
+ f.mu.Lock()
+ d := n - f.limit
+ f.limit = n
+ f.mu.Unlock()
+ return d
+}
+
+func (f *inFlow) maybeAdjust(n uint32) uint32 {
+ if n > uint32(math.MaxInt32) {
+ n = uint32(math.MaxInt32)
+ }
+ f.mu.Lock()
+ // estSenderQuota is the receiver's view of the maximum number of bytes the sender
+ // can send without a window update.
+ estSenderQuota := int32(f.limit - (f.pendingData + f.pendingUpdate))
+ // estUntransmittedData is the maximum number of bytes the sends might not have put
+ // on the wire yet. A value of 0 or less means that we have already received all or
+ // more bytes than the application is requesting to read.
+ estUntransmittedData := int32(n - f.pendingData) // Casting into int32 since it could be negative.
+ // This implies that unless we send a window update, the sender won't be able to send all the bytes
+ // for this message. Therefore we must send an update over the limit since there's an active read
+ // request from the application.
+ if estUntransmittedData > estSenderQuota {
+ // Sender's window shouldn't go more than 2^31 - 1 as specified in the HTTP spec.
+ if f.limit+n > maxWindowSize {
+ f.delta = maxWindowSize - f.limit
+ } else {
+ // Send a window update for the whole message and not just the difference between
+ // estUntransmittedData and estSenderQuota. This will be helpful in case the message
+ // is padded; We will fallback on the current available window(at least a 1/4th of the limit).
+ f.delta = n
+ }
+ f.mu.Unlock()
+ return f.delta
+ }
+ f.mu.Unlock()
+ return 0
+}
+
+// onData is invoked when some data frame is received. It updates pendingData.
+func (f *inFlow) onData(n uint32) error {
+ f.mu.Lock()
+ f.pendingData += n
+ if f.pendingData+f.pendingUpdate > f.limit+f.delta {
+ limit := f.limit
+ rcvd := f.pendingData + f.pendingUpdate
+ f.mu.Unlock()
+ return fmt.Errorf("received %d-bytes data exceeding the limit %d bytes", rcvd, limit)
+ }
+ f.mu.Unlock()
+ return nil
+}
+
+// onRead is invoked when the application reads the data. It returns the window size
+// to be sent to the peer.
+func (f *inFlow) onRead(n uint32) uint32 {
+ f.mu.Lock()
+ if f.pendingData == 0 {
+ f.mu.Unlock()
+ return 0
+ }
+ f.pendingData -= n
+ if n > f.delta {
+ n -= f.delta
+ f.delta = 0
+ } else {
+ f.delta -= n
+ n = 0
+ }
+ f.pendingUpdate += n
+ if f.pendingUpdate >= f.limit/4 {
+ wu := f.pendingUpdate
+ f.pendingUpdate = 0
+ f.mu.Unlock()
+ return wu
+ }
+ f.mu.Unlock()
+ return 0
+}
diff --git a/vendor/google.golang.org/grpc/internal/transport/handler_server.go b/vendor/google.golang.org/grpc/internal/transport/handler_server.go
new file mode 100644
index 000000000..73b41ea7e
--- /dev/null
+++ b/vendor/google.golang.org/grpc/internal/transport/handler_server.go
@@ -0,0 +1,449 @@
+/*
+ *
+ * Copyright 2016 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// This file is the implementation of a gRPC server using HTTP/2 which
+// uses the standard Go http2 Server implementation (via the
+// http.Handler interface), rather than speaking low-level HTTP/2
+// frames itself. It is the implementation of *grpc.Server.ServeHTTP.
+
+package transport
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "io"
+ "net"
+ "net/http"
+ "strings"
+ "sync"
+ "time"
+
+ "github.com/golang/protobuf/proto"
+ "golang.org/x/net/http2"
+ "google.golang.org/grpc/codes"
+ "google.golang.org/grpc/credentials"
+ "google.golang.org/grpc/metadata"
+ "google.golang.org/grpc/peer"
+ "google.golang.org/grpc/stats"
+ "google.golang.org/grpc/status"
+)
+
+// NewServerHandlerTransport returns a ServerTransport handling gRPC
+// from inside an http.Handler. It requires that the http Server
+// supports HTTP/2.
+func NewServerHandlerTransport(w http.ResponseWriter, r *http.Request, stats stats.Handler) (ServerTransport, error) {
+ if r.ProtoMajor != 2 {
+ return nil, errors.New("gRPC requires HTTP/2")
+ }
+ if r.Method != "POST" {
+ return nil, errors.New("invalid gRPC request method")
+ }
+ contentType := r.Header.Get("Content-Type")
+ // TODO: do we assume contentType is lowercase? we did before
+ contentSubtype, validContentType := contentSubtype(contentType)
+ if !validContentType {
+ return nil, errors.New("invalid gRPC request content-type")
+ }
+ if _, ok := w.(http.Flusher); !ok {
+ return nil, errors.New("gRPC requires a ResponseWriter supporting http.Flusher")
+ }
+ if _, ok := w.(http.CloseNotifier); !ok {
+ return nil, errors.New("gRPC requires a ResponseWriter supporting http.CloseNotifier")
+ }
+
+ st := &serverHandlerTransport{
+ rw: w,
+ req: r,
+ closedCh: make(chan struct{}),
+ writes: make(chan func()),
+ contentType: contentType,
+ contentSubtype: contentSubtype,
+ stats: stats,
+ }
+
+ if v := r.Header.Get("grpc-timeout"); v != "" {
+ to, err := decodeTimeout(v)
+ if err != nil {
+ return nil, status.Errorf(codes.Internal, "malformed time-out: %v", err)
+ }
+ st.timeoutSet = true
+ st.timeout = to
+ }
+
+ metakv := []string{"content-type", contentType}
+ if r.Host != "" {
+ metakv = append(metakv, ":authority", r.Host)
+ }
+ for k, vv := range r.Header {
+ k = strings.ToLower(k)
+ if isReservedHeader(k) && !isWhitelistedHeader(k) {
+ continue
+ }
+ for _, v := range vv {
+ v, err := decodeMetadataHeader(k, v)
+ if err != nil {
+ return nil, status.Errorf(codes.Internal, "malformed binary metadata: %v", err)
+ }
+ metakv = append(metakv, k, v)
+ }
+ }
+ st.headerMD = metadata.Pairs(metakv...)
+
+ return st, nil
+}
+
+// serverHandlerTransport is an implementation of ServerTransport
+// which replies to exactly one gRPC request (exactly one HTTP request),
+// using the net/http.Handler interface. This http.Handler is guaranteed
+// at this point to be speaking over HTTP/2, so it's able to speak valid
+// gRPC.
+type serverHandlerTransport struct {
+ rw http.ResponseWriter
+ req *http.Request
+ timeoutSet bool
+ timeout time.Duration
+ didCommonHeaders bool
+
+ headerMD metadata.MD
+
+ closeOnce sync.Once
+ closedCh chan struct{} // closed on Close
+
+ // writes is a channel of code to run serialized in the
+ // ServeHTTP (HandleStreams) goroutine. The channel is closed
+ // when WriteStatus is called.
+ writes chan func()
+
+ // block concurrent WriteStatus calls
+ // e.g. grpc/(*serverStream).SendMsg/RecvMsg
+ writeStatusMu sync.Mutex
+
+ // we just mirror the request content-type
+ contentType string
+ // we store both contentType and contentSubtype so we don't keep recreating them
+ // TODO make sure this is consistent across handler_server and http2_server
+ contentSubtype string
+
+ stats stats.Handler
+}
+
+func (ht *serverHandlerTransport) Close() error {
+ ht.closeOnce.Do(ht.closeCloseChanOnce)
+ return nil
+}
+
+func (ht *serverHandlerTransport) closeCloseChanOnce() { close(ht.closedCh) }
+
+func (ht *serverHandlerTransport) RemoteAddr() net.Addr { return strAddr(ht.req.RemoteAddr) }
+
+// strAddr is a net.Addr backed by either a TCP "ip:port" string, or
+// the empty string if unknown.
+type strAddr string
+
+func (a strAddr) Network() string {
+ if a != "" {
+ // Per the documentation on net/http.Request.RemoteAddr, if this is
+ // set, it's set to the IP:port of the peer (hence, TCP):
+ // https://golang.org/pkg/net/http/#Request
+ //
+ // If we want to support Unix sockets later, we can
+ // add our own grpc-specific convention within the
+ // grpc codebase to set RemoteAddr to a different
+ // format, or probably better: we can attach it to the
+ // context and use that from serverHandlerTransport.RemoteAddr.
+ return "tcp"
+ }
+ return ""
+}
+
+func (a strAddr) String() string { return string(a) }
+
+// do runs fn in the ServeHTTP goroutine.
+func (ht *serverHandlerTransport) do(fn func()) error {
+ // Avoid a panic writing to closed channel. Imperfect but maybe good enough.
+ select {
+ case <-ht.closedCh:
+ return ErrConnClosing
+ default:
+ select {
+ case ht.writes <- fn:
+ return nil
+ case <-ht.closedCh:
+ return ErrConnClosing
+ }
+ }
+}
+
+func (ht *serverHandlerTransport) WriteStatus(s *Stream, st *status.Status) error {
+ ht.writeStatusMu.Lock()
+ defer ht.writeStatusMu.Unlock()
+
+ err := ht.do(func() {
+ ht.writeCommonHeaders(s)
+
+ // And flush, in case no header or body has been sent yet.
+ // This forces a separation of headers and trailers if this is the
+ // first call (for example, in end2end tests's TestNoService).
+ ht.rw.(http.Flusher).Flush()
+
+ h := ht.rw.Header()
+ h.Set("Grpc-Status", fmt.Sprintf("%d", st.Code()))
+ if m := st.Message(); m != "" {
+ h.Set("Grpc-Message", encodeGrpcMessage(m))
+ }
+
+ if p := st.Proto(); p != nil && len(p.Details) > 0 {
+ stBytes, err := proto.Marshal(p)
+ if err != nil {
+ // TODO: return error instead, when callers are able to handle it.
+ panic(err)
+ }
+
+ h.Set("Grpc-Status-Details-Bin", encodeBinHeader(stBytes))
+ }
+
+ if md := s.Trailer(); len(md) > 0 {
+ for k, vv := range md {
+ // Clients don't tolerate reading restricted headers after some non restricted ones were sent.
+ if isReservedHeader(k) {
+ continue
+ }
+ for _, v := range vv {
+ // http2 ResponseWriter mechanism to send undeclared Trailers after
+ // the headers have possibly been written.
+ h.Add(http2.TrailerPrefix+k, encodeMetadataHeader(k, v))
+ }
+ }
+ }
+ })
+
+ if err == nil { // transport has not been closed
+ if ht.stats != nil {
+ ht.stats.HandleRPC(s.Context(), &stats.OutTrailer{})
+ }
+ close(ht.writes)
+ }
+ ht.Close()
+ return err
+}
+
+// writeCommonHeaders sets common headers on the first write
+// call (Write, WriteHeader, or WriteStatus).
+func (ht *serverHandlerTransport) writeCommonHeaders(s *Stream) {
+ if ht.didCommonHeaders {
+ return
+ }
+ ht.didCommonHeaders = true
+
+ h := ht.rw.Header()
+ h["Date"] = nil // suppress Date to make tests happy; TODO: restore
+ h.Set("Content-Type", ht.contentType)
+
+ // Predeclare trailers we'll set later in WriteStatus (after the body).
+ // This is a SHOULD in the HTTP RFC, and the way you add (known)
+ // Trailers per the net/http.ResponseWriter contract.
+ // See https://golang.org/pkg/net/http/#ResponseWriter
+ // and https://golang.org/pkg/net/http/#example_ResponseWriter_trailers
+ h.Add("Trailer", "Grpc-Status")
+ h.Add("Trailer", "Grpc-Message")
+ h.Add("Trailer", "Grpc-Status-Details-Bin")
+
+ if s.sendCompress != "" {
+ h.Set("Grpc-Encoding", s.sendCompress)
+ }
+}
+
+func (ht *serverHandlerTransport) Write(s *Stream, hdr []byte, data []byte, opts *Options) error {
+ return ht.do(func() {
+ ht.writeCommonHeaders(s)
+ ht.rw.Write(hdr)
+ ht.rw.Write(data)
+ ht.rw.(http.Flusher).Flush()
+ })
+}
+
+func (ht *serverHandlerTransport) WriteHeader(s *Stream, md metadata.MD) error {
+ err := ht.do(func() {
+ ht.writeCommonHeaders(s)
+ h := ht.rw.Header()
+ for k, vv := range md {
+ // Clients don't tolerate reading restricted headers after some non restricted ones were sent.
+ if isReservedHeader(k) {
+ continue
+ }
+ for _, v := range vv {
+ v = encodeMetadataHeader(k, v)
+ h.Add(k, v)
+ }
+ }
+ ht.rw.WriteHeader(200)
+ ht.rw.(http.Flusher).Flush()
+ })
+
+ if err == nil {
+ if ht.stats != nil {
+ ht.stats.HandleRPC(s.Context(), &stats.OutHeader{})
+ }
+ }
+ return err
+}
+
+func (ht *serverHandlerTransport) HandleStreams(startStream func(*Stream), traceCtx func(context.Context, string) context.Context) {
+ // With this transport type there will be exactly 1 stream: this HTTP request.
+
+ ctx := ht.req.Context()
+ var cancel context.CancelFunc
+ if ht.timeoutSet {
+ ctx, cancel = context.WithTimeout(ctx, ht.timeout)
+ } else {
+ ctx, cancel = context.WithCancel(ctx)
+ }
+
+ // requestOver is closed when either the request's context is done
+ // or the status has been written via WriteStatus.
+ requestOver := make(chan struct{})
+
+ // clientGone receives a single value if peer is gone, either
+ // because the underlying connection is dead or because the
+ // peer sends an http2 RST_STREAM.
+ clientGone := ht.rw.(http.CloseNotifier).CloseNotify()
+ go func() {
+ select {
+ case <-requestOver:
+ case <-ht.closedCh:
+ case <-clientGone:
+ }
+ cancel()
+ ht.Close()
+ }()
+
+ req := ht.req
+
+ s := &Stream{
+ id: 0, // irrelevant
+ requestRead: func(int) {},
+ cancel: cancel,
+ buf: newRecvBuffer(),
+ st: ht,
+ method: req.URL.Path,
+ recvCompress: req.Header.Get("grpc-encoding"),
+ contentSubtype: ht.contentSubtype,
+ }
+ pr := &peer.Peer{
+ Addr: ht.RemoteAddr(),
+ }
+ if req.TLS != nil {
+ pr.AuthInfo = credentials.TLSInfo{State: *req.TLS}
+ }
+ ctx = metadata.NewIncomingContext(ctx, ht.headerMD)
+ s.ctx = peer.NewContext(ctx, pr)
+ if ht.stats != nil {
+ s.ctx = ht.stats.TagRPC(s.ctx, &stats.RPCTagInfo{FullMethodName: s.method})
+ inHeader := &stats.InHeader{
+ FullMethod: s.method,
+ RemoteAddr: ht.RemoteAddr(),
+ Compression: s.recvCompress,
+ }
+ ht.stats.HandleRPC(s.ctx, inHeader)
+ }
+ s.trReader = &transportReader{
+ reader: &recvBufferReader{ctx: s.ctx, ctxDone: s.ctx.Done(), recv: s.buf},
+ windowHandler: func(int) {},
+ }
+
+ // readerDone is closed when the Body.Read-ing goroutine exits.
+ readerDone := make(chan struct{})
+ go func() {
+ defer close(readerDone)
+
+ // TODO: minimize garbage, optimize recvBuffer code/ownership
+ const readSize = 8196
+ for buf := make([]byte, readSize); ; {
+ n, err := req.Body.Read(buf)
+ if n > 0 {
+ s.buf.put(recvMsg{data: buf[:n:n]})
+ buf = buf[n:]
+ }
+ if err != nil {
+ s.buf.put(recvMsg{err: mapRecvMsgError(err)})
+ return
+ }
+ if len(buf) == 0 {
+ buf = make([]byte, readSize)
+ }
+ }
+ }()
+
+ // startStream is provided by the *grpc.Server's serveStreams.
+ // It starts a goroutine serving s and exits immediately.
+ // The goroutine that is started is the one that then calls
+ // into ht, calling WriteHeader, Write, WriteStatus, Close, etc.
+ startStream(s)
+
+ ht.runStream()
+ close(requestOver)
+
+ // Wait for reading goroutine to finish.
+ req.Body.Close()
+ <-readerDone
+}
+
+func (ht *serverHandlerTransport) runStream() {
+ for {
+ select {
+ case fn, ok := <-ht.writes:
+ if !ok {
+ return
+ }
+ fn()
+ case <-ht.closedCh:
+ return
+ }
+ }
+}
+
+func (ht *serverHandlerTransport) IncrMsgSent() {}
+
+func (ht *serverHandlerTransport) IncrMsgRecv() {}
+
+func (ht *serverHandlerTransport) Drain() {
+ panic("Drain() is not implemented")
+}
+
+// mapRecvMsgError returns the non-nil err into the appropriate
+// error value as expected by callers of *grpc.parser.recvMsg.
+// In particular, in can only be:
+// * io.EOF
+// * io.ErrUnexpectedEOF
+// * of type transport.ConnectionError
+// * an error from the status package
+func mapRecvMsgError(err error) error {
+ if err == io.EOF || err == io.ErrUnexpectedEOF {
+ return err
+ }
+ if se, ok := err.(http2.StreamError); ok {
+ if code, ok := http2ErrConvTab[se.Code]; ok {
+ return status.Error(code, se.Error())
+ }
+ }
+ if strings.Contains(err.Error(), "body closed by handler") {
+ return status.Error(codes.Canceled, err.Error())
+ }
+ return connectionErrorf(true, err, err.Error())
+}
diff --git a/vendor/google.golang.org/grpc/internal/transport/http2_client.go b/vendor/google.golang.org/grpc/internal/transport/http2_client.go
new file mode 100644
index 000000000..39208b146
--- /dev/null
+++ b/vendor/google.golang.org/grpc/internal/transport/http2_client.go
@@ -0,0 +1,1377 @@
+/*
+ *
+ * Copyright 2014 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package transport
+
+import (
+ "context"
+ "fmt"
+ "io"
+ "math"
+ "net"
+ "strconv"
+ "strings"
+ "sync"
+ "sync/atomic"
+ "time"
+
+ "golang.org/x/net/http2"
+ "golang.org/x/net/http2/hpack"
+
+ "google.golang.org/grpc/codes"
+ "google.golang.org/grpc/credentials"
+ "google.golang.org/grpc/internal/channelz"
+ "google.golang.org/grpc/internal/syscall"
+ "google.golang.org/grpc/keepalive"
+ "google.golang.org/grpc/metadata"
+ "google.golang.org/grpc/peer"
+ "google.golang.org/grpc/stats"
+ "google.golang.org/grpc/status"
+)
+
+// http2Client implements the ClientTransport interface with HTTP2.
+type http2Client struct {
+ ctx context.Context
+ cancel context.CancelFunc
+ ctxDone <-chan struct{} // Cache the ctx.Done() chan.
+ userAgent string
+ md interface{}
+ conn net.Conn // underlying communication channel
+ loopy *loopyWriter
+ remoteAddr net.Addr
+ localAddr net.Addr
+ authInfo credentials.AuthInfo // auth info about the connection
+
+ readerDone chan struct{} // sync point to enable testing.
+ writerDone chan struct{} // sync point to enable testing.
+ // goAway is closed to notify the upper layer (i.e., addrConn.transportMonitor)
+ // that the server sent GoAway on this transport.
+ goAway chan struct{}
+ // awakenKeepalive is used to wake up keepalive when after it has gone dormant.
+ awakenKeepalive chan struct{}
+
+ framer *framer
+ // controlBuf delivers all the control related tasks (e.g., window
+ // updates, reset streams, and various settings) to the controller.
+ controlBuf *controlBuffer
+ fc *trInFlow
+ // The scheme used: https if TLS is on, http otherwise.
+ scheme string
+
+ isSecure bool
+
+ perRPCCreds []credentials.PerRPCCredentials
+
+ // Boolean to keep track of reading activity on transport.
+ // 1 is true and 0 is false.
+ activity uint32 // Accessed atomically.
+ kp keepalive.ClientParameters
+ keepaliveEnabled bool
+
+ statsHandler stats.Handler
+
+ initialWindowSize int32
+
+ // configured by peer through SETTINGS_MAX_HEADER_LIST_SIZE
+ maxSendHeaderListSize *uint32
+
+ bdpEst *bdpEstimator
+ // onSuccess is a callback that client transport calls upon
+ // receiving server preface to signal that a succefull HTTP2
+ // connection was established.
+ onSuccess func()
+
+ maxConcurrentStreams uint32
+ streamQuota int64
+ streamsQuotaAvailable chan struct{}
+ waitingStreams uint32
+ nextID uint32
+
+ mu sync.Mutex // guard the following variables
+ state transportState
+ activeStreams map[uint32]*Stream
+ // prevGoAway ID records the Last-Stream-ID in the previous GOAway frame.
+ prevGoAwayID uint32
+ // goAwayReason records the http2.ErrCode and debug data received with the
+ // GoAway frame.
+ goAwayReason GoAwayReason
+
+ // Fields below are for channelz metric collection.
+ channelzID int64 // channelz unique identification number
+ czData *channelzData
+
+ onGoAway func(GoAwayReason)
+ onClose func()
+}
+
+func dial(ctx context.Context, fn func(context.Context, string) (net.Conn, error), addr string) (net.Conn, error) {
+ if fn != nil {
+ return fn(ctx, addr)
+ }
+ return (&net.Dialer{}).DialContext(ctx, "tcp", addr)
+}
+
+func isTemporary(err error) bool {
+ switch err := err.(type) {
+ case interface {
+ Temporary() bool
+ }:
+ return err.Temporary()
+ case interface {
+ Timeout() bool
+ }:
+ // Timeouts may be resolved upon retry, and are thus treated as
+ // temporary.
+ return err.Timeout()
+ }
+ return true
+}
+
+// newHTTP2Client constructs a connected ClientTransport to addr based on HTTP2
+// and starts to receive messages on it. Non-nil error returns if construction
+// fails.
+func newHTTP2Client(connectCtx, ctx context.Context, addr TargetInfo, opts ConnectOptions, onSuccess func(), onGoAway func(GoAwayReason), onClose func()) (_ *http2Client, err error) {
+ scheme := "http"
+ ctx, cancel := context.WithCancel(ctx)
+ defer func() {
+ if err != nil {
+ cancel()
+ }
+ }()
+
+ conn, err := dial(connectCtx, opts.Dialer, addr.Addr)
+ if err != nil {
+ if opts.FailOnNonTempDialError {
+ return nil, connectionErrorf(isTemporary(err), err, "transport: error while dialing: %v", err)
+ }
+ return nil, connectionErrorf(true, err, "transport: Error while dialing %v", err)
+ }
+ // Any further errors will close the underlying connection
+ defer func(conn net.Conn) {
+ if err != nil {
+ conn.Close()
+ }
+ }(conn)
+ kp := opts.KeepaliveParams
+ // Validate keepalive parameters.
+ if kp.Time == 0 {
+ kp.Time = defaultClientKeepaliveTime
+ }
+ if kp.Timeout == 0 {
+ kp.Timeout = defaultClientKeepaliveTimeout
+ }
+ keepaliveEnabled := false
+ if kp.Time != infinity {
+ if err = syscall.SetTCPUserTimeout(conn, kp.Timeout); err != nil {
+ return nil, connectionErrorf(false, err, "transport: failed to set TCP_USER_TIMEOUT: %v", err)
+ }
+ keepaliveEnabled = true
+ }
+ var (
+ isSecure bool
+ authInfo credentials.AuthInfo
+ )
+ transportCreds := opts.TransportCredentials
+ perRPCCreds := opts.PerRPCCredentials
+
+ if b := opts.CredsBundle; b != nil {
+ if t := b.TransportCredentials(); t != nil {
+ transportCreds = t
+ }
+ if t := b.PerRPCCredentials(); t != nil {
+ perRPCCreds = append(perRPCCreds, t)
+ }
+ }
+ if transportCreds != nil {
+ scheme = "https"
+ conn, authInfo, err = transportCreds.ClientHandshake(connectCtx, addr.Authority, conn)
+ if err != nil {
+ return nil, connectionErrorf(isTemporary(err), err, "transport: authentication handshake failed: %v", err)
+ }
+ isSecure = true
+ }
+ dynamicWindow := true
+ icwz := int32(initialWindowSize)
+ if opts.InitialConnWindowSize >= defaultWindowSize {
+ icwz = opts.InitialConnWindowSize
+ dynamicWindow = false
+ }
+ writeBufSize := opts.WriteBufferSize
+ readBufSize := opts.ReadBufferSize
+ maxHeaderListSize := defaultClientMaxHeaderListSize
+ if opts.MaxHeaderListSize != nil {
+ maxHeaderListSize = *opts.MaxHeaderListSize
+ }
+ t := &http2Client{
+ ctx: ctx,
+ ctxDone: ctx.Done(), // Cache Done chan.
+ cancel: cancel,
+ userAgent: opts.UserAgent,
+ md: addr.Metadata,
+ conn: conn,
+ remoteAddr: conn.RemoteAddr(),
+ localAddr: conn.LocalAddr(),
+ authInfo: authInfo,
+ readerDone: make(chan struct{}),
+ writerDone: make(chan struct{}),
+ goAway: make(chan struct{}),
+ awakenKeepalive: make(chan struct{}, 1),
+ framer: newFramer(conn, writeBufSize, readBufSize, maxHeaderListSize),
+ fc: &trInFlow{limit: uint32(icwz)},
+ scheme: scheme,
+ activeStreams: make(map[uint32]*Stream),
+ isSecure: isSecure,
+ perRPCCreds: perRPCCreds,
+ kp: kp,
+ statsHandler: opts.StatsHandler,
+ initialWindowSize: initialWindowSize,
+ onSuccess: onSuccess,
+ nextID: 1,
+ maxConcurrentStreams: defaultMaxStreamsClient,
+ streamQuota: defaultMaxStreamsClient,
+ streamsQuotaAvailable: make(chan struct{}, 1),
+ czData: new(channelzData),
+ onGoAway: onGoAway,
+ onClose: onClose,
+ keepaliveEnabled: keepaliveEnabled,
+ }
+ t.controlBuf = newControlBuffer(t.ctxDone)
+ if opts.InitialWindowSize >= defaultWindowSize {
+ t.initialWindowSize = opts.InitialWindowSize
+ dynamicWindow = false
+ }
+ if dynamicWindow {
+ t.bdpEst = &bdpEstimator{
+ bdp: initialWindowSize,
+ updateFlowControl: t.updateFlowControl,
+ }
+ }
+ // Make sure awakenKeepalive can't be written upon.
+ // keepalive routine will make it writable, if need be.
+ t.awakenKeepalive <- struct{}{}
+ if t.statsHandler != nil {
+ t.ctx = t.statsHandler.TagConn(t.ctx, &stats.ConnTagInfo{
+ RemoteAddr: t.remoteAddr,
+ LocalAddr: t.localAddr,
+ })
+ connBegin := &stats.ConnBegin{
+ Client: true,
+ }
+ t.statsHandler.HandleConn(t.ctx, connBegin)
+ }
+ if channelz.IsOn() {
+ t.channelzID = channelz.RegisterNormalSocket(t, opts.ChannelzParentID, fmt.Sprintf("%s -> %s", t.localAddr, t.remoteAddr))
+ }
+ if t.keepaliveEnabled {
+ go t.keepalive()
+ }
+ // Start the reader goroutine for incoming message. Each transport has
+ // a dedicated goroutine which reads HTTP2 frame from network. Then it
+ // dispatches the frame to the corresponding stream entity.
+ go t.reader()
+
+ // Send connection preface to server.
+ n, err := t.conn.Write(clientPreface)
+ if err != nil {
+ t.Close()
+ return nil, connectionErrorf(true, err, "transport: failed to write client preface: %v", err)
+ }
+ if n != len(clientPreface) {
+ t.Close()
+ return nil, connectionErrorf(true, err, "transport: preface mismatch, wrote %d bytes; want %d", n, len(clientPreface))
+ }
+ var ss []http2.Setting
+
+ if t.initialWindowSize != defaultWindowSize {
+ ss = append(ss, http2.Setting{
+ ID: http2.SettingInitialWindowSize,
+ Val: uint32(t.initialWindowSize),
+ })
+ }
+ if opts.MaxHeaderListSize != nil {
+ ss = append(ss, http2.Setting{
+ ID: http2.SettingMaxHeaderListSize,
+ Val: *opts.MaxHeaderListSize,
+ })
+ }
+ err = t.framer.fr.WriteSettings(ss...)
+ if err != nil {
+ t.Close()
+ return nil, connectionErrorf(true, err, "transport: failed to write initial settings frame: %v", err)
+ }
+ // Adjust the connection flow control window if needed.
+ if delta := uint32(icwz - defaultWindowSize); delta > 0 {
+ if err := t.framer.fr.WriteWindowUpdate(0, delta); err != nil {
+ t.Close()
+ return nil, connectionErrorf(true, err, "transport: failed to write window update: %v", err)
+ }
+ }
+
+ t.framer.writer.Flush()
+ go func() {
+ t.loopy = newLoopyWriter(clientSide, t.framer, t.controlBuf, t.bdpEst)
+ err := t.loopy.run()
+ if err != nil {
+ errorf("transport: loopyWriter.run returning. Err: %v", err)
+ }
+ // If it's a connection error, let reader goroutine handle it
+ // since there might be data in the buffers.
+ if _, ok := err.(net.Error); !ok {
+ t.conn.Close()
+ }
+ close(t.writerDone)
+ }()
+ return t, nil
+}
+
+func (t *http2Client) newStream(ctx context.Context, callHdr *CallHdr) *Stream {
+ // TODO(zhaoq): Handle uint32 overflow of Stream.id.
+ s := &Stream{
+ done: make(chan struct{}),
+ method: callHdr.Method,
+ sendCompress: callHdr.SendCompress,
+ buf: newRecvBuffer(),
+ headerChan: make(chan struct{}),
+ contentSubtype: callHdr.ContentSubtype,
+ }
+ s.wq = newWriteQuota(defaultWriteQuota, s.done)
+ s.requestRead = func(n int) {
+ t.adjustWindow(s, uint32(n))
+ }
+ // The client side stream context should have exactly the same life cycle with the user provided context.
+ // That means, s.ctx should be read-only. And s.ctx is done iff ctx is done.
+ // So we use the original context here instead of creating a copy.
+ s.ctx = ctx
+ s.trReader = &transportReader{
+ reader: &recvBufferReader{
+ ctx: s.ctx,
+ ctxDone: s.ctx.Done(),
+ recv: s.buf,
+ },
+ windowHandler: func(n int) {
+ t.updateWindow(s, uint32(n))
+ },
+ }
+ return s
+}
+
+func (t *http2Client) getPeer() *peer.Peer {
+ pr := &peer.Peer{
+ Addr: t.remoteAddr,
+ }
+ // Attach Auth info if there is any.
+ if t.authInfo != nil {
+ pr.AuthInfo = t.authInfo
+ }
+ return pr
+}
+
+func (t *http2Client) createHeaderFields(ctx context.Context, callHdr *CallHdr) ([]hpack.HeaderField, error) {
+ aud := t.createAudience(callHdr)
+ authData, err := t.getTrAuthData(ctx, aud)
+ if err != nil {
+ return nil, err
+ }
+ callAuthData, err := t.getCallAuthData(ctx, aud, callHdr)
+ if err != nil {
+ return nil, err
+ }
+ // TODO(mmukhi): Benchmark if the performance gets better if count the metadata and other header fields
+ // first and create a slice of that exact size.
+ // Make the slice of certain predictable size to reduce allocations made by append.
+ hfLen := 7 // :method, :scheme, :path, :authority, content-type, user-agent, te
+ hfLen += len(authData) + len(callAuthData)
+ headerFields := make([]hpack.HeaderField, 0, hfLen)
+ headerFields = append(headerFields, hpack.HeaderField{Name: ":method", Value: "POST"})
+ headerFields = append(headerFields, hpack.HeaderField{Name: ":scheme", Value: t.scheme})
+ headerFields = append(headerFields, hpack.HeaderField{Name: ":path", Value: callHdr.Method})
+ headerFields = append(headerFields, hpack.HeaderField{Name: ":authority", Value: callHdr.Host})
+ headerFields = append(headerFields, hpack.HeaderField{Name: "content-type", Value: contentType(callHdr.ContentSubtype)})
+ headerFields = append(headerFields, hpack.HeaderField{Name: "user-agent", Value: t.userAgent})
+ headerFields = append(headerFields, hpack.HeaderField{Name: "te", Value: "trailers"})
+ if callHdr.PreviousAttempts > 0 {
+ headerFields = append(headerFields, hpack.HeaderField{Name: "grpc-previous-rpc-attempts", Value: strconv.Itoa(callHdr.PreviousAttempts)})
+ }
+
+ if callHdr.SendCompress != "" {
+ headerFields = append(headerFields, hpack.HeaderField{Name: "grpc-encoding", Value: callHdr.SendCompress})
+ }
+ if dl, ok := ctx.Deadline(); ok {
+ // Send out timeout regardless its value. The server can detect timeout context by itself.
+ // TODO(mmukhi): Perhaps this field should be updated when actually writing out to the wire.
+ timeout := dl.Sub(time.Now())
+ headerFields = append(headerFields, hpack.HeaderField{Name: "grpc-timeout", Value: encodeTimeout(timeout)})
+ }
+ for k, v := range authData {
+ headerFields = append(headerFields, hpack.HeaderField{Name: k, Value: encodeMetadataHeader(k, v)})
+ }
+ for k, v := range callAuthData {
+ headerFields = append(headerFields, hpack.HeaderField{Name: k, Value: encodeMetadataHeader(k, v)})
+ }
+ if b := stats.OutgoingTags(ctx); b != nil {
+ headerFields = append(headerFields, hpack.HeaderField{Name: "grpc-tags-bin", Value: encodeBinHeader(b)})
+ }
+ if b := stats.OutgoingTrace(ctx); b != nil {
+ headerFields = append(headerFields, hpack.HeaderField{Name: "grpc-trace-bin", Value: encodeBinHeader(b)})
+ }
+
+ if md, added, ok := metadata.FromOutgoingContextRaw(ctx); ok {
+ var k string
+ for _, vv := range added {
+ for i, v := range vv {
+ if i%2 == 0 {
+ k = v
+ continue
+ }
+ // HTTP doesn't allow you to set pseudoheaders after non pseudoheaders were set.
+ if isReservedHeader(k) {
+ continue
+ }
+ headerFields = append(headerFields, hpack.HeaderField{Name: strings.ToLower(k), Value: encodeMetadataHeader(k, v)})
+ }
+ }
+ for k, vv := range md {
+ // HTTP doesn't allow you to set pseudoheaders after non pseudoheaders were set.
+ if isReservedHeader(k) {
+ continue
+ }
+ for _, v := range vv {
+ headerFields = append(headerFields, hpack.HeaderField{Name: k, Value: encodeMetadataHeader(k, v)})
+ }
+ }
+ }
+ if md, ok := t.md.(*metadata.MD); ok {
+ for k, vv := range *md {
+ if isReservedHeader(k) {
+ continue
+ }
+ for _, v := range vv {
+ headerFields = append(headerFields, hpack.HeaderField{Name: k, Value: encodeMetadataHeader(k, v)})
+ }
+ }
+ }
+ return headerFields, nil
+}
+
+func (t *http2Client) createAudience(callHdr *CallHdr) string {
+ // Create an audience string only if needed.
+ if len(t.perRPCCreds) == 0 && callHdr.Creds == nil {
+ return ""
+ }
+ // Construct URI required to get auth request metadata.
+ // Omit port if it is the default one.
+ host := strings.TrimSuffix(callHdr.Host, ":443")
+ pos := strings.LastIndex(callHdr.Method, "/")
+ if pos == -1 {
+ pos = len(callHdr.Method)
+ }
+ return "https://" + host + callHdr.Method[:pos]
+}
+
+func (t *http2Client) getTrAuthData(ctx context.Context, audience string) (map[string]string, error) {
+ authData := map[string]string{}
+ for _, c := range t.perRPCCreds {
+ data, err := c.GetRequestMetadata(ctx, audience)
+ if err != nil {
+ if _, ok := status.FromError(err); ok {
+ return nil, err
+ }
+
+ return nil, status.Errorf(codes.Unauthenticated, "transport: %v", err)
+ }
+ for k, v := range data {
+ // Capital header names are illegal in HTTP/2.
+ k = strings.ToLower(k)
+ authData[k] = v
+ }
+ }
+ return authData, nil
+}
+
+func (t *http2Client) getCallAuthData(ctx context.Context, audience string, callHdr *CallHdr) (map[string]string, error) {
+ callAuthData := map[string]string{}
+ // Check if credentials.PerRPCCredentials were provided via call options.
+ // Note: if these credentials are provided both via dial options and call
+ // options, then both sets of credentials will be applied.
+ if callCreds := callHdr.Creds; callCreds != nil {
+ if !t.isSecure && callCreds.RequireTransportSecurity() {
+ return nil, status.Error(codes.Unauthenticated, "transport: cannot send secure credentials on an insecure connection")
+ }
+ data, err := callCreds.GetRequestMetadata(ctx, audience)
+ if err != nil {
+ return nil, status.Errorf(codes.Internal, "transport: %v", err)
+ }
+ for k, v := range data {
+ // Capital header names are illegal in HTTP/2
+ k = strings.ToLower(k)
+ callAuthData[k] = v
+ }
+ }
+ return callAuthData, nil
+}
+
+// NewStream creates a stream and registers it into the transport as "active"
+// streams.
+func (t *http2Client) NewStream(ctx context.Context, callHdr *CallHdr) (_ *Stream, err error) {
+ ctx = peer.NewContext(ctx, t.getPeer())
+ headerFields, err := t.createHeaderFields(ctx, callHdr)
+ if err != nil {
+ return nil, err
+ }
+ s := t.newStream(ctx, callHdr)
+ cleanup := func(err error) {
+ if s.swapState(streamDone) == streamDone {
+ // If it was already done, return.
+ return
+ }
+ // The stream was unprocessed by the server.
+ atomic.StoreUint32(&s.unprocessed, 1)
+ s.write(recvMsg{err: err})
+ close(s.done)
+ // If headerChan isn't closed, then close it.
+ if atomic.SwapUint32(&s.headerDone, 1) == 0 {
+ close(s.headerChan)
+ }
+
+ }
+ hdr := &headerFrame{
+ hf: headerFields,
+ endStream: false,
+ initStream: func(id uint32) (bool, error) {
+ t.mu.Lock()
+ if state := t.state; state != reachable {
+ t.mu.Unlock()
+ // Do a quick cleanup.
+ err := error(errStreamDrain)
+ if state == closing {
+ err = ErrConnClosing
+ }
+ cleanup(err)
+ return false, err
+ }
+ t.activeStreams[id] = s
+ if channelz.IsOn() {
+ atomic.AddInt64(&t.czData.streamsStarted, 1)
+ atomic.StoreInt64(&t.czData.lastStreamCreatedTime, time.Now().UnixNano())
+ }
+ var sendPing bool
+ // If the number of active streams change from 0 to 1, then check if keepalive
+ // has gone dormant. If so, wake it up.
+ if len(t.activeStreams) == 1 && t.keepaliveEnabled {
+ select {
+ case t.awakenKeepalive <- struct{}{}:
+ sendPing = true
+ // Fill the awakenKeepalive channel again as this channel must be
+ // kept non-writable except at the point that the keepalive()
+ // goroutine is waiting either to be awaken or shutdown.
+ t.awakenKeepalive <- struct{}{}
+ default:
+ }
+ }
+ t.mu.Unlock()
+ return sendPing, nil
+ },
+ onOrphaned: cleanup,
+ wq: s.wq,
+ }
+ firstTry := true
+ var ch chan struct{}
+ checkForStreamQuota := func(it interface{}) bool {
+ if t.streamQuota <= 0 { // Can go negative if server decreases it.
+ if firstTry {
+ t.waitingStreams++
+ }
+ ch = t.streamsQuotaAvailable
+ return false
+ }
+ if !firstTry {
+ t.waitingStreams--
+ }
+ t.streamQuota--
+ h := it.(*headerFrame)
+ h.streamID = t.nextID
+ t.nextID += 2
+ s.id = h.streamID
+ s.fc = &inFlow{limit: uint32(t.initialWindowSize)}
+ if t.streamQuota > 0 && t.waitingStreams > 0 {
+ select {
+ case t.streamsQuotaAvailable <- struct{}{}:
+ default:
+ }
+ }
+ return true
+ }
+ var hdrListSizeErr error
+ checkForHeaderListSize := func(it interface{}) bool {
+ if t.maxSendHeaderListSize == nil {
+ return true
+ }
+ hdrFrame := it.(*headerFrame)
+ var sz int64
+ for _, f := range hdrFrame.hf {
+ if sz += int64(f.Size()); sz > int64(*t.maxSendHeaderListSize) {
+ hdrListSizeErr = status.Errorf(codes.Internal, "header list size to send violates the maximum size (%d bytes) set by server", *t.maxSendHeaderListSize)
+ return false
+ }
+ }
+ return true
+ }
+ for {
+ success, err := t.controlBuf.executeAndPut(func(it interface{}) bool {
+ if !checkForStreamQuota(it) {
+ return false
+ }
+ if !checkForHeaderListSize(it) {
+ return false
+ }
+ return true
+ }, hdr)
+ if err != nil {
+ return nil, err
+ }
+ if success {
+ break
+ }
+ if hdrListSizeErr != nil {
+ return nil, hdrListSizeErr
+ }
+ firstTry = false
+ select {
+ case <-ch:
+ case <-s.ctx.Done():
+ return nil, ContextErr(s.ctx.Err())
+ case <-t.goAway:
+ return nil, errStreamDrain
+ case <-t.ctx.Done():
+ return nil, ErrConnClosing
+ }
+ }
+ if t.statsHandler != nil {
+ outHeader := &stats.OutHeader{
+ Client: true,
+ FullMethod: callHdr.Method,
+ RemoteAddr: t.remoteAddr,
+ LocalAddr: t.localAddr,
+ Compression: callHdr.SendCompress,
+ }
+ t.statsHandler.HandleRPC(s.ctx, outHeader)
+ }
+ return s, nil
+}
+
+// CloseStream clears the footprint of a stream when the stream is not needed any more.
+// This must not be executed in reader's goroutine.
+func (t *http2Client) CloseStream(s *Stream, err error) {
+ var (
+ rst bool
+ rstCode http2.ErrCode
+ )
+ if err != nil {
+ rst = true
+ rstCode = http2.ErrCodeCancel
+ }
+ t.closeStream(s, err, rst, rstCode, status.Convert(err), nil, false)
+}
+
+func (t *http2Client) closeStream(s *Stream, err error, rst bool, rstCode http2.ErrCode, st *status.Status, mdata map[string][]string, eosReceived bool) {
+ // Set stream status to done.
+ if s.swapState(streamDone) == streamDone {
+ // If it was already done, return. If multiple closeStream calls
+ // happen simultaneously, wait for the first to finish.
+ <-s.done
+ return
+ }
+ // status and trailers can be updated here without any synchronization because the stream goroutine will
+ // only read it after it sees an io.EOF error from read or write and we'll write those errors
+ // only after updating this.
+ s.status = st
+ if len(mdata) > 0 {
+ s.trailer = mdata
+ }
+ if err != nil {
+ // This will unblock reads eventually.
+ s.write(recvMsg{err: err})
+ }
+ // If headerChan isn't closed, then close it.
+ if atomic.SwapUint32(&s.headerDone, 1) == 0 {
+ s.noHeaders = true
+ close(s.headerChan)
+ }
+ cleanup := &cleanupStream{
+ streamID: s.id,
+ onWrite: func() {
+ t.mu.Lock()
+ if t.activeStreams != nil {
+ delete(t.activeStreams, s.id)
+ }
+ t.mu.Unlock()
+ if channelz.IsOn() {
+ if eosReceived {
+ atomic.AddInt64(&t.czData.streamsSucceeded, 1)
+ } else {
+ atomic.AddInt64(&t.czData.streamsFailed, 1)
+ }
+ }
+ },
+ rst: rst,
+ rstCode: rstCode,
+ }
+ addBackStreamQuota := func(interface{}) bool {
+ t.streamQuota++
+ if t.streamQuota > 0 && t.waitingStreams > 0 {
+ select {
+ case t.streamsQuotaAvailable <- struct{}{}:
+ default:
+ }
+ }
+ return true
+ }
+ t.controlBuf.executeAndPut(addBackStreamQuota, cleanup)
+ // This will unblock write.
+ close(s.done)
+}
+
+// Close kicks off the shutdown process of the transport. This should be called
+// only once on a transport. Once it is called, the transport should not be
+// accessed any more.
+//
+// This method blocks until the addrConn that initiated this transport is
+// re-connected. This happens because t.onClose() begins reconnect logic at the
+// addrConn level and blocks until the addrConn is successfully connected.
+func (t *http2Client) Close() error {
+ t.mu.Lock()
+ // Make sure we only Close once.
+ if t.state == closing {
+ t.mu.Unlock()
+ return nil
+ }
+ t.state = closing
+ streams := t.activeStreams
+ t.activeStreams = nil
+ t.mu.Unlock()
+ t.controlBuf.finish()
+ t.cancel()
+ err := t.conn.Close()
+ if channelz.IsOn() {
+ channelz.RemoveEntry(t.channelzID)
+ }
+ // Notify all active streams.
+ for _, s := range streams {
+ t.closeStream(s, ErrConnClosing, false, http2.ErrCodeNo, status.New(codes.Unavailable, ErrConnClosing.Desc), nil, false)
+ }
+ if t.statsHandler != nil {
+ connEnd := &stats.ConnEnd{
+ Client: true,
+ }
+ t.statsHandler.HandleConn(t.ctx, connEnd)
+ }
+ go t.onClose()
+ return err
+}
+
+// GracefulClose sets the state to draining, which prevents new streams from
+// being created and causes the transport to be closed when the last active
+// stream is closed. If there are no active streams, the transport is closed
+// immediately. This does nothing if the transport is already draining or
+// closing.
+func (t *http2Client) GracefulClose() error {
+ t.mu.Lock()
+ // Make sure we move to draining only from active.
+ if t.state == draining || t.state == closing {
+ t.mu.Unlock()
+ return nil
+ }
+ t.state = draining
+ active := len(t.activeStreams)
+ t.mu.Unlock()
+ if active == 0 {
+ return t.Close()
+ }
+ t.controlBuf.put(&incomingGoAway{})
+ return nil
+}
+
+// Write formats the data into HTTP2 data frame(s) and sends it out. The caller
+// should proceed only if Write returns nil.
+func (t *http2Client) Write(s *Stream, hdr []byte, data []byte, opts *Options) error {
+ if opts.Last {
+ // If it's the last message, update stream state.
+ if !s.compareAndSwapState(streamActive, streamWriteDone) {
+ return errStreamDone
+ }
+ } else if s.getState() != streamActive {
+ return errStreamDone
+ }
+ df := &dataFrame{
+ streamID: s.id,
+ endStream: opts.Last,
+ }
+ if hdr != nil || data != nil { // If it's not an empty data frame.
+ // Add some data to grpc message header so that we can equally
+ // distribute bytes across frames.
+ emptyLen := http2MaxFrameLen - len(hdr)
+ if emptyLen > len(data) {
+ emptyLen = len(data)
+ }
+ hdr = append(hdr, data[:emptyLen]...)
+ data = data[emptyLen:]
+ df.h, df.d = hdr, data
+ // TODO(mmukhi): The above logic in this if can be moved to loopyWriter's data handler.
+ if err := s.wq.get(int32(len(hdr) + len(data))); err != nil {
+ return err
+ }
+ }
+ return t.controlBuf.put(df)
+}
+
+func (t *http2Client) getStream(f http2.Frame) (*Stream, bool) {
+ t.mu.Lock()
+ defer t.mu.Unlock()
+ s, ok := t.activeStreams[f.Header().StreamID]
+ return s, ok
+}
+
+// adjustWindow sends out extra window update over the initial window size
+// of stream if the application is requesting data larger in size than
+// the window.
+func (t *http2Client) adjustWindow(s *Stream, n uint32) {
+ if w := s.fc.maybeAdjust(n); w > 0 {
+ t.controlBuf.put(&outgoingWindowUpdate{streamID: s.id, increment: w})
+ }
+}
+
+// updateWindow adjusts the inbound quota for the stream.
+// Window updates will be sent out when the cumulative quota
+// exceeds the corresponding threshold.
+func (t *http2Client) updateWindow(s *Stream, n uint32) {
+ if w := s.fc.onRead(n); w > 0 {
+ t.controlBuf.put(&outgoingWindowUpdate{streamID: s.id, increment: w})
+ }
+}
+
+// updateFlowControl updates the incoming flow control windows
+// for the transport and the stream based on the current bdp
+// estimation.
+func (t *http2Client) updateFlowControl(n uint32) {
+ t.mu.Lock()
+ for _, s := range t.activeStreams {
+ s.fc.newLimit(n)
+ }
+ t.mu.Unlock()
+ updateIWS := func(interface{}) bool {
+ t.initialWindowSize = int32(n)
+ return true
+ }
+ t.controlBuf.executeAndPut(updateIWS, &outgoingWindowUpdate{streamID: 0, increment: t.fc.newLimit(n)})
+ t.controlBuf.put(&outgoingSettings{
+ ss: []http2.Setting{
+ {
+ ID: http2.SettingInitialWindowSize,
+ Val: n,
+ },
+ },
+ })
+}
+
+func (t *http2Client) handleData(f *http2.DataFrame) {
+ size := f.Header().Length
+ var sendBDPPing bool
+ if t.bdpEst != nil {
+ sendBDPPing = t.bdpEst.add(size)
+ }
+ // Decouple connection's flow control from application's read.
+ // An update on connection's flow control should not depend on
+ // whether user application has read the data or not. Such a
+ // restriction is already imposed on the stream's flow control,
+ // and therefore the sender will be blocked anyways.
+ // Decoupling the connection flow control will prevent other
+ // active(fast) streams from starving in presence of slow or
+ // inactive streams.
+ //
+ if w := t.fc.onData(size); w > 0 {
+ t.controlBuf.put(&outgoingWindowUpdate{
+ streamID: 0,
+ increment: w,
+ })
+ }
+ if sendBDPPing {
+ // Avoid excessive ping detection (e.g. in an L7 proxy)
+ // by sending a window update prior to the BDP ping.
+
+ if w := t.fc.reset(); w > 0 {
+ t.controlBuf.put(&outgoingWindowUpdate{
+ streamID: 0,
+ increment: w,
+ })
+ }
+
+ t.controlBuf.put(bdpPing)
+ }
+ // Select the right stream to dispatch.
+ s, ok := t.getStream(f)
+ if !ok {
+ return
+ }
+ if size > 0 {
+ if err := s.fc.onData(size); err != nil {
+ t.closeStream(s, io.EOF, true, http2.ErrCodeFlowControl, status.New(codes.Internal, err.Error()), nil, false)
+ return
+ }
+ if f.Header().Flags.Has(http2.FlagDataPadded) {
+ if w := s.fc.onRead(size - uint32(len(f.Data()))); w > 0 {
+ t.controlBuf.put(&outgoingWindowUpdate{s.id, w})
+ }
+ }
+ // TODO(bradfitz, zhaoq): A copy is required here because there is no
+ // guarantee f.Data() is consumed before the arrival of next frame.
+ // Can this copy be eliminated?
+ if len(f.Data()) > 0 {
+ data := make([]byte, len(f.Data()))
+ copy(data, f.Data())
+ s.write(recvMsg{data: data})
+ }
+ }
+ // The server has closed the stream without sending trailers. Record that
+ // the read direction is closed, and set the status appropriately.
+ if f.FrameHeader.Flags.Has(http2.FlagDataEndStream) {
+ t.closeStream(s, io.EOF, false, http2.ErrCodeNo, status.New(codes.Internal, "server closed the stream without sending trailers"), nil, true)
+ }
+}
+
+func (t *http2Client) handleRSTStream(f *http2.RSTStreamFrame) {
+ s, ok := t.getStream(f)
+ if !ok {
+ return
+ }
+ if f.ErrCode == http2.ErrCodeRefusedStream {
+ // The stream was unprocessed by the server.
+ atomic.StoreUint32(&s.unprocessed, 1)
+ }
+ statusCode, ok := http2ErrConvTab[f.ErrCode]
+ if !ok {
+ warningf("transport: http2Client.handleRSTStream found no mapped gRPC status for the received http2 error %v", f.ErrCode)
+ statusCode = codes.Unknown
+ }
+ if statusCode == codes.Canceled {
+ // Our deadline was already exceeded, and that was likely the cause of
+ // this cancelation. Alter the status code accordingly.
+ if d, ok := s.ctx.Deadline(); ok && d.After(time.Now()) {
+ statusCode = codes.DeadlineExceeded
+ }
+ }
+ t.closeStream(s, io.EOF, false, http2.ErrCodeNo, status.Newf(statusCode, "stream terminated by RST_STREAM with error code: %v", f.ErrCode), nil, false)
+}
+
+func (t *http2Client) handleSettings(f *http2.SettingsFrame, isFirst bool) {
+ if f.IsAck() {
+ return
+ }
+ var maxStreams *uint32
+ var ss []http2.Setting
+ var updateFuncs []func()
+ f.ForeachSetting(func(s http2.Setting) error {
+ switch s.ID {
+ case http2.SettingMaxConcurrentStreams:
+ maxStreams = new(uint32)
+ *maxStreams = s.Val
+ case http2.SettingMaxHeaderListSize:
+ updateFuncs = append(updateFuncs, func() {
+ t.maxSendHeaderListSize = new(uint32)
+ *t.maxSendHeaderListSize = s.Val
+ })
+ default:
+ ss = append(ss, s)
+ }
+ return nil
+ })
+ if isFirst && maxStreams == nil {
+ maxStreams = new(uint32)
+ *maxStreams = math.MaxUint32
+ }
+ sf := &incomingSettings{
+ ss: ss,
+ }
+ if maxStreams != nil {
+ updateStreamQuota := func() {
+ delta := int64(*maxStreams) - int64(t.maxConcurrentStreams)
+ t.maxConcurrentStreams = *maxStreams
+ t.streamQuota += delta
+ if delta > 0 && t.waitingStreams > 0 {
+ close(t.streamsQuotaAvailable) // wake all of them up.
+ t.streamsQuotaAvailable = make(chan struct{}, 1)
+ }
+ }
+ updateFuncs = append(updateFuncs, updateStreamQuota)
+ }
+ t.controlBuf.executeAndPut(func(interface{}) bool {
+ for _, f := range updateFuncs {
+ f()
+ }
+ return true
+ }, sf)
+}
+
+func (t *http2Client) handlePing(f *http2.PingFrame) {
+ if f.IsAck() {
+ // Maybe it's a BDP ping.
+ if t.bdpEst != nil {
+ t.bdpEst.calculate(f.Data)
+ }
+ return
+ }
+ pingAck := &ping{ack: true}
+ copy(pingAck.data[:], f.Data[:])
+ t.controlBuf.put(pingAck)
+}
+
+func (t *http2Client) handleGoAway(f *http2.GoAwayFrame) {
+ t.mu.Lock()
+ if t.state == closing {
+ t.mu.Unlock()
+ return
+ }
+ if f.ErrCode == http2.ErrCodeEnhanceYourCalm {
+ infof("Client received GoAway with http2.ErrCodeEnhanceYourCalm.")
+ }
+ id := f.LastStreamID
+ if id > 0 && id%2 != 1 {
+ t.mu.Unlock()
+ t.Close()
+ return
+ }
+ // A client can receive multiple GoAways from the server (see
+ // https://github.com/grpc/grpc-go/issues/1387). The idea is that the first
+ // GoAway will be sent with an ID of MaxInt32 and the second GoAway will be
+ // sent after an RTT delay with the ID of the last stream the server will
+ // process.
+ //
+ // Therefore, when we get the first GoAway we don't necessarily close any
+ // streams. While in case of second GoAway we close all streams created after
+ // the GoAwayId. This way streams that were in-flight while the GoAway from
+ // server was being sent don't get killed.
+ select {
+ case <-t.goAway: // t.goAway has been closed (i.e.,multiple GoAways).
+ // If there are multiple GoAways the first one should always have an ID greater than the following ones.
+ if id > t.prevGoAwayID {
+ t.mu.Unlock()
+ t.Close()
+ return
+ }
+ default:
+ t.setGoAwayReason(f)
+ close(t.goAway)
+ t.state = draining
+ t.controlBuf.put(&incomingGoAway{})
+
+ // This has to be a new goroutine because we're still using the current goroutine to read in the transport.
+ t.onGoAway(t.goAwayReason)
+ }
+ // All streams with IDs greater than the GoAwayId
+ // and smaller than the previous GoAway ID should be killed.
+ upperLimit := t.prevGoAwayID
+ if upperLimit == 0 { // This is the first GoAway Frame.
+ upperLimit = math.MaxUint32 // Kill all streams after the GoAway ID.
+ }
+ for streamID, stream := range t.activeStreams {
+ if streamID > id && streamID <= upperLimit {
+ // The stream was unprocessed by the server.
+ atomic.StoreUint32(&stream.unprocessed, 1)
+ t.closeStream(stream, errStreamDrain, false, http2.ErrCodeNo, statusGoAway, nil, false)
+ }
+ }
+ t.prevGoAwayID = id
+ active := len(t.activeStreams)
+ t.mu.Unlock()
+ if active == 0 {
+ t.Close()
+ }
+}
+
+// setGoAwayReason sets the value of t.goAwayReason based
+// on the GoAway frame received.
+// It expects a lock on transport's mutext to be held by
+// the caller.
+func (t *http2Client) setGoAwayReason(f *http2.GoAwayFrame) {
+ t.goAwayReason = GoAwayNoReason
+ switch f.ErrCode {
+ case http2.ErrCodeEnhanceYourCalm:
+ if string(f.DebugData()) == "too_many_pings" {
+ t.goAwayReason = GoAwayTooManyPings
+ }
+ }
+}
+
+func (t *http2Client) GetGoAwayReason() GoAwayReason {
+ t.mu.Lock()
+ defer t.mu.Unlock()
+ return t.goAwayReason
+}
+
+func (t *http2Client) handleWindowUpdate(f *http2.WindowUpdateFrame) {
+ t.controlBuf.put(&incomingWindowUpdate{
+ streamID: f.Header().StreamID,
+ increment: f.Increment,
+ })
+}
+
+// operateHeaders takes action on the decoded headers.
+func (t *http2Client) operateHeaders(frame *http2.MetaHeadersFrame) {
+ s, ok := t.getStream(frame)
+ if !ok {
+ return
+ }
+ atomic.StoreUint32(&s.bytesReceived, 1)
+ var state decodeState
+ if err := state.decodeHeader(frame); err != nil {
+ t.closeStream(s, err, true, http2.ErrCodeProtocol, status.New(codes.Internal, err.Error()), nil, false)
+ // Something wrong. Stops reading even when there is remaining.
+ return
+ }
+
+ endStream := frame.StreamEnded()
+ var isHeader bool
+ defer func() {
+ if t.statsHandler != nil {
+ if isHeader {
+ inHeader := &stats.InHeader{
+ Client: true,
+ WireLength: int(frame.Header().Length),
+ }
+ t.statsHandler.HandleRPC(s.ctx, inHeader)
+ } else {
+ inTrailer := &stats.InTrailer{
+ Client: true,
+ WireLength: int(frame.Header().Length),
+ }
+ t.statsHandler.HandleRPC(s.ctx, inTrailer)
+ }
+ }
+ }()
+ // If headers haven't been received yet.
+ if atomic.SwapUint32(&s.headerDone, 1) == 0 {
+ if !endStream {
+ // Headers frame is not actually a trailers-only frame.
+ isHeader = true
+ // These values can be set without any synchronization because
+ // stream goroutine will read it only after seeing a closed
+ // headerChan which we'll close after setting this.
+ s.recvCompress = state.encoding
+ if len(state.mdata) > 0 {
+ s.header = state.mdata
+ }
+ } else {
+ s.noHeaders = true
+ }
+ close(s.headerChan)
+ }
+ if !endStream {
+ return
+ }
+ // if client received END_STREAM from server while stream was still active, send RST_STREAM
+ rst := s.getState() == streamActive
+ t.closeStream(s, io.EOF, rst, http2.ErrCodeNo, state.status(), state.mdata, true)
+}
+
+// reader runs as a separate goroutine in charge of reading data from network
+// connection.
+//
+// TODO(zhaoq): currently one reader per transport. Investigate whether this is
+// optimal.
+// TODO(zhaoq): Check the validity of the incoming frame sequence.
+func (t *http2Client) reader() {
+ defer close(t.readerDone)
+ // Check the validity of server preface.
+ frame, err := t.framer.fr.ReadFrame()
+ if err != nil {
+ t.Close() // this kicks off resetTransport, so must be last before return
+ return
+ }
+ t.conn.SetReadDeadline(time.Time{}) // reset deadline once we get the settings frame (we didn't time out, yay!)
+ if t.keepaliveEnabled {
+ atomic.CompareAndSwapUint32(&t.activity, 0, 1)
+ }
+ sf, ok := frame.(*http2.SettingsFrame)
+ if !ok {
+ t.Close() // this kicks off resetTransport, so must be last before return
+ return
+ }
+ t.onSuccess()
+ t.handleSettings(sf, true)
+
+ // loop to keep reading incoming messages on this transport.
+ for {
+ frame, err := t.framer.fr.ReadFrame()
+ if t.keepaliveEnabled {
+ atomic.CompareAndSwapUint32(&t.activity, 0, 1)
+ }
+ if err != nil {
+ // Abort an active stream if the http2.Framer returns a
+ // http2.StreamError. This can happen only if the server's response
+ // is malformed http2.
+ if se, ok := err.(http2.StreamError); ok {
+ t.mu.Lock()
+ s := t.activeStreams[se.StreamID]
+ t.mu.Unlock()
+ if s != nil {
+ // use error detail to provide better err message
+ code := http2ErrConvTab[se.Code]
+ msg := t.framer.fr.ErrorDetail().Error()
+ t.closeStream(s, status.Error(code, msg), true, http2.ErrCodeProtocol, status.New(code, msg), nil, false)
+ }
+ continue
+ } else {
+ // Transport error.
+ t.Close()
+ return
+ }
+ }
+ switch frame := frame.(type) {
+ case *http2.MetaHeadersFrame:
+ t.operateHeaders(frame)
+ case *http2.DataFrame:
+ t.handleData(frame)
+ case *http2.RSTStreamFrame:
+ t.handleRSTStream(frame)
+ case *http2.SettingsFrame:
+ t.handleSettings(frame, false)
+ case *http2.PingFrame:
+ t.handlePing(frame)
+ case *http2.GoAwayFrame:
+ t.handleGoAway(frame)
+ case *http2.WindowUpdateFrame:
+ t.handleWindowUpdate(frame)
+ default:
+ errorf("transport: http2Client.reader got unhandled frame type %v.", frame)
+ }
+ }
+}
+
+// keepalive running in a separate goroutune makes sure the connection is alive by sending pings.
+func (t *http2Client) keepalive() {
+ p := &ping{data: [8]byte{}}
+ timer := time.NewTimer(t.kp.Time)
+ for {
+ select {
+ case <-timer.C:
+ if atomic.CompareAndSwapUint32(&t.activity, 1, 0) {
+ timer.Reset(t.kp.Time)
+ continue
+ }
+ // Check if keepalive should go dormant.
+ t.mu.Lock()
+ if len(t.activeStreams) < 1 && !t.kp.PermitWithoutStream {
+ // Make awakenKeepalive writable.
+ <-t.awakenKeepalive
+ t.mu.Unlock()
+ select {
+ case <-t.awakenKeepalive:
+ // If the control gets here a ping has been sent
+ // need to reset the timer with keepalive.Timeout.
+ case <-t.ctx.Done():
+ return
+ }
+ } else {
+ t.mu.Unlock()
+ if channelz.IsOn() {
+ atomic.AddInt64(&t.czData.kpCount, 1)
+ }
+ // Send ping.
+ t.controlBuf.put(p)
+ }
+
+ // By the time control gets here a ping has been sent one way or the other.
+ timer.Reset(t.kp.Timeout)
+ select {
+ case <-timer.C:
+ if atomic.CompareAndSwapUint32(&t.activity, 1, 0) {
+ timer.Reset(t.kp.Time)
+ continue
+ }
+ t.Close()
+ return
+ case <-t.ctx.Done():
+ if !timer.Stop() {
+ <-timer.C
+ }
+ return
+ }
+ case <-t.ctx.Done():
+ if !timer.Stop() {
+ <-timer.C
+ }
+ return
+ }
+ }
+}
+
+func (t *http2Client) Error() <-chan struct{} {
+ return t.ctx.Done()
+}
+
+func (t *http2Client) GoAway() <-chan struct{} {
+ return t.goAway
+}
+
+func (t *http2Client) ChannelzMetric() *channelz.SocketInternalMetric {
+ s := channelz.SocketInternalMetric{
+ StreamsStarted: atomic.LoadInt64(&t.czData.streamsStarted),
+ StreamsSucceeded: atomic.LoadInt64(&t.czData.streamsSucceeded),
+ StreamsFailed: atomic.LoadInt64(&t.czData.streamsFailed),
+ MessagesSent: atomic.LoadInt64(&t.czData.msgSent),
+ MessagesReceived: atomic.LoadInt64(&t.czData.msgRecv),
+ KeepAlivesSent: atomic.LoadInt64(&t.czData.kpCount),
+ LastLocalStreamCreatedTimestamp: time.Unix(0, atomic.LoadInt64(&t.czData.lastStreamCreatedTime)),
+ LastMessageSentTimestamp: time.Unix(0, atomic.LoadInt64(&t.czData.lastMsgSentTime)),
+ LastMessageReceivedTimestamp: time.Unix(0, atomic.LoadInt64(&t.czData.lastMsgRecvTime)),
+ LocalFlowControlWindow: int64(t.fc.getSize()),
+ SocketOptions: channelz.GetSocketOption(t.conn),
+ LocalAddr: t.localAddr,
+ RemoteAddr: t.remoteAddr,
+ // RemoteName :
+ }
+ if au, ok := t.authInfo.(credentials.ChannelzSecurityInfo); ok {
+ s.Security = au.GetSecurityValue()
+ }
+ s.RemoteFlowControlWindow = t.getOutFlowWindow()
+ return &s
+}
+
+func (t *http2Client) IncrMsgSent() {
+ atomic.AddInt64(&t.czData.msgSent, 1)
+ atomic.StoreInt64(&t.czData.lastMsgSentTime, time.Now().UnixNano())
+}
+
+func (t *http2Client) IncrMsgRecv() {
+ atomic.AddInt64(&t.czData.msgRecv, 1)
+ atomic.StoreInt64(&t.czData.lastMsgRecvTime, time.Now().UnixNano())
+}
+
+func (t *http2Client) getOutFlowWindow() int64 {
+ resp := make(chan uint32, 1)
+ timer := time.NewTimer(time.Second)
+ defer timer.Stop()
+ t.controlBuf.put(&outFlowControlSizeRequest{resp})
+ select {
+ case sz := <-resp:
+ return int64(sz)
+ case <-t.ctxDone:
+ return -1
+ case <-timer.C:
+ return -2
+ }
+}
diff --git a/vendor/google.golang.org/grpc/internal/transport/http2_server.go b/vendor/google.golang.org/grpc/internal/transport/http2_server.go
new file mode 100644
index 000000000..df2740398
--- /dev/null
+++ b/vendor/google.golang.org/grpc/internal/transport/http2_server.go
@@ -0,0 +1,1180 @@
+/*
+ *
+ * Copyright 2014 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package transport
+
+import (
+ "bytes"
+ "context"
+ "errors"
+ "fmt"
+ "io"
+ "math"
+ "net"
+ "strconv"
+ "sync"
+ "sync/atomic"
+ "time"
+
+ "github.com/golang/protobuf/proto"
+ "golang.org/x/net/http2"
+ "golang.org/x/net/http2/hpack"
+
+ "google.golang.org/grpc/codes"
+ "google.golang.org/grpc/credentials"
+ "google.golang.org/grpc/grpclog"
+ "google.golang.org/grpc/internal/channelz"
+ "google.golang.org/grpc/internal/grpcrand"
+ "google.golang.org/grpc/keepalive"
+ "google.golang.org/grpc/metadata"
+ "google.golang.org/grpc/peer"
+ "google.golang.org/grpc/stats"
+ "google.golang.org/grpc/status"
+ "google.golang.org/grpc/tap"
+)
+
+var (
+ // ErrIllegalHeaderWrite indicates that setting header is illegal because of
+ // the stream's state.
+ ErrIllegalHeaderWrite = errors.New("transport: the stream is done or WriteHeader was already called")
+ // ErrHeaderListSizeLimitViolation indicates that the header list size is larger
+ // than the limit set by peer.
+ ErrHeaderListSizeLimitViolation = errors.New("transport: trying to send header list size larger than the limit set by peer")
+)
+
+// http2Server implements the ServerTransport interface with HTTP2.
+type http2Server struct {
+ ctx context.Context
+ ctxDone <-chan struct{} // Cache the context.Done() chan
+ cancel context.CancelFunc
+ conn net.Conn
+ loopy *loopyWriter
+ readerDone chan struct{} // sync point to enable testing.
+ writerDone chan struct{} // sync point to enable testing.
+ remoteAddr net.Addr
+ localAddr net.Addr
+ maxStreamID uint32 // max stream ID ever seen
+ authInfo credentials.AuthInfo // auth info about the connection
+ inTapHandle tap.ServerInHandle
+ framer *framer
+ // The max number of concurrent streams.
+ maxStreams uint32
+ // controlBuf delivers all the control related tasks (e.g., window
+ // updates, reset streams, and various settings) to the controller.
+ controlBuf *controlBuffer
+ fc *trInFlow
+ stats stats.Handler
+ // Flag to keep track of reading activity on transport.
+ // 1 is true and 0 is false.
+ activity uint32 // Accessed atomically.
+ // Keepalive and max-age parameters for the server.
+ kp keepalive.ServerParameters
+
+ // Keepalive enforcement policy.
+ kep keepalive.EnforcementPolicy
+ // The time instance last ping was received.
+ lastPingAt time.Time
+ // Number of times the client has violated keepalive ping policy so far.
+ pingStrikes uint8
+ // Flag to signify that number of ping strikes should be reset to 0.
+ // This is set whenever data or header frames are sent.
+ // 1 means yes.
+ resetPingStrikes uint32 // Accessed atomically.
+ initialWindowSize int32
+ bdpEst *bdpEstimator
+ maxSendHeaderListSize *uint32
+
+ mu sync.Mutex // guard the following
+
+ // drainChan is initialized when drain(...) is called the first time.
+ // After which the server writes out the first GoAway(with ID 2^31-1) frame.
+ // Then an independent goroutine will be launched to later send the second GoAway.
+ // During this time we don't want to write another first GoAway(with ID 2^31 -1) frame.
+ // Thus call to drain(...) will be a no-op if drainChan is already initialized since draining is
+ // already underway.
+ drainChan chan struct{}
+ state transportState
+ activeStreams map[uint32]*Stream
+ // idle is the time instant when the connection went idle.
+ // This is either the beginning of the connection or when the number of
+ // RPCs go down to 0.
+ // When the connection is busy, this value is set to 0.
+ idle time.Time
+
+ // Fields below are for channelz metric collection.
+ channelzID int64 // channelz unique identification number
+ czData *channelzData
+}
+
+// newHTTP2Server constructs a ServerTransport based on HTTP2. ConnectionError is
+// returned if something goes wrong.
+func newHTTP2Server(conn net.Conn, config *ServerConfig) (_ ServerTransport, err error) {
+ writeBufSize := config.WriteBufferSize
+ readBufSize := config.ReadBufferSize
+ maxHeaderListSize := defaultServerMaxHeaderListSize
+ if config.MaxHeaderListSize != nil {
+ maxHeaderListSize = *config.MaxHeaderListSize
+ }
+ framer := newFramer(conn, writeBufSize, readBufSize, maxHeaderListSize)
+ // Send initial settings as connection preface to client.
+ var isettings []http2.Setting
+ // TODO(zhaoq): Have a better way to signal "no limit" because 0 is
+ // permitted in the HTTP2 spec.
+ maxStreams := config.MaxStreams
+ if maxStreams == 0 {
+ maxStreams = math.MaxUint32
+ } else {
+ isettings = append(isettings, http2.Setting{
+ ID: http2.SettingMaxConcurrentStreams,
+ Val: maxStreams,
+ })
+ }
+ dynamicWindow := true
+ iwz := int32(initialWindowSize)
+ if config.InitialWindowSize >= defaultWindowSize {
+ iwz = config.InitialWindowSize
+ dynamicWindow = false
+ }
+ icwz := int32(initialWindowSize)
+ if config.InitialConnWindowSize >= defaultWindowSize {
+ icwz = config.InitialConnWindowSize
+ dynamicWindow = false
+ }
+ if iwz != defaultWindowSize {
+ isettings = append(isettings, http2.Setting{
+ ID: http2.SettingInitialWindowSize,
+ Val: uint32(iwz)})
+ }
+ if config.MaxHeaderListSize != nil {
+ isettings = append(isettings, http2.Setting{
+ ID: http2.SettingMaxHeaderListSize,
+ Val: *config.MaxHeaderListSize,
+ })
+ }
+ if err := framer.fr.WriteSettings(isettings...); err != nil {
+ return nil, connectionErrorf(false, err, "transport: %v", err)
+ }
+ // Adjust the connection flow control window if needed.
+ if delta := uint32(icwz - defaultWindowSize); delta > 0 {
+ if err := framer.fr.WriteWindowUpdate(0, delta); err != nil {
+ return nil, connectionErrorf(false, err, "transport: %v", err)
+ }
+ }
+ kp := config.KeepaliveParams
+ if kp.MaxConnectionIdle == 0 {
+ kp.MaxConnectionIdle = defaultMaxConnectionIdle
+ }
+ if kp.MaxConnectionAge == 0 {
+ kp.MaxConnectionAge = defaultMaxConnectionAge
+ }
+ // Add a jitter to MaxConnectionAge.
+ kp.MaxConnectionAge += getJitter(kp.MaxConnectionAge)
+ if kp.MaxConnectionAgeGrace == 0 {
+ kp.MaxConnectionAgeGrace = defaultMaxConnectionAgeGrace
+ }
+ if kp.Time == 0 {
+ kp.Time = defaultServerKeepaliveTime
+ }
+ if kp.Timeout == 0 {
+ kp.Timeout = defaultServerKeepaliveTimeout
+ }
+ kep := config.KeepalivePolicy
+ if kep.MinTime == 0 {
+ kep.MinTime = defaultKeepalivePolicyMinTime
+ }
+ ctx, cancel := context.WithCancel(context.Background())
+ t := &http2Server{
+ ctx: ctx,
+ cancel: cancel,
+ ctxDone: ctx.Done(),
+ conn: conn,
+ remoteAddr: conn.RemoteAddr(),
+ localAddr: conn.LocalAddr(),
+ authInfo: config.AuthInfo,
+ framer: framer,
+ readerDone: make(chan struct{}),
+ writerDone: make(chan struct{}),
+ maxStreams: maxStreams,
+ inTapHandle: config.InTapHandle,
+ fc: &trInFlow{limit: uint32(icwz)},
+ state: reachable,
+ activeStreams: make(map[uint32]*Stream),
+ stats: config.StatsHandler,
+ kp: kp,
+ idle: time.Now(),
+ kep: kep,
+ initialWindowSize: iwz,
+ czData: new(channelzData),
+ }
+ t.controlBuf = newControlBuffer(t.ctxDone)
+ if dynamicWindow {
+ t.bdpEst = &bdpEstimator{
+ bdp: initialWindowSize,
+ updateFlowControl: t.updateFlowControl,
+ }
+ }
+ if t.stats != nil {
+ t.ctx = t.stats.TagConn(t.ctx, &stats.ConnTagInfo{
+ RemoteAddr: t.remoteAddr,
+ LocalAddr: t.localAddr,
+ })
+ connBegin := &stats.ConnBegin{}
+ t.stats.HandleConn(t.ctx, connBegin)
+ }
+ if channelz.IsOn() {
+ t.channelzID = channelz.RegisterNormalSocket(t, config.ChannelzParentID, fmt.Sprintf("%s -> %s", t.remoteAddr, t.localAddr))
+ }
+ t.framer.writer.Flush()
+
+ defer func() {
+ if err != nil {
+ t.Close()
+ }
+ }()
+
+ // Check the validity of client preface.
+ preface := make([]byte, len(clientPreface))
+ if _, err := io.ReadFull(t.conn, preface); err != nil {
+ return nil, connectionErrorf(false, err, "transport: http2Server.HandleStreams failed to receive the preface from client: %v", err)
+ }
+ if !bytes.Equal(preface, clientPreface) {
+ return nil, connectionErrorf(false, nil, "transport: http2Server.HandleStreams received bogus greeting from client: %q", preface)
+ }
+
+ frame, err := t.framer.fr.ReadFrame()
+ if err == io.EOF || err == io.ErrUnexpectedEOF {
+ return nil, err
+ }
+ if err != nil {
+ return nil, connectionErrorf(false, err, "transport: http2Server.HandleStreams failed to read initial settings frame: %v", err)
+ }
+ atomic.StoreUint32(&t.activity, 1)
+ sf, ok := frame.(*http2.SettingsFrame)
+ if !ok {
+ return nil, connectionErrorf(false, nil, "transport: http2Server.HandleStreams saw invalid preface type %T from client", frame)
+ }
+ t.handleSettings(sf)
+
+ go func() {
+ t.loopy = newLoopyWriter(serverSide, t.framer, t.controlBuf, t.bdpEst)
+ t.loopy.ssGoAwayHandler = t.outgoingGoAwayHandler
+ if err := t.loopy.run(); err != nil {
+ errorf("transport: loopyWriter.run returning. Err: %v", err)
+ }
+ t.conn.Close()
+ close(t.writerDone)
+ }()
+ go t.keepalive()
+ return t, nil
+}
+
+// operateHeader takes action on the decoded headers.
+func (t *http2Server) operateHeaders(frame *http2.MetaHeadersFrame, handle func(*Stream), traceCtx func(context.Context, string) context.Context) (fatal bool) {
+ streamID := frame.Header().StreamID
+ state := decodeState{serverSide: true}
+ if err := state.decodeHeader(frame); err != nil {
+ if se, ok := status.FromError(err); ok {
+ t.controlBuf.put(&cleanupStream{
+ streamID: streamID,
+ rst: true,
+ rstCode: statusCodeConvTab[se.Code()],
+ onWrite: func() {},
+ })
+ }
+ return false
+ }
+
+ buf := newRecvBuffer()
+ s := &Stream{
+ id: streamID,
+ st: t,
+ buf: buf,
+ fc: &inFlow{limit: uint32(t.initialWindowSize)},
+ recvCompress: state.encoding,
+ method: state.method,
+ contentSubtype: state.contentSubtype,
+ }
+ if frame.StreamEnded() {
+ // s is just created by the caller. No lock needed.
+ s.state = streamReadDone
+ }
+ if state.timeoutSet {
+ s.ctx, s.cancel = context.WithTimeout(t.ctx, state.timeout)
+ } else {
+ s.ctx, s.cancel = context.WithCancel(t.ctx)
+ }
+ pr := &peer.Peer{
+ Addr: t.remoteAddr,
+ }
+ // Attach Auth info if there is any.
+ if t.authInfo != nil {
+ pr.AuthInfo = t.authInfo
+ }
+ s.ctx = peer.NewContext(s.ctx, pr)
+ // Attach the received metadata to the context.
+ if len(state.mdata) > 0 {
+ s.ctx = metadata.NewIncomingContext(s.ctx, state.mdata)
+ }
+ if state.statsTags != nil {
+ s.ctx = stats.SetIncomingTags(s.ctx, state.statsTags)
+ }
+ if state.statsTrace != nil {
+ s.ctx = stats.SetIncomingTrace(s.ctx, state.statsTrace)
+ }
+ if t.inTapHandle != nil {
+ var err error
+ info := &tap.Info{
+ FullMethodName: state.method,
+ }
+ s.ctx, err = t.inTapHandle(s.ctx, info)
+ if err != nil {
+ warningf("transport: http2Server.operateHeaders got an error from InTapHandle: %v", err)
+ t.controlBuf.put(&cleanupStream{
+ streamID: s.id,
+ rst: true,
+ rstCode: http2.ErrCodeRefusedStream,
+ onWrite: func() {},
+ })
+ return false
+ }
+ }
+ t.mu.Lock()
+ if t.state != reachable {
+ t.mu.Unlock()
+ return false
+ }
+ if uint32(len(t.activeStreams)) >= t.maxStreams {
+ t.mu.Unlock()
+ t.controlBuf.put(&cleanupStream{
+ streamID: streamID,
+ rst: true,
+ rstCode: http2.ErrCodeRefusedStream,
+ onWrite: func() {},
+ })
+ return false
+ }
+ if streamID%2 != 1 || streamID <= t.maxStreamID {
+ t.mu.Unlock()
+ // illegal gRPC stream id.
+ errorf("transport: http2Server.HandleStreams received an illegal stream id: %v", streamID)
+ return true
+ }
+ t.maxStreamID = streamID
+ t.activeStreams[streamID] = s
+ if len(t.activeStreams) == 1 {
+ t.idle = time.Time{}
+ }
+ t.mu.Unlock()
+ if channelz.IsOn() {
+ atomic.AddInt64(&t.czData.streamsStarted, 1)
+ atomic.StoreInt64(&t.czData.lastStreamCreatedTime, time.Now().UnixNano())
+ }
+ s.requestRead = func(n int) {
+ t.adjustWindow(s, uint32(n))
+ }
+ s.ctx = traceCtx(s.ctx, s.method)
+ if t.stats != nil {
+ s.ctx = t.stats.TagRPC(s.ctx, &stats.RPCTagInfo{FullMethodName: s.method})
+ inHeader := &stats.InHeader{
+ FullMethod: s.method,
+ RemoteAddr: t.remoteAddr,
+ LocalAddr: t.localAddr,
+ Compression: s.recvCompress,
+ WireLength: int(frame.Header().Length),
+ }
+ t.stats.HandleRPC(s.ctx, inHeader)
+ }
+ s.ctxDone = s.ctx.Done()
+ s.wq = newWriteQuota(defaultWriteQuota, s.ctxDone)
+ s.trReader = &transportReader{
+ reader: &recvBufferReader{
+ ctx: s.ctx,
+ ctxDone: s.ctxDone,
+ recv: s.buf,
+ },
+ windowHandler: func(n int) {
+ t.updateWindow(s, uint32(n))
+ },
+ }
+ // Register the stream with loopy.
+ t.controlBuf.put(&registerStream{
+ streamID: s.id,
+ wq: s.wq,
+ })
+ handle(s)
+ return false
+}
+
+// HandleStreams receives incoming streams using the given handler. This is
+// typically run in a separate goroutine.
+// traceCtx attaches trace to ctx and returns the new context.
+func (t *http2Server) HandleStreams(handle func(*Stream), traceCtx func(context.Context, string) context.Context) {
+ defer close(t.readerDone)
+ for {
+ frame, err := t.framer.fr.ReadFrame()
+ atomic.StoreUint32(&t.activity, 1)
+ if err != nil {
+ if se, ok := err.(http2.StreamError); ok {
+ warningf("transport: http2Server.HandleStreams encountered http2.StreamError: %v", se)
+ t.mu.Lock()
+ s := t.activeStreams[se.StreamID]
+ t.mu.Unlock()
+ if s != nil {
+ t.closeStream(s, true, se.Code, nil, false)
+ } else {
+ t.controlBuf.put(&cleanupStream{
+ streamID: se.StreamID,
+ rst: true,
+ rstCode: se.Code,
+ onWrite: func() {},
+ })
+ }
+ continue
+ }
+ if err == io.EOF || err == io.ErrUnexpectedEOF {
+ t.Close()
+ return
+ }
+ warningf("transport: http2Server.HandleStreams failed to read frame: %v", err)
+ t.Close()
+ return
+ }
+ switch frame := frame.(type) {
+ case *http2.MetaHeadersFrame:
+ if t.operateHeaders(frame, handle, traceCtx) {
+ t.Close()
+ break
+ }
+ case *http2.DataFrame:
+ t.handleData(frame)
+ case *http2.RSTStreamFrame:
+ t.handleRSTStream(frame)
+ case *http2.SettingsFrame:
+ t.handleSettings(frame)
+ case *http2.PingFrame:
+ t.handlePing(frame)
+ case *http2.WindowUpdateFrame:
+ t.handleWindowUpdate(frame)
+ case *http2.GoAwayFrame:
+ // TODO: Handle GoAway from the client appropriately.
+ default:
+ errorf("transport: http2Server.HandleStreams found unhandled frame type %v.", frame)
+ }
+ }
+}
+
+func (t *http2Server) getStream(f http2.Frame) (*Stream, bool) {
+ t.mu.Lock()
+ defer t.mu.Unlock()
+ if t.activeStreams == nil {
+ // The transport is closing.
+ return nil, false
+ }
+ s, ok := t.activeStreams[f.Header().StreamID]
+ if !ok {
+ // The stream is already done.
+ return nil, false
+ }
+ return s, true
+}
+
+// adjustWindow sends out extra window update over the initial window size
+// of stream if the application is requesting data larger in size than
+// the window.
+func (t *http2Server) adjustWindow(s *Stream, n uint32) {
+ if w := s.fc.maybeAdjust(n); w > 0 {
+ t.controlBuf.put(&outgoingWindowUpdate{streamID: s.id, increment: w})
+ }
+
+}
+
+// updateWindow adjusts the inbound quota for the stream and the transport.
+// Window updates will deliver to the controller for sending when
+// the cumulative quota exceeds the corresponding threshold.
+func (t *http2Server) updateWindow(s *Stream, n uint32) {
+ if w := s.fc.onRead(n); w > 0 {
+ t.controlBuf.put(&outgoingWindowUpdate{streamID: s.id,
+ increment: w,
+ })
+ }
+}
+
+// updateFlowControl updates the incoming flow control windows
+// for the transport and the stream based on the current bdp
+// estimation.
+func (t *http2Server) updateFlowControl(n uint32) {
+ t.mu.Lock()
+ for _, s := range t.activeStreams {
+ s.fc.newLimit(n)
+ }
+ t.initialWindowSize = int32(n)
+ t.mu.Unlock()
+ t.controlBuf.put(&outgoingWindowUpdate{
+ streamID: 0,
+ increment: t.fc.newLimit(n),
+ })
+ t.controlBuf.put(&outgoingSettings{
+ ss: []http2.Setting{
+ {
+ ID: http2.SettingInitialWindowSize,
+ Val: n,
+ },
+ },
+ })
+
+}
+
+func (t *http2Server) handleData(f *http2.DataFrame) {
+ size := f.Header().Length
+ var sendBDPPing bool
+ if t.bdpEst != nil {
+ sendBDPPing = t.bdpEst.add(size)
+ }
+ // Decouple connection's flow control from application's read.
+ // An update on connection's flow control should not depend on
+ // whether user application has read the data or not. Such a
+ // restriction is already imposed on the stream's flow control,
+ // and therefore the sender will be blocked anyways.
+ // Decoupling the connection flow control will prevent other
+ // active(fast) streams from starving in presence of slow or
+ // inactive streams.
+ if w := t.fc.onData(size); w > 0 {
+ t.controlBuf.put(&outgoingWindowUpdate{
+ streamID: 0,
+ increment: w,
+ })
+ }
+ if sendBDPPing {
+ // Avoid excessive ping detection (e.g. in an L7 proxy)
+ // by sending a window update prior to the BDP ping.
+ if w := t.fc.reset(); w > 0 {
+ t.controlBuf.put(&outgoingWindowUpdate{
+ streamID: 0,
+ increment: w,
+ })
+ }
+ t.controlBuf.put(bdpPing)
+ }
+ // Select the right stream to dispatch.
+ s, ok := t.getStream(f)
+ if !ok {
+ return
+ }
+ if size > 0 {
+ if err := s.fc.onData(size); err != nil {
+ t.closeStream(s, true, http2.ErrCodeFlowControl, nil, false)
+ return
+ }
+ if f.Header().Flags.Has(http2.FlagDataPadded) {
+ if w := s.fc.onRead(size - uint32(len(f.Data()))); w > 0 {
+ t.controlBuf.put(&outgoingWindowUpdate{s.id, w})
+ }
+ }
+ // TODO(bradfitz, zhaoq): A copy is required here because there is no
+ // guarantee f.Data() is consumed before the arrival of next frame.
+ // Can this copy be eliminated?
+ if len(f.Data()) > 0 {
+ data := make([]byte, len(f.Data()))
+ copy(data, f.Data())
+ s.write(recvMsg{data: data})
+ }
+ }
+ if f.Header().Flags.Has(http2.FlagDataEndStream) {
+ // Received the end of stream from the client.
+ s.compareAndSwapState(streamActive, streamReadDone)
+ s.write(recvMsg{err: io.EOF})
+ }
+}
+
+func (t *http2Server) handleRSTStream(f *http2.RSTStreamFrame) {
+ s, ok := t.getStream(f)
+ if !ok {
+ return
+ }
+ t.closeStream(s, false, 0, nil, false)
+}
+
+func (t *http2Server) handleSettings(f *http2.SettingsFrame) {
+ if f.IsAck() {
+ return
+ }
+ var ss []http2.Setting
+ var updateFuncs []func()
+ f.ForeachSetting(func(s http2.Setting) error {
+ switch s.ID {
+ case http2.SettingMaxHeaderListSize:
+ updateFuncs = append(updateFuncs, func() {
+ t.maxSendHeaderListSize = new(uint32)
+ *t.maxSendHeaderListSize = s.Val
+ })
+ default:
+ ss = append(ss, s)
+ }
+ return nil
+ })
+ t.controlBuf.executeAndPut(func(interface{}) bool {
+ for _, f := range updateFuncs {
+ f()
+ }
+ return true
+ }, &incomingSettings{
+ ss: ss,
+ })
+}
+
+const (
+ maxPingStrikes = 2
+ defaultPingTimeout = 2 * time.Hour
+)
+
+func (t *http2Server) handlePing(f *http2.PingFrame) {
+ if f.IsAck() {
+ if f.Data == goAwayPing.data && t.drainChan != nil {
+ close(t.drainChan)
+ return
+ }
+ // Maybe it's a BDP ping.
+ if t.bdpEst != nil {
+ t.bdpEst.calculate(f.Data)
+ }
+ return
+ }
+ pingAck := &ping{ack: true}
+ copy(pingAck.data[:], f.Data[:])
+ t.controlBuf.put(pingAck)
+
+ now := time.Now()
+ defer func() {
+ t.lastPingAt = now
+ }()
+ // A reset ping strikes means that we don't need to check for policy
+ // violation for this ping and the pingStrikes counter should be set
+ // to 0.
+ if atomic.CompareAndSwapUint32(&t.resetPingStrikes, 1, 0) {
+ t.pingStrikes = 0
+ return
+ }
+ t.mu.Lock()
+ ns := len(t.activeStreams)
+ t.mu.Unlock()
+ if ns < 1 && !t.kep.PermitWithoutStream {
+ // Keepalive shouldn't be active thus, this new ping should
+ // have come after at least defaultPingTimeout.
+ if t.lastPingAt.Add(defaultPingTimeout).After(now) {
+ t.pingStrikes++
+ }
+ } else {
+ // Check if keepalive policy is respected.
+ if t.lastPingAt.Add(t.kep.MinTime).After(now) {
+ t.pingStrikes++
+ }
+ }
+
+ if t.pingStrikes > maxPingStrikes {
+ // Send goaway and close the connection.
+ errorf("transport: Got too many pings from the client, closing the connection.")
+ t.controlBuf.put(&goAway{code: http2.ErrCodeEnhanceYourCalm, debugData: []byte("too_many_pings"), closeConn: true})
+ }
+}
+
+func (t *http2Server) handleWindowUpdate(f *http2.WindowUpdateFrame) {
+ t.controlBuf.put(&incomingWindowUpdate{
+ streamID: f.Header().StreamID,
+ increment: f.Increment,
+ })
+}
+
+func appendHeaderFieldsFromMD(headerFields []hpack.HeaderField, md metadata.MD) []hpack.HeaderField {
+ for k, vv := range md {
+ if isReservedHeader(k) {
+ // Clients don't tolerate reading restricted headers after some non restricted ones were sent.
+ continue
+ }
+ for _, v := range vv {
+ headerFields = append(headerFields, hpack.HeaderField{Name: k, Value: encodeMetadataHeader(k, v)})
+ }
+ }
+ return headerFields
+}
+
+func (t *http2Server) checkForHeaderListSize(it interface{}) bool {
+ if t.maxSendHeaderListSize == nil {
+ return true
+ }
+ hdrFrame := it.(*headerFrame)
+ var sz int64
+ for _, f := range hdrFrame.hf {
+ if sz += int64(f.Size()); sz > int64(*t.maxSendHeaderListSize) {
+ errorf("header list size to send violates the maximum size (%d bytes) set by client", *t.maxSendHeaderListSize)
+ return false
+ }
+ }
+ return true
+}
+
+// WriteHeader sends the header metedata md back to the client.
+func (t *http2Server) WriteHeader(s *Stream, md metadata.MD) error {
+ if s.updateHeaderSent() || s.getState() == streamDone {
+ return ErrIllegalHeaderWrite
+ }
+ s.hdrMu.Lock()
+ if md.Len() > 0 {
+ if s.header.Len() > 0 {
+ s.header = metadata.Join(s.header, md)
+ } else {
+ s.header = md
+ }
+ }
+ if err := t.writeHeaderLocked(s); err != nil {
+ s.hdrMu.Unlock()
+ return err
+ }
+ s.hdrMu.Unlock()
+ return nil
+}
+
+func (t *http2Server) writeHeaderLocked(s *Stream) error {
+ // TODO(mmukhi): Benchmark if the performance gets better if count the metadata and other header fields
+ // first and create a slice of that exact size.
+ headerFields := make([]hpack.HeaderField, 0, 2) // at least :status, content-type will be there if none else.
+ headerFields = append(headerFields, hpack.HeaderField{Name: ":status", Value: "200"})
+ headerFields = append(headerFields, hpack.HeaderField{Name: "content-type", Value: contentType(s.contentSubtype)})
+ if s.sendCompress != "" {
+ headerFields = append(headerFields, hpack.HeaderField{Name: "grpc-encoding", Value: s.sendCompress})
+ }
+ headerFields = appendHeaderFieldsFromMD(headerFields, s.header)
+ success, err := t.controlBuf.executeAndPut(t.checkForHeaderListSize, &headerFrame{
+ streamID: s.id,
+ hf: headerFields,
+ endStream: false,
+ onWrite: func() {
+ atomic.StoreUint32(&t.resetPingStrikes, 1)
+ },
+ })
+ if !success {
+ if err != nil {
+ return err
+ }
+ t.closeStream(s, true, http2.ErrCodeInternal, nil, false)
+ return ErrHeaderListSizeLimitViolation
+ }
+ if t.stats != nil {
+ // Note: WireLength is not set in outHeader.
+ // TODO(mmukhi): Revisit this later, if needed.
+ outHeader := &stats.OutHeader{}
+ t.stats.HandleRPC(s.Context(), outHeader)
+ }
+ return nil
+}
+
+// WriteStatus sends stream status to the client and terminates the stream.
+// There is no further I/O operations being able to perform on this stream.
+// TODO(zhaoq): Now it indicates the end of entire stream. Revisit if early
+// OK is adopted.
+func (t *http2Server) WriteStatus(s *Stream, st *status.Status) error {
+ if s.getState() == streamDone {
+ return nil
+ }
+ s.hdrMu.Lock()
+ // TODO(mmukhi): Benchmark if the performance gets better if count the metadata and other header fields
+ // first and create a slice of that exact size.
+ headerFields := make([]hpack.HeaderField, 0, 2) // grpc-status and grpc-message will be there if none else.
+ if !s.updateHeaderSent() { // No headers have been sent.
+ if len(s.header) > 0 { // Send a separate header frame.
+ if err := t.writeHeaderLocked(s); err != nil {
+ s.hdrMu.Unlock()
+ return err
+ }
+ } else { // Send a trailer only response.
+ headerFields = append(headerFields, hpack.HeaderField{Name: ":status", Value: "200"})
+ headerFields = append(headerFields, hpack.HeaderField{Name: "content-type", Value: contentType(s.contentSubtype)})
+ }
+ }
+ headerFields = append(headerFields, hpack.HeaderField{Name: "grpc-status", Value: strconv.Itoa(int(st.Code()))})
+ headerFields = append(headerFields, hpack.HeaderField{Name: "grpc-message", Value: encodeGrpcMessage(st.Message())})
+
+ if p := st.Proto(); p != nil && len(p.Details) > 0 {
+ stBytes, err := proto.Marshal(p)
+ if err != nil {
+ // TODO: return error instead, when callers are able to handle it.
+ grpclog.Errorf("transport: failed to marshal rpc status: %v, error: %v", p, err)
+ } else {
+ headerFields = append(headerFields, hpack.HeaderField{Name: "grpc-status-details-bin", Value: encodeBinHeader(stBytes)})
+ }
+ }
+
+ // Attach the trailer metadata.
+ headerFields = appendHeaderFieldsFromMD(headerFields, s.trailer)
+ trailingHeader := &headerFrame{
+ streamID: s.id,
+ hf: headerFields,
+ endStream: true,
+ onWrite: func() {
+ atomic.StoreUint32(&t.resetPingStrikes, 1)
+ },
+ }
+ s.hdrMu.Unlock()
+ success, err := t.controlBuf.execute(t.checkForHeaderListSize, trailingHeader)
+ if !success {
+ if err != nil {
+ return err
+ }
+ t.closeStream(s, true, http2.ErrCodeInternal, nil, false)
+ return ErrHeaderListSizeLimitViolation
+ }
+ t.closeStream(s, false, 0, trailingHeader, true)
+ if t.stats != nil {
+ t.stats.HandleRPC(s.Context(), &stats.OutTrailer{})
+ }
+ return nil
+}
+
+// Write converts the data into HTTP2 data frame and sends it out. Non-nil error
+// is returns if it fails (e.g., framing error, transport error).
+func (t *http2Server) Write(s *Stream, hdr []byte, data []byte, opts *Options) error {
+ if !s.isHeaderSent() { // Headers haven't been written yet.
+ if err := t.WriteHeader(s, nil); err != nil {
+ // TODO(mmukhi, dfawley): Make sure this is the right code to return.
+ return status.Errorf(codes.Internal, "transport: %v", err)
+ }
+ } else {
+ // Writing headers checks for this condition.
+ if s.getState() == streamDone {
+ // TODO(mmukhi, dfawley): Should the server write also return io.EOF?
+ s.cancel()
+ select {
+ case <-t.ctx.Done():
+ return ErrConnClosing
+ default:
+ }
+ return ContextErr(s.ctx.Err())
+ }
+ }
+ // Add some data to header frame so that we can equally distribute bytes across frames.
+ emptyLen := http2MaxFrameLen - len(hdr)
+ if emptyLen > len(data) {
+ emptyLen = len(data)
+ }
+ hdr = append(hdr, data[:emptyLen]...)
+ data = data[emptyLen:]
+ df := &dataFrame{
+ streamID: s.id,
+ h: hdr,
+ d: data,
+ onEachWrite: func() {
+ atomic.StoreUint32(&t.resetPingStrikes, 1)
+ },
+ }
+ if err := s.wq.get(int32(len(hdr) + len(data))); err != nil {
+ select {
+ case <-t.ctx.Done():
+ return ErrConnClosing
+ default:
+ }
+ return ContextErr(s.ctx.Err())
+ }
+ return t.controlBuf.put(df)
+}
+
+// keepalive running in a separate goroutine does the following:
+// 1. Gracefully closes an idle connection after a duration of keepalive.MaxConnectionIdle.
+// 2. Gracefully closes any connection after a duration of keepalive.MaxConnectionAge.
+// 3. Forcibly closes a connection after an additive period of keepalive.MaxConnectionAgeGrace over keepalive.MaxConnectionAge.
+// 4. Makes sure a connection is alive by sending pings with a frequency of keepalive.Time and closes a non-responsive connection
+// after an additional duration of keepalive.Timeout.
+func (t *http2Server) keepalive() {
+ p := &ping{}
+ var pingSent bool
+ maxIdle := time.NewTimer(t.kp.MaxConnectionIdle)
+ maxAge := time.NewTimer(t.kp.MaxConnectionAge)
+ keepalive := time.NewTimer(t.kp.Time)
+ // NOTE: All exit paths of this function should reset their
+ // respective timers. A failure to do so will cause the
+ // following clean-up to deadlock and eventually leak.
+ defer func() {
+ if !maxIdle.Stop() {
+ <-maxIdle.C
+ }
+ if !maxAge.Stop() {
+ <-maxAge.C
+ }
+ if !keepalive.Stop() {
+ <-keepalive.C
+ }
+ }()
+ for {
+ select {
+ case <-maxIdle.C:
+ t.mu.Lock()
+ idle := t.idle
+ if idle.IsZero() { // The connection is non-idle.
+ t.mu.Unlock()
+ maxIdle.Reset(t.kp.MaxConnectionIdle)
+ continue
+ }
+ val := t.kp.MaxConnectionIdle - time.Since(idle)
+ t.mu.Unlock()
+ if val <= 0 {
+ // The connection has been idle for a duration of keepalive.MaxConnectionIdle or more.
+ // Gracefully close the connection.
+ t.drain(http2.ErrCodeNo, []byte{})
+ // Resetting the timer so that the clean-up doesn't deadlock.
+ maxIdle.Reset(infinity)
+ return
+ }
+ maxIdle.Reset(val)
+ case <-maxAge.C:
+ t.drain(http2.ErrCodeNo, []byte{})
+ maxAge.Reset(t.kp.MaxConnectionAgeGrace)
+ select {
+ case <-maxAge.C:
+ // Close the connection after grace period.
+ t.Close()
+ // Resetting the timer so that the clean-up doesn't deadlock.
+ maxAge.Reset(infinity)
+ case <-t.ctx.Done():
+ }
+ return
+ case <-keepalive.C:
+ if atomic.CompareAndSwapUint32(&t.activity, 1, 0) {
+ pingSent = false
+ keepalive.Reset(t.kp.Time)
+ continue
+ }
+ if pingSent {
+ t.Close()
+ // Resetting the timer so that the clean-up doesn't deadlock.
+ keepalive.Reset(infinity)
+ return
+ }
+ pingSent = true
+ if channelz.IsOn() {
+ atomic.AddInt64(&t.czData.kpCount, 1)
+ }
+ t.controlBuf.put(p)
+ keepalive.Reset(t.kp.Timeout)
+ case <-t.ctx.Done():
+ return
+ }
+ }
+}
+
+// Close starts shutting down the http2Server transport.
+// TODO(zhaoq): Now the destruction is not blocked on any pending streams. This
+// could cause some resource issue. Revisit this later.
+func (t *http2Server) Close() error {
+ t.mu.Lock()
+ if t.state == closing {
+ t.mu.Unlock()
+ return errors.New("transport: Close() was already called")
+ }
+ t.state = closing
+ streams := t.activeStreams
+ t.activeStreams = nil
+ t.mu.Unlock()
+ t.controlBuf.finish()
+ t.cancel()
+ err := t.conn.Close()
+ if channelz.IsOn() {
+ channelz.RemoveEntry(t.channelzID)
+ }
+ // Cancel all active streams.
+ for _, s := range streams {
+ s.cancel()
+ }
+ if t.stats != nil {
+ connEnd := &stats.ConnEnd{}
+ t.stats.HandleConn(t.ctx, connEnd)
+ }
+ return err
+}
+
+// closeStream clears the footprint of a stream when the stream is not needed
+// any more.
+func (t *http2Server) closeStream(s *Stream, rst bool, rstCode http2.ErrCode, hdr *headerFrame, eosReceived bool) {
+ if s.swapState(streamDone) == streamDone {
+ // If the stream was already done, return.
+ return
+ }
+ // In case stream sending and receiving are invoked in separate
+ // goroutines (e.g., bi-directional streaming), cancel needs to be
+ // called to interrupt the potential blocking on other goroutines.
+ s.cancel()
+ cleanup := &cleanupStream{
+ streamID: s.id,
+ rst: rst,
+ rstCode: rstCode,
+ onWrite: func() {
+ t.mu.Lock()
+ if t.activeStreams != nil {
+ delete(t.activeStreams, s.id)
+ if len(t.activeStreams) == 0 {
+ t.idle = time.Now()
+ }
+ }
+ t.mu.Unlock()
+ if channelz.IsOn() {
+ if eosReceived {
+ atomic.AddInt64(&t.czData.streamsSucceeded, 1)
+ } else {
+ atomic.AddInt64(&t.czData.streamsFailed, 1)
+ }
+ }
+ },
+ }
+ if hdr != nil {
+ hdr.cleanup = cleanup
+ t.controlBuf.put(hdr)
+ } else {
+ t.controlBuf.put(cleanup)
+ }
+}
+
+func (t *http2Server) RemoteAddr() net.Addr {
+ return t.remoteAddr
+}
+
+func (t *http2Server) Drain() {
+ t.drain(http2.ErrCodeNo, []byte{})
+}
+
+func (t *http2Server) drain(code http2.ErrCode, debugData []byte) {
+ t.mu.Lock()
+ defer t.mu.Unlock()
+ if t.drainChan != nil {
+ return
+ }
+ t.drainChan = make(chan struct{})
+ t.controlBuf.put(&goAway{code: code, debugData: debugData, headsUp: true})
+}
+
+var goAwayPing = &ping{data: [8]byte{1, 6, 1, 8, 0, 3, 3, 9}}
+
+// Handles outgoing GoAway and returns true if loopy needs to put itself
+// in draining mode.
+func (t *http2Server) outgoingGoAwayHandler(g *goAway) (bool, error) {
+ t.mu.Lock()
+ if t.state == closing { // TODO(mmukhi): This seems unnecessary.
+ t.mu.Unlock()
+ // The transport is closing.
+ return false, ErrConnClosing
+ }
+ sid := t.maxStreamID
+ if !g.headsUp {
+ // Stop accepting more streams now.
+ t.state = draining
+ if len(t.activeStreams) == 0 {
+ g.closeConn = true
+ }
+ t.mu.Unlock()
+ if err := t.framer.fr.WriteGoAway(sid, g.code, g.debugData); err != nil {
+ return false, err
+ }
+ if g.closeConn {
+ // Abruptly close the connection following the GoAway (via
+ // loopywriter). But flush out what's inside the buffer first.
+ t.framer.writer.Flush()
+ return false, fmt.Errorf("transport: Connection closing")
+ }
+ return true, nil
+ }
+ t.mu.Unlock()
+ // For a graceful close, send out a GoAway with stream ID of MaxUInt32,
+ // Follow that with a ping and wait for the ack to come back or a timer
+ // to expire. During this time accept new streams since they might have
+ // originated before the GoAway reaches the client.
+ // After getting the ack or timer expiration send out another GoAway this
+ // time with an ID of the max stream server intends to process.
+ if err := t.framer.fr.WriteGoAway(math.MaxUint32, http2.ErrCodeNo, []byte{}); err != nil {
+ return false, err
+ }
+ if err := t.framer.fr.WritePing(false, goAwayPing.data); err != nil {
+ return false, err
+ }
+ go func() {
+ timer := time.NewTimer(time.Minute)
+ defer timer.Stop()
+ select {
+ case <-t.drainChan:
+ case <-timer.C:
+ case <-t.ctx.Done():
+ return
+ }
+ t.controlBuf.put(&goAway{code: g.code, debugData: g.debugData})
+ }()
+ return false, nil
+}
+
+func (t *http2Server) ChannelzMetric() *channelz.SocketInternalMetric {
+ s := channelz.SocketInternalMetric{
+ StreamsStarted: atomic.LoadInt64(&t.czData.streamsStarted),
+ StreamsSucceeded: atomic.LoadInt64(&t.czData.streamsSucceeded),
+ StreamsFailed: atomic.LoadInt64(&t.czData.streamsFailed),
+ MessagesSent: atomic.LoadInt64(&t.czData.msgSent),
+ MessagesReceived: atomic.LoadInt64(&t.czData.msgRecv),
+ KeepAlivesSent: atomic.LoadInt64(&t.czData.kpCount),
+ LastRemoteStreamCreatedTimestamp: time.Unix(0, atomic.LoadInt64(&t.czData.lastStreamCreatedTime)),
+ LastMessageSentTimestamp: time.Unix(0, atomic.LoadInt64(&t.czData.lastMsgSentTime)),
+ LastMessageReceivedTimestamp: time.Unix(0, atomic.LoadInt64(&t.czData.lastMsgRecvTime)),
+ LocalFlowControlWindow: int64(t.fc.getSize()),
+ SocketOptions: channelz.GetSocketOption(t.conn),
+ LocalAddr: t.localAddr,
+ RemoteAddr: t.remoteAddr,
+ // RemoteName :
+ }
+ if au, ok := t.authInfo.(credentials.ChannelzSecurityInfo); ok {
+ s.Security = au.GetSecurityValue()
+ }
+ s.RemoteFlowControlWindow = t.getOutFlowWindow()
+ return &s
+}
+
+func (t *http2Server) IncrMsgSent() {
+ atomic.AddInt64(&t.czData.msgSent, 1)
+ atomic.StoreInt64(&t.czData.lastMsgSentTime, time.Now().UnixNano())
+}
+
+func (t *http2Server) IncrMsgRecv() {
+ atomic.AddInt64(&t.czData.msgRecv, 1)
+ atomic.StoreInt64(&t.czData.lastMsgRecvTime, time.Now().UnixNano())
+}
+
+func (t *http2Server) getOutFlowWindow() int64 {
+ resp := make(chan uint32)
+ timer := time.NewTimer(time.Second)
+ defer timer.Stop()
+ t.controlBuf.put(&outFlowControlSizeRequest{resp})
+ select {
+ case sz := <-resp:
+ return int64(sz)
+ case <-t.ctxDone:
+ return -1
+ case <-timer.C:
+ return -2
+ }
+}
+
+func getJitter(v time.Duration) time.Duration {
+ if v == infinity {
+ return 0
+ }
+ // Generate a jitter between +/- 10% of the value.
+ r := int64(v / 10)
+ j := grpcrand.Int63n(2*r) - r
+ return time.Duration(j)
+}
diff --git a/vendor/google.golang.org/grpc/internal/transport/http_util.go b/vendor/google.golang.org/grpc/internal/transport/http_util.go
new file mode 100644
index 000000000..77a2cfaae
--- /dev/null
+++ b/vendor/google.golang.org/grpc/internal/transport/http_util.go
@@ -0,0 +1,623 @@
+/*
+ *
+ * Copyright 2014 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package transport
+
+import (
+ "bufio"
+ "bytes"
+ "encoding/base64"
+ "fmt"
+ "io"
+ "math"
+ "net"
+ "net/http"
+ "strconv"
+ "strings"
+ "time"
+ "unicode/utf8"
+
+ "github.com/golang/protobuf/proto"
+ "golang.org/x/net/http2"
+ "golang.org/x/net/http2/hpack"
+ spb "google.golang.org/genproto/googleapis/rpc/status"
+ "google.golang.org/grpc/codes"
+ "google.golang.org/grpc/status"
+)
+
+const (
+ // http2MaxFrameLen specifies the max length of a HTTP2 frame.
+ http2MaxFrameLen = 16384 // 16KB frame
+ // http://http2.github.io/http2-spec/#SettingValues
+ http2InitHeaderTableSize = 4096
+ // baseContentType is the base content-type for gRPC. This is a valid
+ // content-type on it's own, but can also include a content-subtype such as
+ // "proto" as a suffix after "+" or ";". See
+ // https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md#requests
+ // for more details.
+ baseContentType = "application/grpc"
+)
+
+var (
+ clientPreface = []byte(http2.ClientPreface)
+ http2ErrConvTab = map[http2.ErrCode]codes.Code{
+ http2.ErrCodeNo: codes.Internal,
+ http2.ErrCodeProtocol: codes.Internal,
+ http2.ErrCodeInternal: codes.Internal,
+ http2.ErrCodeFlowControl: codes.ResourceExhausted,
+ http2.ErrCodeSettingsTimeout: codes.Internal,
+ http2.ErrCodeStreamClosed: codes.Internal,
+ http2.ErrCodeFrameSize: codes.Internal,
+ http2.ErrCodeRefusedStream: codes.Unavailable,
+ http2.ErrCodeCancel: codes.Canceled,
+ http2.ErrCodeCompression: codes.Internal,
+ http2.ErrCodeConnect: codes.Internal,
+ http2.ErrCodeEnhanceYourCalm: codes.ResourceExhausted,
+ http2.ErrCodeInadequateSecurity: codes.PermissionDenied,
+ http2.ErrCodeHTTP11Required: codes.Internal,
+ }
+ statusCodeConvTab = map[codes.Code]http2.ErrCode{
+ codes.Internal: http2.ErrCodeInternal,
+ codes.Canceled: http2.ErrCodeCancel,
+ codes.Unavailable: http2.ErrCodeRefusedStream,
+ codes.ResourceExhausted: http2.ErrCodeEnhanceYourCalm,
+ codes.PermissionDenied: http2.ErrCodeInadequateSecurity,
+ }
+ httpStatusConvTab = map[int]codes.Code{
+ // 400 Bad Request - INTERNAL.
+ http.StatusBadRequest: codes.Internal,
+ // 401 Unauthorized - UNAUTHENTICATED.
+ http.StatusUnauthorized: codes.Unauthenticated,
+ // 403 Forbidden - PERMISSION_DENIED.
+ http.StatusForbidden: codes.PermissionDenied,
+ // 404 Not Found - UNIMPLEMENTED.
+ http.StatusNotFound: codes.Unimplemented,
+ // 429 Too Many Requests - UNAVAILABLE.
+ http.StatusTooManyRequests: codes.Unavailable,
+ // 502 Bad Gateway - UNAVAILABLE.
+ http.StatusBadGateway: codes.Unavailable,
+ // 503 Service Unavailable - UNAVAILABLE.
+ http.StatusServiceUnavailable: codes.Unavailable,
+ // 504 Gateway timeout - UNAVAILABLE.
+ http.StatusGatewayTimeout: codes.Unavailable,
+ }
+)
+
+// Records the states during HPACK decoding. Must be reset once the
+// decoding of the entire headers are finished.
+type decodeState struct {
+ encoding string
+ // statusGen caches the stream status received from the trailer the server
+ // sent. Client side only. Do not access directly. After all trailers are
+ // parsed, use the status method to retrieve the status.
+ statusGen *status.Status
+ // rawStatusCode and rawStatusMsg are set from the raw trailer fields and are not
+ // intended for direct access outside of parsing.
+ rawStatusCode *int
+ rawStatusMsg string
+ httpStatus *int
+ // Server side only fields.
+ timeoutSet bool
+ timeout time.Duration
+ method string
+ // key-value metadata map from the peer.
+ mdata map[string][]string
+ statsTags []byte
+ statsTrace []byte
+ contentSubtype string
+ // whether decoding on server side or not
+ serverSide bool
+}
+
+// isReservedHeader checks whether hdr belongs to HTTP2 headers
+// reserved by gRPC protocol. Any other headers are classified as the
+// user-specified metadata.
+func isReservedHeader(hdr string) bool {
+ if hdr != "" && hdr[0] == ':' {
+ return true
+ }
+ switch hdr {
+ case "content-type",
+ "user-agent",
+ "grpc-message-type",
+ "grpc-encoding",
+ "grpc-message",
+ "grpc-status",
+ "grpc-timeout",
+ "grpc-status-details-bin",
+ // Intentionally exclude grpc-previous-rpc-attempts and
+ // grpc-retry-pushback-ms, which are "reserved", but their API
+ // intentionally works via metadata.
+ "te":
+ return true
+ default:
+ return false
+ }
+}
+
+// isWhitelistedHeader checks whether hdr should be propagated into metadata
+// visible to users, even though it is classified as "reserved", above.
+func isWhitelistedHeader(hdr string) bool {
+ switch hdr {
+ case ":authority", "user-agent":
+ return true
+ default:
+ return false
+ }
+}
+
+// contentSubtype returns the content-subtype for the given content-type. The
+// given content-type must be a valid content-type that starts with
+// "application/grpc". A content-subtype will follow "application/grpc" after a
+// "+" or ";". See
+// https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md#requests for
+// more details.
+//
+// If contentType is not a valid content-type for gRPC, the boolean
+// will be false, otherwise true. If content-type == "application/grpc",
+// "application/grpc+", or "application/grpc;", the boolean will be true,
+// but no content-subtype will be returned.
+//
+// contentType is assumed to be lowercase already.
+func contentSubtype(contentType string) (string, bool) {
+ if contentType == baseContentType {
+ return "", true
+ }
+ if !strings.HasPrefix(contentType, baseContentType) {
+ return "", false
+ }
+ // guaranteed since != baseContentType and has baseContentType prefix
+ switch contentType[len(baseContentType)] {
+ case '+', ';':
+ // this will return true for "application/grpc+" or "application/grpc;"
+ // which the previous validContentType function tested to be valid, so we
+ // just say that no content-subtype is specified in this case
+ return contentType[len(baseContentType)+1:], true
+ default:
+ return "", false
+ }
+}
+
+// contentSubtype is assumed to be lowercase
+func contentType(contentSubtype string) string {
+ if contentSubtype == "" {
+ return baseContentType
+ }
+ return baseContentType + "+" + contentSubtype
+}
+
+func (d *decodeState) status() *status.Status {
+ if d.statusGen == nil {
+ // No status-details were provided; generate status using code/msg.
+ d.statusGen = status.New(codes.Code(int32(*(d.rawStatusCode))), d.rawStatusMsg)
+ }
+ return d.statusGen
+}
+
+const binHdrSuffix = "-bin"
+
+func encodeBinHeader(v []byte) string {
+ return base64.RawStdEncoding.EncodeToString(v)
+}
+
+func decodeBinHeader(v string) ([]byte, error) {
+ if len(v)%4 == 0 {
+ // Input was padded, or padding was not necessary.
+ return base64.StdEncoding.DecodeString(v)
+ }
+ return base64.RawStdEncoding.DecodeString(v)
+}
+
+func encodeMetadataHeader(k, v string) string {
+ if strings.HasSuffix(k, binHdrSuffix) {
+ return encodeBinHeader(([]byte)(v))
+ }
+ return v
+}
+
+func decodeMetadataHeader(k, v string) (string, error) {
+ if strings.HasSuffix(k, binHdrSuffix) {
+ b, err := decodeBinHeader(v)
+ return string(b), err
+ }
+ return v, nil
+}
+
+func (d *decodeState) decodeHeader(frame *http2.MetaHeadersFrame) error {
+ // frame.Truncated is set to true when framer detects that the current header
+ // list size hits MaxHeaderListSize limit.
+ if frame.Truncated {
+ return status.Error(codes.Internal, "peer header list size exceeded limit")
+ }
+ for _, hf := range frame.Fields {
+ if err := d.processHeaderField(hf); err != nil {
+ return err
+ }
+ }
+
+ if d.serverSide {
+ return nil
+ }
+
+ // If grpc status exists, no need to check further.
+ if d.rawStatusCode != nil || d.statusGen != nil {
+ return nil
+ }
+
+ // If grpc status doesn't exist and http status doesn't exist,
+ // then it's a malformed header.
+ if d.httpStatus == nil {
+ return status.Error(codes.Internal, "malformed header: doesn't contain status(gRPC or HTTP)")
+ }
+
+ if *(d.httpStatus) != http.StatusOK {
+ code, ok := httpStatusConvTab[*(d.httpStatus)]
+ if !ok {
+ code = codes.Unknown
+ }
+ return status.Error(code, http.StatusText(*(d.httpStatus)))
+ }
+
+ // gRPC status doesn't exist and http status is OK.
+ // Set rawStatusCode to be unknown and return nil error.
+ // So that, if the stream has ended this Unknown status
+ // will be propagated to the user.
+ // Otherwise, it will be ignored. In which case, status from
+ // a later trailer, that has StreamEnded flag set, is propagated.
+ code := int(codes.Unknown)
+ d.rawStatusCode = &code
+ return nil
+}
+
+func (d *decodeState) addMetadata(k, v string) {
+ if d.mdata == nil {
+ d.mdata = make(map[string][]string)
+ }
+ d.mdata[k] = append(d.mdata[k], v)
+}
+
+func (d *decodeState) processHeaderField(f hpack.HeaderField) error {
+ switch f.Name {
+ case "content-type":
+ contentSubtype, validContentType := contentSubtype(f.Value)
+ if !validContentType {
+ return status.Errorf(codes.Internal, "transport: received the unexpected content-type %q", f.Value)
+ }
+ d.contentSubtype = contentSubtype
+ // TODO: do we want to propagate the whole content-type in the metadata,
+ // or come up with a way to just propagate the content-subtype if it was set?
+ // ie {"content-type": "application/grpc+proto"} or {"content-subtype": "proto"}
+ // in the metadata?
+ d.addMetadata(f.Name, f.Value)
+ case "grpc-encoding":
+ d.encoding = f.Value
+ case "grpc-status":
+ code, err := strconv.Atoi(f.Value)
+ if err != nil {
+ return status.Errorf(codes.Internal, "transport: malformed grpc-status: %v", err)
+ }
+ d.rawStatusCode = &code
+ case "grpc-message":
+ d.rawStatusMsg = decodeGrpcMessage(f.Value)
+ case "grpc-status-details-bin":
+ v, err := decodeBinHeader(f.Value)
+ if err != nil {
+ return status.Errorf(codes.Internal, "transport: malformed grpc-status-details-bin: %v", err)
+ }
+ s := &spb.Status{}
+ if err := proto.Unmarshal(v, s); err != nil {
+ return status.Errorf(codes.Internal, "transport: malformed grpc-status-details-bin: %v", err)
+ }
+ d.statusGen = status.FromProto(s)
+ case "grpc-timeout":
+ d.timeoutSet = true
+ var err error
+ if d.timeout, err = decodeTimeout(f.Value); err != nil {
+ return status.Errorf(codes.Internal, "transport: malformed time-out: %v", err)
+ }
+ case ":path":
+ d.method = f.Value
+ case ":status":
+ code, err := strconv.Atoi(f.Value)
+ if err != nil {
+ return status.Errorf(codes.Internal, "transport: malformed http-status: %v", err)
+ }
+ d.httpStatus = &code
+ case "grpc-tags-bin":
+ v, err := decodeBinHeader(f.Value)
+ if err != nil {
+ return status.Errorf(codes.Internal, "transport: malformed grpc-tags-bin: %v", err)
+ }
+ d.statsTags = v
+ d.addMetadata(f.Name, string(v))
+ case "grpc-trace-bin":
+ v, err := decodeBinHeader(f.Value)
+ if err != nil {
+ return status.Errorf(codes.Internal, "transport: malformed grpc-trace-bin: %v", err)
+ }
+ d.statsTrace = v
+ d.addMetadata(f.Name, string(v))
+ default:
+ if isReservedHeader(f.Name) && !isWhitelistedHeader(f.Name) {
+ break
+ }
+ v, err := decodeMetadataHeader(f.Name, f.Value)
+ if err != nil {
+ errorf("Failed to decode metadata header (%q, %q): %v", f.Name, f.Value, err)
+ return nil
+ }
+ d.addMetadata(f.Name, v)
+ }
+ return nil
+}
+
+type timeoutUnit uint8
+
+const (
+ hour timeoutUnit = 'H'
+ minute timeoutUnit = 'M'
+ second timeoutUnit = 'S'
+ millisecond timeoutUnit = 'm'
+ microsecond timeoutUnit = 'u'
+ nanosecond timeoutUnit = 'n'
+)
+
+func timeoutUnitToDuration(u timeoutUnit) (d time.Duration, ok bool) {
+ switch u {
+ case hour:
+ return time.Hour, true
+ case minute:
+ return time.Minute, true
+ case second:
+ return time.Second, true
+ case millisecond:
+ return time.Millisecond, true
+ case microsecond:
+ return time.Microsecond, true
+ case nanosecond:
+ return time.Nanosecond, true
+ default:
+ }
+ return
+}
+
+const maxTimeoutValue int64 = 100000000 - 1
+
+// div does integer division and round-up the result. Note that this is
+// equivalent to (d+r-1)/r but has less chance to overflow.
+func div(d, r time.Duration) int64 {
+ if m := d % r; m > 0 {
+ return int64(d/r + 1)
+ }
+ return int64(d / r)
+}
+
+// TODO(zhaoq): It is the simplistic and not bandwidth efficient. Improve it.
+func encodeTimeout(t time.Duration) string {
+ if t <= 0 {
+ return "0n"
+ }
+ if d := div(t, time.Nanosecond); d <= maxTimeoutValue {
+ return strconv.FormatInt(d, 10) + "n"
+ }
+ if d := div(t, time.Microsecond); d <= maxTimeoutValue {
+ return strconv.FormatInt(d, 10) + "u"
+ }
+ if d := div(t, time.Millisecond); d <= maxTimeoutValue {
+ return strconv.FormatInt(d, 10) + "m"
+ }
+ if d := div(t, time.Second); d <= maxTimeoutValue {
+ return strconv.FormatInt(d, 10) + "S"
+ }
+ if d := div(t, time.Minute); d <= maxTimeoutValue {
+ return strconv.FormatInt(d, 10) + "M"
+ }
+ // Note that maxTimeoutValue * time.Hour > MaxInt64.
+ return strconv.FormatInt(div(t, time.Hour), 10) + "H"
+}
+
+func decodeTimeout(s string) (time.Duration, error) {
+ size := len(s)
+ if size < 2 {
+ return 0, fmt.Errorf("transport: timeout string is too short: %q", s)
+ }
+ if size > 9 {
+ // Spec allows for 8 digits plus the unit.
+ return 0, fmt.Errorf("transport: timeout string is too long: %q", s)
+ }
+ unit := timeoutUnit(s[size-1])
+ d, ok := timeoutUnitToDuration(unit)
+ if !ok {
+ return 0, fmt.Errorf("transport: timeout unit is not recognized: %q", s)
+ }
+ t, err := strconv.ParseInt(s[:size-1], 10, 64)
+ if err != nil {
+ return 0, err
+ }
+ const maxHours = math.MaxInt64 / int64(time.Hour)
+ if d == time.Hour && t > maxHours {
+ // This timeout would overflow math.MaxInt64; clamp it.
+ return time.Duration(math.MaxInt64), nil
+ }
+ return d * time.Duration(t), nil
+}
+
+const (
+ spaceByte = ' '
+ tildeByte = '~'
+ percentByte = '%'
+)
+
+// encodeGrpcMessage is used to encode status code in header field
+// "grpc-message". It does percent encoding and also replaces invalid utf-8
+// characters with Unicode replacement character.
+//
+// It checks to see if each individual byte in msg is an allowable byte, and
+// then either percent encoding or passing it through. When percent encoding,
+// the byte is converted into hexadecimal notation with a '%' prepended.
+func encodeGrpcMessage(msg string) string {
+ if msg == "" {
+ return ""
+ }
+ lenMsg := len(msg)
+ for i := 0; i < lenMsg; i++ {
+ c := msg[i]
+ if !(c >= spaceByte && c <= tildeByte && c != percentByte) {
+ return encodeGrpcMessageUnchecked(msg)
+ }
+ }
+ return msg
+}
+
+func encodeGrpcMessageUnchecked(msg string) string {
+ var buf bytes.Buffer
+ for len(msg) > 0 {
+ r, size := utf8.DecodeRuneInString(msg)
+ for _, b := range []byte(string(r)) {
+ if size > 1 {
+ // If size > 1, r is not ascii. Always do percent encoding.
+ buf.WriteString(fmt.Sprintf("%%%02X", b))
+ continue
+ }
+
+ // The for loop is necessary even if size == 1. r could be
+ // utf8.RuneError.
+ //
+ // fmt.Sprintf("%%%02X", utf8.RuneError) gives "%FFFD".
+ if b >= spaceByte && b <= tildeByte && b != percentByte {
+ buf.WriteByte(b)
+ } else {
+ buf.WriteString(fmt.Sprintf("%%%02X", b))
+ }
+ }
+ msg = msg[size:]
+ }
+ return buf.String()
+}
+
+// decodeGrpcMessage decodes the msg encoded by encodeGrpcMessage.
+func decodeGrpcMessage(msg string) string {
+ if msg == "" {
+ return ""
+ }
+ lenMsg := len(msg)
+ for i := 0; i < lenMsg; i++ {
+ if msg[i] == percentByte && i+2 < lenMsg {
+ return decodeGrpcMessageUnchecked(msg)
+ }
+ }
+ return msg
+}
+
+func decodeGrpcMessageUnchecked(msg string) string {
+ var buf bytes.Buffer
+ lenMsg := len(msg)
+ for i := 0; i < lenMsg; i++ {
+ c := msg[i]
+ if c == percentByte && i+2 < lenMsg {
+ parsed, err := strconv.ParseUint(msg[i+1:i+3], 16, 8)
+ if err != nil {
+ buf.WriteByte(c)
+ } else {
+ buf.WriteByte(byte(parsed))
+ i += 2
+ }
+ } else {
+ buf.WriteByte(c)
+ }
+ }
+ return buf.String()
+}
+
+type bufWriter struct {
+ buf []byte
+ offset int
+ batchSize int
+ conn net.Conn
+ err error
+
+ onFlush func()
+}
+
+func newBufWriter(conn net.Conn, batchSize int) *bufWriter {
+ return &bufWriter{
+ buf: make([]byte, batchSize*2),
+ batchSize: batchSize,
+ conn: conn,
+ }
+}
+
+func (w *bufWriter) Write(b []byte) (n int, err error) {
+ if w.err != nil {
+ return 0, w.err
+ }
+ if w.batchSize == 0 { // Buffer has been disabled.
+ return w.conn.Write(b)
+ }
+ for len(b) > 0 {
+ nn := copy(w.buf[w.offset:], b)
+ b = b[nn:]
+ w.offset += nn
+ n += nn
+ if w.offset >= w.batchSize {
+ err = w.Flush()
+ }
+ }
+ return n, err
+}
+
+func (w *bufWriter) Flush() error {
+ if w.err != nil {
+ return w.err
+ }
+ if w.offset == 0 {
+ return nil
+ }
+ if w.onFlush != nil {
+ w.onFlush()
+ }
+ _, w.err = w.conn.Write(w.buf[:w.offset])
+ w.offset = 0
+ return w.err
+}
+
+type framer struct {
+ writer *bufWriter
+ fr *http2.Framer
+}
+
+func newFramer(conn net.Conn, writeBufferSize, readBufferSize int, maxHeaderListSize uint32) *framer {
+ if writeBufferSize < 0 {
+ writeBufferSize = 0
+ }
+ var r io.Reader = conn
+ if readBufferSize > 0 {
+ r = bufio.NewReaderSize(r, readBufferSize)
+ }
+ w := newBufWriter(conn, writeBufferSize)
+ f := &framer{
+ writer: w,
+ fr: http2.NewFramer(w, r),
+ }
+ // Opt-in to Frame reuse API on framer to reduce garbage.
+ // Frames aren't safe to read from after a subsequent call to ReadFrame.
+ f.fr.SetReuseFrames()
+ f.fr.MaxHeaderListSize = maxHeaderListSize
+ f.fr.ReadMetaHeaders = hpack.NewDecoder(http2InitHeaderTableSize, nil)
+ return f
+}
diff --git a/vendor/google.golang.org/grpc/internal/transport/log.go b/vendor/google.golang.org/grpc/internal/transport/log.go
new file mode 100644
index 000000000..879df80c4
--- /dev/null
+++ b/vendor/google.golang.org/grpc/internal/transport/log.go
@@ -0,0 +1,44 @@
+/*
+ *
+ * Copyright 2017 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// This file contains wrappers for grpclog functions.
+// The transport package only logs to verbose level 2 by default.
+
+package transport
+
+import "google.golang.org/grpc/grpclog"
+
+const logLevel = 2
+
+func infof(format string, args ...interface{}) {
+ if grpclog.V(logLevel) {
+ grpclog.Infof(format, args...)
+ }
+}
+
+func warningf(format string, args ...interface{}) {
+ if grpclog.V(logLevel) {
+ grpclog.Warningf(format, args...)
+ }
+}
+
+func errorf(format string, args ...interface{}) {
+ if grpclog.V(logLevel) {
+ grpclog.Errorf(format, args...)
+ }
+}
diff --git a/vendor/google.golang.org/grpc/internal/transport/transport.go b/vendor/google.golang.org/grpc/internal/transport/transport.go
new file mode 100644
index 000000000..4d7e89067
--- /dev/null
+++ b/vendor/google.golang.org/grpc/internal/transport/transport.go
@@ -0,0 +1,736 @@
+/*
+ *
+ * Copyright 2014 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// Package transport defines and implements message oriented communication
+// channel to complete various transactions (e.g., an RPC). It is meant for
+// grpc-internal usage and is not intended to be imported directly by users.
+package transport
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "io"
+ "net"
+ "sync"
+ "sync/atomic"
+
+ "google.golang.org/grpc/codes"
+ "google.golang.org/grpc/credentials"
+ "google.golang.org/grpc/keepalive"
+ "google.golang.org/grpc/metadata"
+ "google.golang.org/grpc/stats"
+ "google.golang.org/grpc/status"
+ "google.golang.org/grpc/tap"
+)
+
+// recvMsg represents the received msg from the transport. All transport
+// protocol specific info has been removed.
+type recvMsg struct {
+ data []byte
+ // nil: received some data
+ // io.EOF: stream is completed. data is nil.
+ // other non-nil error: transport failure. data is nil.
+ err error
+}
+
+// recvBuffer is an unbounded channel of recvMsg structs.
+// Note recvBuffer differs from controlBuffer only in that recvBuffer
+// holds a channel of only recvMsg structs instead of objects implementing "item" interface.
+// recvBuffer is written to much more often than
+// controlBuffer and using strict recvMsg structs helps avoid allocation in "recvBuffer.put"
+type recvBuffer struct {
+ c chan recvMsg
+ mu sync.Mutex
+ backlog []recvMsg
+ err error
+}
+
+func newRecvBuffer() *recvBuffer {
+ b := &recvBuffer{
+ c: make(chan recvMsg, 1),
+ }
+ return b
+}
+
+func (b *recvBuffer) put(r recvMsg) {
+ b.mu.Lock()
+ if b.err != nil {
+ b.mu.Unlock()
+ // An error had occurred earlier, don't accept more
+ // data or errors.
+ return
+ }
+ b.err = r.err
+ if len(b.backlog) == 0 {
+ select {
+ case b.c <- r:
+ b.mu.Unlock()
+ return
+ default:
+ }
+ }
+ b.backlog = append(b.backlog, r)
+ b.mu.Unlock()
+}
+
+func (b *recvBuffer) load() {
+ b.mu.Lock()
+ if len(b.backlog) > 0 {
+ select {
+ case b.c <- b.backlog[0]:
+ b.backlog[0] = recvMsg{}
+ b.backlog = b.backlog[1:]
+ default:
+ }
+ }
+ b.mu.Unlock()
+}
+
+// get returns the channel that receives a recvMsg in the buffer.
+//
+// Upon receipt of a recvMsg, the caller should call load to send another
+// recvMsg onto the channel if there is any.
+func (b *recvBuffer) get() <-chan recvMsg {
+ return b.c
+}
+
+//
+// recvBufferReader implements io.Reader interface to read the data from
+// recvBuffer.
+type recvBufferReader struct {
+ ctx context.Context
+ ctxDone <-chan struct{} // cache of ctx.Done() (for performance).
+ recv *recvBuffer
+ last []byte // Stores the remaining data in the previous calls.
+ err error
+}
+
+// Read reads the next len(p) bytes from last. If last is drained, it tries to
+// read additional data from recv. It blocks if there no additional data available
+// in recv. If Read returns any non-nil error, it will continue to return that error.
+func (r *recvBufferReader) Read(p []byte) (n int, err error) {
+ if r.err != nil {
+ return 0, r.err
+ }
+ n, r.err = r.read(p)
+ return n, r.err
+}
+
+func (r *recvBufferReader) read(p []byte) (n int, err error) {
+ if r.last != nil && len(r.last) > 0 {
+ // Read remaining data left in last call.
+ copied := copy(p, r.last)
+ r.last = r.last[copied:]
+ return copied, nil
+ }
+ select {
+ case <-r.ctxDone:
+ return 0, ContextErr(r.ctx.Err())
+ case m := <-r.recv.get():
+ r.recv.load()
+ if m.err != nil {
+ return 0, m.err
+ }
+ copied := copy(p, m.data)
+ r.last = m.data[copied:]
+ return copied, nil
+ }
+}
+
+type streamState uint32
+
+const (
+ streamActive streamState = iota
+ streamWriteDone // EndStream sent
+ streamReadDone // EndStream received
+ streamDone // the entire stream is finished.
+)
+
+// Stream represents an RPC in the transport layer.
+type Stream struct {
+ id uint32
+ st ServerTransport // nil for client side Stream
+ ctx context.Context // the associated context of the stream
+ cancel context.CancelFunc // always nil for client side Stream
+ done chan struct{} // closed at the end of stream to unblock writers. On the client side.
+ ctxDone <-chan struct{} // same as done chan but for server side. Cache of ctx.Done() (for performance)
+ method string // the associated RPC method of the stream
+ recvCompress string
+ sendCompress string
+ buf *recvBuffer
+ trReader io.Reader
+ fc *inFlow
+ wq *writeQuota
+
+ // Callback to state application's intentions to read data. This
+ // is used to adjust flow control, if needed.
+ requestRead func(int)
+
+ headerChan chan struct{} // closed to indicate the end of header metadata.
+ headerDone uint32 // set when headerChan is closed. Used to avoid closing headerChan multiple times.
+
+ // hdrMu protects header and trailer metadata on the server-side.
+ hdrMu sync.Mutex
+ // On client side, header keeps the received header metadata.
+ //
+ // On server side, header keeps the header set by SetHeader(). The complete
+ // header will merged into this after t.WriteHeader() is called.
+ header metadata.MD
+ trailer metadata.MD // the key-value map of trailer metadata.
+
+ noHeaders bool // set if the client never received headers (set only after the stream is done).
+
+ // On the server-side, headerSent is atomically set to 1 when the headers are sent out.
+ headerSent uint32
+
+ state streamState
+
+ // On client-side it is the status error received from the server.
+ // On server-side it is unused.
+ status *status.Status
+
+ bytesReceived uint32 // indicates whether any bytes have been received on this stream
+ unprocessed uint32 // set if the server sends a refused stream or GOAWAY including this stream
+
+ // contentSubtype is the content-subtype for requests.
+ // this must be lowercase or the behavior is undefined.
+ contentSubtype string
+}
+
+// isHeaderSent is only valid on the server-side.
+func (s *Stream) isHeaderSent() bool {
+ return atomic.LoadUint32(&s.headerSent) == 1
+}
+
+// updateHeaderSent updates headerSent and returns true
+// if it was alreay set. It is valid only on server-side.
+func (s *Stream) updateHeaderSent() bool {
+ return atomic.SwapUint32(&s.headerSent, 1) == 1
+}
+
+func (s *Stream) swapState(st streamState) streamState {
+ return streamState(atomic.SwapUint32((*uint32)(&s.state), uint32(st)))
+}
+
+func (s *Stream) compareAndSwapState(oldState, newState streamState) bool {
+ return atomic.CompareAndSwapUint32((*uint32)(&s.state), uint32(oldState), uint32(newState))
+}
+
+func (s *Stream) getState() streamState {
+ return streamState(atomic.LoadUint32((*uint32)(&s.state)))
+}
+
+func (s *Stream) waitOnHeader() error {
+ if s.headerChan == nil {
+ // On the server headerChan is always nil since a stream originates
+ // only after having received headers.
+ return nil
+ }
+ select {
+ case <-s.ctx.Done():
+ return ContextErr(s.ctx.Err())
+ case <-s.headerChan:
+ return nil
+ }
+}
+
+// RecvCompress returns the compression algorithm applied to the inbound
+// message. It is empty string if there is no compression applied.
+func (s *Stream) RecvCompress() string {
+ if err := s.waitOnHeader(); err != nil {
+ return ""
+ }
+ return s.recvCompress
+}
+
+// SetSendCompress sets the compression algorithm to the stream.
+func (s *Stream) SetSendCompress(str string) {
+ s.sendCompress = str
+}
+
+// Done returns a channel which is closed when it receives the final status
+// from the server.
+func (s *Stream) Done() <-chan struct{} {
+ return s.done
+}
+
+// Header returns the header metadata of the stream.
+//
+// On client side, it acquires the key-value pairs of header metadata once it is
+// available. It blocks until i) the metadata is ready or ii) there is no header
+// metadata or iii) the stream is canceled/expired.
+//
+// On server side, it returns the out header after t.WriteHeader is called.
+func (s *Stream) Header() (metadata.MD, error) {
+ if s.headerChan == nil && s.header != nil {
+ // On server side, return the header in stream. It will be the out
+ // header after t.WriteHeader is called.
+ return s.header.Copy(), nil
+ }
+ err := s.waitOnHeader()
+ // Even if the stream is closed, header is returned if available.
+ select {
+ case <-s.headerChan:
+ if s.header == nil {
+ return nil, nil
+ }
+ return s.header.Copy(), nil
+ default:
+ }
+ return nil, err
+}
+
+// TrailersOnly blocks until a header or trailers-only frame is received and
+// then returns true if the stream was trailers-only. If the stream ends
+// before headers are received, returns true, nil. If a context error happens
+// first, returns it as a status error. Client-side only.
+func (s *Stream) TrailersOnly() (bool, error) {
+ err := s.waitOnHeader()
+ if err != nil {
+ return false, err
+ }
+ // if !headerDone, some other connection error occurred.
+ return s.noHeaders && atomic.LoadUint32(&s.headerDone) == 1, nil
+}
+
+// Trailer returns the cached trailer metedata. Note that if it is not called
+// after the entire stream is done, it could return an empty MD. Client
+// side only.
+// It can be safely read only after stream has ended that is either read
+// or write have returned io.EOF.
+func (s *Stream) Trailer() metadata.MD {
+ c := s.trailer.Copy()
+ return c
+}
+
+// ContentSubtype returns the content-subtype for a request. For example, a
+// content-subtype of "proto" will result in a content-type of
+// "application/grpc+proto". This will always be lowercase. See
+// https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md#requests for
+// more details.
+func (s *Stream) ContentSubtype() string {
+ return s.contentSubtype
+}
+
+// Context returns the context of the stream.
+func (s *Stream) Context() context.Context {
+ return s.ctx
+}
+
+// Method returns the method for the stream.
+func (s *Stream) Method() string {
+ return s.method
+}
+
+// Status returns the status received from the server.
+// Status can be read safely only after the stream has ended,
+// that is, after Done() is closed.
+func (s *Stream) Status() *status.Status {
+ return s.status
+}
+
+// SetHeader sets the header metadata. This can be called multiple times.
+// Server side only.
+// This should not be called in parallel to other data writes.
+func (s *Stream) SetHeader(md metadata.MD) error {
+ if md.Len() == 0 {
+ return nil
+ }
+ if s.isHeaderSent() || s.getState() == streamDone {
+ return ErrIllegalHeaderWrite
+ }
+ s.hdrMu.Lock()
+ s.header = metadata.Join(s.header, md)
+ s.hdrMu.Unlock()
+ return nil
+}
+
+// SendHeader sends the given header metadata. The given metadata is
+// combined with any metadata set by previous calls to SetHeader and
+// then written to the transport stream.
+func (s *Stream) SendHeader(md metadata.MD) error {
+ return s.st.WriteHeader(s, md)
+}
+
+// SetTrailer sets the trailer metadata which will be sent with the RPC status
+// by the server. This can be called multiple times. Server side only.
+// This should not be called parallel to other data writes.
+func (s *Stream) SetTrailer(md metadata.MD) error {
+ if md.Len() == 0 {
+ return nil
+ }
+ if s.getState() == streamDone {
+ return ErrIllegalHeaderWrite
+ }
+ s.hdrMu.Lock()
+ s.trailer = metadata.Join(s.trailer, md)
+ s.hdrMu.Unlock()
+ return nil
+}
+
+func (s *Stream) write(m recvMsg) {
+ s.buf.put(m)
+}
+
+// Read reads all p bytes from the wire for this stream.
+func (s *Stream) Read(p []byte) (n int, err error) {
+ // Don't request a read if there was an error earlier
+ if er := s.trReader.(*transportReader).er; er != nil {
+ return 0, er
+ }
+ s.requestRead(len(p))
+ return io.ReadFull(s.trReader, p)
+}
+
+// tranportReader reads all the data available for this Stream from the transport and
+// passes them into the decoder, which converts them into a gRPC message stream.
+// The error is io.EOF when the stream is done or another non-nil error if
+// the stream broke.
+type transportReader struct {
+ reader io.Reader
+ // The handler to control the window update procedure for both this
+ // particular stream and the associated transport.
+ windowHandler func(int)
+ er error
+}
+
+func (t *transportReader) Read(p []byte) (n int, err error) {
+ n, err = t.reader.Read(p)
+ if err != nil {
+ t.er = err
+ return
+ }
+ t.windowHandler(n)
+ return
+}
+
+// BytesReceived indicates whether any bytes have been received on this stream.
+func (s *Stream) BytesReceived() bool {
+ return atomic.LoadUint32(&s.bytesReceived) == 1
+}
+
+// Unprocessed indicates whether the server did not process this stream --
+// i.e. it sent a refused stream or GOAWAY including this stream ID.
+func (s *Stream) Unprocessed() bool {
+ return atomic.LoadUint32(&s.unprocessed) == 1
+}
+
+// GoString is implemented by Stream so context.String() won't
+// race when printing %#v.
+func (s *Stream) GoString() string {
+ return fmt.Sprintf("<stream: %p, %v>", s, s.method)
+}
+
+// state of transport
+type transportState int
+
+const (
+ reachable transportState = iota
+ closing
+ draining
+)
+
+// ServerConfig consists of all the configurations to establish a server transport.
+type ServerConfig struct {
+ MaxStreams uint32
+ AuthInfo credentials.AuthInfo
+ InTapHandle tap.ServerInHandle
+ StatsHandler stats.Handler
+ KeepaliveParams keepalive.ServerParameters
+ KeepalivePolicy keepalive.EnforcementPolicy
+ InitialWindowSize int32
+ InitialConnWindowSize int32
+ WriteBufferSize int
+ ReadBufferSize int
+ ChannelzParentID int64
+ MaxHeaderListSize *uint32
+}
+
+// NewServerTransport creates a ServerTransport with conn or non-nil error
+// if it fails.
+func NewServerTransport(protocol string, conn net.Conn, config *ServerConfig) (ServerTransport, error) {
+ return newHTTP2Server(conn, config)
+}
+
+// ConnectOptions covers all relevant options for communicating with the server.
+type ConnectOptions struct {
+ // UserAgent is the application user agent.
+ UserAgent string
+ // Dialer specifies how to dial a network address.
+ Dialer func(context.Context, string) (net.Conn, error)
+ // FailOnNonTempDialError specifies if gRPC fails on non-temporary dial errors.
+ FailOnNonTempDialError bool
+ // PerRPCCredentials stores the PerRPCCredentials required to issue RPCs.
+ PerRPCCredentials []credentials.PerRPCCredentials
+ // TransportCredentials stores the Authenticator required to setup a client
+ // connection. Only one of TransportCredentials and CredsBundle is non-nil.
+ TransportCredentials credentials.TransportCredentials
+ // CredsBundle is the credentials bundle to be used. Only one of
+ // TransportCredentials and CredsBundle is non-nil.
+ CredsBundle credentials.Bundle
+ // KeepaliveParams stores the keepalive parameters.
+ KeepaliveParams keepalive.ClientParameters
+ // StatsHandler stores the handler for stats.
+ StatsHandler stats.Handler
+ // InitialWindowSize sets the initial window size for a stream.
+ InitialWindowSize int32
+ // InitialConnWindowSize sets the initial window size for a connection.
+ InitialConnWindowSize int32
+ // WriteBufferSize sets the size of write buffer which in turn determines how much data can be batched before it's written on the wire.
+ WriteBufferSize int
+ // ReadBufferSize sets the size of read buffer, which in turn determines how much data can be read at most for one read syscall.
+ ReadBufferSize int
+ // ChannelzParentID sets the addrConn id which initiate the creation of this client transport.
+ ChannelzParentID int64
+ // MaxHeaderListSize sets the max (uncompressed) size of header list that is prepared to be received.
+ MaxHeaderListSize *uint32
+}
+
+// TargetInfo contains the information of the target such as network address and metadata.
+type TargetInfo struct {
+ Addr string
+ Metadata interface{}
+ Authority string
+}
+
+// NewClientTransport establishes the transport with the required ConnectOptions
+// and returns it to the caller.
+func NewClientTransport(connectCtx, ctx context.Context, target TargetInfo, opts ConnectOptions, onSuccess func(), onGoAway func(GoAwayReason), onClose func()) (ClientTransport, error) {
+ return newHTTP2Client(connectCtx, ctx, target, opts, onSuccess, onGoAway, onClose)
+}
+
+// Options provides additional hints and information for message
+// transmission.
+type Options struct {
+ // Last indicates whether this write is the last piece for
+ // this stream.
+ Last bool
+}
+
+// CallHdr carries the information of a particular RPC.
+type CallHdr struct {
+ // Host specifies the peer's host.
+ Host string
+
+ // Method specifies the operation to perform.
+ Method string
+
+ // SendCompress specifies the compression algorithm applied on
+ // outbound message.
+ SendCompress string
+
+ // Creds specifies credentials.PerRPCCredentials for a call.
+ Creds credentials.PerRPCCredentials
+
+ // ContentSubtype specifies the content-subtype for a request. For example, a
+ // content-subtype of "proto" will result in a content-type of
+ // "application/grpc+proto". The value of ContentSubtype must be all
+ // lowercase, otherwise the behavior is undefined. See
+ // https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md#requests
+ // for more details.
+ ContentSubtype string
+
+ PreviousAttempts int // value of grpc-previous-rpc-attempts header to set
+}
+
+// ClientTransport is the common interface for all gRPC client-side transport
+// implementations.
+type ClientTransport interface {
+ // Close tears down this transport. Once it returns, the transport
+ // should not be accessed any more. The caller must make sure this
+ // is called only once.
+ Close() error
+
+ // GracefulClose starts to tear down the transport. It stops accepting
+ // new RPCs and wait the completion of the pending RPCs.
+ GracefulClose() error
+
+ // Write sends the data for the given stream. A nil stream indicates
+ // the write is to be performed on the transport as a whole.
+ Write(s *Stream, hdr []byte, data []byte, opts *Options) error
+
+ // NewStream creates a Stream for an RPC.
+ NewStream(ctx context.Context, callHdr *CallHdr) (*Stream, error)
+
+ // CloseStream clears the footprint of a stream when the stream is
+ // not needed any more. The err indicates the error incurred when
+ // CloseStream is called. Must be called when a stream is finished
+ // unless the associated transport is closing.
+ CloseStream(stream *Stream, err error)
+
+ // Error returns a channel that is closed when some I/O error
+ // happens. Typically the caller should have a goroutine to monitor
+ // this in order to take action (e.g., close the current transport
+ // and create a new one) in error case. It should not return nil
+ // once the transport is initiated.
+ Error() <-chan struct{}
+
+ // GoAway returns a channel that is closed when ClientTransport
+ // receives the draining signal from the server (e.g., GOAWAY frame in
+ // HTTP/2).
+ GoAway() <-chan struct{}
+
+ // GetGoAwayReason returns the reason why GoAway frame was received.
+ GetGoAwayReason() GoAwayReason
+
+ // IncrMsgSent increments the number of message sent through this transport.
+ IncrMsgSent()
+
+ // IncrMsgRecv increments the number of message received through this transport.
+ IncrMsgRecv()
+}
+
+// ServerTransport is the common interface for all gRPC server-side transport
+// implementations.
+//
+// Methods may be called concurrently from multiple goroutines, but
+// Write methods for a given Stream will be called serially.
+type ServerTransport interface {
+ // HandleStreams receives incoming streams using the given handler.
+ HandleStreams(func(*Stream), func(context.Context, string) context.Context)
+
+ // WriteHeader sends the header metadata for the given stream.
+ // WriteHeader may not be called on all streams.
+ WriteHeader(s *Stream, md metadata.MD) error
+
+ // Write sends the data for the given stream.
+ // Write may not be called on all streams.
+ Write(s *Stream, hdr []byte, data []byte, opts *Options) error
+
+ // WriteStatus sends the status of a stream to the client. WriteStatus is
+ // the final call made on a stream and always occurs.
+ WriteStatus(s *Stream, st *status.Status) error
+
+ // Close tears down the transport. Once it is called, the transport
+ // should not be accessed any more. All the pending streams and their
+ // handlers will be terminated asynchronously.
+ Close() error
+
+ // RemoteAddr returns the remote network address.
+ RemoteAddr() net.Addr
+
+ // Drain notifies the client this ServerTransport stops accepting new RPCs.
+ Drain()
+
+ // IncrMsgSent increments the number of message sent through this transport.
+ IncrMsgSent()
+
+ // IncrMsgRecv increments the number of message received through this transport.
+ IncrMsgRecv()
+}
+
+// connectionErrorf creates an ConnectionError with the specified error description.
+func connectionErrorf(temp bool, e error, format string, a ...interface{}) ConnectionError {
+ return ConnectionError{
+ Desc: fmt.Sprintf(format, a...),
+ temp: temp,
+ err: e,
+ }
+}
+
+// ConnectionError is an error that results in the termination of the
+// entire connection and the retry of all the active streams.
+type ConnectionError struct {
+ Desc string
+ temp bool
+ err error
+}
+
+func (e ConnectionError) Error() string {
+ return fmt.Sprintf("connection error: desc = %q", e.Desc)
+}
+
+// Temporary indicates if this connection error is temporary or fatal.
+func (e ConnectionError) Temporary() bool {
+ return e.temp
+}
+
+// Origin returns the original error of this connection error.
+func (e ConnectionError) Origin() error {
+ // Never return nil error here.
+ // If the original error is nil, return itself.
+ if e.err == nil {
+ return e
+ }
+ return e.err
+}
+
+var (
+ // ErrConnClosing indicates that the transport is closing.
+ ErrConnClosing = connectionErrorf(true, nil, "transport is closing")
+ // errStreamDrain indicates that the stream is rejected because the
+ // connection is draining. This could be caused by goaway or balancer
+ // removing the address.
+ errStreamDrain = status.Error(codes.Unavailable, "the connection is draining")
+ // errStreamDone is returned from write at the client side to indiacte application
+ // layer of an error.
+ errStreamDone = errors.New("the stream is done")
+ // StatusGoAway indicates that the server sent a GOAWAY that included this
+ // stream's ID in unprocessed RPCs.
+ statusGoAway = status.New(codes.Unavailable, "the stream is rejected because server is draining the connection")
+)
+
+// GoAwayReason contains the reason for the GoAway frame received.
+type GoAwayReason uint8
+
+const (
+ // GoAwayInvalid indicates that no GoAway frame is received.
+ GoAwayInvalid GoAwayReason = 0
+ // GoAwayNoReason is the default value when GoAway frame is received.
+ GoAwayNoReason GoAwayReason = 1
+ // GoAwayTooManyPings indicates that a GoAway frame with
+ // ErrCodeEnhanceYourCalm was received and that the debug data said
+ // "too_many_pings".
+ GoAwayTooManyPings GoAwayReason = 2
+)
+
+// channelzData is used to store channelz related data for http2Client and http2Server.
+// These fields cannot be embedded in the original structs (e.g. http2Client), since to do atomic
+// operation on int64 variable on 32-bit machine, user is responsible to enforce memory alignment.
+// Here, by grouping those int64 fields inside a struct, we are enforcing the alignment.
+type channelzData struct {
+ kpCount int64
+ // The number of streams that have started, including already finished ones.
+ streamsStarted int64
+ // Client side: The number of streams that have ended successfully by receiving
+ // EoS bit set frame from server.
+ // Server side: The number of streams that have ended successfully by sending
+ // frame with EoS bit set.
+ streamsSucceeded int64
+ streamsFailed int64
+ // lastStreamCreatedTime stores the timestamp that the last stream gets created. It is of int64 type
+ // instead of time.Time since it's more costly to atomically update time.Time variable than int64
+ // variable. The same goes for lastMsgSentTime and lastMsgRecvTime.
+ lastStreamCreatedTime int64
+ msgSent int64
+ msgRecv int64
+ lastMsgSentTime int64
+ lastMsgRecvTime int64
+}
+
+// ContextErr converts the error from context package into a status error.
+func ContextErr(err error) error {
+ switch err {
+ case context.DeadlineExceeded:
+ return status.Error(codes.DeadlineExceeded, err.Error())
+ case context.Canceled:
+ return status.Error(codes.Canceled, err.Error())
+ }
+ return status.Errorf(codes.Internal, "Unexpected error from context packet: %v", err)
+}
diff --git a/vendor/google.golang.org/grpc/keepalive/keepalive.go b/vendor/google.golang.org/grpc/keepalive/keepalive.go
new file mode 100644
index 000000000..78eea1fc9
--- /dev/null
+++ b/vendor/google.golang.org/grpc/keepalive/keepalive.go
@@ -0,0 +1,83 @@
+/*
+ *
+ * Copyright 2017 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// Package keepalive defines configurable parameters for point-to-point
+// healthcheck.
+package keepalive
+
+import (
+ "time"
+)
+
+// ClientParameters is used to set keepalive parameters on the client-side.
+// These configure how the client will actively probe to notice when a
+// connection is broken and send pings so intermediaries will be aware of the
+// liveness of the connection. Make sure these parameters are set in
+// coordination with the keepalive policy on the server, as incompatible
+// settings can result in closing of connection.
+type ClientParameters struct {
+ // After a duration of this time if the client doesn't see any activity it
+ // pings the server to see if the transport is still alive.
+ Time time.Duration // The current default value is infinity.
+ // After having pinged for keepalive check, the client waits for a duration
+ // of Timeout and if no activity is seen even after that the connection is
+ // closed.
+ Timeout time.Duration // The current default value is 20 seconds.
+ // If true, client sends keepalive pings even with no active RPCs. If false,
+ // when there are no active RPCs, Time and Timeout will be ignored and no
+ // keepalive pings will be sent.
+ PermitWithoutStream bool // false by default.
+}
+
+// ServerParameters is used to set keepalive and max-age parameters on the
+// server-side.
+type ServerParameters struct {
+ // MaxConnectionIdle is a duration for the amount of time after which an
+ // idle connection would be closed by sending a GoAway. Idleness duration is
+ // defined since the most recent time the number of outstanding RPCs became
+ // zero or the connection establishment.
+ MaxConnectionIdle time.Duration // The current default value is infinity.
+ // MaxConnectionAge is a duration for the maximum amount of time a
+ // connection may exist before it will be closed by sending a GoAway. A
+ // random jitter of +/-10% will be added to MaxConnectionAge to spread out
+ // connection storms.
+ MaxConnectionAge time.Duration // The current default value is infinity.
+ // MaxConnectinoAgeGrace is an additive period after MaxConnectionAge after
+ // which the connection will be forcibly closed.
+ MaxConnectionAgeGrace time.Duration // The current default value is infinity.
+ // After a duration of this time if the server doesn't see any activity it
+ // pings the client to see if the transport is still alive.
+ Time time.Duration // The current default value is 2 hours.
+ // After having pinged for keepalive check, the server waits for a duration
+ // of Timeout and if no activity is seen even after that the connection is
+ // closed.
+ Timeout time.Duration // The current default value is 20 seconds.
+}
+
+// EnforcementPolicy is used to set keepalive enforcement policy on the
+// server-side. Server will close connection with a client that violates this
+// policy.
+type EnforcementPolicy struct {
+ // MinTime is the minimum amount of time a client should wait before sending
+ // a keepalive ping.
+ MinTime time.Duration // The current default value is 5 minutes.
+ // If true, server allows keepalive pings even when there are no active
+ // streams(RPCs). If false, and client sends ping when there are no active
+ // streams, server will send GOAWAY and close the connection.
+ PermitWithoutStream bool // false by default.
+}
diff --git a/vendor/google.golang.org/grpc/metadata/metadata.go b/vendor/google.golang.org/grpc/metadata/metadata.go
new file mode 100644
index 000000000..cf6d1b947
--- /dev/null
+++ b/vendor/google.golang.org/grpc/metadata/metadata.go
@@ -0,0 +1,209 @@
+/*
+ *
+ * Copyright 2014 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// Package metadata define the structure of the metadata supported by gRPC library.
+// Please refer to https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md
+// for more information about custom-metadata.
+package metadata // import "google.golang.org/grpc/metadata"
+
+import (
+ "context"
+ "fmt"
+ "strings"
+)
+
+// DecodeKeyValue returns k, v, nil.
+//
+// Deprecated: use k and v directly instead.
+func DecodeKeyValue(k, v string) (string, string, error) {
+ return k, v, nil
+}
+
+// MD is a mapping from metadata keys to values. Users should use the following
+// two convenience functions New and Pairs to generate MD.
+type MD map[string][]string
+
+// New creates an MD from a given key-value map.
+//
+// Only the following ASCII characters are allowed in keys:
+// - digits: 0-9
+// - uppercase letters: A-Z (normalized to lower)
+// - lowercase letters: a-z
+// - special characters: -_.
+// Uppercase letters are automatically converted to lowercase.
+//
+// Keys beginning with "grpc-" are reserved for grpc-internal use only and may
+// result in errors if set in metadata.
+func New(m map[string]string) MD {
+ md := MD{}
+ for k, val := range m {
+ key := strings.ToLower(k)
+ md[key] = append(md[key], val)
+ }
+ return md
+}
+
+// Pairs returns an MD formed by the mapping of key, value ...
+// Pairs panics if len(kv) is odd.
+//
+// Only the following ASCII characters are allowed in keys:
+// - digits: 0-9
+// - uppercase letters: A-Z (normalized to lower)
+// - lowercase letters: a-z
+// - special characters: -_.
+// Uppercase letters are automatically converted to lowercase.
+//
+// Keys beginning with "grpc-" are reserved for grpc-internal use only and may
+// result in errors if set in metadata.
+func Pairs(kv ...string) MD {
+ if len(kv)%2 == 1 {
+ panic(fmt.Sprintf("metadata: Pairs got the odd number of input pairs for metadata: %d", len(kv)))
+ }
+ md := MD{}
+ var key string
+ for i, s := range kv {
+ if i%2 == 0 {
+ key = strings.ToLower(s)
+ continue
+ }
+ md[key] = append(md[key], s)
+ }
+ return md
+}
+
+// Len returns the number of items in md.
+func (md MD) Len() int {
+ return len(md)
+}
+
+// Copy returns a copy of md.
+func (md MD) Copy() MD {
+ return Join(md)
+}
+
+// Get obtains the values for a given key.
+func (md MD) Get(k string) []string {
+ k = strings.ToLower(k)
+ return md[k]
+}
+
+// Set sets the value of a given key with a slice of values.
+func (md MD) Set(k string, vals ...string) {
+ if len(vals) == 0 {
+ return
+ }
+ k = strings.ToLower(k)
+ md[k] = vals
+}
+
+// Append adds the values to key k, not overwriting what was already stored at that key.
+func (md MD) Append(k string, vals ...string) {
+ if len(vals) == 0 {
+ return
+ }
+ k = strings.ToLower(k)
+ md[k] = append(md[k], vals...)
+}
+
+// Join joins any number of mds into a single MD.
+// The order of values for each key is determined by the order in which
+// the mds containing those values are presented to Join.
+func Join(mds ...MD) MD {
+ out := MD{}
+ for _, md := range mds {
+ for k, v := range md {
+ out[k] = append(out[k], v...)
+ }
+ }
+ return out
+}
+
+type mdIncomingKey struct{}
+type mdOutgoingKey struct{}
+
+// NewIncomingContext creates a new context with incoming md attached.
+func NewIncomingContext(ctx context.Context, md MD) context.Context {
+ return context.WithValue(ctx, mdIncomingKey{}, md)
+}
+
+// NewOutgoingContext creates a new context with outgoing md attached. If used
+// in conjunction with AppendToOutgoingContext, NewOutgoingContext will
+// overwrite any previously-appended metadata.
+func NewOutgoingContext(ctx context.Context, md MD) context.Context {
+ return context.WithValue(ctx, mdOutgoingKey{}, rawMD{md: md})
+}
+
+// AppendToOutgoingContext returns a new context with the provided kv merged
+// with any existing metadata in the context. Please refer to the
+// documentation of Pairs for a description of kv.
+func AppendToOutgoingContext(ctx context.Context, kv ...string) context.Context {
+ if len(kv)%2 == 1 {
+ panic(fmt.Sprintf("metadata: AppendToOutgoingContext got an odd number of input pairs for metadata: %d", len(kv)))
+ }
+ md, _ := ctx.Value(mdOutgoingKey{}).(rawMD)
+ added := make([][]string, len(md.added)+1)
+ copy(added, md.added)
+ added[len(added)-1] = make([]string, len(kv))
+ copy(added[len(added)-1], kv)
+ return context.WithValue(ctx, mdOutgoingKey{}, rawMD{md: md.md, added: added})
+}
+
+// FromIncomingContext returns the incoming metadata in ctx if it exists. The
+// returned MD should not be modified. Writing to it may cause races.
+// Modification should be made to copies of the returned MD.
+func FromIncomingContext(ctx context.Context) (md MD, ok bool) {
+ md, ok = ctx.Value(mdIncomingKey{}).(MD)
+ return
+}
+
+// FromOutgoingContextRaw returns the un-merged, intermediary contents
+// of rawMD. Remember to perform strings.ToLower on the keys. The returned
+// MD should not be modified. Writing to it may cause races. Modification
+// should be made to copies of the returned MD.
+//
+// This is intended for gRPC-internal use ONLY.
+func FromOutgoingContextRaw(ctx context.Context) (MD, [][]string, bool) {
+ raw, ok := ctx.Value(mdOutgoingKey{}).(rawMD)
+ if !ok {
+ return nil, nil, false
+ }
+
+ return raw.md, raw.added, true
+}
+
+// FromOutgoingContext returns the outgoing metadata in ctx if it exists. The
+// returned MD should not be modified. Writing to it may cause races.
+// Modification should be made to copies of the returned MD.
+func FromOutgoingContext(ctx context.Context) (MD, bool) {
+ raw, ok := ctx.Value(mdOutgoingKey{}).(rawMD)
+ if !ok {
+ return nil, false
+ }
+
+ mds := make([]MD, 0, len(raw.added)+1)
+ mds = append(mds, raw.md)
+ for _, vv := range raw.added {
+ mds = append(mds, Pairs(vv...))
+ }
+ return Join(mds...), ok
+}
+
+type rawMD struct {
+ md MD
+ added [][]string
+}
diff --git a/vendor/google.golang.org/grpc/naming/dns_resolver.go b/vendor/google.golang.org/grpc/naming/dns_resolver.go
new file mode 100644
index 000000000..fd8cd3b5a
--- /dev/null
+++ b/vendor/google.golang.org/grpc/naming/dns_resolver.go
@@ -0,0 +1,293 @@
+/*
+ *
+ * Copyright 2017 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package naming
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "net"
+ "strconv"
+ "time"
+
+ "google.golang.org/grpc/grpclog"
+)
+
+const (
+ defaultPort = "443"
+ defaultFreq = time.Minute * 30
+)
+
+var (
+ errMissingAddr = errors.New("missing address")
+ errWatcherClose = errors.New("watcher has been closed")
+
+ lookupHost = net.DefaultResolver.LookupHost
+ lookupSRV = net.DefaultResolver.LookupSRV
+)
+
+// NewDNSResolverWithFreq creates a DNS Resolver that can resolve DNS names, and
+// create watchers that poll the DNS server using the frequency set by freq.
+func NewDNSResolverWithFreq(freq time.Duration) (Resolver, error) {
+ return &dnsResolver{freq: freq}, nil
+}
+
+// NewDNSResolver creates a DNS Resolver that can resolve DNS names, and create
+// watchers that poll the DNS server using the default frequency defined by defaultFreq.
+func NewDNSResolver() (Resolver, error) {
+ return NewDNSResolverWithFreq(defaultFreq)
+}
+
+// dnsResolver handles name resolution for names following the DNS scheme
+type dnsResolver struct {
+ // frequency of polling the DNS server that the watchers created by this resolver will use.
+ freq time.Duration
+}
+
+// formatIP returns ok = false if addr is not a valid textual representation of an IP address.
+// If addr is an IPv4 address, return the addr and ok = true.
+// If addr is an IPv6 address, return the addr enclosed in square brackets and ok = true.
+func formatIP(addr string) (addrIP string, ok bool) {
+ ip := net.ParseIP(addr)
+ if ip == nil {
+ return "", false
+ }
+ if ip.To4() != nil {
+ return addr, true
+ }
+ return "[" + addr + "]", true
+}
+
+// parseTarget takes the user input target string, returns formatted host and port info.
+// If target doesn't specify a port, set the port to be the defaultPort.
+// If target is in IPv6 format and host-name is enclosed in sqarue brackets, brackets
+// are strippd when setting the host.
+// examples:
+// target: "www.google.com" returns host: "www.google.com", port: "443"
+// target: "ipv4-host:80" returns host: "ipv4-host", port: "80"
+// target: "[ipv6-host]" returns host: "ipv6-host", port: "443"
+// target: ":80" returns host: "localhost", port: "80"
+// target: ":" returns host: "localhost", port: "443"
+func parseTarget(target string) (host, port string, err error) {
+ if target == "" {
+ return "", "", errMissingAddr
+ }
+
+ if ip := net.ParseIP(target); ip != nil {
+ // target is an IPv4 or IPv6(without brackets) address
+ return target, defaultPort, nil
+ }
+ if host, port, err := net.SplitHostPort(target); err == nil {
+ // target has port, i.e ipv4-host:port, [ipv6-host]:port, host-name:port
+ if host == "" {
+ // Keep consistent with net.Dial(): If the host is empty, as in ":80", the local system is assumed.
+ host = "localhost"
+ }
+ if port == "" {
+ // If the port field is empty(target ends with colon), e.g. "[::1]:", defaultPort is used.
+ port = defaultPort
+ }
+ return host, port, nil
+ }
+ if host, port, err := net.SplitHostPort(target + ":" + defaultPort); err == nil {
+ // target doesn't have port
+ return host, port, nil
+ }
+ return "", "", fmt.Errorf("invalid target address %v", target)
+}
+
+// Resolve creates a watcher that watches the name resolution of the target.
+func (r *dnsResolver) Resolve(target string) (Watcher, error) {
+ host, port, err := parseTarget(target)
+ if err != nil {
+ return nil, err
+ }
+
+ if net.ParseIP(host) != nil {
+ ipWatcher := &ipWatcher{
+ updateChan: make(chan *Update, 1),
+ }
+ host, _ = formatIP(host)
+ ipWatcher.updateChan <- &Update{Op: Add, Addr: host + ":" + port}
+ return ipWatcher, nil
+ }
+
+ ctx, cancel := context.WithCancel(context.Background())
+ return &dnsWatcher{
+ r: r,
+ host: host,
+ port: port,
+ ctx: ctx,
+ cancel: cancel,
+ t: time.NewTimer(0),
+ }, nil
+}
+
+// dnsWatcher watches for the name resolution update for a specific target
+type dnsWatcher struct {
+ r *dnsResolver
+ host string
+ port string
+ // The latest resolved address set
+ curAddrs map[string]*Update
+ ctx context.Context
+ cancel context.CancelFunc
+ t *time.Timer
+}
+
+// ipWatcher watches for the name resolution update for an IP address.
+type ipWatcher struct {
+ updateChan chan *Update
+}
+
+// Next returns the address resolution Update for the target. For IP address,
+// the resolution is itself, thus polling name server is unnecessary. Therefore,
+// Next() will return an Update the first time it is called, and will be blocked
+// for all following calls as no Update exists until watcher is closed.
+func (i *ipWatcher) Next() ([]*Update, error) {
+ u, ok := <-i.updateChan
+ if !ok {
+ return nil, errWatcherClose
+ }
+ return []*Update{u}, nil
+}
+
+// Close closes the ipWatcher.
+func (i *ipWatcher) Close() {
+ close(i.updateChan)
+}
+
+// AddressType indicates the address type returned by name resolution.
+type AddressType uint8
+
+const (
+ // Backend indicates the server is a backend server.
+ Backend AddressType = iota
+ // GRPCLB indicates the server is a grpclb load balancer.
+ GRPCLB
+)
+
+// AddrMetadataGRPCLB contains the information the name resolver for grpclb should provide. The
+// name resolver used by the grpclb balancer is required to provide this type of metadata in
+// its address updates.
+type AddrMetadataGRPCLB struct {
+ // AddrType is the type of server (grpc load balancer or backend).
+ AddrType AddressType
+ // ServerName is the name of the grpc load balancer. Used for authentication.
+ ServerName string
+}
+
+// compileUpdate compares the old resolved addresses and newly resolved addresses,
+// and generates an update list
+func (w *dnsWatcher) compileUpdate(newAddrs map[string]*Update) []*Update {
+ var res []*Update
+ for a, u := range w.curAddrs {
+ if _, ok := newAddrs[a]; !ok {
+ u.Op = Delete
+ res = append(res, u)
+ }
+ }
+ for a, u := range newAddrs {
+ if _, ok := w.curAddrs[a]; !ok {
+ res = append(res, u)
+ }
+ }
+ return res
+}
+
+func (w *dnsWatcher) lookupSRV() map[string]*Update {
+ newAddrs := make(map[string]*Update)
+ _, srvs, err := lookupSRV(w.ctx, "grpclb", "tcp", w.host)
+ if err != nil {
+ grpclog.Infof("grpc: failed dns SRV record lookup due to %v.\n", err)
+ return nil
+ }
+ for _, s := range srvs {
+ lbAddrs, err := lookupHost(w.ctx, s.Target)
+ if err != nil {
+ grpclog.Warningf("grpc: failed load banlacer address dns lookup due to %v.\n", err)
+ continue
+ }
+ for _, a := range lbAddrs {
+ a, ok := formatIP(a)
+ if !ok {
+ grpclog.Errorf("grpc: failed IP parsing due to %v.\n", err)
+ continue
+ }
+ addr := a + ":" + strconv.Itoa(int(s.Port))
+ newAddrs[addr] = &Update{Addr: addr,
+ Metadata: AddrMetadataGRPCLB{AddrType: GRPCLB, ServerName: s.Target}}
+ }
+ }
+ return newAddrs
+}
+
+func (w *dnsWatcher) lookupHost() map[string]*Update {
+ newAddrs := make(map[string]*Update)
+ addrs, err := lookupHost(w.ctx, w.host)
+ if err != nil {
+ grpclog.Warningf("grpc: failed dns A record lookup due to %v.\n", err)
+ return nil
+ }
+ for _, a := range addrs {
+ a, ok := formatIP(a)
+ if !ok {
+ grpclog.Errorf("grpc: failed IP parsing due to %v.\n", err)
+ continue
+ }
+ addr := a + ":" + w.port
+ newAddrs[addr] = &Update{Addr: addr}
+ }
+ return newAddrs
+}
+
+func (w *dnsWatcher) lookup() []*Update {
+ newAddrs := w.lookupSRV()
+ if newAddrs == nil {
+ // If failed to get any balancer address (either no corresponding SRV for the
+ // target, or caused by failure during resolution/parsing of the balancer target),
+ // return any A record info available.
+ newAddrs = w.lookupHost()
+ }
+ result := w.compileUpdate(newAddrs)
+ w.curAddrs = newAddrs
+ return result
+}
+
+// Next returns the resolved address update(delta) for the target. If there's no
+// change, it will sleep for 30 mins and try to resolve again after that.
+func (w *dnsWatcher) Next() ([]*Update, error) {
+ for {
+ select {
+ case <-w.ctx.Done():
+ return nil, errWatcherClose
+ case <-w.t.C:
+ }
+ result := w.lookup()
+ // Next lookup should happen after an interval defined by w.r.freq.
+ w.t.Reset(w.r.freq)
+ if len(result) > 0 {
+ return result, nil
+ }
+ }
+}
+
+func (w *dnsWatcher) Close() {
+ w.cancel()
+}
diff --git a/vendor/google.golang.org/grpc/naming/naming.go b/vendor/google.golang.org/grpc/naming/naming.go
new file mode 100644
index 000000000..8cc39e937
--- /dev/null
+++ b/vendor/google.golang.org/grpc/naming/naming.go
@@ -0,0 +1,69 @@
+/*
+ *
+ * Copyright 2014 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// Package naming defines the naming API and related data structures for gRPC.
+// The interface is EXPERIMENTAL and may be suject to change.
+//
+// Deprecated: please use package resolver.
+package naming
+
+// Operation defines the corresponding operations for a name resolution change.
+//
+// Deprecated: please use package resolver.
+type Operation uint8
+
+const (
+ // Add indicates a new address is added.
+ Add Operation = iota
+ // Delete indicates an existing address is deleted.
+ Delete
+)
+
+// Update defines a name resolution update. Notice that it is not valid having both
+// empty string Addr and nil Metadata in an Update.
+//
+// Deprecated: please use package resolver.
+type Update struct {
+ // Op indicates the operation of the update.
+ Op Operation
+ // Addr is the updated address. It is empty string if there is no address update.
+ Addr string
+ // Metadata is the updated metadata. It is nil if there is no metadata update.
+ // Metadata is not required for a custom naming implementation.
+ Metadata interface{}
+}
+
+// Resolver creates a Watcher for a target to track its resolution changes.
+//
+// Deprecated: please use package resolver.
+type Resolver interface {
+ // Resolve creates a Watcher for target.
+ Resolve(target string) (Watcher, error)
+}
+
+// Watcher watches for the updates on the specified target.
+//
+// Deprecated: please use package resolver.
+type Watcher interface {
+ // Next blocks until an update or error happens. It may return one or more
+ // updates. The first call should get the full set of the results. It should
+ // return an error if and only if Watcher cannot recover.
+ Next() ([]*Update, error)
+ // Close closes the Watcher.
+ Close()
+}
diff --git a/vendor/google.golang.org/grpc/peer/peer.go b/vendor/google.golang.org/grpc/peer/peer.go
new file mode 100644
index 000000000..e01d219ff
--- /dev/null
+++ b/vendor/google.golang.org/grpc/peer/peer.go
@@ -0,0 +1,51 @@
+/*
+ *
+ * Copyright 2014 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// Package peer defines various peer information associated with RPCs and
+// corresponding utils.
+package peer
+
+import (
+ "context"
+ "net"
+
+ "google.golang.org/grpc/credentials"
+)
+
+// Peer contains the information of the peer for an RPC, such as the address
+// and authentication information.
+type Peer struct {
+ // Addr is the peer address.
+ Addr net.Addr
+ // AuthInfo is the authentication information of the transport.
+ // It is nil if there is no transport security being used.
+ AuthInfo credentials.AuthInfo
+}
+
+type peerKey struct{}
+
+// NewContext creates a new context with peer information attached.
+func NewContext(ctx context.Context, p *Peer) context.Context {
+ return context.WithValue(ctx, peerKey{}, p)
+}
+
+// FromContext returns the peer information in ctx if it exists.
+func FromContext(ctx context.Context) (p *Peer, ok bool) {
+ p, ok = ctx.Value(peerKey{}).(*Peer)
+ return
+}
diff --git a/vendor/google.golang.org/grpc/picker_wrapper.go b/vendor/google.golang.org/grpc/picker_wrapper.go
new file mode 100644
index 000000000..14f915d67
--- /dev/null
+++ b/vendor/google.golang.org/grpc/picker_wrapper.go
@@ -0,0 +1,180 @@
+/*
+ *
+ * Copyright 2017 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package grpc
+
+import (
+ "context"
+ "io"
+ "sync"
+
+ "google.golang.org/grpc/balancer"
+ "google.golang.org/grpc/codes"
+ "google.golang.org/grpc/grpclog"
+ "google.golang.org/grpc/internal/channelz"
+ "google.golang.org/grpc/internal/transport"
+ "google.golang.org/grpc/status"
+)
+
+// pickerWrapper is a wrapper of balancer.Picker. It blocks on certain pick
+// actions and unblock when there's a picker update.
+type pickerWrapper struct {
+ mu sync.Mutex
+ done bool
+ blockingCh chan struct{}
+ picker balancer.Picker
+
+ // The latest connection happened.
+ connErrMu sync.Mutex
+ connErr error
+}
+
+func newPickerWrapper() *pickerWrapper {
+ bp := &pickerWrapper{blockingCh: make(chan struct{})}
+ return bp
+}
+
+func (bp *pickerWrapper) updateConnectionError(err error) {
+ bp.connErrMu.Lock()
+ bp.connErr = err
+ bp.connErrMu.Unlock()
+}
+
+func (bp *pickerWrapper) connectionError() error {
+ bp.connErrMu.Lock()
+ err := bp.connErr
+ bp.connErrMu.Unlock()
+ return err
+}
+
+// updatePicker is called by UpdateBalancerState. It unblocks all blocked pick.
+func (bp *pickerWrapper) updatePicker(p balancer.Picker) {
+ bp.mu.Lock()
+ if bp.done {
+ bp.mu.Unlock()
+ return
+ }
+ bp.picker = p
+ // bp.blockingCh should never be nil.
+ close(bp.blockingCh)
+ bp.blockingCh = make(chan struct{})
+ bp.mu.Unlock()
+}
+
+func doneChannelzWrapper(acw *acBalancerWrapper, done func(balancer.DoneInfo)) func(balancer.DoneInfo) {
+ acw.mu.Lock()
+ ac := acw.ac
+ acw.mu.Unlock()
+ ac.incrCallsStarted()
+ return func(b balancer.DoneInfo) {
+ if b.Err != nil && b.Err != io.EOF {
+ ac.incrCallsFailed()
+ } else {
+ ac.incrCallsSucceeded()
+ }
+ if done != nil {
+ done(b)
+ }
+ }
+}
+
+// pick returns the transport that will be used for the RPC.
+// It may block in the following cases:
+// - there's no picker
+// - the current picker returns ErrNoSubConnAvailable
+// - the current picker returns other errors and failfast is false.
+// - the subConn returned by the current picker is not READY
+// When one of these situations happens, pick blocks until the picker gets updated.
+func (bp *pickerWrapper) pick(ctx context.Context, failfast bool, opts balancer.PickOptions) (transport.ClientTransport, func(balancer.DoneInfo), error) {
+ var (
+ p balancer.Picker
+ ch chan struct{}
+ )
+
+ for {
+ bp.mu.Lock()
+ if bp.done {
+ bp.mu.Unlock()
+ return nil, nil, ErrClientConnClosing
+ }
+
+ if bp.picker == nil {
+ ch = bp.blockingCh
+ }
+ if ch == bp.blockingCh {
+ // This could happen when either:
+ // - bp.picker is nil (the previous if condition), or
+ // - has called pick on the current picker.
+ bp.mu.Unlock()
+ select {
+ case <-ctx.Done():
+ return nil, nil, ctx.Err()
+ case <-ch:
+ }
+ continue
+ }
+
+ ch = bp.blockingCh
+ p = bp.picker
+ bp.mu.Unlock()
+
+ subConn, done, err := p.Pick(ctx, opts)
+
+ if err != nil {
+ switch err {
+ case balancer.ErrNoSubConnAvailable:
+ continue
+ case balancer.ErrTransientFailure:
+ if !failfast {
+ continue
+ }
+ return nil, nil, status.Errorf(codes.Unavailable, "%v, latest connection error: %v", err, bp.connectionError())
+ default:
+ // err is some other error.
+ return nil, nil, toRPCErr(err)
+ }
+ }
+
+ acw, ok := subConn.(*acBalancerWrapper)
+ if !ok {
+ grpclog.Infof("subconn returned from pick is not *acBalancerWrapper")
+ continue
+ }
+ if t, ok := acw.getAddrConn().getReadyTransport(); ok {
+ if channelz.IsOn() {
+ return t, doneChannelzWrapper(acw, done), nil
+ }
+ return t, done, nil
+ }
+ grpclog.Infof("blockingPicker: the picked transport is not ready, loop back to repick")
+ // If ok == false, ac.state is not READY.
+ // A valid picker always returns READY subConn. This means the state of ac
+ // just changed, and picker will be updated shortly.
+ // continue back to the beginning of the for loop to repick.
+ }
+}
+
+func (bp *pickerWrapper) close() {
+ bp.mu.Lock()
+ defer bp.mu.Unlock()
+ if bp.done {
+ return
+ }
+ bp.done = true
+ close(bp.blockingCh)
+}
diff --git a/vendor/google.golang.org/grpc/pickfirst.go b/vendor/google.golang.org/grpc/pickfirst.go
new file mode 100644
index 000000000..d1e38aad7
--- /dev/null
+++ b/vendor/google.golang.org/grpc/pickfirst.go
@@ -0,0 +1,110 @@
+/*
+ *
+ * Copyright 2017 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package grpc
+
+import (
+ "context"
+
+ "google.golang.org/grpc/balancer"
+ "google.golang.org/grpc/connectivity"
+ "google.golang.org/grpc/grpclog"
+ "google.golang.org/grpc/resolver"
+)
+
+// PickFirstBalancerName is the name of the pick_first balancer.
+const PickFirstBalancerName = "pick_first"
+
+func newPickfirstBuilder() balancer.Builder {
+ return &pickfirstBuilder{}
+}
+
+type pickfirstBuilder struct{}
+
+func (*pickfirstBuilder) Build(cc balancer.ClientConn, opt balancer.BuildOptions) balancer.Balancer {
+ return &pickfirstBalancer{cc: cc}
+}
+
+func (*pickfirstBuilder) Name() string {
+ return PickFirstBalancerName
+}
+
+type pickfirstBalancer struct {
+ cc balancer.ClientConn
+ sc balancer.SubConn
+}
+
+func (b *pickfirstBalancer) HandleResolvedAddrs(addrs []resolver.Address, err error) {
+ if err != nil {
+ grpclog.Infof("pickfirstBalancer: HandleResolvedAddrs called with error %v", err)
+ return
+ }
+ if b.sc == nil {
+ b.sc, err = b.cc.NewSubConn(addrs, balancer.NewSubConnOptions{})
+ if err != nil {
+ //TODO(yuxuanli): why not change the cc state to Idle?
+ grpclog.Errorf("pickfirstBalancer: failed to NewSubConn: %v", err)
+ return
+ }
+ b.cc.UpdateBalancerState(connectivity.Idle, &picker{sc: b.sc})
+ b.sc.Connect()
+ } else {
+ b.sc.UpdateAddresses(addrs)
+ b.sc.Connect()
+ }
+}
+
+func (b *pickfirstBalancer) HandleSubConnStateChange(sc balancer.SubConn, s connectivity.State) {
+ grpclog.Infof("pickfirstBalancer: HandleSubConnStateChange: %p, %v", sc, s)
+ if b.sc != sc {
+ grpclog.Infof("pickfirstBalancer: ignored state change because sc is not recognized")
+ return
+ }
+ if s == connectivity.Shutdown {
+ b.sc = nil
+ return
+ }
+
+ switch s {
+ case connectivity.Ready, connectivity.Idle:
+ b.cc.UpdateBalancerState(s, &picker{sc: sc})
+ case connectivity.Connecting:
+ b.cc.UpdateBalancerState(s, &picker{err: balancer.ErrNoSubConnAvailable})
+ case connectivity.TransientFailure:
+ b.cc.UpdateBalancerState(s, &picker{err: balancer.ErrTransientFailure})
+ }
+}
+
+func (b *pickfirstBalancer) Close() {
+}
+
+type picker struct {
+ err error
+ sc balancer.SubConn
+}
+
+func (p *picker) Pick(ctx context.Context, opts balancer.PickOptions) (balancer.SubConn, func(balancer.DoneInfo), error) {
+ if p.err != nil {
+ return nil, nil, p.err
+ }
+ return p.sc, nil, nil
+}
+
+func init() {
+ balancer.Register(newPickfirstBuilder())
+}
diff --git a/vendor/google.golang.org/grpc/proxy.go b/vendor/google.golang.org/grpc/proxy.go
new file mode 100644
index 000000000..f8f69bfb7
--- /dev/null
+++ b/vendor/google.golang.org/grpc/proxy.go
@@ -0,0 +1,152 @@
+/*
+ *
+ * Copyright 2017 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package grpc
+
+import (
+ "bufio"
+ "context"
+ "encoding/base64"
+ "errors"
+ "fmt"
+ "io"
+ "net"
+ "net/http"
+ "net/http/httputil"
+ "net/url"
+)
+
+const proxyAuthHeaderKey = "Proxy-Authorization"
+
+var (
+ // errDisabled indicates that proxy is disabled for the address.
+ errDisabled = errors.New("proxy is disabled for the address")
+ // The following variable will be overwritten in the tests.
+ httpProxyFromEnvironment = http.ProxyFromEnvironment
+)
+
+func mapAddress(ctx context.Context, address string) (*url.URL, error) {
+ req := &http.Request{
+ URL: &url.URL{
+ Scheme: "https",
+ Host: address,
+ },
+ }
+ url, err := httpProxyFromEnvironment(req)
+ if err != nil {
+ return nil, err
+ }
+ if url == nil {
+ return nil, errDisabled
+ }
+ return url, nil
+}
+
+// To read a response from a net.Conn, http.ReadResponse() takes a bufio.Reader.
+// It's possible that this reader reads more than what's need for the response and stores
+// those bytes in the buffer.
+// bufConn wraps the original net.Conn and the bufio.Reader to make sure we don't lose the
+// bytes in the buffer.
+type bufConn struct {
+ net.Conn
+ r io.Reader
+}
+
+func (c *bufConn) Read(b []byte) (int, error) {
+ return c.r.Read(b)
+}
+
+func basicAuth(username, password string) string {
+ auth := username + ":" + password
+ return base64.StdEncoding.EncodeToString([]byte(auth))
+}
+
+func doHTTPConnectHandshake(ctx context.Context, conn net.Conn, backendAddr string, proxyURL *url.URL) (_ net.Conn, err error) {
+ defer func() {
+ if err != nil {
+ conn.Close()
+ }
+ }()
+
+ req := &http.Request{
+ Method: http.MethodConnect,
+ URL: &url.URL{Host: backendAddr},
+ Header: map[string][]string{"User-Agent": {grpcUA}},
+ }
+ if t := proxyURL.User; t != nil {
+ u := t.Username()
+ p, _ := t.Password()
+ req.Header.Add(proxyAuthHeaderKey, "Basic "+basicAuth(u, p))
+ }
+
+ if err := sendHTTPRequest(ctx, req, conn); err != nil {
+ return nil, fmt.Errorf("failed to write the HTTP request: %v", err)
+ }
+
+ r := bufio.NewReader(conn)
+ resp, err := http.ReadResponse(r, req)
+ if err != nil {
+ return nil, fmt.Errorf("reading server HTTP response: %v", err)
+ }
+ defer resp.Body.Close()
+ if resp.StatusCode != http.StatusOK {
+ dump, err := httputil.DumpResponse(resp, true)
+ if err != nil {
+ return nil, fmt.Errorf("failed to do connect handshake, status code: %s", resp.Status)
+ }
+ return nil, fmt.Errorf("failed to do connect handshake, response: %q", dump)
+ }
+
+ return &bufConn{Conn: conn, r: r}, nil
+}
+
+// newProxyDialer returns a dialer that connects to proxy first if necessary.
+// The returned dialer checks if a proxy is necessary, dial to the proxy with the
+// provided dialer, does HTTP CONNECT handshake and returns the connection.
+func newProxyDialer(dialer func(context.Context, string) (net.Conn, error)) func(context.Context, string) (net.Conn, error) {
+ return func(ctx context.Context, addr string) (conn net.Conn, err error) {
+ var newAddr string
+ proxyURL, err := mapAddress(ctx, addr)
+ if err != nil {
+ if err != errDisabled {
+ return nil, err
+ }
+ newAddr = addr
+ } else {
+ newAddr = proxyURL.Host
+ }
+
+ conn, err = dialer(ctx, newAddr)
+ if err != nil {
+ return
+ }
+ if proxyURL != nil {
+ // proxy is disabled if proxyURL is nil.
+ conn, err = doHTTPConnectHandshake(ctx, conn, addr, proxyURL)
+ }
+ return
+ }
+}
+
+func sendHTTPRequest(ctx context.Context, req *http.Request, conn net.Conn) error {
+ req = req.WithContext(ctx)
+ if err := req.Write(conn); err != nil {
+ return fmt.Errorf("failed to write the HTTP request: %v", err)
+ }
+ return nil
+}
diff --git a/vendor/google.golang.org/grpc/resolver/dns/dns_resolver.go b/vendor/google.golang.org/grpc/resolver/dns/dns_resolver.go
new file mode 100644
index 000000000..f33189fed
--- /dev/null
+++ b/vendor/google.golang.org/grpc/resolver/dns/dns_resolver.go
@@ -0,0 +1,436 @@
+/*
+ *
+ * Copyright 2018 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// Package dns implements a dns resolver to be installed as the default resolver
+// in grpc.
+package dns
+
+import (
+ "context"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "net"
+ "os"
+ "strconv"
+ "strings"
+ "sync"
+ "time"
+
+ "google.golang.org/grpc/grpclog"
+ "google.golang.org/grpc/internal/backoff"
+ "google.golang.org/grpc/internal/grpcrand"
+ "google.golang.org/grpc/resolver"
+)
+
+func init() {
+ resolver.Register(NewBuilder())
+}
+
+const (
+ defaultPort = "443"
+ defaultFreq = time.Minute * 30
+ defaultDNSSvrPort = "53"
+ golang = "GO"
+ // In DNS, service config is encoded in a TXT record via the mechanism
+ // described in RFC-1464 using the attribute name grpc_config.
+ txtAttribute = "grpc_config="
+)
+
+var (
+ errMissingAddr = errors.New("dns resolver: missing address")
+
+ // Addresses ending with a colon that is supposed to be the separator
+ // between host and port is not allowed. E.g. "::" is a valid address as
+ // it is an IPv6 address (host only) and "[::]:" is invalid as it ends with
+ // a colon as the host and port separator
+ errEndsWithColon = errors.New("dns resolver: missing port after port-separator colon")
+)
+
+var (
+ defaultResolver netResolver = net.DefaultResolver
+)
+
+var customAuthorityDialler = func(authority string) func(ctx context.Context, network, address string) (net.Conn, error) {
+ return func(ctx context.Context, network, address string) (net.Conn, error) {
+ var dialer net.Dialer
+ return dialer.DialContext(ctx, network, authority)
+ }
+}
+
+var customAuthorityResolver = func(authority string) (netResolver, error) {
+ host, port, err := parseTarget(authority, defaultDNSSvrPort)
+ if err != nil {
+ return nil, err
+ }
+
+ authorityWithPort := net.JoinHostPort(host, port)
+
+ return &net.Resolver{
+ PreferGo: true,
+ Dial: customAuthorityDialler(authorityWithPort),
+ }, nil
+}
+
+// NewBuilder creates a dnsBuilder which is used to factory DNS resolvers.
+func NewBuilder() resolver.Builder {
+ return &dnsBuilder{minFreq: defaultFreq}
+}
+
+type dnsBuilder struct {
+ // minimum frequency of polling the DNS server.
+ minFreq time.Duration
+}
+
+// Build creates and starts a DNS resolver that watches the name resolution of the target.
+func (b *dnsBuilder) Build(target resolver.Target, cc resolver.ClientConn, opts resolver.BuildOption) (resolver.Resolver, error) {
+ host, port, err := parseTarget(target.Endpoint, defaultPort)
+ if err != nil {
+ return nil, err
+ }
+
+ // IP address.
+ if net.ParseIP(host) != nil {
+ host, _ = formatIP(host)
+ addr := []resolver.Address{{Addr: host + ":" + port}}
+ i := &ipResolver{
+ cc: cc,
+ ip: addr,
+ rn: make(chan struct{}, 1),
+ q: make(chan struct{}),
+ }
+ cc.NewAddress(addr)
+ go i.watcher()
+ return i, nil
+ }
+
+ // DNS address (non-IP).
+ ctx, cancel := context.WithCancel(context.Background())
+ d := &dnsResolver{
+ freq: b.minFreq,
+ backoff: backoff.Exponential{MaxDelay: b.minFreq},
+ host: host,
+ port: port,
+ ctx: ctx,
+ cancel: cancel,
+ cc: cc,
+ t: time.NewTimer(0),
+ rn: make(chan struct{}, 1),
+ disableServiceConfig: opts.DisableServiceConfig,
+ }
+
+ if target.Authority == "" {
+ d.resolver = defaultResolver
+ } else {
+ d.resolver, err = customAuthorityResolver(target.Authority)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ d.wg.Add(1)
+ go d.watcher()
+ return d, nil
+}
+
+// Scheme returns the naming scheme of this resolver builder, which is "dns".
+func (b *dnsBuilder) Scheme() string {
+ return "dns"
+}
+
+type netResolver interface {
+ LookupHost(ctx context.Context, host string) (addrs []string, err error)
+ LookupSRV(ctx context.Context, service, proto, name string) (cname string, addrs []*net.SRV, err error)
+ LookupTXT(ctx context.Context, name string) (txts []string, err error)
+}
+
+// ipResolver watches for the name resolution update for an IP address.
+type ipResolver struct {
+ cc resolver.ClientConn
+ ip []resolver.Address
+ // rn channel is used by ResolveNow() to force an immediate resolution of the target.
+ rn chan struct{}
+ q chan struct{}
+}
+
+// ResolveNow resend the address it stores, no resolution is needed.
+func (i *ipResolver) ResolveNow(opt resolver.ResolveNowOption) {
+ select {
+ case i.rn <- struct{}{}:
+ default:
+ }
+}
+
+// Close closes the ipResolver.
+func (i *ipResolver) Close() {
+ close(i.q)
+}
+
+func (i *ipResolver) watcher() {
+ for {
+ select {
+ case <-i.rn:
+ i.cc.NewAddress(i.ip)
+ case <-i.q:
+ return
+ }
+ }
+}
+
+// dnsResolver watches for the name resolution update for a non-IP target.
+type dnsResolver struct {
+ freq time.Duration
+ backoff backoff.Exponential
+ retryCount int
+ host string
+ port string
+ resolver netResolver
+ ctx context.Context
+ cancel context.CancelFunc
+ cc resolver.ClientConn
+ // rn channel is used by ResolveNow() to force an immediate resolution of the target.
+ rn chan struct{}
+ t *time.Timer
+ // wg is used to enforce Close() to return after the watcher() goroutine has finished.
+ // Otherwise, data race will be possible. [Race Example] in dns_resolver_test we
+ // replace the real lookup functions with mocked ones to facilitate testing.
+ // If Close() doesn't wait for watcher() goroutine finishes, race detector sometimes
+ // will warns lookup (READ the lookup function pointers) inside watcher() goroutine
+ // has data race with replaceNetFunc (WRITE the lookup function pointers).
+ wg sync.WaitGroup
+ disableServiceConfig bool
+}
+
+// ResolveNow invoke an immediate resolution of the target that this dnsResolver watches.
+func (d *dnsResolver) ResolveNow(opt resolver.ResolveNowOption) {
+ select {
+ case d.rn <- struct{}{}:
+ default:
+ }
+}
+
+// Close closes the dnsResolver.
+func (d *dnsResolver) Close() {
+ d.cancel()
+ d.wg.Wait()
+ d.t.Stop()
+}
+
+func (d *dnsResolver) watcher() {
+ defer d.wg.Done()
+ for {
+ select {
+ case <-d.ctx.Done():
+ return
+ case <-d.t.C:
+ case <-d.rn:
+ }
+ result, sc := d.lookup()
+ // Next lookup should happen within an interval defined by d.freq. It may be
+ // more often due to exponential retry on empty address list.
+ if len(result) == 0 {
+ d.retryCount++
+ d.t.Reset(d.backoff.Backoff(d.retryCount))
+ } else {
+ d.retryCount = 0
+ d.t.Reset(d.freq)
+ }
+ d.cc.NewServiceConfig(sc)
+ d.cc.NewAddress(result)
+ }
+}
+
+func (d *dnsResolver) lookupSRV() []resolver.Address {
+ var newAddrs []resolver.Address
+ _, srvs, err := d.resolver.LookupSRV(d.ctx, "grpclb", "tcp", d.host)
+ if err != nil {
+ grpclog.Infof("grpc: failed dns SRV record lookup due to %v.\n", err)
+ return nil
+ }
+ for _, s := range srvs {
+ lbAddrs, err := d.resolver.LookupHost(d.ctx, s.Target)
+ if err != nil {
+ grpclog.Infof("grpc: failed load balancer address dns lookup due to %v.\n", err)
+ continue
+ }
+ for _, a := range lbAddrs {
+ a, ok := formatIP(a)
+ if !ok {
+ grpclog.Errorf("grpc: failed IP parsing due to %v.\n", err)
+ continue
+ }
+ addr := a + ":" + strconv.Itoa(int(s.Port))
+ newAddrs = append(newAddrs, resolver.Address{Addr: addr, Type: resolver.GRPCLB, ServerName: s.Target})
+ }
+ }
+ return newAddrs
+}
+
+func (d *dnsResolver) lookupTXT() string {
+ ss, err := d.resolver.LookupTXT(d.ctx, d.host)
+ if err != nil {
+ grpclog.Infof("grpc: failed dns TXT record lookup due to %v.\n", err)
+ return ""
+ }
+ var res string
+ for _, s := range ss {
+ res += s
+ }
+
+ // TXT record must have "grpc_config=" attribute in order to be used as service config.
+ if !strings.HasPrefix(res, txtAttribute) {
+ grpclog.Warningf("grpc: TXT record %v missing %v attribute", res, txtAttribute)
+ return ""
+ }
+ return strings.TrimPrefix(res, txtAttribute)
+}
+
+func (d *dnsResolver) lookupHost() []resolver.Address {
+ var newAddrs []resolver.Address
+ addrs, err := d.resolver.LookupHost(d.ctx, d.host)
+ if err != nil {
+ grpclog.Warningf("grpc: failed dns A record lookup due to %v.\n", err)
+ return nil
+ }
+ for _, a := range addrs {
+ a, ok := formatIP(a)
+ if !ok {
+ grpclog.Errorf("grpc: failed IP parsing due to %v.\n", err)
+ continue
+ }
+ addr := a + ":" + d.port
+ newAddrs = append(newAddrs, resolver.Address{Addr: addr})
+ }
+ return newAddrs
+}
+
+func (d *dnsResolver) lookup() ([]resolver.Address, string) {
+ newAddrs := d.lookupSRV()
+ // Support fallback to non-balancer address.
+ newAddrs = append(newAddrs, d.lookupHost()...)
+ if d.disableServiceConfig {
+ return newAddrs, ""
+ }
+ sc := d.lookupTXT()
+ return newAddrs, canaryingSC(sc)
+}
+
+// formatIP returns ok = false if addr is not a valid textual representation of an IP address.
+// If addr is an IPv4 address, return the addr and ok = true.
+// If addr is an IPv6 address, return the addr enclosed in square brackets and ok = true.
+func formatIP(addr string) (addrIP string, ok bool) {
+ ip := net.ParseIP(addr)
+ if ip == nil {
+ return "", false
+ }
+ if ip.To4() != nil {
+ return addr, true
+ }
+ return "[" + addr + "]", true
+}
+
+// parseTarget takes the user input target string and default port, returns formatted host and port info.
+// If target doesn't specify a port, set the port to be the defaultPort.
+// If target is in IPv6 format and host-name is enclosed in sqarue brackets, brackets
+// are strippd when setting the host.
+// examples:
+// target: "www.google.com" defaultPort: "443" returns host: "www.google.com", port: "443"
+// target: "ipv4-host:80" defaultPort: "443" returns host: "ipv4-host", port: "80"
+// target: "[ipv6-host]" defaultPort: "443" returns host: "ipv6-host", port: "443"
+// target: ":80" defaultPort: "443" returns host: "localhost", port: "80"
+func parseTarget(target, defaultPort string) (host, port string, err error) {
+ if target == "" {
+ return "", "", errMissingAddr
+ }
+ if ip := net.ParseIP(target); ip != nil {
+ // target is an IPv4 or IPv6(without brackets) address
+ return target, defaultPort, nil
+ }
+ if host, port, err = net.SplitHostPort(target); err == nil {
+ if port == "" {
+ // If the port field is empty (target ends with colon), e.g. "[::1]:", this is an error.
+ return "", "", errEndsWithColon
+ }
+ // target has port, i.e ipv4-host:port, [ipv6-host]:port, host-name:port
+ if host == "" {
+ // Keep consistent with net.Dial(): If the host is empty, as in ":80", the local system is assumed.
+ host = "localhost"
+ }
+ return host, port, nil
+ }
+ if host, port, err = net.SplitHostPort(target + ":" + defaultPort); err == nil {
+ // target doesn't have port
+ return host, port, nil
+ }
+ return "", "", fmt.Errorf("invalid target address %v, error info: %v", target, err)
+}
+
+type rawChoice struct {
+ ClientLanguage *[]string `json:"clientLanguage,omitempty"`
+ Percentage *int `json:"percentage,omitempty"`
+ ClientHostName *[]string `json:"clientHostName,omitempty"`
+ ServiceConfig *json.RawMessage `json:"serviceConfig,omitempty"`
+}
+
+func containsString(a *[]string, b string) bool {
+ if a == nil {
+ return true
+ }
+ for _, c := range *a {
+ if c == b {
+ return true
+ }
+ }
+ return false
+}
+
+func chosenByPercentage(a *int) bool {
+ if a == nil {
+ return true
+ }
+ return grpcrand.Intn(100)+1 <= *a
+}
+
+func canaryingSC(js string) string {
+ if js == "" {
+ return ""
+ }
+ var rcs []rawChoice
+ err := json.Unmarshal([]byte(js), &rcs)
+ if err != nil {
+ grpclog.Warningf("grpc: failed to parse service config json string due to %v.\n", err)
+ return ""
+ }
+ cliHostname, err := os.Hostname()
+ if err != nil {
+ grpclog.Warningf("grpc: failed to get client hostname due to %v.\n", err)
+ return ""
+ }
+ var sc string
+ for _, c := range rcs {
+ if !containsString(c.ClientLanguage, golang) ||
+ !chosenByPercentage(c.Percentage) ||
+ !containsString(c.ClientHostName, cliHostname) ||
+ c.ServiceConfig == nil {
+ continue
+ }
+ sc = string(*c.ServiceConfig)
+ break
+ }
+ return sc
+}
diff --git a/vendor/google.golang.org/grpc/resolver/passthrough/passthrough.go b/vendor/google.golang.org/grpc/resolver/passthrough/passthrough.go
new file mode 100644
index 000000000..b76010d74
--- /dev/null
+++ b/vendor/google.golang.org/grpc/resolver/passthrough/passthrough.go
@@ -0,0 +1,57 @@
+/*
+ *
+ * Copyright 2017 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// Package passthrough implements a pass-through resolver. It sends the target
+// name without scheme back to gRPC as resolved address.
+package passthrough
+
+import "google.golang.org/grpc/resolver"
+
+const scheme = "passthrough"
+
+type passthroughBuilder struct{}
+
+func (*passthroughBuilder) Build(target resolver.Target, cc resolver.ClientConn, opts resolver.BuildOption) (resolver.Resolver, error) {
+ r := &passthroughResolver{
+ target: target,
+ cc: cc,
+ }
+ r.start()
+ return r, nil
+}
+
+func (*passthroughBuilder) Scheme() string {
+ return scheme
+}
+
+type passthroughResolver struct {
+ target resolver.Target
+ cc resolver.ClientConn
+}
+
+func (r *passthroughResolver) start() {
+ r.cc.NewAddress([]resolver.Address{{Addr: r.target.Endpoint}})
+}
+
+func (*passthroughResolver) ResolveNow(o resolver.ResolveNowOption) {}
+
+func (*passthroughResolver) Close() {}
+
+func init() {
+ resolver.Register(&passthroughBuilder{})
+}
diff --git a/vendor/google.golang.org/grpc/resolver/resolver.go b/vendor/google.golang.org/grpc/resolver/resolver.go
new file mode 100644
index 000000000..145cf477e
--- /dev/null
+++ b/vendor/google.golang.org/grpc/resolver/resolver.go
@@ -0,0 +1,158 @@
+/*
+ *
+ * Copyright 2017 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// Package resolver defines APIs for name resolution in gRPC.
+// All APIs in this package are experimental.
+package resolver
+
+var (
+ // m is a map from scheme to resolver builder.
+ m = make(map[string]Builder)
+ // defaultScheme is the default scheme to use.
+ defaultScheme = "passthrough"
+)
+
+// TODO(bar) install dns resolver in init(){}.
+
+// Register registers the resolver builder to the resolver map. b.Scheme will be
+// used as the scheme registered with this builder.
+//
+// NOTE: this function must only be called during initialization time (i.e. in
+// an init() function), and is not thread-safe. If multiple Resolvers are
+// registered with the same name, the one registered last will take effect.
+func Register(b Builder) {
+ m[b.Scheme()] = b
+}
+
+// Get returns the resolver builder registered with the given scheme.
+//
+// If no builder is register with the scheme, nil will be returned.
+func Get(scheme string) Builder {
+ if b, ok := m[scheme]; ok {
+ return b
+ }
+ return nil
+}
+
+// SetDefaultScheme sets the default scheme that will be used. The default
+// default scheme is "passthrough".
+//
+// NOTE: this function must only be called during initialization time (i.e. in
+// an init() function), and is not thread-safe. The scheme set last overrides
+// previously set values.
+func SetDefaultScheme(scheme string) {
+ defaultScheme = scheme
+}
+
+// GetDefaultScheme gets the default scheme that will be used.
+func GetDefaultScheme() string {
+ return defaultScheme
+}
+
+// AddressType indicates the address type returned by name resolution.
+type AddressType uint8
+
+const (
+ // Backend indicates the address is for a backend server.
+ Backend AddressType = iota
+ // GRPCLB indicates the address is for a grpclb load balancer.
+ GRPCLB
+)
+
+// Address represents a server the client connects to.
+// This is the EXPERIMENTAL API and may be changed or extended in the future.
+type Address struct {
+ // Addr is the server address on which a connection will be established.
+ Addr string
+ // Type is the type of this address.
+ Type AddressType
+ // ServerName is the name of this address.
+ //
+ // e.g. if Type is GRPCLB, ServerName should be the name of the remote load
+ // balancer, not the name of the backend.
+ ServerName string
+ // Metadata is the information associated with Addr, which may be used
+ // to make load balancing decision.
+ Metadata interface{}
+}
+
+// BuildOption includes additional information for the builder to create
+// the resolver.
+type BuildOption struct {
+ // DisableServiceConfig indicates whether resolver should fetch service config data.
+ DisableServiceConfig bool
+}
+
+// ClientConn contains the callbacks for resolver to notify any updates
+// to the gRPC ClientConn.
+//
+// This interface is to be implemented by gRPC. Users should not need a
+// brand new implementation of this interface. For the situations like
+// testing, the new implementation should embed this interface. This allows
+// gRPC to add new methods to this interface.
+type ClientConn interface {
+ // NewAddress is called by resolver to notify ClientConn a new list
+ // of resolved addresses.
+ // The address list should be the complete list of resolved addresses.
+ NewAddress(addresses []Address)
+ // NewServiceConfig is called by resolver to notify ClientConn a new
+ // service config. The service config should be provided as a json string.
+ NewServiceConfig(serviceConfig string)
+}
+
+// Target represents a target for gRPC, as specified in:
+// https://github.com/grpc/grpc/blob/master/doc/naming.md.
+type Target struct {
+ Scheme string
+ Authority string
+ Endpoint string
+}
+
+// Builder creates a resolver that will be used to watch name resolution updates.
+type Builder interface {
+ // Build creates a new resolver for the given target.
+ //
+ // gRPC dial calls Build synchronously, and fails if the returned error is
+ // not nil.
+ Build(target Target, cc ClientConn, opts BuildOption) (Resolver, error)
+ // Scheme returns the scheme supported by this resolver.
+ // Scheme is defined at https://github.com/grpc/grpc/blob/master/doc/naming.md.
+ Scheme() string
+}
+
+// ResolveNowOption includes additional information for ResolveNow.
+type ResolveNowOption struct{}
+
+// Resolver watches for the updates on the specified target.
+// Updates include address updates and service config updates.
+type Resolver interface {
+ // ResolveNow will be called by gRPC to try to resolve the target name
+ // again. It's just a hint, resolver can ignore this if it's not necessary.
+ //
+ // It could be called multiple times concurrently.
+ ResolveNow(ResolveNowOption)
+ // Close closes the resolver.
+ Close()
+}
+
+// UnregisterForTesting removes the resolver builder with the given scheme from the
+// resolver map.
+// This function is for testing only.
+func UnregisterForTesting(scheme string) {
+ delete(m, scheme)
+}
diff --git a/vendor/google.golang.org/grpc/resolver_conn_wrapper.go b/vendor/google.golang.org/grpc/resolver_conn_wrapper.go
new file mode 100644
index 000000000..9d7602539
--- /dev/null
+++ b/vendor/google.golang.org/grpc/resolver_conn_wrapper.go
@@ -0,0 +1,155 @@
+/*
+ *
+ * Copyright 2017 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package grpc
+
+import (
+ "fmt"
+ "strings"
+
+ "google.golang.org/grpc/grpclog"
+ "google.golang.org/grpc/internal/channelz"
+ "google.golang.org/grpc/resolver"
+)
+
+// ccResolverWrapper is a wrapper on top of cc for resolvers.
+// It implements resolver.ClientConnection interface.
+type ccResolverWrapper struct {
+ cc *ClientConn
+ resolver resolver.Resolver
+ addrCh chan []resolver.Address
+ scCh chan string
+ done chan struct{}
+ lastAddressesCount int
+}
+
+// split2 returns the values from strings.SplitN(s, sep, 2).
+// If sep is not found, it returns ("", s, false) instead.
+func split2(s, sep string) (string, string, bool) {
+ spl := strings.SplitN(s, sep, 2)
+ if len(spl) < 2 {
+ return "", "", false
+ }
+ return spl[0], spl[1], true
+}
+
+// parseTarget splits target into a struct containing scheme, authority and
+// endpoint.
+//
+// If target is not a valid scheme://authority/endpoint, it returns {Endpoint:
+// target}.
+func parseTarget(target string) (ret resolver.Target) {
+ var ok bool
+ ret.Scheme, ret.Endpoint, ok = split2(target, "://")
+ if !ok {
+ return resolver.Target{Endpoint: target}
+ }
+ ret.Authority, ret.Endpoint, ok = split2(ret.Endpoint, "/")
+ if !ok {
+ return resolver.Target{Endpoint: target}
+ }
+ return ret
+}
+
+// newCCResolverWrapper parses cc.target for scheme and gets the resolver
+// builder for this scheme and builds the resolver. The monitoring goroutine
+// for it is not started yet and can be created by calling start().
+//
+// If withResolverBuilder dial option is set, the specified resolver will be
+// used instead.
+func newCCResolverWrapper(cc *ClientConn) (*ccResolverWrapper, error) {
+ rb := cc.dopts.resolverBuilder
+ if rb == nil {
+ return nil, fmt.Errorf("could not get resolver for scheme: %q", cc.parsedTarget.Scheme)
+ }
+
+ ccr := &ccResolverWrapper{
+ cc: cc,
+ addrCh: make(chan []resolver.Address, 1),
+ scCh: make(chan string, 1),
+ done: make(chan struct{}),
+ }
+
+ var err error
+ ccr.resolver, err = rb.Build(cc.parsedTarget, ccr, resolver.BuildOption{DisableServiceConfig: cc.dopts.disableServiceConfig})
+ if err != nil {
+ return nil, err
+ }
+ return ccr, nil
+}
+
+func (ccr *ccResolverWrapper) resolveNow(o resolver.ResolveNowOption) {
+ ccr.resolver.ResolveNow(o)
+}
+
+func (ccr *ccResolverWrapper) close() {
+ ccr.resolver.Close()
+ close(ccr.done)
+}
+
+// NewAddress is called by the resolver implemenetion to send addresses to gRPC.
+func (ccr *ccResolverWrapper) NewAddress(addrs []resolver.Address) {
+ select {
+ case <-ccr.done:
+ return
+ default:
+ }
+ grpclog.Infof("ccResolverWrapper: sending new addresses to cc: %v", addrs)
+ if channelz.IsOn() {
+ ccr.addChannelzTraceEvent(addrs)
+ }
+ ccr.cc.handleResolvedAddrs(addrs, nil)
+}
+
+// NewServiceConfig is called by the resolver implemenetion to send service
+// configs to gRPC.
+func (ccr *ccResolverWrapper) NewServiceConfig(sc string) {
+ select {
+ case <-ccr.done:
+ return
+ default:
+ }
+ grpclog.Infof("ccResolverWrapper: got new service config: %v", sc)
+ ccr.cc.handleServiceConfig(sc)
+}
+
+func (ccr *ccResolverWrapper) addChannelzTraceEvent(addrs []resolver.Address) {
+ if len(addrs) == 0 && ccr.lastAddressesCount != 0 {
+ channelz.AddTraceEvent(ccr.cc.channelzID, &channelz.TraceEventDesc{
+ Desc: "Resolver returns an empty address list",
+ Severity: channelz.CtWarning,
+ })
+ } else if len(addrs) != 0 && ccr.lastAddressesCount == 0 {
+ var s string
+ for i, a := range addrs {
+ if a.ServerName != "" {
+ s += a.Addr + "(" + a.ServerName + ")"
+ } else {
+ s += a.Addr
+ }
+ if i != len(addrs)-1 {
+ s += " "
+ }
+ }
+ channelz.AddTraceEvent(ccr.cc.channelzID, &channelz.TraceEventDesc{
+ Desc: fmt.Sprintf("Resolver returns a non-empty address list (previous one was empty) %q", s),
+ Severity: channelz.CtINFO,
+ })
+ }
+ ccr.lastAddressesCount = len(addrs)
+}
diff --git a/vendor/google.golang.org/grpc/rpc_util.go b/vendor/google.golang.org/grpc/rpc_util.go
new file mode 100644
index 000000000..86f00e5a2
--- /dev/null
+++ b/vendor/google.golang.org/grpc/rpc_util.go
@@ -0,0 +1,815 @@
+/*
+ *
+ * Copyright 2014 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package grpc
+
+import (
+ "bytes"
+ "compress/gzip"
+ "context"
+ "encoding/binary"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "math"
+ "net/url"
+ "strings"
+ "sync"
+ "time"
+
+ "google.golang.org/grpc/codes"
+ "google.golang.org/grpc/credentials"
+ "google.golang.org/grpc/encoding"
+ "google.golang.org/grpc/encoding/proto"
+ "google.golang.org/grpc/internal/transport"
+ "google.golang.org/grpc/metadata"
+ "google.golang.org/grpc/peer"
+ "google.golang.org/grpc/stats"
+ "google.golang.org/grpc/status"
+)
+
+// Compressor defines the interface gRPC uses to compress a message.
+//
+// Deprecated: use package encoding.
+type Compressor interface {
+ // Do compresses p into w.
+ Do(w io.Writer, p []byte) error
+ // Type returns the compression algorithm the Compressor uses.
+ Type() string
+}
+
+type gzipCompressor struct {
+ pool sync.Pool
+}
+
+// NewGZIPCompressor creates a Compressor based on GZIP.
+//
+// Deprecated: use package encoding/gzip.
+func NewGZIPCompressor() Compressor {
+ c, _ := NewGZIPCompressorWithLevel(gzip.DefaultCompression)
+ return c
+}
+
+// NewGZIPCompressorWithLevel is like NewGZIPCompressor but specifies the gzip compression level instead
+// of assuming DefaultCompression.
+//
+// The error returned will be nil if the level is valid.
+//
+// Deprecated: use package encoding/gzip.
+func NewGZIPCompressorWithLevel(level int) (Compressor, error) {
+ if level < gzip.DefaultCompression || level > gzip.BestCompression {
+ return nil, fmt.Errorf("grpc: invalid compression level: %d", level)
+ }
+ return &gzipCompressor{
+ pool: sync.Pool{
+ New: func() interface{} {
+ w, err := gzip.NewWriterLevel(ioutil.Discard, level)
+ if err != nil {
+ panic(err)
+ }
+ return w
+ },
+ },
+ }, nil
+}
+
+func (c *gzipCompressor) Do(w io.Writer, p []byte) error {
+ z := c.pool.Get().(*gzip.Writer)
+ defer c.pool.Put(z)
+ z.Reset(w)
+ if _, err := z.Write(p); err != nil {
+ return err
+ }
+ return z.Close()
+}
+
+func (c *gzipCompressor) Type() string {
+ return "gzip"
+}
+
+// Decompressor defines the interface gRPC uses to decompress a message.
+//
+// Deprecated: use package encoding.
+type Decompressor interface {
+ // Do reads the data from r and uncompress them.
+ Do(r io.Reader) ([]byte, error)
+ // Type returns the compression algorithm the Decompressor uses.
+ Type() string
+}
+
+type gzipDecompressor struct {
+ pool sync.Pool
+}
+
+// NewGZIPDecompressor creates a Decompressor based on GZIP.
+//
+// Deprecated: use package encoding/gzip.
+func NewGZIPDecompressor() Decompressor {
+ return &gzipDecompressor{}
+}
+
+func (d *gzipDecompressor) Do(r io.Reader) ([]byte, error) {
+ var z *gzip.Reader
+ switch maybeZ := d.pool.Get().(type) {
+ case nil:
+ newZ, err := gzip.NewReader(r)
+ if err != nil {
+ return nil, err
+ }
+ z = newZ
+ case *gzip.Reader:
+ z = maybeZ
+ if err := z.Reset(r); err != nil {
+ d.pool.Put(z)
+ return nil, err
+ }
+ }
+
+ defer func() {
+ z.Close()
+ d.pool.Put(z)
+ }()
+ return ioutil.ReadAll(z)
+}
+
+func (d *gzipDecompressor) Type() string {
+ return "gzip"
+}
+
+// callInfo contains all related configuration and information about an RPC.
+type callInfo struct {
+ compressorType string
+ failFast bool
+ stream ClientStream
+ maxReceiveMessageSize *int
+ maxSendMessageSize *int
+ creds credentials.PerRPCCredentials
+ contentSubtype string
+ codec baseCodec
+ maxRetryRPCBufferSize int
+}
+
+func defaultCallInfo() *callInfo {
+ return &callInfo{
+ failFast: true,
+ maxRetryRPCBufferSize: 256 * 1024, // 256KB
+ }
+}
+
+// CallOption configures a Call before it starts or extracts information from
+// a Call after it completes.
+type CallOption interface {
+ // before is called before the call is sent to any server. If before
+ // returns a non-nil error, the RPC fails with that error.
+ before(*callInfo) error
+
+ // after is called after the call has completed. after cannot return an
+ // error, so any failures should be reported via output parameters.
+ after(*callInfo)
+}
+
+// EmptyCallOption does not alter the Call configuration.
+// It can be embedded in another structure to carry satellite data for use
+// by interceptors.
+type EmptyCallOption struct{}
+
+func (EmptyCallOption) before(*callInfo) error { return nil }
+func (EmptyCallOption) after(*callInfo) {}
+
+// Header returns a CallOptions that retrieves the header metadata
+// for a unary RPC.
+func Header(md *metadata.MD) CallOption {
+ return HeaderCallOption{HeaderAddr: md}
+}
+
+// HeaderCallOption is a CallOption for collecting response header metadata.
+// The metadata field will be populated *after* the RPC completes.
+// This is an EXPERIMENTAL API.
+type HeaderCallOption struct {
+ HeaderAddr *metadata.MD
+}
+
+func (o HeaderCallOption) before(c *callInfo) error { return nil }
+func (o HeaderCallOption) after(c *callInfo) {
+ if c.stream != nil {
+ *o.HeaderAddr, _ = c.stream.Header()
+ }
+}
+
+// Trailer returns a CallOptions that retrieves the trailer metadata
+// for a unary RPC.
+func Trailer(md *metadata.MD) CallOption {
+ return TrailerCallOption{TrailerAddr: md}
+}
+
+// TrailerCallOption is a CallOption for collecting response trailer metadata.
+// The metadata field will be populated *after* the RPC completes.
+// This is an EXPERIMENTAL API.
+type TrailerCallOption struct {
+ TrailerAddr *metadata.MD
+}
+
+func (o TrailerCallOption) before(c *callInfo) error { return nil }
+func (o TrailerCallOption) after(c *callInfo) {
+ if c.stream != nil {
+ *o.TrailerAddr = c.stream.Trailer()
+ }
+}
+
+// Peer returns a CallOption that retrieves peer information for a unary RPC.
+// The peer field will be populated *after* the RPC completes.
+func Peer(p *peer.Peer) CallOption {
+ return PeerCallOption{PeerAddr: p}
+}
+
+// PeerCallOption is a CallOption for collecting the identity of the remote
+// peer. The peer field will be populated *after* the RPC completes.
+// This is an EXPERIMENTAL API.
+type PeerCallOption struct {
+ PeerAddr *peer.Peer
+}
+
+func (o PeerCallOption) before(c *callInfo) error { return nil }
+func (o PeerCallOption) after(c *callInfo) {
+ if c.stream != nil {
+ if x, ok := peer.FromContext(c.stream.Context()); ok {
+ *o.PeerAddr = *x
+ }
+ }
+}
+
+// FailFast configures the action to take when an RPC is attempted on broken
+// connections or unreachable servers. If failFast is true, the RPC will fail
+// immediately. Otherwise, the RPC client will block the call until a
+// connection is available (or the call is canceled or times out) and will
+// retry the call if it fails due to a transient error. gRPC will not retry if
+// data was written to the wire unless the server indicates it did not process
+// the data. Please refer to
+// https://github.com/grpc/grpc/blob/master/doc/wait-for-ready.md.
+//
+// By default, RPCs are "Fail Fast".
+func FailFast(failFast bool) CallOption {
+ return FailFastCallOption{FailFast: failFast}
+}
+
+// FailFastCallOption is a CallOption for indicating whether an RPC should fail
+// fast or not.
+// This is an EXPERIMENTAL API.
+type FailFastCallOption struct {
+ FailFast bool
+}
+
+func (o FailFastCallOption) before(c *callInfo) error {
+ c.failFast = o.FailFast
+ return nil
+}
+func (o FailFastCallOption) after(c *callInfo) {}
+
+// MaxCallRecvMsgSize returns a CallOption which sets the maximum message size the client can receive.
+func MaxCallRecvMsgSize(s int) CallOption {
+ return MaxRecvMsgSizeCallOption{MaxRecvMsgSize: s}
+}
+
+// MaxRecvMsgSizeCallOption is a CallOption that indicates the maximum message
+// size the client can receive.
+// This is an EXPERIMENTAL API.
+type MaxRecvMsgSizeCallOption struct {
+ MaxRecvMsgSize int
+}
+
+func (o MaxRecvMsgSizeCallOption) before(c *callInfo) error {
+ c.maxReceiveMessageSize = &o.MaxRecvMsgSize
+ return nil
+}
+func (o MaxRecvMsgSizeCallOption) after(c *callInfo) {}
+
+// MaxCallSendMsgSize returns a CallOption which sets the maximum message size the client can send.
+func MaxCallSendMsgSize(s int) CallOption {
+ return MaxSendMsgSizeCallOption{MaxSendMsgSize: s}
+}
+
+// MaxSendMsgSizeCallOption is a CallOption that indicates the maximum message
+// size the client can send.
+// This is an EXPERIMENTAL API.
+type MaxSendMsgSizeCallOption struct {
+ MaxSendMsgSize int
+}
+
+func (o MaxSendMsgSizeCallOption) before(c *callInfo) error {
+ c.maxSendMessageSize = &o.MaxSendMsgSize
+ return nil
+}
+func (o MaxSendMsgSizeCallOption) after(c *callInfo) {}
+
+// PerRPCCredentials returns a CallOption that sets credentials.PerRPCCredentials
+// for a call.
+func PerRPCCredentials(creds credentials.PerRPCCredentials) CallOption {
+ return PerRPCCredsCallOption{Creds: creds}
+}
+
+// PerRPCCredsCallOption is a CallOption that indicates the per-RPC
+// credentials to use for the call.
+// This is an EXPERIMENTAL API.
+type PerRPCCredsCallOption struct {
+ Creds credentials.PerRPCCredentials
+}
+
+func (o PerRPCCredsCallOption) before(c *callInfo) error {
+ c.creds = o.Creds
+ return nil
+}
+func (o PerRPCCredsCallOption) after(c *callInfo) {}
+
+// UseCompressor returns a CallOption which sets the compressor used when
+// sending the request. If WithCompressor is also set, UseCompressor has
+// higher priority.
+//
+// This API is EXPERIMENTAL.
+func UseCompressor(name string) CallOption {
+ return CompressorCallOption{CompressorType: name}
+}
+
+// CompressorCallOption is a CallOption that indicates the compressor to use.
+// This is an EXPERIMENTAL API.
+type CompressorCallOption struct {
+ CompressorType string
+}
+
+func (o CompressorCallOption) before(c *callInfo) error {
+ c.compressorType = o.CompressorType
+ return nil
+}
+func (o CompressorCallOption) after(c *callInfo) {}
+
+// CallContentSubtype returns a CallOption that will set the content-subtype
+// for a call. For example, if content-subtype is "json", the Content-Type over
+// the wire will be "application/grpc+json". The content-subtype is converted
+// to lowercase before being included in Content-Type. See Content-Type on
+// https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md#requests for
+// more details.
+//
+// If CallCustomCodec is not also used, the content-subtype will be used to
+// look up the Codec to use in the registry controlled by RegisterCodec. See
+// the documentation on RegisterCodec for details on registration. The lookup
+// of content-subtype is case-insensitive. If no such Codec is found, the call
+// will result in an error with code codes.Internal.
+//
+// If CallCustomCodec is also used, that Codec will be used for all request and
+// response messages, with the content-subtype set to the given contentSubtype
+// here for requests.
+func CallContentSubtype(contentSubtype string) CallOption {
+ return ContentSubtypeCallOption{ContentSubtype: strings.ToLower(contentSubtype)}
+}
+
+// ContentSubtypeCallOption is a CallOption that indicates the content-subtype
+// used for marshaling messages.
+// This is an EXPERIMENTAL API.
+type ContentSubtypeCallOption struct {
+ ContentSubtype string
+}
+
+func (o ContentSubtypeCallOption) before(c *callInfo) error {
+ c.contentSubtype = o.ContentSubtype
+ return nil
+}
+func (o ContentSubtypeCallOption) after(c *callInfo) {}
+
+// CallCustomCodec returns a CallOption that will set the given Codec to be
+// used for all request and response messages for a call. The result of calling
+// String() will be used as the content-subtype in a case-insensitive manner.
+//
+// See Content-Type on
+// https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md#requests for
+// more details. Also see the documentation on RegisterCodec and
+// CallContentSubtype for more details on the interaction between Codec and
+// content-subtype.
+//
+// This function is provided for advanced users; prefer to use only
+// CallContentSubtype to select a registered codec instead.
+func CallCustomCodec(codec Codec) CallOption {
+ return CustomCodecCallOption{Codec: codec}
+}
+
+// CustomCodecCallOption is a CallOption that indicates the codec used for
+// marshaling messages.
+// This is an EXPERIMENTAL API.
+type CustomCodecCallOption struct {
+ Codec Codec
+}
+
+func (o CustomCodecCallOption) before(c *callInfo) error {
+ c.codec = o.Codec
+ return nil
+}
+func (o CustomCodecCallOption) after(c *callInfo) {}
+
+// MaxRetryRPCBufferSize returns a CallOption that limits the amount of memory
+// used for buffering this RPC's requests for retry purposes.
+//
+// This API is EXPERIMENTAL.
+func MaxRetryRPCBufferSize(bytes int) CallOption {
+ return MaxRetryRPCBufferSizeCallOption{bytes}
+}
+
+// MaxRetryRPCBufferSizeCallOption is a CallOption indicating the amount of
+// memory to be used for caching this RPC for retry purposes.
+// This is an EXPERIMENTAL API.
+type MaxRetryRPCBufferSizeCallOption struct {
+ MaxRetryRPCBufferSize int
+}
+
+func (o MaxRetryRPCBufferSizeCallOption) before(c *callInfo) error {
+ c.maxRetryRPCBufferSize = o.MaxRetryRPCBufferSize
+ return nil
+}
+func (o MaxRetryRPCBufferSizeCallOption) after(c *callInfo) {}
+
+// The format of the payload: compressed or not?
+type payloadFormat uint8
+
+const (
+ compressionNone payloadFormat = 0 // no compression
+ compressionMade payloadFormat = 1 // compressed
+)
+
+// parser reads complete gRPC messages from the underlying reader.
+type parser struct {
+ // r is the underlying reader.
+ // See the comment on recvMsg for the permissible
+ // error types.
+ r io.Reader
+
+ // The header of a gRPC message. Find more detail at
+ // https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md
+ header [5]byte
+}
+
+// recvMsg reads a complete gRPC message from the stream.
+//
+// It returns the message and its payload (compression/encoding)
+// format. The caller owns the returned msg memory.
+//
+// If there is an error, possible values are:
+// * io.EOF, when no messages remain
+// * io.ErrUnexpectedEOF
+// * of type transport.ConnectionError
+// * an error from the status package
+// No other error values or types must be returned, which also means
+// that the underlying io.Reader must not return an incompatible
+// error.
+func (p *parser) recvMsg(maxReceiveMessageSize int) (pf payloadFormat, msg []byte, err error) {
+ if _, err := p.r.Read(p.header[:]); err != nil {
+ return 0, nil, err
+ }
+
+ pf = payloadFormat(p.header[0])
+ length := binary.BigEndian.Uint32(p.header[1:])
+
+ if length == 0 {
+ return pf, nil, nil
+ }
+ if int64(length) > int64(maxInt) {
+ return 0, nil, status.Errorf(codes.ResourceExhausted, "grpc: received message larger than max length allowed on current machine (%d vs. %d)", length, maxInt)
+ }
+ if int(length) > maxReceiveMessageSize {
+ return 0, nil, status.Errorf(codes.ResourceExhausted, "grpc: received message larger than max (%d vs. %d)", length, maxReceiveMessageSize)
+ }
+ // TODO(bradfitz,zhaoq): garbage. reuse buffer after proto decoding instead
+ // of making it for each message:
+ msg = make([]byte, int(length))
+ if _, err := p.r.Read(msg); err != nil {
+ if err == io.EOF {
+ err = io.ErrUnexpectedEOF
+ }
+ return 0, nil, err
+ }
+ return pf, msg, nil
+}
+
+// encode serializes msg and returns a buffer containing the message, or an
+// error if it is too large to be transmitted by grpc. If msg is nil, it
+// generates an empty message.
+func encode(c baseCodec, msg interface{}) ([]byte, error) {
+ if msg == nil { // NOTE: typed nils will not be caught by this check
+ return nil, nil
+ }
+ b, err := c.Marshal(msg)
+ if err != nil {
+ return nil, status.Errorf(codes.Internal, "grpc: error while marshaling: %v", err.Error())
+ }
+ if uint(len(b)) > math.MaxUint32 {
+ return nil, status.Errorf(codes.ResourceExhausted, "grpc: message too large (%d bytes)", len(b))
+ }
+ return b, nil
+}
+
+// compress returns the input bytes compressed by compressor or cp. If both
+// compressors are nil, returns nil.
+//
+// TODO(dfawley): eliminate cp parameter by wrapping Compressor in an encoding.Compressor.
+func compress(in []byte, cp Compressor, compressor encoding.Compressor) ([]byte, error) {
+ if compressor == nil && cp == nil {
+ return nil, nil
+ }
+ wrapErr := func(err error) error {
+ return status.Errorf(codes.Internal, "grpc: error while compressing: %v", err.Error())
+ }
+ cbuf := &bytes.Buffer{}
+ if compressor != nil {
+ z, err := compressor.Compress(cbuf)
+ if err != nil {
+ return nil, wrapErr(err)
+ }
+ if _, err := z.Write(in); err != nil {
+ return nil, wrapErr(err)
+ }
+ if err := z.Close(); err != nil {
+ return nil, wrapErr(err)
+ }
+ } else {
+ if err := cp.Do(cbuf, in); err != nil {
+ return nil, wrapErr(err)
+ }
+ }
+ return cbuf.Bytes(), nil
+}
+
+const (
+ payloadLen = 1
+ sizeLen = 4
+ headerLen = payloadLen + sizeLen
+)
+
+// msgHeader returns a 5-byte header for the message being transmitted and the
+// payload, which is compData if non-nil or data otherwise.
+func msgHeader(data, compData []byte) (hdr []byte, payload []byte) {
+ hdr = make([]byte, headerLen)
+ if compData != nil {
+ hdr[0] = byte(compressionMade)
+ data = compData
+ } else {
+ hdr[0] = byte(compressionNone)
+ }
+
+ // Write length of payload into buf
+ binary.BigEndian.PutUint32(hdr[payloadLen:], uint32(len(data)))
+ return hdr, data
+}
+
+func outPayload(client bool, msg interface{}, data, payload []byte, t time.Time) *stats.OutPayload {
+ return &stats.OutPayload{
+ Client: client,
+ Payload: msg,
+ Data: data,
+ Length: len(data),
+ WireLength: len(payload) + headerLen,
+ SentTime: t,
+ }
+}
+
+func checkRecvPayload(pf payloadFormat, recvCompress string, haveCompressor bool) *status.Status {
+ switch pf {
+ case compressionNone:
+ case compressionMade:
+ if recvCompress == "" || recvCompress == encoding.Identity {
+ return status.New(codes.Internal, "grpc: compressed flag set with identity or empty encoding")
+ }
+ if !haveCompressor {
+ return status.Newf(codes.Unimplemented, "grpc: Decompressor is not installed for grpc-encoding %q", recvCompress)
+ }
+ default:
+ return status.Newf(codes.Internal, "grpc: received unexpected payload format %d", pf)
+ }
+ return nil
+}
+
+type payloadInfo struct {
+ wireLength int // The compressed length got from wire.
+ uncompressedBytes []byte
+}
+
+func recvAndDecompress(p *parser, s *transport.Stream, dc Decompressor, maxReceiveMessageSize int, payInfo *payloadInfo, compressor encoding.Compressor) ([]byte, error) {
+ pf, d, err := p.recvMsg(maxReceiveMessageSize)
+ if err != nil {
+ return nil, err
+ }
+ if payInfo != nil {
+ payInfo.wireLength = len(d)
+ }
+
+ if st := checkRecvPayload(pf, s.RecvCompress(), compressor != nil || dc != nil); st != nil {
+ return nil, st.Err()
+ }
+
+ if pf == compressionMade {
+ // To match legacy behavior, if the decompressor is set by WithDecompressor or RPCDecompressor,
+ // use this decompressor as the default.
+ if dc != nil {
+ d, err = dc.Do(bytes.NewReader(d))
+ if err != nil {
+ return nil, status.Errorf(codes.Internal, "grpc: failed to decompress the received message %v", err)
+ }
+ } else {
+ dcReader, err := compressor.Decompress(bytes.NewReader(d))
+ if err != nil {
+ return nil, status.Errorf(codes.Internal, "grpc: failed to decompress the received message %v", err)
+ }
+ d, err = ioutil.ReadAll(dcReader)
+ if err != nil {
+ return nil, status.Errorf(codes.Internal, "grpc: failed to decompress the received message %v", err)
+ }
+ }
+ }
+ if len(d) > maxReceiveMessageSize {
+ // TODO: Revisit the error code. Currently keep it consistent with java
+ // implementation.
+ return nil, status.Errorf(codes.ResourceExhausted, "grpc: received message larger than max (%d vs. %d)", len(d), maxReceiveMessageSize)
+ }
+ return d, nil
+}
+
+// For the two compressor parameters, both should not be set, but if they are,
+// dc takes precedence over compressor.
+// TODO(dfawley): wrap the old compressor/decompressor using the new API?
+func recv(p *parser, c baseCodec, s *transport.Stream, dc Decompressor, m interface{}, maxReceiveMessageSize int, payInfo *payloadInfo, compressor encoding.Compressor) error {
+ d, err := recvAndDecompress(p, s, dc, maxReceiveMessageSize, payInfo, compressor)
+ if err != nil {
+ return err
+ }
+ if err := c.Unmarshal(d, m); err != nil {
+ return status.Errorf(codes.Internal, "grpc: failed to unmarshal the received message %v", err)
+ }
+ if payInfo != nil {
+ payInfo.uncompressedBytes = d
+ }
+ return nil
+}
+
+type rpcInfo struct {
+ failfast bool
+}
+
+type rpcInfoContextKey struct{}
+
+func newContextWithRPCInfo(ctx context.Context, failfast bool) context.Context {
+ return context.WithValue(ctx, rpcInfoContextKey{}, &rpcInfo{failfast: failfast})
+}
+
+func rpcInfoFromContext(ctx context.Context) (s *rpcInfo, ok bool) {
+ s, ok = ctx.Value(rpcInfoContextKey{}).(*rpcInfo)
+ return
+}
+
+// Code returns the error code for err if it was produced by the rpc system.
+// Otherwise, it returns codes.Unknown.
+//
+// Deprecated: use status.FromError and Code method instead.
+func Code(err error) codes.Code {
+ if s, ok := status.FromError(err); ok {
+ return s.Code()
+ }
+ return codes.Unknown
+}
+
+// ErrorDesc returns the error description of err if it was produced by the rpc system.
+// Otherwise, it returns err.Error() or empty string when err is nil.
+//
+// Deprecated: use status.FromError and Message method instead.
+func ErrorDesc(err error) string {
+ if s, ok := status.FromError(err); ok {
+ return s.Message()
+ }
+ return err.Error()
+}
+
+// Errorf returns an error containing an error code and a description;
+// Errorf returns nil if c is OK.
+//
+// Deprecated: use status.Errorf instead.
+func Errorf(c codes.Code, format string, a ...interface{}) error {
+ return status.Errorf(c, format, a...)
+}
+
+// toRPCErr converts an error into an error from the status package.
+func toRPCErr(err error) error {
+ if err == nil || err == io.EOF {
+ return err
+ }
+ if err == io.ErrUnexpectedEOF {
+ return status.Error(codes.Internal, err.Error())
+ }
+ if _, ok := status.FromError(err); ok {
+ return err
+ }
+ switch e := err.(type) {
+ case transport.ConnectionError:
+ return status.Error(codes.Unavailable, e.Desc)
+ default:
+ switch err {
+ case context.DeadlineExceeded:
+ return status.Error(codes.DeadlineExceeded, err.Error())
+ case context.Canceled:
+ return status.Error(codes.Canceled, err.Error())
+ }
+ }
+ return status.Error(codes.Unknown, err.Error())
+}
+
+// setCallInfoCodec should only be called after CallOptions have been applied.
+func setCallInfoCodec(c *callInfo) error {
+ if c.codec != nil {
+ // codec was already set by a CallOption; use it.
+ return nil
+ }
+
+ if c.contentSubtype == "" {
+ // No codec specified in CallOptions; use proto by default.
+ c.codec = encoding.GetCodec(proto.Name)
+ return nil
+ }
+
+ // c.contentSubtype is already lowercased in CallContentSubtype
+ c.codec = encoding.GetCodec(c.contentSubtype)
+ if c.codec == nil {
+ return status.Errorf(codes.Internal, "no codec registered for content-subtype %s", c.contentSubtype)
+ }
+ return nil
+}
+
+// parseDialTarget returns the network and address to pass to dialer
+func parseDialTarget(target string) (net string, addr string) {
+ net = "tcp"
+
+ m1 := strings.Index(target, ":")
+ m2 := strings.Index(target, ":/")
+
+ // handle unix:addr which will fail with url.Parse
+ if m1 >= 0 && m2 < 0 {
+ if n := target[0:m1]; n == "unix" {
+ net = n
+ addr = target[m1+1:]
+ return net, addr
+ }
+ }
+ if m2 >= 0 {
+ t, err := url.Parse(target)
+ if err != nil {
+ return net, target
+ }
+ scheme := t.Scheme
+ addr = t.Path
+ if scheme == "unix" {
+ net = scheme
+ if addr == "" {
+ addr = t.Host
+ }
+ return net, addr
+ }
+ }
+
+ return net, target
+}
+
+// channelzData is used to store channelz related data for ClientConn, addrConn and Server.
+// These fields cannot be embedded in the original structs (e.g. ClientConn), since to do atomic
+// operation on int64 variable on 32-bit machine, user is responsible to enforce memory alignment.
+// Here, by grouping those int64 fields inside a struct, we are enforcing the alignment.
+type channelzData struct {
+ callsStarted int64
+ callsFailed int64
+ callsSucceeded int64
+ // lastCallStartedTime stores the timestamp that last call starts. It is of int64 type instead of
+ // time.Time since it's more costly to atomically update time.Time variable than int64 variable.
+ lastCallStartedTime int64
+}
+
+// The SupportPackageIsVersion variables are referenced from generated protocol
+// buffer files to ensure compatibility with the gRPC version used. The latest
+// support package version is 5.
+//
+// Older versions are kept for compatibility. They may be removed if
+// compatibility cannot be maintained.
+//
+// These constants should not be referenced from any other code.
+const (
+ SupportPackageIsVersion3 = true
+ SupportPackageIsVersion4 = true
+ SupportPackageIsVersion5 = true
+)
+
+const grpcUA = "grpc-go/" + Version
diff --git a/vendor/google.golang.org/grpc/server.go b/vendor/google.golang.org/grpc/server.go
new file mode 100644
index 000000000..a7e4e1d9d
--- /dev/null
+++ b/vendor/google.golang.org/grpc/server.go
@@ -0,0 +1,1486 @@
+/*
+ *
+ * Copyright 2014 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package grpc
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "io"
+ "math"
+ "net"
+ "net/http"
+ "reflect"
+ "runtime"
+ "strings"
+ "sync"
+ "sync/atomic"
+ "time"
+
+ "golang.org/x/net/trace"
+
+ "google.golang.org/grpc/codes"
+ "google.golang.org/grpc/credentials"
+ "google.golang.org/grpc/encoding"
+ "google.golang.org/grpc/encoding/proto"
+ "google.golang.org/grpc/grpclog"
+ "google.golang.org/grpc/internal/binarylog"
+ "google.golang.org/grpc/internal/channelz"
+ "google.golang.org/grpc/internal/transport"
+ "google.golang.org/grpc/keepalive"
+ "google.golang.org/grpc/metadata"
+ "google.golang.org/grpc/peer"
+ "google.golang.org/grpc/stats"
+ "google.golang.org/grpc/status"
+ "google.golang.org/grpc/tap"
+)
+
+const (
+ defaultServerMaxReceiveMessageSize = 1024 * 1024 * 4
+ defaultServerMaxSendMessageSize = math.MaxInt32
+)
+
+type methodHandler func(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor UnaryServerInterceptor) (interface{}, error)
+
+// MethodDesc represents an RPC service's method specification.
+type MethodDesc struct {
+ MethodName string
+ Handler methodHandler
+}
+
+// ServiceDesc represents an RPC service's specification.
+type ServiceDesc struct {
+ ServiceName string
+ // The pointer to the service interface. Used to check whether the user
+ // provided implementation satisfies the interface requirements.
+ HandlerType interface{}
+ Methods []MethodDesc
+ Streams []StreamDesc
+ Metadata interface{}
+}
+
+// service consists of the information of the server serving this service and
+// the methods in this service.
+type service struct {
+ server interface{} // the server for service methods
+ md map[string]*MethodDesc
+ sd map[string]*StreamDesc
+ mdata interface{}
+}
+
+// Server is a gRPC server to serve RPC requests.
+type Server struct {
+ opts options
+
+ mu sync.Mutex // guards following
+ lis map[net.Listener]bool
+ conns map[io.Closer]bool
+ serve bool
+ drain bool
+ cv *sync.Cond // signaled when connections close for GracefulStop
+ m map[string]*service // service name -> service info
+ events trace.EventLog
+
+ quit chan struct{}
+ done chan struct{}
+ quitOnce sync.Once
+ doneOnce sync.Once
+ channelzRemoveOnce sync.Once
+ serveWG sync.WaitGroup // counts active Serve goroutines for GracefulStop
+
+ channelzID int64 // channelz unique identification number
+ czData *channelzData
+}
+
+type options struct {
+ creds credentials.TransportCredentials
+ codec baseCodec
+ cp Compressor
+ dc Decompressor
+ unaryInt UnaryServerInterceptor
+ streamInt StreamServerInterceptor
+ inTapHandle tap.ServerInHandle
+ statsHandler stats.Handler
+ maxConcurrentStreams uint32
+ maxReceiveMessageSize int
+ maxSendMessageSize int
+ unknownStreamDesc *StreamDesc
+ keepaliveParams keepalive.ServerParameters
+ keepalivePolicy keepalive.EnforcementPolicy
+ initialWindowSize int32
+ initialConnWindowSize int32
+ writeBufferSize int
+ readBufferSize int
+ connectionTimeout time.Duration
+ maxHeaderListSize *uint32
+}
+
+var defaultServerOptions = options{
+ maxReceiveMessageSize: defaultServerMaxReceiveMessageSize,
+ maxSendMessageSize: defaultServerMaxSendMessageSize,
+ connectionTimeout: 120 * time.Second,
+ writeBufferSize: defaultWriteBufSize,
+ readBufferSize: defaultReadBufSize,
+}
+
+// A ServerOption sets options such as credentials, codec and keepalive parameters, etc.
+type ServerOption func(*options)
+
+// WriteBufferSize determines how much data can be batched before doing a write on the wire.
+// The corresponding memory allocation for this buffer will be twice the size to keep syscalls low.
+// The default value for this buffer is 32KB.
+// Zero will disable the write buffer such that each write will be on underlying connection.
+// Note: A Send call may not directly translate to a write.
+func WriteBufferSize(s int) ServerOption {
+ return func(o *options) {
+ o.writeBufferSize = s
+ }
+}
+
+// ReadBufferSize lets you set the size of read buffer, this determines how much data can be read at most
+// for one read syscall.
+// The default value for this buffer is 32KB.
+// Zero will disable read buffer for a connection so data framer can access the underlying
+// conn directly.
+func ReadBufferSize(s int) ServerOption {
+ return func(o *options) {
+ o.readBufferSize = s
+ }
+}
+
+// InitialWindowSize returns a ServerOption that sets window size for stream.
+// The lower bound for window size is 64K and any value smaller than that will be ignored.
+func InitialWindowSize(s int32) ServerOption {
+ return func(o *options) {
+ o.initialWindowSize = s
+ }
+}
+
+// InitialConnWindowSize returns a ServerOption that sets window size for a connection.
+// The lower bound for window size is 64K and any value smaller than that will be ignored.
+func InitialConnWindowSize(s int32) ServerOption {
+ return func(o *options) {
+ o.initialConnWindowSize = s
+ }
+}
+
+// KeepaliveParams returns a ServerOption that sets keepalive and max-age parameters for the server.
+func KeepaliveParams(kp keepalive.ServerParameters) ServerOption {
+ return func(o *options) {
+ o.keepaliveParams = kp
+ }
+}
+
+// KeepaliveEnforcementPolicy returns a ServerOption that sets keepalive enforcement policy for the server.
+func KeepaliveEnforcementPolicy(kep keepalive.EnforcementPolicy) ServerOption {
+ return func(o *options) {
+ o.keepalivePolicy = kep
+ }
+}
+
+// CustomCodec returns a ServerOption that sets a codec for message marshaling and unmarshaling.
+//
+// This will override any lookups by content-subtype for Codecs registered with RegisterCodec.
+func CustomCodec(codec Codec) ServerOption {
+ return func(o *options) {
+ o.codec = codec
+ }
+}
+
+// RPCCompressor returns a ServerOption that sets a compressor for outbound
+// messages. For backward compatibility, all outbound messages will be sent
+// using this compressor, regardless of incoming message compression. By
+// default, server messages will be sent using the same compressor with which
+// request messages were sent.
+//
+// Deprecated: use encoding.RegisterCompressor instead.
+func RPCCompressor(cp Compressor) ServerOption {
+ return func(o *options) {
+ o.cp = cp
+ }
+}
+
+// RPCDecompressor returns a ServerOption that sets a decompressor for inbound
+// messages. It has higher priority than decompressors registered via
+// encoding.RegisterCompressor.
+//
+// Deprecated: use encoding.RegisterCompressor instead.
+func RPCDecompressor(dc Decompressor) ServerOption {
+ return func(o *options) {
+ o.dc = dc
+ }
+}
+
+// MaxMsgSize returns a ServerOption to set the max message size in bytes the server can receive.
+// If this is not set, gRPC uses the default limit.
+//
+// Deprecated: use MaxRecvMsgSize instead.
+func MaxMsgSize(m int) ServerOption {
+ return MaxRecvMsgSize(m)
+}
+
+// MaxRecvMsgSize returns a ServerOption to set the max message size in bytes the server can receive.
+// If this is not set, gRPC uses the default 4MB.
+func MaxRecvMsgSize(m int) ServerOption {
+ return func(o *options) {
+ o.maxReceiveMessageSize = m
+ }
+}
+
+// MaxSendMsgSize returns a ServerOption to set the max message size in bytes the server can send.
+// If this is not set, gRPC uses the default 4MB.
+func MaxSendMsgSize(m int) ServerOption {
+ return func(o *options) {
+ o.maxSendMessageSize = m
+ }
+}
+
+// MaxConcurrentStreams returns a ServerOption that will apply a limit on the number
+// of concurrent streams to each ServerTransport.
+func MaxConcurrentStreams(n uint32) ServerOption {
+ return func(o *options) {
+ o.maxConcurrentStreams = n
+ }
+}
+
+// Creds returns a ServerOption that sets credentials for server connections.
+func Creds(c credentials.TransportCredentials) ServerOption {
+ return func(o *options) {
+ o.creds = c
+ }
+}
+
+// UnaryInterceptor returns a ServerOption that sets the UnaryServerInterceptor for the
+// server. Only one unary interceptor can be installed. The construction of multiple
+// interceptors (e.g., chaining) can be implemented at the caller.
+func UnaryInterceptor(i UnaryServerInterceptor) ServerOption {
+ return func(o *options) {
+ if o.unaryInt != nil {
+ panic("The unary server interceptor was already set and may not be reset.")
+ }
+ o.unaryInt = i
+ }
+}
+
+// StreamInterceptor returns a ServerOption that sets the StreamServerInterceptor for the
+// server. Only one stream interceptor can be installed.
+func StreamInterceptor(i StreamServerInterceptor) ServerOption {
+ return func(o *options) {
+ if o.streamInt != nil {
+ panic("The stream server interceptor was already set and may not be reset.")
+ }
+ o.streamInt = i
+ }
+}
+
+// InTapHandle returns a ServerOption that sets the tap handle for all the server
+// transport to be created. Only one can be installed.
+func InTapHandle(h tap.ServerInHandle) ServerOption {
+ return func(o *options) {
+ if o.inTapHandle != nil {
+ panic("The tap handle was already set and may not be reset.")
+ }
+ o.inTapHandle = h
+ }
+}
+
+// StatsHandler returns a ServerOption that sets the stats handler for the server.
+func StatsHandler(h stats.Handler) ServerOption {
+ return func(o *options) {
+ o.statsHandler = h
+ }
+}
+
+// UnknownServiceHandler returns a ServerOption that allows for adding a custom
+// unknown service handler. The provided method is a bidi-streaming RPC service
+// handler that will be invoked instead of returning the "unimplemented" gRPC
+// error whenever a request is received for an unregistered service or method.
+// The handling function has full access to the Context of the request and the
+// stream, and the invocation bypasses interceptors.
+func UnknownServiceHandler(streamHandler StreamHandler) ServerOption {
+ return func(o *options) {
+ o.unknownStreamDesc = &StreamDesc{
+ StreamName: "unknown_service_handler",
+ Handler: streamHandler,
+ // We need to assume that the users of the streamHandler will want to use both.
+ ClientStreams: true,
+ ServerStreams: true,
+ }
+ }
+}
+
+// ConnectionTimeout returns a ServerOption that sets the timeout for
+// connection establishment (up to and including HTTP/2 handshaking) for all
+// new connections. If this is not set, the default is 120 seconds. A zero or
+// negative value will result in an immediate timeout.
+//
+// This API is EXPERIMENTAL.
+func ConnectionTimeout(d time.Duration) ServerOption {
+ return func(o *options) {
+ o.connectionTimeout = d
+ }
+}
+
+// MaxHeaderListSize returns a ServerOption that sets the max (uncompressed) size
+// of header list that the server is prepared to accept.
+func MaxHeaderListSize(s uint32) ServerOption {
+ return func(o *options) {
+ o.maxHeaderListSize = &s
+ }
+}
+
+// NewServer creates a gRPC server which has no service registered and has not
+// started to accept requests yet.
+func NewServer(opt ...ServerOption) *Server {
+ opts := defaultServerOptions
+ for _, o := range opt {
+ o(&opts)
+ }
+ s := &Server{
+ lis: make(map[net.Listener]bool),
+ opts: opts,
+ conns: make(map[io.Closer]bool),
+ m: make(map[string]*service),
+ quit: make(chan struct{}),
+ done: make(chan struct{}),
+ czData: new(channelzData),
+ }
+ s.cv = sync.NewCond(&s.mu)
+ if EnableTracing {
+ _, file, line, _ := runtime.Caller(1)
+ s.events = trace.NewEventLog("grpc.Server", fmt.Sprintf("%s:%d", file, line))
+ }
+
+ if channelz.IsOn() {
+ s.channelzID = channelz.RegisterServer(&channelzServer{s}, "")
+ }
+ return s
+}
+
+// printf records an event in s's event log, unless s has been stopped.
+// REQUIRES s.mu is held.
+func (s *Server) printf(format string, a ...interface{}) {
+ if s.events != nil {
+ s.events.Printf(format, a...)
+ }
+}
+
+// errorf records an error in s's event log, unless s has been stopped.
+// REQUIRES s.mu is held.
+func (s *Server) errorf(format string, a ...interface{}) {
+ if s.events != nil {
+ s.events.Errorf(format, a...)
+ }
+}
+
+// RegisterService registers a service and its implementation to the gRPC
+// server. It is called from the IDL generated code. This must be called before
+// invoking Serve.
+func (s *Server) RegisterService(sd *ServiceDesc, ss interface{}) {
+ ht := reflect.TypeOf(sd.HandlerType).Elem()
+ st := reflect.TypeOf(ss)
+ if !st.Implements(ht) {
+ grpclog.Fatalf("grpc: Server.RegisterService found the handler of type %v that does not satisfy %v", st, ht)
+ }
+ s.register(sd, ss)
+}
+
+func (s *Server) register(sd *ServiceDesc, ss interface{}) {
+ s.mu.Lock()
+ defer s.mu.Unlock()
+ s.printf("RegisterService(%q)", sd.ServiceName)
+ if s.serve {
+ grpclog.Fatalf("grpc: Server.RegisterService after Server.Serve for %q", sd.ServiceName)
+ }
+ if _, ok := s.m[sd.ServiceName]; ok {
+ grpclog.Fatalf("grpc: Server.RegisterService found duplicate service registration for %q", sd.ServiceName)
+ }
+ srv := &service{
+ server: ss,
+ md: make(map[string]*MethodDesc),
+ sd: make(map[string]*StreamDesc),
+ mdata: sd.Metadata,
+ }
+ for i := range sd.Methods {
+ d := &sd.Methods[i]
+ srv.md[d.MethodName] = d
+ }
+ for i := range sd.Streams {
+ d := &sd.Streams[i]
+ srv.sd[d.StreamName] = d
+ }
+ s.m[sd.ServiceName] = srv
+}
+
+// MethodInfo contains the information of an RPC including its method name and type.
+type MethodInfo struct {
+ // Name is the method name only, without the service name or package name.
+ Name string
+ // IsClientStream indicates whether the RPC is a client streaming RPC.
+ IsClientStream bool
+ // IsServerStream indicates whether the RPC is a server streaming RPC.
+ IsServerStream bool
+}
+
+// ServiceInfo contains unary RPC method info, streaming RPC method info and metadata for a service.
+type ServiceInfo struct {
+ Methods []MethodInfo
+ // Metadata is the metadata specified in ServiceDesc when registering service.
+ Metadata interface{}
+}
+
+// GetServiceInfo returns a map from service names to ServiceInfo.
+// Service names include the package names, in the form of <package>.<service>.
+func (s *Server) GetServiceInfo() map[string]ServiceInfo {
+ ret := make(map[string]ServiceInfo)
+ for n, srv := range s.m {
+ methods := make([]MethodInfo, 0, len(srv.md)+len(srv.sd))
+ for m := range srv.md {
+ methods = append(methods, MethodInfo{
+ Name: m,
+ IsClientStream: false,
+ IsServerStream: false,
+ })
+ }
+ for m, d := range srv.sd {
+ methods = append(methods, MethodInfo{
+ Name: m,
+ IsClientStream: d.ClientStreams,
+ IsServerStream: d.ServerStreams,
+ })
+ }
+
+ ret[n] = ServiceInfo{
+ Methods: methods,
+ Metadata: srv.mdata,
+ }
+ }
+ return ret
+}
+
+// ErrServerStopped indicates that the operation is now illegal because of
+// the server being stopped.
+var ErrServerStopped = errors.New("grpc: the server has been stopped")
+
+func (s *Server) useTransportAuthenticator(rawConn net.Conn) (net.Conn, credentials.AuthInfo, error) {
+ if s.opts.creds == nil {
+ return rawConn, nil, nil
+ }
+ return s.opts.creds.ServerHandshake(rawConn)
+}
+
+type listenSocket struct {
+ net.Listener
+ channelzID int64
+}
+
+func (l *listenSocket) ChannelzMetric() *channelz.SocketInternalMetric {
+ return &channelz.SocketInternalMetric{
+ SocketOptions: channelz.GetSocketOption(l.Listener),
+ LocalAddr: l.Listener.Addr(),
+ }
+}
+
+func (l *listenSocket) Close() error {
+ err := l.Listener.Close()
+ if channelz.IsOn() {
+ channelz.RemoveEntry(l.channelzID)
+ }
+ return err
+}
+
+// Serve accepts incoming connections on the listener lis, creating a new
+// ServerTransport and service goroutine for each. The service goroutines
+// read gRPC requests and then call the registered handlers to reply to them.
+// Serve returns when lis.Accept fails with fatal errors. lis will be closed when
+// this method returns.
+// Serve will return a non-nil error unless Stop or GracefulStop is called.
+func (s *Server) Serve(lis net.Listener) error {
+ s.mu.Lock()
+ s.printf("serving")
+ s.serve = true
+ if s.lis == nil {
+ // Serve called after Stop or GracefulStop.
+ s.mu.Unlock()
+ lis.Close()
+ return ErrServerStopped
+ }
+
+ s.serveWG.Add(1)
+ defer func() {
+ s.serveWG.Done()
+ select {
+ // Stop or GracefulStop called; block until done and return nil.
+ case <-s.quit:
+ <-s.done
+ default:
+ }
+ }()
+
+ ls := &listenSocket{Listener: lis}
+ s.lis[ls] = true
+
+ if channelz.IsOn() {
+ ls.channelzID = channelz.RegisterListenSocket(ls, s.channelzID, lis.Addr().String())
+ }
+ s.mu.Unlock()
+
+ defer func() {
+ s.mu.Lock()
+ if s.lis != nil && s.lis[ls] {
+ ls.Close()
+ delete(s.lis, ls)
+ }
+ s.mu.Unlock()
+ }()
+
+ var tempDelay time.Duration // how long to sleep on accept failure
+
+ for {
+ rawConn, err := lis.Accept()
+ if err != nil {
+ if ne, ok := err.(interface {
+ Temporary() bool
+ }); ok && ne.Temporary() {
+ if tempDelay == 0 {
+ tempDelay = 5 * time.Millisecond
+ } else {
+ tempDelay *= 2
+ }
+ if max := 1 * time.Second; tempDelay > max {
+ tempDelay = max
+ }
+ s.mu.Lock()
+ s.printf("Accept error: %v; retrying in %v", err, tempDelay)
+ s.mu.Unlock()
+ timer := time.NewTimer(tempDelay)
+ select {
+ case <-timer.C:
+ case <-s.quit:
+ timer.Stop()
+ return nil
+ }
+ continue
+ }
+ s.mu.Lock()
+ s.printf("done serving; Accept = %v", err)
+ s.mu.Unlock()
+
+ select {
+ case <-s.quit:
+ return nil
+ default:
+ }
+ return err
+ }
+ tempDelay = 0
+ // Start a new goroutine to deal with rawConn so we don't stall this Accept
+ // loop goroutine.
+ //
+ // Make sure we account for the goroutine so GracefulStop doesn't nil out
+ // s.conns before this conn can be added.
+ s.serveWG.Add(1)
+ go func() {
+ s.handleRawConn(rawConn)
+ s.serveWG.Done()
+ }()
+ }
+}
+
+// handleRawConn forks a goroutine to handle a just-accepted connection that
+// has not had any I/O performed on it yet.
+func (s *Server) handleRawConn(rawConn net.Conn) {
+ rawConn.SetDeadline(time.Now().Add(s.opts.connectionTimeout))
+ conn, authInfo, err := s.useTransportAuthenticator(rawConn)
+ if err != nil {
+ s.mu.Lock()
+ s.errorf("ServerHandshake(%q) failed: %v", rawConn.RemoteAddr(), err)
+ s.mu.Unlock()
+ grpclog.Warningf("grpc: Server.Serve failed to complete security handshake from %q: %v", rawConn.RemoteAddr(), err)
+ // If serverHandshake returns ErrConnDispatched, keep rawConn open.
+ if err != credentials.ErrConnDispatched {
+ rawConn.Close()
+ }
+ rawConn.SetDeadline(time.Time{})
+ return
+ }
+
+ s.mu.Lock()
+ if s.conns == nil {
+ s.mu.Unlock()
+ conn.Close()
+ return
+ }
+ s.mu.Unlock()
+
+ // Finish handshaking (HTTP2)
+ st := s.newHTTP2Transport(conn, authInfo)
+ if st == nil {
+ return
+ }
+
+ rawConn.SetDeadline(time.Time{})
+ if !s.addConn(st) {
+ return
+ }
+ go func() {
+ s.serveStreams(st)
+ s.removeConn(st)
+ }()
+}
+
+// newHTTP2Transport sets up a http/2 transport (using the
+// gRPC http2 server transport in transport/http2_server.go).
+func (s *Server) newHTTP2Transport(c net.Conn, authInfo credentials.AuthInfo) transport.ServerTransport {
+ config := &transport.ServerConfig{
+ MaxStreams: s.opts.maxConcurrentStreams,
+ AuthInfo: authInfo,
+ InTapHandle: s.opts.inTapHandle,
+ StatsHandler: s.opts.statsHandler,
+ KeepaliveParams: s.opts.keepaliveParams,
+ KeepalivePolicy: s.opts.keepalivePolicy,
+ InitialWindowSize: s.opts.initialWindowSize,
+ InitialConnWindowSize: s.opts.initialConnWindowSize,
+ WriteBufferSize: s.opts.writeBufferSize,
+ ReadBufferSize: s.opts.readBufferSize,
+ ChannelzParentID: s.channelzID,
+ MaxHeaderListSize: s.opts.maxHeaderListSize,
+ }
+ st, err := transport.NewServerTransport("http2", c, config)
+ if err != nil {
+ s.mu.Lock()
+ s.errorf("NewServerTransport(%q) failed: %v", c.RemoteAddr(), err)
+ s.mu.Unlock()
+ c.Close()
+ grpclog.Warningln("grpc: Server.Serve failed to create ServerTransport: ", err)
+ return nil
+ }
+
+ return st
+}
+
+func (s *Server) serveStreams(st transport.ServerTransport) {
+ defer st.Close()
+ var wg sync.WaitGroup
+ st.HandleStreams(func(stream *transport.Stream) {
+ wg.Add(1)
+ go func() {
+ defer wg.Done()
+ s.handleStream(st, stream, s.traceInfo(st, stream))
+ }()
+ }, func(ctx context.Context, method string) context.Context {
+ if !EnableTracing {
+ return ctx
+ }
+ tr := trace.New("grpc.Recv."+methodFamily(method), method)
+ return trace.NewContext(ctx, tr)
+ })
+ wg.Wait()
+}
+
+var _ http.Handler = (*Server)(nil)
+
+// ServeHTTP implements the Go standard library's http.Handler
+// interface by responding to the gRPC request r, by looking up
+// the requested gRPC method in the gRPC server s.
+//
+// The provided HTTP request must have arrived on an HTTP/2
+// connection. When using the Go standard library's server,
+// practically this means that the Request must also have arrived
+// over TLS.
+//
+// To share one port (such as 443 for https) between gRPC and an
+// existing http.Handler, use a root http.Handler such as:
+//
+// if r.ProtoMajor == 2 && strings.HasPrefix(
+// r.Header.Get("Content-Type"), "application/grpc") {
+// grpcServer.ServeHTTP(w, r)
+// } else {
+// yourMux.ServeHTTP(w, r)
+// }
+//
+// Note that ServeHTTP uses Go's HTTP/2 server implementation which is totally
+// separate from grpc-go's HTTP/2 server. Performance and features may vary
+// between the two paths. ServeHTTP does not support some gRPC features
+// available through grpc-go's HTTP/2 server, and it is currently EXPERIMENTAL
+// and subject to change.
+func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+ st, err := transport.NewServerHandlerTransport(w, r, s.opts.statsHandler)
+ if err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+ if !s.addConn(st) {
+ return
+ }
+ defer s.removeConn(st)
+ s.serveStreams(st)
+}
+
+// traceInfo returns a traceInfo and associates it with stream, if tracing is enabled.
+// If tracing is not enabled, it returns nil.
+func (s *Server) traceInfo(st transport.ServerTransport, stream *transport.Stream) (trInfo *traceInfo) {
+ tr, ok := trace.FromContext(stream.Context())
+ if !ok {
+ return nil
+ }
+
+ trInfo = &traceInfo{
+ tr: tr,
+ }
+ trInfo.firstLine.client = false
+ trInfo.firstLine.remoteAddr = st.RemoteAddr()
+
+ if dl, ok := stream.Context().Deadline(); ok {
+ trInfo.firstLine.deadline = dl.Sub(time.Now())
+ }
+ return trInfo
+}
+
+func (s *Server) addConn(c io.Closer) bool {
+ s.mu.Lock()
+ defer s.mu.Unlock()
+ if s.conns == nil {
+ c.Close()
+ return false
+ }
+ if s.drain {
+ // Transport added after we drained our existing conns: drain it
+ // immediately.
+ c.(transport.ServerTransport).Drain()
+ }
+ s.conns[c] = true
+ return true
+}
+
+func (s *Server) removeConn(c io.Closer) {
+ s.mu.Lock()
+ defer s.mu.Unlock()
+ if s.conns != nil {
+ delete(s.conns, c)
+ s.cv.Broadcast()
+ }
+}
+
+func (s *Server) channelzMetric() *channelz.ServerInternalMetric {
+ return &channelz.ServerInternalMetric{
+ CallsStarted: atomic.LoadInt64(&s.czData.callsStarted),
+ CallsSucceeded: atomic.LoadInt64(&s.czData.callsSucceeded),
+ CallsFailed: atomic.LoadInt64(&s.czData.callsFailed),
+ LastCallStartedTimestamp: time.Unix(0, atomic.LoadInt64(&s.czData.lastCallStartedTime)),
+ }
+}
+
+func (s *Server) incrCallsStarted() {
+ atomic.AddInt64(&s.czData.callsStarted, 1)
+ atomic.StoreInt64(&s.czData.lastCallStartedTime, time.Now().UnixNano())
+}
+
+func (s *Server) incrCallsSucceeded() {
+ atomic.AddInt64(&s.czData.callsSucceeded, 1)
+}
+
+func (s *Server) incrCallsFailed() {
+ atomic.AddInt64(&s.czData.callsFailed, 1)
+}
+
+func (s *Server) sendResponse(t transport.ServerTransport, stream *transport.Stream, msg interface{}, cp Compressor, opts *transport.Options, comp encoding.Compressor) error {
+ data, err := encode(s.getCodec(stream.ContentSubtype()), msg)
+ if err != nil {
+ grpclog.Errorln("grpc: server failed to encode response: ", err)
+ return err
+ }
+ compData, err := compress(data, cp, comp)
+ if err != nil {
+ grpclog.Errorln("grpc: server failed to compress response: ", err)
+ return err
+ }
+ hdr, payload := msgHeader(data, compData)
+ // TODO(dfawley): should we be checking len(data) instead?
+ if len(payload) > s.opts.maxSendMessageSize {
+ return status.Errorf(codes.ResourceExhausted, "grpc: trying to send message larger than max (%d vs. %d)", len(payload), s.opts.maxSendMessageSize)
+ }
+ err = t.Write(stream, hdr, payload, opts)
+ if err == nil && s.opts.statsHandler != nil {
+ s.opts.statsHandler.HandleRPC(stream.Context(), outPayload(false, msg, data, payload, time.Now()))
+ }
+ return err
+}
+
+func (s *Server) processUnaryRPC(t transport.ServerTransport, stream *transport.Stream, srv *service, md *MethodDesc, trInfo *traceInfo) (err error) {
+ if channelz.IsOn() {
+ s.incrCallsStarted()
+ defer func() {
+ if err != nil && err != io.EOF {
+ s.incrCallsFailed()
+ } else {
+ s.incrCallsSucceeded()
+ }
+ }()
+ }
+ sh := s.opts.statsHandler
+ if sh != nil {
+ beginTime := time.Now()
+ begin := &stats.Begin{
+ BeginTime: beginTime,
+ }
+ sh.HandleRPC(stream.Context(), begin)
+ defer func() {
+ end := &stats.End{
+ BeginTime: beginTime,
+ EndTime: time.Now(),
+ }
+ if err != nil && err != io.EOF {
+ end.Error = toRPCErr(err)
+ }
+ sh.HandleRPC(stream.Context(), end)
+ }()
+ }
+ if trInfo != nil {
+ defer trInfo.tr.Finish()
+ trInfo.firstLine.client = false
+ trInfo.tr.LazyLog(&trInfo.firstLine, false)
+ defer func() {
+ if err != nil && err != io.EOF {
+ trInfo.tr.LazyLog(&fmtStringer{"%v", []interface{}{err}}, true)
+ trInfo.tr.SetError()
+ }
+ }()
+ }
+
+ binlog := binarylog.GetMethodLogger(stream.Method())
+ if binlog != nil {
+ ctx := stream.Context()
+ md, _ := metadata.FromIncomingContext(ctx)
+ logEntry := &binarylog.ClientHeader{
+ Header: md,
+ MethodName: stream.Method(),
+ PeerAddr: nil,
+ }
+ if deadline, ok := ctx.Deadline(); ok {
+ logEntry.Timeout = deadline.Sub(time.Now())
+ if logEntry.Timeout < 0 {
+ logEntry.Timeout = 0
+ }
+ }
+ if a := md[":authority"]; len(a) > 0 {
+ logEntry.Authority = a[0]
+ }
+ if peer, ok := peer.FromContext(ctx); ok {
+ logEntry.PeerAddr = peer.Addr
+ }
+ binlog.Log(logEntry)
+ }
+
+ // comp and cp are used for compression. decomp and dc are used for
+ // decompression. If comp and decomp are both set, they are the same;
+ // however they are kept separate to ensure that at most one of the
+ // compressor/decompressor variable pairs are set for use later.
+ var comp, decomp encoding.Compressor
+ var cp Compressor
+ var dc Decompressor
+
+ // If dc is set and matches the stream's compression, use it. Otherwise, try
+ // to find a matching registered compressor for decomp.
+ if rc := stream.RecvCompress(); s.opts.dc != nil && s.opts.dc.Type() == rc {
+ dc = s.opts.dc
+ } else if rc != "" && rc != encoding.Identity {
+ decomp = encoding.GetCompressor(rc)
+ if decomp == nil {
+ st := status.Newf(codes.Unimplemented, "grpc: Decompressor is not installed for grpc-encoding %q", rc)
+ t.WriteStatus(stream, st)
+ return st.Err()
+ }
+ }
+
+ // If cp is set, use it. Otherwise, attempt to compress the response using
+ // the incoming message compression method.
+ //
+ // NOTE: this needs to be ahead of all handling, https://github.com/grpc/grpc-go/issues/686.
+ if s.opts.cp != nil {
+ cp = s.opts.cp
+ stream.SetSendCompress(cp.Type())
+ } else if rc := stream.RecvCompress(); rc != "" && rc != encoding.Identity {
+ // Legacy compressor not specified; attempt to respond with same encoding.
+ comp = encoding.GetCompressor(rc)
+ if comp != nil {
+ stream.SetSendCompress(rc)
+ }
+ }
+
+ var payInfo *payloadInfo
+ if sh != nil || binlog != nil {
+ payInfo = &payloadInfo{}
+ }
+ d, err := recvAndDecompress(&parser{r: stream}, stream, dc, s.opts.maxReceiveMessageSize, payInfo, decomp)
+ if err != nil {
+ if st, ok := status.FromError(err); ok {
+ if e := t.WriteStatus(stream, st); e != nil {
+ grpclog.Warningf("grpc: Server.processUnaryRPC failed to write status %v", e)
+ }
+ }
+ return err
+ }
+ if channelz.IsOn() {
+ t.IncrMsgRecv()
+ }
+ df := func(v interface{}) error {
+ if err := s.getCodec(stream.ContentSubtype()).Unmarshal(d, v); err != nil {
+ return status.Errorf(codes.Internal, "grpc: error unmarshalling request: %v", err)
+ }
+ if sh != nil {
+ sh.HandleRPC(stream.Context(), &stats.InPayload{
+ RecvTime: time.Now(),
+ Payload: v,
+ Data: d,
+ Length: len(d),
+ })
+ }
+ if binlog != nil {
+ binlog.Log(&binarylog.ClientMessage{
+ Message: d,
+ })
+ }
+ if trInfo != nil {
+ trInfo.tr.LazyLog(&payload{sent: false, msg: v}, true)
+ }
+ return nil
+ }
+ ctx := NewContextWithServerTransportStream(stream.Context(), stream)
+ reply, appErr := md.Handler(srv.server, ctx, df, s.opts.unaryInt)
+ if appErr != nil {
+ appStatus, ok := status.FromError(appErr)
+ if !ok {
+ // Convert appErr if it is not a grpc status error.
+ appErr = status.Error(codes.Unknown, appErr.Error())
+ appStatus, _ = status.FromError(appErr)
+ }
+ if trInfo != nil {
+ trInfo.tr.LazyLog(stringer(appStatus.Message()), true)
+ trInfo.tr.SetError()
+ }
+ if e := t.WriteStatus(stream, appStatus); e != nil {
+ grpclog.Warningf("grpc: Server.processUnaryRPC failed to write status: %v", e)
+ }
+ if binlog != nil {
+ if h, _ := stream.Header(); h.Len() > 0 {
+ // Only log serverHeader if there was header. Otherwise it can
+ // be trailer only.
+ binlog.Log(&binarylog.ServerHeader{
+ Header: h,
+ })
+ }
+ binlog.Log(&binarylog.ServerTrailer{
+ Trailer: stream.Trailer(),
+ Err: appErr,
+ })
+ }
+ return appErr
+ }
+ if trInfo != nil {
+ trInfo.tr.LazyLog(stringer("OK"), false)
+ }
+ opts := &transport.Options{Last: true}
+
+ if err := s.sendResponse(t, stream, reply, cp, opts, comp); err != nil {
+ if err == io.EOF {
+ // The entire stream is done (for unary RPC only).
+ return err
+ }
+ if s, ok := status.FromError(err); ok {
+ if e := t.WriteStatus(stream, s); e != nil {
+ grpclog.Warningf("grpc: Server.processUnaryRPC failed to write status: %v", e)
+ }
+ } else {
+ switch st := err.(type) {
+ case transport.ConnectionError:
+ // Nothing to do here.
+ default:
+ panic(fmt.Sprintf("grpc: Unexpected error (%T) from sendResponse: %v", st, st))
+ }
+ }
+ if binlog != nil {
+ h, _ := stream.Header()
+ binlog.Log(&binarylog.ServerHeader{
+ Header: h,
+ })
+ binlog.Log(&binarylog.ServerTrailer{
+ Trailer: stream.Trailer(),
+ Err: appErr,
+ })
+ }
+ return err
+ }
+ if binlog != nil {
+ h, _ := stream.Header()
+ binlog.Log(&binarylog.ServerHeader{
+ Header: h,
+ })
+ binlog.Log(&binarylog.ServerMessage{
+ Message: reply,
+ })
+ }
+ if channelz.IsOn() {
+ t.IncrMsgSent()
+ }
+ if trInfo != nil {
+ trInfo.tr.LazyLog(&payload{sent: true, msg: reply}, true)
+ }
+ // TODO: Should we be logging if writing status failed here, like above?
+ // Should the logging be in WriteStatus? Should we ignore the WriteStatus
+ // error or allow the stats handler to see it?
+ err = t.WriteStatus(stream, status.New(codes.OK, ""))
+ if binlog != nil {
+ binlog.Log(&binarylog.ServerTrailer{
+ Trailer: stream.Trailer(),
+ Err: appErr,
+ })
+ }
+ return err
+}
+
+func (s *Server) processStreamingRPC(t transport.ServerTransport, stream *transport.Stream, srv *service, sd *StreamDesc, trInfo *traceInfo) (err error) {
+ if channelz.IsOn() {
+ s.incrCallsStarted()
+ defer func() {
+ if err != nil && err != io.EOF {
+ s.incrCallsFailed()
+ } else {
+ s.incrCallsSucceeded()
+ }
+ }()
+ }
+ sh := s.opts.statsHandler
+ if sh != nil {
+ beginTime := time.Now()
+ begin := &stats.Begin{
+ BeginTime: beginTime,
+ }
+ sh.HandleRPC(stream.Context(), begin)
+ defer func() {
+ end := &stats.End{
+ BeginTime: beginTime,
+ EndTime: time.Now(),
+ }
+ if err != nil && err != io.EOF {
+ end.Error = toRPCErr(err)
+ }
+ sh.HandleRPC(stream.Context(), end)
+ }()
+ }
+ ctx := NewContextWithServerTransportStream(stream.Context(), stream)
+ ss := &serverStream{
+ ctx: ctx,
+ t: t,
+ s: stream,
+ p: &parser{r: stream},
+ codec: s.getCodec(stream.ContentSubtype()),
+ maxReceiveMessageSize: s.opts.maxReceiveMessageSize,
+ maxSendMessageSize: s.opts.maxSendMessageSize,
+ trInfo: trInfo,
+ statsHandler: sh,
+ }
+
+ ss.binlog = binarylog.GetMethodLogger(stream.Method())
+ if ss.binlog != nil {
+ md, _ := metadata.FromIncomingContext(ctx)
+ logEntry := &binarylog.ClientHeader{
+ Header: md,
+ MethodName: stream.Method(),
+ PeerAddr: nil,
+ }
+ if deadline, ok := ctx.Deadline(); ok {
+ logEntry.Timeout = deadline.Sub(time.Now())
+ if logEntry.Timeout < 0 {
+ logEntry.Timeout = 0
+ }
+ }
+ if a := md[":authority"]; len(a) > 0 {
+ logEntry.Authority = a[0]
+ }
+ if peer, ok := peer.FromContext(ss.Context()); ok {
+ logEntry.PeerAddr = peer.Addr
+ }
+ ss.binlog.Log(logEntry)
+ }
+
+ // If dc is set and matches the stream's compression, use it. Otherwise, try
+ // to find a matching registered compressor for decomp.
+ if rc := stream.RecvCompress(); s.opts.dc != nil && s.opts.dc.Type() == rc {
+ ss.dc = s.opts.dc
+ } else if rc != "" && rc != encoding.Identity {
+ ss.decomp = encoding.GetCompressor(rc)
+ if ss.decomp == nil {
+ st := status.Newf(codes.Unimplemented, "grpc: Decompressor is not installed for grpc-encoding %q", rc)
+ t.WriteStatus(ss.s, st)
+ return st.Err()
+ }
+ }
+
+ // If cp is set, use it. Otherwise, attempt to compress the response using
+ // the incoming message compression method.
+ //
+ // NOTE: this needs to be ahead of all handling, https://github.com/grpc/grpc-go/issues/686.
+ if s.opts.cp != nil {
+ ss.cp = s.opts.cp
+ stream.SetSendCompress(s.opts.cp.Type())
+ } else if rc := stream.RecvCompress(); rc != "" && rc != encoding.Identity {
+ // Legacy compressor not specified; attempt to respond with same encoding.
+ ss.comp = encoding.GetCompressor(rc)
+ if ss.comp != nil {
+ stream.SetSendCompress(rc)
+ }
+ }
+
+ if trInfo != nil {
+ trInfo.tr.LazyLog(&trInfo.firstLine, false)
+ defer func() {
+ ss.mu.Lock()
+ if err != nil && err != io.EOF {
+ ss.trInfo.tr.LazyLog(&fmtStringer{"%v", []interface{}{err}}, true)
+ ss.trInfo.tr.SetError()
+ }
+ ss.trInfo.tr.Finish()
+ ss.trInfo.tr = nil
+ ss.mu.Unlock()
+ }()
+ }
+ var appErr error
+ var server interface{}
+ if srv != nil {
+ server = srv.server
+ }
+ if s.opts.streamInt == nil {
+ appErr = sd.Handler(server, ss)
+ } else {
+ info := &StreamServerInfo{
+ FullMethod: stream.Method(),
+ IsClientStream: sd.ClientStreams,
+ IsServerStream: sd.ServerStreams,
+ }
+ appErr = s.opts.streamInt(server, ss, info, sd.Handler)
+ }
+ if appErr != nil {
+ appStatus, ok := status.FromError(appErr)
+ if !ok {
+ appStatus = status.New(codes.Unknown, appErr.Error())
+ appErr = appStatus.Err()
+ }
+ if trInfo != nil {
+ ss.mu.Lock()
+ ss.trInfo.tr.LazyLog(stringer(appStatus.Message()), true)
+ ss.trInfo.tr.SetError()
+ ss.mu.Unlock()
+ }
+ t.WriteStatus(ss.s, appStatus)
+ if ss.binlog != nil {
+ ss.binlog.Log(&binarylog.ServerTrailer{
+ Trailer: ss.s.Trailer(),
+ Err: appErr,
+ })
+ }
+ // TODO: Should we log an error from WriteStatus here and below?
+ return appErr
+ }
+ if trInfo != nil {
+ ss.mu.Lock()
+ ss.trInfo.tr.LazyLog(stringer("OK"), false)
+ ss.mu.Unlock()
+ }
+ err = t.WriteStatus(ss.s, status.New(codes.OK, ""))
+ if ss.binlog != nil {
+ ss.binlog.Log(&binarylog.ServerTrailer{
+ Trailer: ss.s.Trailer(),
+ Err: appErr,
+ })
+ }
+ return err
+}
+
+func (s *Server) handleStream(t transport.ServerTransport, stream *transport.Stream, trInfo *traceInfo) {
+ sm := stream.Method()
+ if sm != "" && sm[0] == '/' {
+ sm = sm[1:]
+ }
+ pos := strings.LastIndex(sm, "/")
+ if pos == -1 {
+ if trInfo != nil {
+ trInfo.tr.LazyLog(&fmtStringer{"Malformed method name %q", []interface{}{sm}}, true)
+ trInfo.tr.SetError()
+ }
+ errDesc := fmt.Sprintf("malformed method name: %q", stream.Method())
+ if err := t.WriteStatus(stream, status.New(codes.ResourceExhausted, errDesc)); err != nil {
+ if trInfo != nil {
+ trInfo.tr.LazyLog(&fmtStringer{"%v", []interface{}{err}}, true)
+ trInfo.tr.SetError()
+ }
+ grpclog.Warningf("grpc: Server.handleStream failed to write status: %v", err)
+ }
+ if trInfo != nil {
+ trInfo.tr.Finish()
+ }
+ return
+ }
+ service := sm[:pos]
+ method := sm[pos+1:]
+
+ if srv, ok := s.m[service]; ok {
+ if md, ok := srv.md[method]; ok {
+ s.processUnaryRPC(t, stream, srv, md, trInfo)
+ return
+ }
+ if sd, ok := srv.sd[method]; ok {
+ s.processStreamingRPC(t, stream, srv, sd, trInfo)
+ return
+ }
+ }
+ // Unknown service, or known server unknown method.
+ if unknownDesc := s.opts.unknownStreamDesc; unknownDesc != nil {
+ s.processStreamingRPC(t, stream, nil, unknownDesc, trInfo)
+ return
+ }
+ if trInfo != nil {
+ trInfo.tr.LazyLog(&fmtStringer{"Unknown service %v", []interface{}{service}}, true)
+ trInfo.tr.SetError()
+ }
+ errDesc := fmt.Sprintf("unknown service %v", service)
+ if err := t.WriteStatus(stream, status.New(codes.Unimplemented, errDesc)); err != nil {
+ if trInfo != nil {
+ trInfo.tr.LazyLog(&fmtStringer{"%v", []interface{}{err}}, true)
+ trInfo.tr.SetError()
+ }
+ grpclog.Warningf("grpc: Server.handleStream failed to write status: %v", err)
+ }
+ if trInfo != nil {
+ trInfo.tr.Finish()
+ }
+}
+
+// The key to save ServerTransportStream in the context.
+type streamKey struct{}
+
+// NewContextWithServerTransportStream creates a new context from ctx and
+// attaches stream to it.
+//
+// This API is EXPERIMENTAL.
+func NewContextWithServerTransportStream(ctx context.Context, stream ServerTransportStream) context.Context {
+ return context.WithValue(ctx, streamKey{}, stream)
+}
+
+// ServerTransportStream is a minimal interface that a transport stream must
+// implement. This can be used to mock an actual transport stream for tests of
+// handler code that use, for example, grpc.SetHeader (which requires some
+// stream to be in context).
+//
+// See also NewContextWithServerTransportStream.
+//
+// This API is EXPERIMENTAL.
+type ServerTransportStream interface {
+ Method() string
+ SetHeader(md metadata.MD) error
+ SendHeader(md metadata.MD) error
+ SetTrailer(md metadata.MD) error
+}
+
+// ServerTransportStreamFromContext returns the ServerTransportStream saved in
+// ctx. Returns nil if the given context has no stream associated with it
+// (which implies it is not an RPC invocation context).
+//
+// This API is EXPERIMENTAL.
+func ServerTransportStreamFromContext(ctx context.Context) ServerTransportStream {
+ s, _ := ctx.Value(streamKey{}).(ServerTransportStream)
+ return s
+}
+
+// Stop stops the gRPC server. It immediately closes all open
+// connections and listeners.
+// It cancels all active RPCs on the server side and the corresponding
+// pending RPCs on the client side will get notified by connection
+// errors.
+func (s *Server) Stop() {
+ s.quitOnce.Do(func() {
+ close(s.quit)
+ })
+
+ defer func() {
+ s.serveWG.Wait()
+ s.doneOnce.Do(func() {
+ close(s.done)
+ })
+ }()
+
+ s.channelzRemoveOnce.Do(func() {
+ if channelz.IsOn() {
+ channelz.RemoveEntry(s.channelzID)
+ }
+ })
+
+ s.mu.Lock()
+ listeners := s.lis
+ s.lis = nil
+ st := s.conns
+ s.conns = nil
+ // interrupt GracefulStop if Stop and GracefulStop are called concurrently.
+ s.cv.Broadcast()
+ s.mu.Unlock()
+
+ for lis := range listeners {
+ lis.Close()
+ }
+ for c := range st {
+ c.Close()
+ }
+
+ s.mu.Lock()
+ if s.events != nil {
+ s.events.Finish()
+ s.events = nil
+ }
+ s.mu.Unlock()
+}
+
+// GracefulStop stops the gRPC server gracefully. It stops the server from
+// accepting new connections and RPCs and blocks until all the pending RPCs are
+// finished.
+func (s *Server) GracefulStop() {
+ s.quitOnce.Do(func() {
+ close(s.quit)
+ })
+
+ defer func() {
+ s.doneOnce.Do(func() {
+ close(s.done)
+ })
+ }()
+
+ s.channelzRemoveOnce.Do(func() {
+ if channelz.IsOn() {
+ channelz.RemoveEntry(s.channelzID)
+ }
+ })
+ s.mu.Lock()
+ if s.conns == nil {
+ s.mu.Unlock()
+ return
+ }
+
+ for lis := range s.lis {
+ lis.Close()
+ }
+ s.lis = nil
+ if !s.drain {
+ for c := range s.conns {
+ c.(transport.ServerTransport).Drain()
+ }
+ s.drain = true
+ }
+
+ // Wait for serving threads to be ready to exit. Only then can we be sure no
+ // new conns will be created.
+ s.mu.Unlock()
+ s.serveWG.Wait()
+ s.mu.Lock()
+
+ for len(s.conns) != 0 {
+ s.cv.Wait()
+ }
+ s.conns = nil
+ if s.events != nil {
+ s.events.Finish()
+ s.events = nil
+ }
+ s.mu.Unlock()
+}
+
+// contentSubtype must be lowercase
+// cannot return nil
+func (s *Server) getCodec(contentSubtype string) baseCodec {
+ if s.opts.codec != nil {
+ return s.opts.codec
+ }
+ if contentSubtype == "" {
+ return encoding.GetCodec(proto.Name)
+ }
+ codec := encoding.GetCodec(contentSubtype)
+ if codec == nil {
+ return encoding.GetCodec(proto.Name)
+ }
+ return codec
+}
+
+// SetHeader sets the header metadata.
+// When called multiple times, all the provided metadata will be merged.
+// All the metadata will be sent out when one of the following happens:
+// - grpc.SendHeader() is called;
+// - The first response is sent out;
+// - An RPC status is sent out (error or success).
+func SetHeader(ctx context.Context, md metadata.MD) error {
+ if md.Len() == 0 {
+ return nil
+ }
+ stream := ServerTransportStreamFromContext(ctx)
+ if stream == nil {
+ return status.Errorf(codes.Internal, "grpc: failed to fetch the stream from the context %v", ctx)
+ }
+ return stream.SetHeader(md)
+}
+
+// SendHeader sends header metadata. It may be called at most once.
+// The provided md and headers set by SetHeader() will be sent.
+func SendHeader(ctx context.Context, md metadata.MD) error {
+ stream := ServerTransportStreamFromContext(ctx)
+ if stream == nil {
+ return status.Errorf(codes.Internal, "grpc: failed to fetch the stream from the context %v", ctx)
+ }
+ if err := stream.SendHeader(md); err != nil {
+ return toRPCErr(err)
+ }
+ return nil
+}
+
+// SetTrailer sets the trailer metadata that will be sent when an RPC returns.
+// When called more than once, all the provided metadata will be merged.
+func SetTrailer(ctx context.Context, md metadata.MD) error {
+ if md.Len() == 0 {
+ return nil
+ }
+ stream := ServerTransportStreamFromContext(ctx)
+ if stream == nil {
+ return status.Errorf(codes.Internal, "grpc: failed to fetch the stream from the context %v", ctx)
+ }
+ return stream.SetTrailer(md)
+}
+
+// Method returns the method string for the server context. The returned
+// string is in the format of "/service/method".
+func Method(ctx context.Context) (string, bool) {
+ s := ServerTransportStreamFromContext(ctx)
+ if s == nil {
+ return "", false
+ }
+ return s.Method(), true
+}
+
+type channelzServer struct {
+ s *Server
+}
+
+func (c *channelzServer) ChannelzMetric() *channelz.ServerInternalMetric {
+ return c.s.channelzMetric()
+}
diff --git a/vendor/google.golang.org/grpc/service_config.go b/vendor/google.golang.org/grpc/service_config.go
new file mode 100644
index 000000000..162857e20
--- /dev/null
+++ b/vendor/google.golang.org/grpc/service_config.go
@@ -0,0 +1,372 @@
+/*
+ *
+ * Copyright 2017 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package grpc
+
+import (
+ "encoding/json"
+ "fmt"
+ "strconv"
+ "strings"
+ "time"
+
+ "google.golang.org/grpc/codes"
+ "google.golang.org/grpc/grpclog"
+)
+
+const maxInt = int(^uint(0) >> 1)
+
+// MethodConfig defines the configuration recommended by the service providers for a
+// particular method.
+//
+// Deprecated: Users should not use this struct. Service config should be received
+// through name resolver, as specified here
+// https://github.com/grpc/grpc/blob/master/doc/service_config.md
+type MethodConfig struct {
+ // WaitForReady indicates whether RPCs sent to this method should wait until
+ // the connection is ready by default (!failfast). The value specified via the
+ // gRPC client API will override the value set here.
+ WaitForReady *bool
+ // Timeout is the default timeout for RPCs sent to this method. The actual
+ // deadline used will be the minimum of the value specified here and the value
+ // set by the application via the gRPC client API. If either one is not set,
+ // then the other will be used. If neither is set, then the RPC has no deadline.
+ Timeout *time.Duration
+ // MaxReqSize is the maximum allowed payload size for an individual request in a
+ // stream (client->server) in bytes. The size which is measured is the serialized
+ // payload after per-message compression (but before stream compression) in bytes.
+ // The actual value used is the minimum of the value specified here and the value set
+ // by the application via the gRPC client API. If either one is not set, then the other
+ // will be used. If neither is set, then the built-in default is used.
+ MaxReqSize *int
+ // MaxRespSize is the maximum allowed payload size for an individual response in a
+ // stream (server->client) in bytes.
+ MaxRespSize *int
+ // RetryPolicy configures retry options for the method.
+ retryPolicy *retryPolicy
+}
+
+// ServiceConfig is provided by the service provider and contains parameters for how
+// clients that connect to the service should behave.
+//
+// Deprecated: Users should not use this struct. Service config should be received
+// through name resolver, as specified here
+// https://github.com/grpc/grpc/blob/master/doc/service_config.md
+type ServiceConfig struct {
+ // LB is the load balancer the service providers recommends. The balancer specified
+ // via grpc.WithBalancer will override this.
+ LB *string
+
+ // Methods contains a map for the methods in this service. If there is an
+ // exact match for a method (i.e. /service/method) in the map, use the
+ // corresponding MethodConfig. If there's no exact match, look for the
+ // default config for the service (/service/) and use the corresponding
+ // MethodConfig if it exists. Otherwise, the method has no MethodConfig to
+ // use.
+ Methods map[string]MethodConfig
+
+ // If a retryThrottlingPolicy is provided, gRPC will automatically throttle
+ // retry attempts and hedged RPCs when the client’s ratio of failures to
+ // successes exceeds a threshold.
+ //
+ // For each server name, the gRPC client will maintain a token_count which is
+ // initially set to maxTokens, and can take values between 0 and maxTokens.
+ //
+ // Every outgoing RPC (regardless of service or method invoked) will change
+ // token_count as follows:
+ //
+ // - Every failed RPC will decrement the token_count by 1.
+ // - Every successful RPC will increment the token_count by tokenRatio.
+ //
+ // If token_count is less than or equal to maxTokens / 2, then RPCs will not
+ // be retried and hedged RPCs will not be sent.
+ retryThrottling *retryThrottlingPolicy
+ // healthCheckConfig must be set as one of the requirement to enable LB channel
+ // health check.
+ healthCheckConfig *healthCheckConfig
+}
+
+// healthCheckConfig defines the go-native version of the LB channel health check config.
+type healthCheckConfig struct {
+ // serviceName is the service name to use in the health-checking request.
+ ServiceName string
+}
+
+// retryPolicy defines the go-native version of the retry policy defined by the
+// service config here:
+// https://github.com/grpc/proposal/blob/master/A6-client-retries.md#integration-with-service-config
+type retryPolicy struct {
+ // MaxAttempts is the maximum number of attempts, including the original RPC.
+ //
+ // This field is required and must be two or greater.
+ maxAttempts int
+
+ // Exponential backoff parameters. The initial retry attempt will occur at
+ // random(0, initialBackoffMS). In general, the nth attempt will occur at
+ // random(0,
+ // min(initialBackoffMS*backoffMultiplier**(n-1), maxBackoffMS)).
+ //
+ // These fields are required and must be greater than zero.
+ initialBackoff time.Duration
+ maxBackoff time.Duration
+ backoffMultiplier float64
+
+ // The set of status codes which may be retried.
+ //
+ // Status codes are specified as strings, e.g., "UNAVAILABLE".
+ //
+ // This field is required and must be non-empty.
+ // Note: a set is used to store this for easy lookup.
+ retryableStatusCodes map[codes.Code]bool
+}
+
+type jsonRetryPolicy struct {
+ MaxAttempts int
+ InitialBackoff string
+ MaxBackoff string
+ BackoffMultiplier float64
+ RetryableStatusCodes []codes.Code
+}
+
+// retryThrottlingPolicy defines the go-native version of the retry throttling
+// policy defined by the service config here:
+// https://github.com/grpc/proposal/blob/master/A6-client-retries.md#integration-with-service-config
+type retryThrottlingPolicy struct {
+ // The number of tokens starts at maxTokens. The token_count will always be
+ // between 0 and maxTokens.
+ //
+ // This field is required and must be greater than zero.
+ MaxTokens float64
+ // The amount of tokens to add on each successful RPC. Typically this will
+ // be some number between 0 and 1, e.g., 0.1.
+ //
+ // This field is required and must be greater than zero. Up to 3 decimal
+ // places are supported.
+ TokenRatio float64
+}
+
+func parseDuration(s *string) (*time.Duration, error) {
+ if s == nil {
+ return nil, nil
+ }
+ if !strings.HasSuffix(*s, "s") {
+ return nil, fmt.Errorf("malformed duration %q", *s)
+ }
+ ss := strings.SplitN((*s)[:len(*s)-1], ".", 3)
+ if len(ss) > 2 {
+ return nil, fmt.Errorf("malformed duration %q", *s)
+ }
+ // hasDigits is set if either the whole or fractional part of the number is
+ // present, since both are optional but one is required.
+ hasDigits := false
+ var d time.Duration
+ if len(ss[0]) > 0 {
+ i, err := strconv.ParseInt(ss[0], 10, 32)
+ if err != nil {
+ return nil, fmt.Errorf("malformed duration %q: %v", *s, err)
+ }
+ d = time.Duration(i) * time.Second
+ hasDigits = true
+ }
+ if len(ss) == 2 && len(ss[1]) > 0 {
+ if len(ss[1]) > 9 {
+ return nil, fmt.Errorf("malformed duration %q", *s)
+ }
+ f, err := strconv.ParseInt(ss[1], 10, 64)
+ if err != nil {
+ return nil, fmt.Errorf("malformed duration %q: %v", *s, err)
+ }
+ for i := 9; i > len(ss[1]); i-- {
+ f *= 10
+ }
+ d += time.Duration(f)
+ hasDigits = true
+ }
+ if !hasDigits {
+ return nil, fmt.Errorf("malformed duration %q", *s)
+ }
+
+ return &d, nil
+}
+
+type jsonName struct {
+ Service *string
+ Method *string
+}
+
+func (j jsonName) generatePath() (string, bool) {
+ if j.Service == nil {
+ return "", false
+ }
+ res := "/" + *j.Service + "/"
+ if j.Method != nil {
+ res += *j.Method
+ }
+ return res, true
+}
+
+// TODO(lyuxuan): delete this struct after cleaning up old service config implementation.
+type jsonMC struct {
+ Name *[]jsonName
+ WaitForReady *bool
+ Timeout *string
+ MaxRequestMessageBytes *int64
+ MaxResponseMessageBytes *int64
+ RetryPolicy *jsonRetryPolicy
+}
+
+// TODO(lyuxuan): delete this struct after cleaning up old service config implementation.
+type jsonSC struct {
+ LoadBalancingPolicy *string
+ MethodConfig *[]jsonMC
+ RetryThrottling *retryThrottlingPolicy
+ HealthCheckConfig *healthCheckConfig
+}
+
+func parseServiceConfig(js string) (ServiceConfig, error) {
+ if len(js) == 0 {
+ return ServiceConfig{}, fmt.Errorf("no JSON service config provided")
+ }
+ var rsc jsonSC
+ err := json.Unmarshal([]byte(js), &rsc)
+ if err != nil {
+ grpclog.Warningf("grpc: parseServiceConfig error unmarshaling %s due to %v", js, err)
+ return ServiceConfig{}, err
+ }
+ sc := ServiceConfig{
+ LB: rsc.LoadBalancingPolicy,
+ Methods: make(map[string]MethodConfig),
+ retryThrottling: rsc.RetryThrottling,
+ healthCheckConfig: rsc.HealthCheckConfig,
+ }
+ if rsc.MethodConfig == nil {
+ return sc, nil
+ }
+
+ for _, m := range *rsc.MethodConfig {
+ if m.Name == nil {
+ continue
+ }
+ d, err := parseDuration(m.Timeout)
+ if err != nil {
+ grpclog.Warningf("grpc: parseServiceConfig error unmarshaling %s due to %v", js, err)
+ return ServiceConfig{}, err
+ }
+
+ mc := MethodConfig{
+ WaitForReady: m.WaitForReady,
+ Timeout: d,
+ }
+ if mc.retryPolicy, err = convertRetryPolicy(m.RetryPolicy); err != nil {
+ grpclog.Warningf("grpc: parseServiceConfig error unmarshaling %s due to %v", js, err)
+ return ServiceConfig{}, err
+ }
+ if m.MaxRequestMessageBytes != nil {
+ if *m.MaxRequestMessageBytes > int64(maxInt) {
+ mc.MaxReqSize = newInt(maxInt)
+ } else {
+ mc.MaxReqSize = newInt(int(*m.MaxRequestMessageBytes))
+ }
+ }
+ if m.MaxResponseMessageBytes != nil {
+ if *m.MaxResponseMessageBytes > int64(maxInt) {
+ mc.MaxRespSize = newInt(maxInt)
+ } else {
+ mc.MaxRespSize = newInt(int(*m.MaxResponseMessageBytes))
+ }
+ }
+ for _, n := range *m.Name {
+ if path, valid := n.generatePath(); valid {
+ sc.Methods[path] = mc
+ }
+ }
+ }
+
+ if sc.retryThrottling != nil {
+ if sc.retryThrottling.MaxTokens <= 0 ||
+ sc.retryThrottling.MaxTokens >= 1000 ||
+ sc.retryThrottling.TokenRatio <= 0 {
+ // Illegal throttling config; disable throttling.
+ sc.retryThrottling = nil
+ }
+ }
+ return sc, nil
+}
+
+func convertRetryPolicy(jrp *jsonRetryPolicy) (p *retryPolicy, err error) {
+ if jrp == nil {
+ return nil, nil
+ }
+ ib, err := parseDuration(&jrp.InitialBackoff)
+ if err != nil {
+ return nil, err
+ }
+ mb, err := parseDuration(&jrp.MaxBackoff)
+ if err != nil {
+ return nil, err
+ }
+
+ if jrp.MaxAttempts <= 1 ||
+ *ib <= 0 ||
+ *mb <= 0 ||
+ jrp.BackoffMultiplier <= 0 ||
+ len(jrp.RetryableStatusCodes) == 0 {
+ grpclog.Warningf("grpc: ignoring retry policy %v due to illegal configuration", jrp)
+ return nil, nil
+ }
+
+ rp := &retryPolicy{
+ maxAttempts: jrp.MaxAttempts,
+ initialBackoff: *ib,
+ maxBackoff: *mb,
+ backoffMultiplier: jrp.BackoffMultiplier,
+ retryableStatusCodes: make(map[codes.Code]bool),
+ }
+ if rp.maxAttempts > 5 {
+ // TODO(retry): Make the max maxAttempts configurable.
+ rp.maxAttempts = 5
+ }
+ for _, code := range jrp.RetryableStatusCodes {
+ rp.retryableStatusCodes[code] = true
+ }
+ return rp, nil
+}
+
+func min(a, b *int) *int {
+ if *a < *b {
+ return a
+ }
+ return b
+}
+
+func getMaxSize(mcMax, doptMax *int, defaultVal int) *int {
+ if mcMax == nil && doptMax == nil {
+ return &defaultVal
+ }
+ if mcMax != nil && doptMax != nil {
+ return min(mcMax, doptMax)
+ }
+ if mcMax != nil {
+ return mcMax
+ }
+ return doptMax
+}
+
+func newInt(b int) *int {
+ return &b
+}
diff --git a/vendor/google.golang.org/grpc/stats/handlers.go b/vendor/google.golang.org/grpc/stats/handlers.go
new file mode 100644
index 000000000..dc03731e4
--- /dev/null
+++ b/vendor/google.golang.org/grpc/stats/handlers.go
@@ -0,0 +1,63 @@
+/*
+ *
+ * Copyright 2016 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package stats
+
+import (
+ "context"
+ "net"
+)
+
+// ConnTagInfo defines the relevant information needed by connection context tagger.
+type ConnTagInfo struct {
+ // RemoteAddr is the remote address of the corresponding connection.
+ RemoteAddr net.Addr
+ // LocalAddr is the local address of the corresponding connection.
+ LocalAddr net.Addr
+}
+
+// RPCTagInfo defines the relevant information needed by RPC context tagger.
+type RPCTagInfo struct {
+ // FullMethodName is the RPC method in the format of /package.service/method.
+ FullMethodName string
+ // FailFast indicates if this RPC is failfast.
+ // This field is only valid on client side, it's always false on server side.
+ FailFast bool
+}
+
+// Handler defines the interface for the related stats handling (e.g., RPCs, connections).
+type Handler interface {
+ // TagRPC can attach some information to the given context.
+ // The context used for the rest lifetime of the RPC will be derived from
+ // the returned context.
+ TagRPC(context.Context, *RPCTagInfo) context.Context
+ // HandleRPC processes the RPC stats.
+ HandleRPC(context.Context, RPCStats)
+
+ // TagConn can attach some information to the given context.
+ // The returned context will be used for stats handling.
+ // For conn stats handling, the context used in HandleConn for this
+ // connection will be derived from the context returned.
+ // For RPC stats handling,
+ // - On server side, the context used in HandleRPC for all RPCs on this
+ // connection will be derived from the context returned.
+ // - On client side, the context is not derived from the context returned.
+ TagConn(context.Context, *ConnTagInfo) context.Context
+ // HandleConn processes the Conn stats.
+ HandleConn(context.Context, ConnStats)
+}
diff --git a/vendor/google.golang.org/grpc/stats/stats.go b/vendor/google.golang.org/grpc/stats/stats.go
new file mode 100644
index 000000000..84f77dafa
--- /dev/null
+++ b/vendor/google.golang.org/grpc/stats/stats.go
@@ -0,0 +1,295 @@
+/*
+ *
+ * Copyright 2016 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+//go:generate protoc --go_out=plugins=grpc:. grpc_testing/test.proto
+
+// Package stats is for collecting and reporting various network and RPC stats.
+// This package is for monitoring purpose only. All fields are read-only.
+// All APIs are experimental.
+package stats // import "google.golang.org/grpc/stats"
+
+import (
+ "context"
+ "net"
+ "time"
+)
+
+// RPCStats contains stats information about RPCs.
+type RPCStats interface {
+ isRPCStats()
+ // IsClient returns true if this RPCStats is from client side.
+ IsClient() bool
+}
+
+// Begin contains stats when an RPC begins.
+// FailFast is only valid if this Begin is from client side.
+type Begin struct {
+ // Client is true if this Begin is from client side.
+ Client bool
+ // BeginTime is the time when the RPC begins.
+ BeginTime time.Time
+ // FailFast indicates if this RPC is failfast.
+ FailFast bool
+}
+
+// IsClient indicates if the stats information is from client side.
+func (s *Begin) IsClient() bool { return s.Client }
+
+func (s *Begin) isRPCStats() {}
+
+// InPayload contains the information for an incoming payload.
+type InPayload struct {
+ // Client is true if this InPayload is from client side.
+ Client bool
+ // Payload is the payload with original type.
+ Payload interface{}
+ // Data is the serialized message payload.
+ Data []byte
+ // Length is the length of uncompressed data.
+ Length int
+ // WireLength is the length of data on wire (compressed, signed, encrypted).
+ WireLength int
+ // RecvTime is the time when the payload is received.
+ RecvTime time.Time
+}
+
+// IsClient indicates if the stats information is from client side.
+func (s *InPayload) IsClient() bool { return s.Client }
+
+func (s *InPayload) isRPCStats() {}
+
+// InHeader contains stats when a header is received.
+type InHeader struct {
+ // Client is true if this InHeader is from client side.
+ Client bool
+ // WireLength is the wire length of header.
+ WireLength int
+
+ // The following fields are valid only if Client is false.
+ // FullMethod is the full RPC method string, i.e., /package.service/method.
+ FullMethod string
+ // RemoteAddr is the remote address of the corresponding connection.
+ RemoteAddr net.Addr
+ // LocalAddr is the local address of the corresponding connection.
+ LocalAddr net.Addr
+ // Compression is the compression algorithm used for the RPC.
+ Compression string
+}
+
+// IsClient indicates if the stats information is from client side.
+func (s *InHeader) IsClient() bool { return s.Client }
+
+func (s *InHeader) isRPCStats() {}
+
+// InTrailer contains stats when a trailer is received.
+type InTrailer struct {
+ // Client is true if this InTrailer is from client side.
+ Client bool
+ // WireLength is the wire length of trailer.
+ WireLength int
+}
+
+// IsClient indicates if the stats information is from client side.
+func (s *InTrailer) IsClient() bool { return s.Client }
+
+func (s *InTrailer) isRPCStats() {}
+
+// OutPayload contains the information for an outgoing payload.
+type OutPayload struct {
+ // Client is true if this OutPayload is from client side.
+ Client bool
+ // Payload is the payload with original type.
+ Payload interface{}
+ // Data is the serialized message payload.
+ Data []byte
+ // Length is the length of uncompressed data.
+ Length int
+ // WireLength is the length of data on wire (compressed, signed, encrypted).
+ WireLength int
+ // SentTime is the time when the payload is sent.
+ SentTime time.Time
+}
+
+// IsClient indicates if this stats information is from client side.
+func (s *OutPayload) IsClient() bool { return s.Client }
+
+func (s *OutPayload) isRPCStats() {}
+
+// OutHeader contains stats when a header is sent.
+type OutHeader struct {
+ // Client is true if this OutHeader is from client side.
+ Client bool
+
+ // The following fields are valid only if Client is true.
+ // FullMethod is the full RPC method string, i.e., /package.service/method.
+ FullMethod string
+ // RemoteAddr is the remote address of the corresponding connection.
+ RemoteAddr net.Addr
+ // LocalAddr is the local address of the corresponding connection.
+ LocalAddr net.Addr
+ // Compression is the compression algorithm used for the RPC.
+ Compression string
+}
+
+// IsClient indicates if this stats information is from client side.
+func (s *OutHeader) IsClient() bool { return s.Client }
+
+func (s *OutHeader) isRPCStats() {}
+
+// OutTrailer contains stats when a trailer is sent.
+type OutTrailer struct {
+ // Client is true if this OutTrailer is from client side.
+ Client bool
+ // WireLength is the wire length of trailer.
+ WireLength int
+}
+
+// IsClient indicates if this stats information is from client side.
+func (s *OutTrailer) IsClient() bool { return s.Client }
+
+func (s *OutTrailer) isRPCStats() {}
+
+// End contains stats when an RPC ends.
+type End struct {
+ // Client is true if this End is from client side.
+ Client bool
+ // BeginTime is the time when the RPC began.
+ BeginTime time.Time
+ // EndTime is the time when the RPC ends.
+ EndTime time.Time
+ // Error is the error the RPC ended with. It is an error generated from
+ // status.Status and can be converted back to status.Status using
+ // status.FromError if non-nil.
+ Error error
+}
+
+// IsClient indicates if this is from client side.
+func (s *End) IsClient() bool { return s.Client }
+
+func (s *End) isRPCStats() {}
+
+// ConnStats contains stats information about connections.
+type ConnStats interface {
+ isConnStats()
+ // IsClient returns true if this ConnStats is from client side.
+ IsClient() bool
+}
+
+// ConnBegin contains the stats of a connection when it is established.
+type ConnBegin struct {
+ // Client is true if this ConnBegin is from client side.
+ Client bool
+}
+
+// IsClient indicates if this is from client side.
+func (s *ConnBegin) IsClient() bool { return s.Client }
+
+func (s *ConnBegin) isConnStats() {}
+
+// ConnEnd contains the stats of a connection when it ends.
+type ConnEnd struct {
+ // Client is true if this ConnEnd is from client side.
+ Client bool
+}
+
+// IsClient indicates if this is from client side.
+func (s *ConnEnd) IsClient() bool { return s.Client }
+
+func (s *ConnEnd) isConnStats() {}
+
+type incomingTagsKey struct{}
+type outgoingTagsKey struct{}
+
+// SetTags attaches stats tagging data to the context, which will be sent in
+// the outgoing RPC with the header grpc-tags-bin. Subsequent calls to
+// SetTags will overwrite the values from earlier calls.
+//
+// NOTE: this is provided only for backward compatibility with existing clients
+// and will likely be removed in an upcoming release. New uses should transmit
+// this type of data using metadata with a different, non-reserved (i.e. does
+// not begin with "grpc-") header name.
+func SetTags(ctx context.Context, b []byte) context.Context {
+ return context.WithValue(ctx, outgoingTagsKey{}, b)
+}
+
+// Tags returns the tags from the context for the inbound RPC.
+//
+// NOTE: this is provided only for backward compatibility with existing clients
+// and will likely be removed in an upcoming release. New uses should transmit
+// this type of data using metadata with a different, non-reserved (i.e. does
+// not begin with "grpc-") header name.
+func Tags(ctx context.Context) []byte {
+ b, _ := ctx.Value(incomingTagsKey{}).([]byte)
+ return b
+}
+
+// SetIncomingTags attaches stats tagging data to the context, to be read by
+// the application (not sent in outgoing RPCs).
+//
+// This is intended for gRPC-internal use ONLY.
+func SetIncomingTags(ctx context.Context, b []byte) context.Context {
+ return context.WithValue(ctx, incomingTagsKey{}, b)
+}
+
+// OutgoingTags returns the tags from the context for the outbound RPC.
+//
+// This is intended for gRPC-internal use ONLY.
+func OutgoingTags(ctx context.Context) []byte {
+ b, _ := ctx.Value(outgoingTagsKey{}).([]byte)
+ return b
+}
+
+type incomingTraceKey struct{}
+type outgoingTraceKey struct{}
+
+// SetTrace attaches stats tagging data to the context, which will be sent in
+// the outgoing RPC with the header grpc-trace-bin. Subsequent calls to
+// SetTrace will overwrite the values from earlier calls.
+//
+// NOTE: this is provided only for backward compatibility with existing clients
+// and will likely be removed in an upcoming release. New uses should transmit
+// this type of data using metadata with a different, non-reserved (i.e. does
+// not begin with "grpc-") header name.
+func SetTrace(ctx context.Context, b []byte) context.Context {
+ return context.WithValue(ctx, outgoingTraceKey{}, b)
+}
+
+// Trace returns the trace from the context for the inbound RPC.
+//
+// NOTE: this is provided only for backward compatibility with existing clients
+// and will likely be removed in an upcoming release. New uses should transmit
+// this type of data using metadata with a different, non-reserved (i.e. does
+// not begin with "grpc-") header name.
+func Trace(ctx context.Context) []byte {
+ b, _ := ctx.Value(incomingTraceKey{}).([]byte)
+ return b
+}
+
+// SetIncomingTrace attaches stats tagging data to the context, to be read by
+// the application (not sent in outgoing RPCs). It is intended for
+// gRPC-internal use.
+func SetIncomingTrace(ctx context.Context, b []byte) context.Context {
+ return context.WithValue(ctx, incomingTraceKey{}, b)
+}
+
+// OutgoingTrace returns the trace from the context for the outbound RPC. It is
+// intended for gRPC-internal use.
+func OutgoingTrace(ctx context.Context) []byte {
+ b, _ := ctx.Value(outgoingTraceKey{}).([]byte)
+ return b
+}
diff --git a/vendor/google.golang.org/grpc/status/status.go b/vendor/google.golang.org/grpc/status/status.go
new file mode 100644
index 000000000..ed36681bb
--- /dev/null
+++ b/vendor/google.golang.org/grpc/status/status.go
@@ -0,0 +1,210 @@
+/*
+ *
+ * Copyright 2017 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// Package status implements errors returned by gRPC. These errors are
+// serialized and transmitted on the wire between server and client, and allow
+// for additional data to be transmitted via the Details field in the status
+// proto. gRPC service handlers should return an error created by this
+// package, and gRPC clients should expect a corresponding error to be
+// returned from the RPC call.
+//
+// This package upholds the invariants that a non-nil error may not
+// contain an OK code, and an OK code must result in a nil error.
+package status
+
+import (
+ "context"
+ "errors"
+ "fmt"
+
+ "github.com/golang/protobuf/proto"
+ "github.com/golang/protobuf/ptypes"
+ spb "google.golang.org/genproto/googleapis/rpc/status"
+ "google.golang.org/grpc/codes"
+)
+
+// statusError is an alias of a status proto. It implements error and Status,
+// and a nil statusError should never be returned by this package.
+type statusError spb.Status
+
+func (se *statusError) Error() string {
+ p := (*spb.Status)(se)
+ return fmt.Sprintf("rpc error: code = %s desc = %s", codes.Code(p.GetCode()), p.GetMessage())
+}
+
+func (se *statusError) GRPCStatus() *Status {
+ return &Status{s: (*spb.Status)(se)}
+}
+
+// Status represents an RPC status code, message, and details. It is immutable
+// and should be created with New, Newf, or FromProto.
+type Status struct {
+ s *spb.Status
+}
+
+// Code returns the status code contained in s.
+func (s *Status) Code() codes.Code {
+ if s == nil || s.s == nil {
+ return codes.OK
+ }
+ return codes.Code(s.s.Code)
+}
+
+// Message returns the message contained in s.
+func (s *Status) Message() string {
+ if s == nil || s.s == nil {
+ return ""
+ }
+ return s.s.Message
+}
+
+// Proto returns s's status as an spb.Status proto message.
+func (s *Status) Proto() *spb.Status {
+ if s == nil {
+ return nil
+ }
+ return proto.Clone(s.s).(*spb.Status)
+}
+
+// Err returns an immutable error representing s; returns nil if s.Code() is
+// OK.
+func (s *Status) Err() error {
+ if s.Code() == codes.OK {
+ return nil
+ }
+ return (*statusError)(s.s)
+}
+
+// New returns a Status representing c and msg.
+func New(c codes.Code, msg string) *Status {
+ return &Status{s: &spb.Status{Code: int32(c), Message: msg}}
+}
+
+// Newf returns New(c, fmt.Sprintf(format, a...)).
+func Newf(c codes.Code, format string, a ...interface{}) *Status {
+ return New(c, fmt.Sprintf(format, a...))
+}
+
+// Error returns an error representing c and msg. If c is OK, returns nil.
+func Error(c codes.Code, msg string) error {
+ return New(c, msg).Err()
+}
+
+// Errorf returns Error(c, fmt.Sprintf(format, a...)).
+func Errorf(c codes.Code, format string, a ...interface{}) error {
+ return Error(c, fmt.Sprintf(format, a...))
+}
+
+// ErrorProto returns an error representing s. If s.Code is OK, returns nil.
+func ErrorProto(s *spb.Status) error {
+ return FromProto(s).Err()
+}
+
+// FromProto returns a Status representing s.
+func FromProto(s *spb.Status) *Status {
+ return &Status{s: proto.Clone(s).(*spb.Status)}
+}
+
+// FromError returns a Status representing err if it was produced from this
+// package or has a method `GRPCStatus() *Status`. Otherwise, ok is false and a
+// Status is returned with codes.Unknown and the original error message.
+func FromError(err error) (s *Status, ok bool) {
+ if err == nil {
+ return &Status{s: &spb.Status{Code: int32(codes.OK)}}, true
+ }
+ if se, ok := err.(interface {
+ GRPCStatus() *Status
+ }); ok {
+ return se.GRPCStatus(), true
+ }
+ return New(codes.Unknown, err.Error()), false
+}
+
+// Convert is a convenience function which removes the need to handle the
+// boolean return value from FromError.
+func Convert(err error) *Status {
+ s, _ := FromError(err)
+ return s
+}
+
+// WithDetails returns a new status with the provided details messages appended to the status.
+// If any errors are encountered, it returns nil and the first error encountered.
+func (s *Status) WithDetails(details ...proto.Message) (*Status, error) {
+ if s.Code() == codes.OK {
+ return nil, errors.New("no error details for status with code OK")
+ }
+ // s.Code() != OK implies that s.Proto() != nil.
+ p := s.Proto()
+ for _, detail := range details {
+ any, err := ptypes.MarshalAny(detail)
+ if err != nil {
+ return nil, err
+ }
+ p.Details = append(p.Details, any)
+ }
+ return &Status{s: p}, nil
+}
+
+// Details returns a slice of details messages attached to the status.
+// If a detail cannot be decoded, the error is returned in place of the detail.
+func (s *Status) Details() []interface{} {
+ if s == nil || s.s == nil {
+ return nil
+ }
+ details := make([]interface{}, 0, len(s.s.Details))
+ for _, any := range s.s.Details {
+ detail := &ptypes.DynamicAny{}
+ if err := ptypes.UnmarshalAny(any, detail); err != nil {
+ details = append(details, err)
+ continue
+ }
+ details = append(details, detail.Message)
+ }
+ return details
+}
+
+// Code returns the Code of the error if it is a Status error, codes.OK if err
+// is nil, or codes.Unknown otherwise.
+func Code(err error) codes.Code {
+ // Don't use FromError to avoid allocation of OK status.
+ if err == nil {
+ return codes.OK
+ }
+ if se, ok := err.(interface {
+ GRPCStatus() *Status
+ }); ok {
+ return se.GRPCStatus().Code()
+ }
+ return codes.Unknown
+}
+
+// FromContextError converts a context error into a Status. It returns a
+// Status with codes.OK if err is nil, or a Status with codes.Unknown if err is
+// non-nil and not a context error.
+func FromContextError(err error) *Status {
+ switch err {
+ case nil:
+ return New(codes.OK, "")
+ case context.DeadlineExceeded:
+ return New(codes.DeadlineExceeded, err.Error())
+ case context.Canceled:
+ return New(codes.Canceled, err.Error())
+ default:
+ return New(codes.Unknown, err.Error())
+ }
+}
diff --git a/vendor/google.golang.org/grpc/stream.go b/vendor/google.golang.org/grpc/stream.go
new file mode 100644
index 000000000..0c266d6f9
--- /dev/null
+++ b/vendor/google.golang.org/grpc/stream.go
@@ -0,0 +1,1489 @@
+/*
+ *
+ * Copyright 2014 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package grpc
+
+import (
+ "context"
+ "errors"
+ "io"
+ "math"
+ "strconv"
+ "sync"
+ "time"
+
+ "golang.org/x/net/trace"
+ "google.golang.org/grpc/balancer"
+ "google.golang.org/grpc/codes"
+ "google.golang.org/grpc/connectivity"
+ "google.golang.org/grpc/encoding"
+ "google.golang.org/grpc/grpclog"
+ "google.golang.org/grpc/internal/binarylog"
+ "google.golang.org/grpc/internal/channelz"
+ "google.golang.org/grpc/internal/grpcrand"
+ "google.golang.org/grpc/internal/transport"
+ "google.golang.org/grpc/metadata"
+ "google.golang.org/grpc/peer"
+ "google.golang.org/grpc/stats"
+ "google.golang.org/grpc/status"
+)
+
+// StreamHandler defines the handler called by gRPC server to complete the
+// execution of a streaming RPC. If a StreamHandler returns an error, it
+// should be produced by the status package, or else gRPC will use
+// codes.Unknown as the status code and err.Error() as the status message
+// of the RPC.
+type StreamHandler func(srv interface{}, stream ServerStream) error
+
+// StreamDesc represents a streaming RPC service's method specification.
+type StreamDesc struct {
+ StreamName string
+ Handler StreamHandler
+
+ // At least one of these is true.
+ ServerStreams bool
+ ClientStreams bool
+}
+
+// Stream defines the common interface a client or server stream has to satisfy.
+//
+// Deprecated: See ClientStream and ServerStream documentation instead.
+type Stream interface {
+ // Deprecated: See ClientStream and ServerStream documentation instead.
+ Context() context.Context
+ // Deprecated: See ClientStream and ServerStream documentation instead.
+ SendMsg(m interface{}) error
+ // Deprecated: See ClientStream and ServerStream documentation instead.
+ RecvMsg(m interface{}) error
+}
+
+// ClientStream defines the client-side behavior of a streaming RPC.
+//
+// All errors returned from ClientStream methods are compatible with the
+// status package.
+type ClientStream interface {
+ // Header returns the header metadata received from the server if there
+ // is any. It blocks if the metadata is not ready to read.
+ Header() (metadata.MD, error)
+ // Trailer returns the trailer metadata from the server, if there is any.
+ // It must only be called after stream.CloseAndRecv has returned, or
+ // stream.Recv has returned a non-nil error (including io.EOF).
+ Trailer() metadata.MD
+ // CloseSend closes the send direction of the stream. It closes the stream
+ // when non-nil error is met. It is also not safe to call CloseSend
+ // concurrently with SendMsg.
+ CloseSend() error
+ // Context returns the context for this stream.
+ //
+ // It should not be called until after Header or RecvMsg has returned. Once
+ // called, subsequent client-side retries are disabled.
+ Context() context.Context
+ // SendMsg is generally called by generated code. On error, SendMsg aborts
+ // the stream. If the error was generated by the client, the status is
+ // returned directly; otherwise, io.EOF is returned and the status of
+ // the stream may be discovered using RecvMsg.
+ //
+ // SendMsg blocks until:
+ // - There is sufficient flow control to schedule m with the transport, or
+ // - The stream is done, or
+ // - The stream breaks.
+ //
+ // SendMsg does not wait until the message is received by the server. An
+ // untimely stream closure may result in lost messages. To ensure delivery,
+ // users should ensure the RPC completed successfully using RecvMsg.
+ //
+ // It is safe to have a goroutine calling SendMsg and another goroutine
+ // calling RecvMsg on the same stream at the same time, but it is not safe
+ // to call SendMsg on the same stream in different goroutines. It is also
+ // not safe to call CloseSend concurrently with SendMsg.
+ SendMsg(m interface{}) error
+ // RecvMsg blocks until it receives a message into m or the stream is
+ // done. It returns io.EOF when the stream completes successfully. On
+ // any other error, the stream is aborted and the error contains the RPC
+ // status.
+ //
+ // It is safe to have a goroutine calling SendMsg and another goroutine
+ // calling RecvMsg on the same stream at the same time, but it is not
+ // safe to call RecvMsg on the same stream in different goroutines.
+ RecvMsg(m interface{}) error
+}
+
+// NewStream creates a new Stream for the client side. This is typically
+// called by generated code. ctx is used for the lifetime of the stream.
+//
+// To ensure resources are not leaked due to the stream returned, one of the following
+// actions must be performed:
+//
+// 1. Call Close on the ClientConn.
+// 2. Cancel the context provided.
+// 3. Call RecvMsg until a non-nil error is returned. A protobuf-generated
+// client-streaming RPC, for instance, might use the helper function
+// CloseAndRecv (note that CloseSend does not Recv, therefore is not
+// guaranteed to release all resources).
+// 4. Receive a non-nil, non-io.EOF error from Header or SendMsg.
+//
+// If none of the above happen, a goroutine and a context will be leaked, and grpc
+// will not call the optionally-configured stats handler with a stats.End message.
+func (cc *ClientConn) NewStream(ctx context.Context, desc *StreamDesc, method string, opts ...CallOption) (ClientStream, error) {
+ // allow interceptor to see all applicable call options, which means those
+ // configured as defaults from dial option as well as per-call options
+ opts = combine(cc.dopts.callOptions, opts)
+
+ if cc.dopts.streamInt != nil {
+ return cc.dopts.streamInt(ctx, desc, cc, method, newClientStream, opts...)
+ }
+ return newClientStream(ctx, desc, cc, method, opts...)
+}
+
+// NewClientStream is a wrapper for ClientConn.NewStream.
+func NewClientStream(ctx context.Context, desc *StreamDesc, cc *ClientConn, method string, opts ...CallOption) (ClientStream, error) {
+ return cc.NewStream(ctx, desc, method, opts...)
+}
+
+func newClientStream(ctx context.Context, desc *StreamDesc, cc *ClientConn, method string, opts ...CallOption) (_ ClientStream, err error) {
+ if channelz.IsOn() {
+ cc.incrCallsStarted()
+ defer func() {
+ if err != nil {
+ cc.incrCallsFailed()
+ }
+ }()
+ }
+ c := defaultCallInfo()
+ // Provide an opportunity for the first RPC to see the first service config
+ // provided by the resolver.
+ if err := cc.waitForResolvedAddrs(ctx); err != nil {
+ return nil, err
+ }
+ mc := cc.GetMethodConfig(method)
+ if mc.WaitForReady != nil {
+ c.failFast = !*mc.WaitForReady
+ }
+
+ // Possible context leak:
+ // The cancel function for the child context we create will only be called
+ // when RecvMsg returns a non-nil error, if the ClientConn is closed, or if
+ // an error is generated by SendMsg.
+ // https://github.com/grpc/grpc-go/issues/1818.
+ var cancel context.CancelFunc
+ if mc.Timeout != nil && *mc.Timeout >= 0 {
+ ctx, cancel = context.WithTimeout(ctx, *mc.Timeout)
+ } else {
+ ctx, cancel = context.WithCancel(ctx)
+ }
+ defer func() {
+ if err != nil {
+ cancel()
+ }
+ }()
+
+ for _, o := range opts {
+ if err := o.before(c); err != nil {
+ return nil, toRPCErr(err)
+ }
+ }
+ c.maxSendMessageSize = getMaxSize(mc.MaxReqSize, c.maxSendMessageSize, defaultClientMaxSendMessageSize)
+ c.maxReceiveMessageSize = getMaxSize(mc.MaxRespSize, c.maxReceiveMessageSize, defaultClientMaxReceiveMessageSize)
+ if err := setCallInfoCodec(c); err != nil {
+ return nil, err
+ }
+
+ callHdr := &transport.CallHdr{
+ Host: cc.authority,
+ Method: method,
+ ContentSubtype: c.contentSubtype,
+ }
+
+ // Set our outgoing compression according to the UseCompressor CallOption, if
+ // set. In that case, also find the compressor from the encoding package.
+ // Otherwise, use the compressor configured by the WithCompressor DialOption,
+ // if set.
+ var cp Compressor
+ var comp encoding.Compressor
+ if ct := c.compressorType; ct != "" {
+ callHdr.SendCompress = ct
+ if ct != encoding.Identity {
+ comp = encoding.GetCompressor(ct)
+ if comp == nil {
+ return nil, status.Errorf(codes.Internal, "grpc: Compressor is not installed for requested grpc-encoding %q", ct)
+ }
+ }
+ } else if cc.dopts.cp != nil {
+ callHdr.SendCompress = cc.dopts.cp.Type()
+ cp = cc.dopts.cp
+ }
+ if c.creds != nil {
+ callHdr.Creds = c.creds
+ }
+ var trInfo traceInfo
+ if EnableTracing {
+ trInfo.tr = trace.New("grpc.Sent."+methodFamily(method), method)
+ trInfo.firstLine.client = true
+ if deadline, ok := ctx.Deadline(); ok {
+ trInfo.firstLine.deadline = deadline.Sub(time.Now())
+ }
+ trInfo.tr.LazyLog(&trInfo.firstLine, false)
+ ctx = trace.NewContext(ctx, trInfo.tr)
+ }
+ ctx = newContextWithRPCInfo(ctx, c.failFast)
+ sh := cc.dopts.copts.StatsHandler
+ var beginTime time.Time
+ if sh != nil {
+ ctx = sh.TagRPC(ctx, &stats.RPCTagInfo{FullMethodName: method, FailFast: c.failFast})
+ beginTime = time.Now()
+ begin := &stats.Begin{
+ Client: true,
+ BeginTime: beginTime,
+ FailFast: c.failFast,
+ }
+ sh.HandleRPC(ctx, begin)
+ }
+
+ cs := &clientStream{
+ callHdr: callHdr,
+ ctx: ctx,
+ methodConfig: &mc,
+ opts: opts,
+ callInfo: c,
+ cc: cc,
+ desc: desc,
+ codec: c.codec,
+ cp: cp,
+ comp: comp,
+ cancel: cancel,
+ beginTime: beginTime,
+ firstAttempt: true,
+ }
+ if !cc.dopts.disableRetry {
+ cs.retryThrottler = cc.retryThrottler.Load().(*retryThrottler)
+ }
+ cs.binlog = binarylog.GetMethodLogger(method)
+
+ cs.callInfo.stream = cs
+ // Only this initial attempt has stats/tracing.
+ // TODO(dfawley): move to newAttempt when per-attempt stats are implemented.
+ if err := cs.newAttemptLocked(sh, trInfo); err != nil {
+ cs.finish(err)
+ return nil, err
+ }
+
+ op := func(a *csAttempt) error { return a.newStream() }
+ if err := cs.withRetry(op, func() { cs.bufferForRetryLocked(0, op) }); err != nil {
+ cs.finish(err)
+ return nil, err
+ }
+
+ if cs.binlog != nil {
+ md, _ := metadata.FromOutgoingContext(ctx)
+ logEntry := &binarylog.ClientHeader{
+ OnClientSide: true,
+ Header: md,
+ MethodName: method,
+ Authority: cs.cc.authority,
+ }
+ if deadline, ok := ctx.Deadline(); ok {
+ logEntry.Timeout = deadline.Sub(time.Now())
+ if logEntry.Timeout < 0 {
+ logEntry.Timeout = 0
+ }
+ }
+ cs.binlog.Log(logEntry)
+ }
+
+ if desc != unaryStreamDesc {
+ // Listen on cc and stream contexts to cleanup when the user closes the
+ // ClientConn or cancels the stream context. In all other cases, an error
+ // should already be injected into the recv buffer by the transport, which
+ // the client will eventually receive, and then we will cancel the stream's
+ // context in clientStream.finish.
+ go func() {
+ select {
+ case <-cc.ctx.Done():
+ cs.finish(ErrClientConnClosing)
+ case <-ctx.Done():
+ cs.finish(toRPCErr(ctx.Err()))
+ }
+ }()
+ }
+ return cs, nil
+}
+
+func (cs *clientStream) newAttemptLocked(sh stats.Handler, trInfo traceInfo) error {
+ cs.attempt = &csAttempt{
+ cs: cs,
+ dc: cs.cc.dopts.dc,
+ statsHandler: sh,
+ trInfo: trInfo,
+ }
+
+ if err := cs.ctx.Err(); err != nil {
+ return toRPCErr(err)
+ }
+ t, done, err := cs.cc.getTransport(cs.ctx, cs.callInfo.failFast, cs.callHdr.Method)
+ if err != nil {
+ return err
+ }
+ cs.attempt.t = t
+ cs.attempt.done = done
+ return nil
+}
+
+func (a *csAttempt) newStream() error {
+ cs := a.cs
+ cs.callHdr.PreviousAttempts = cs.numRetries
+ s, err := a.t.NewStream(cs.ctx, cs.callHdr)
+ if err != nil {
+ return toRPCErr(err)
+ }
+ cs.attempt.s = s
+ cs.attempt.p = &parser{r: s}
+ return nil
+}
+
+// clientStream implements a client side Stream.
+type clientStream struct {
+ callHdr *transport.CallHdr
+ opts []CallOption
+ callInfo *callInfo
+ cc *ClientConn
+ desc *StreamDesc
+
+ codec baseCodec
+ cp Compressor
+ comp encoding.Compressor
+
+ cancel context.CancelFunc // cancels all attempts
+
+ sentLast bool // sent an end stream
+ beginTime time.Time
+
+ methodConfig *MethodConfig
+
+ ctx context.Context // the application's context, wrapped by stats/tracing
+
+ retryThrottler *retryThrottler // The throttler active when the RPC began.
+
+ binlog *binarylog.MethodLogger // Binary logger, can be nil.
+ // serverHeaderBinlogged is a boolean for whether server header has been
+ // logged. Server header will be logged when the first time one of those
+ // happens: stream.Header(), stream.Recv().
+ //
+ // It's only read and used by Recv() and Header(), so it doesn't need to be
+ // synchronized.
+ serverHeaderBinlogged bool
+
+ mu sync.Mutex
+ firstAttempt bool // if true, transparent retry is valid
+ numRetries int // exclusive of transparent retry attempt(s)
+ numRetriesSincePushback int // retries since pushback; to reset backoff
+ finished bool // TODO: replace with atomic cmpxchg or sync.Once?
+ attempt *csAttempt // the active client stream attempt
+ // TODO(hedging): hedging will have multiple attempts simultaneously.
+ committed bool // active attempt committed for retry?
+ buffer []func(a *csAttempt) error // operations to replay on retry
+ bufferSize int // current size of buffer
+}
+
+// csAttempt implements a single transport stream attempt within a
+// clientStream.
+type csAttempt struct {
+ cs *clientStream
+ t transport.ClientTransport
+ s *transport.Stream
+ p *parser
+ done func(balancer.DoneInfo)
+
+ finished bool
+ dc Decompressor
+ decomp encoding.Compressor
+ decompSet bool
+
+ mu sync.Mutex // guards trInfo.tr
+ // trInfo.tr is set when created (if EnableTracing is true),
+ // and cleared when the finish method is called.
+ trInfo traceInfo
+
+ statsHandler stats.Handler
+}
+
+func (cs *clientStream) commitAttemptLocked() {
+ cs.committed = true
+ cs.buffer = nil
+}
+
+func (cs *clientStream) commitAttempt() {
+ cs.mu.Lock()
+ cs.commitAttemptLocked()
+ cs.mu.Unlock()
+}
+
+// shouldRetry returns nil if the RPC should be retried; otherwise it returns
+// the error that should be returned by the operation.
+func (cs *clientStream) shouldRetry(err error) error {
+ if cs.attempt.s == nil && !cs.callInfo.failFast {
+ // In the event of any error from NewStream (attempt.s == nil), we
+ // never attempted to write anything to the wire, so we can retry
+ // indefinitely for non-fail-fast RPCs.
+ return nil
+ }
+ if cs.finished || cs.committed {
+ // RPC is finished or committed; cannot retry.
+ return err
+ }
+ // Wait for the trailers.
+ if cs.attempt.s != nil {
+ <-cs.attempt.s.Done()
+ }
+ if cs.firstAttempt && !cs.callInfo.failFast && (cs.attempt.s == nil || cs.attempt.s.Unprocessed()) {
+ // First attempt, wait-for-ready, stream unprocessed: transparently retry.
+ cs.firstAttempt = false
+ return nil
+ }
+ cs.firstAttempt = false
+ if cs.cc.dopts.disableRetry {
+ return err
+ }
+
+ pushback := 0
+ hasPushback := false
+ if cs.attempt.s != nil {
+ if to, toErr := cs.attempt.s.TrailersOnly(); toErr != nil {
+ // Context error; stop now.
+ return toErr
+ } else if !to {
+ return err
+ }
+
+ // TODO(retry): Move down if the spec changes to not check server pushback
+ // before considering this a failure for throttling.
+ sps := cs.attempt.s.Trailer()["grpc-retry-pushback-ms"]
+ if len(sps) == 1 {
+ var e error
+ if pushback, e = strconv.Atoi(sps[0]); e != nil || pushback < 0 {
+ grpclog.Infof("Server retry pushback specified to abort (%q).", sps[0])
+ cs.retryThrottler.throttle() // This counts as a failure for throttling.
+ return err
+ }
+ hasPushback = true
+ } else if len(sps) > 1 {
+ grpclog.Warningf("Server retry pushback specified multiple values (%q); not retrying.", sps)
+ cs.retryThrottler.throttle() // This counts as a failure for throttling.
+ return err
+ }
+ }
+
+ var code codes.Code
+ if cs.attempt.s != nil {
+ code = cs.attempt.s.Status().Code()
+ } else {
+ code = status.Convert(err).Code()
+ }
+
+ rp := cs.methodConfig.retryPolicy
+ if rp == nil || !rp.retryableStatusCodes[code] {
+ return err
+ }
+
+ // Note: the ordering here is important; we count this as a failure
+ // only if the code matched a retryable code.
+ if cs.retryThrottler.throttle() {
+ return err
+ }
+ if cs.numRetries+1 >= rp.maxAttempts {
+ return err
+ }
+
+ var dur time.Duration
+ if hasPushback {
+ dur = time.Millisecond * time.Duration(pushback)
+ cs.numRetriesSincePushback = 0
+ } else {
+ fact := math.Pow(rp.backoffMultiplier, float64(cs.numRetriesSincePushback))
+ cur := float64(rp.initialBackoff) * fact
+ if max := float64(rp.maxBackoff); cur > max {
+ cur = max
+ }
+ dur = time.Duration(grpcrand.Int63n(int64(cur)))
+ cs.numRetriesSincePushback++
+ }
+
+ // TODO(dfawley): we could eagerly fail here if dur puts us past the
+ // deadline, but unsure if it is worth doing.
+ t := time.NewTimer(dur)
+ select {
+ case <-t.C:
+ cs.numRetries++
+ return nil
+ case <-cs.ctx.Done():
+ t.Stop()
+ return status.FromContextError(cs.ctx.Err()).Err()
+ }
+}
+
+// Returns nil if a retry was performed and succeeded; error otherwise.
+func (cs *clientStream) retryLocked(lastErr error) error {
+ for {
+ cs.attempt.finish(lastErr)
+ if err := cs.shouldRetry(lastErr); err != nil {
+ cs.commitAttemptLocked()
+ return err
+ }
+ if err := cs.newAttemptLocked(nil, traceInfo{}); err != nil {
+ return err
+ }
+ if lastErr = cs.replayBufferLocked(); lastErr == nil {
+ return nil
+ }
+ }
+}
+
+func (cs *clientStream) Context() context.Context {
+ cs.commitAttempt()
+ // No need to lock before using attempt, since we know it is committed and
+ // cannot change.
+ return cs.attempt.s.Context()
+}
+
+func (cs *clientStream) withRetry(op func(a *csAttempt) error, onSuccess func()) error {
+ cs.mu.Lock()
+ for {
+ if cs.committed {
+ cs.mu.Unlock()
+ return op(cs.attempt)
+ }
+ a := cs.attempt
+ cs.mu.Unlock()
+ err := op(a)
+ cs.mu.Lock()
+ if a != cs.attempt {
+ // We started another attempt already.
+ continue
+ }
+ if err == io.EOF {
+ <-a.s.Done()
+ }
+ if err == nil || (err == io.EOF && a.s.Status().Code() == codes.OK) {
+ onSuccess()
+ cs.mu.Unlock()
+ return err
+ }
+ if err := cs.retryLocked(err); err != nil {
+ cs.mu.Unlock()
+ return err
+ }
+ }
+}
+
+func (cs *clientStream) Header() (metadata.MD, error) {
+ var m metadata.MD
+ err := cs.withRetry(func(a *csAttempt) error {
+ var err error
+ m, err = a.s.Header()
+ return toRPCErr(err)
+ }, cs.commitAttemptLocked)
+ if err != nil {
+ cs.finish(err)
+ return nil, err
+ }
+ if cs.binlog != nil && !cs.serverHeaderBinlogged {
+ // Only log if binary log is on and header has not been logged.
+ logEntry := &binarylog.ServerHeader{
+ OnClientSide: true,
+ Header: m,
+ PeerAddr: nil,
+ }
+ if peer, ok := peer.FromContext(cs.Context()); ok {
+ logEntry.PeerAddr = peer.Addr
+ }
+ cs.binlog.Log(logEntry)
+ cs.serverHeaderBinlogged = true
+ }
+ return m, err
+}
+
+func (cs *clientStream) Trailer() metadata.MD {
+ // On RPC failure, we never need to retry, because usage requires that
+ // RecvMsg() returned a non-nil error before calling this function is valid.
+ // We would have retried earlier if necessary.
+ //
+ // Commit the attempt anyway, just in case users are not following those
+ // directions -- it will prevent races and should not meaningfully impact
+ // performance.
+ cs.commitAttempt()
+ if cs.attempt.s == nil {
+ return nil
+ }
+ return cs.attempt.s.Trailer()
+}
+
+func (cs *clientStream) replayBufferLocked() error {
+ a := cs.attempt
+ for _, f := range cs.buffer {
+ if err := f(a); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func (cs *clientStream) bufferForRetryLocked(sz int, op func(a *csAttempt) error) {
+ // Note: we still will buffer if retry is disabled (for transparent retries).
+ if cs.committed {
+ return
+ }
+ cs.bufferSize += sz
+ if cs.bufferSize > cs.callInfo.maxRetryRPCBufferSize {
+ cs.commitAttemptLocked()
+ return
+ }
+ cs.buffer = append(cs.buffer, op)
+}
+
+func (cs *clientStream) SendMsg(m interface{}) (err error) {
+ defer func() {
+ if err != nil && err != io.EOF {
+ // Call finish on the client stream for errors generated by this SendMsg
+ // call, as these indicate problems created by this client. (Transport
+ // errors are converted to an io.EOF error in csAttempt.sendMsg; the real
+ // error will be returned from RecvMsg eventually in that case, or be
+ // retried.)
+ cs.finish(err)
+ }
+ }()
+ if cs.sentLast {
+ return status.Errorf(codes.Internal, "SendMsg called after CloseSend")
+ }
+ if !cs.desc.ClientStreams {
+ cs.sentLast = true
+ }
+ data, err := encode(cs.codec, m)
+ if err != nil {
+ return err
+ }
+ compData, err := compress(data, cs.cp, cs.comp)
+ if err != nil {
+ return err
+ }
+ hdr, payload := msgHeader(data, compData)
+ // TODO(dfawley): should we be checking len(data) instead?
+ if len(payload) > *cs.callInfo.maxSendMessageSize {
+ return status.Errorf(codes.ResourceExhausted, "trying to send message larger than max (%d vs. %d)", len(payload), *cs.callInfo.maxSendMessageSize)
+ }
+ msgBytes := data // Store the pointer before setting to nil. For binary logging.
+ op := func(a *csAttempt) error {
+ err := a.sendMsg(m, hdr, payload, data)
+ // nil out the message and uncomp when replaying; they are only needed for
+ // stats which is disabled for subsequent attempts.
+ m, data = nil, nil
+ return err
+ }
+ err = cs.withRetry(op, func() { cs.bufferForRetryLocked(len(hdr)+len(payload), op) })
+ if cs.binlog != nil && err == nil {
+ cs.binlog.Log(&binarylog.ClientMessage{
+ OnClientSide: true,
+ Message: msgBytes,
+ })
+ }
+ return
+}
+
+func (cs *clientStream) RecvMsg(m interface{}) error {
+ if cs.binlog != nil && !cs.serverHeaderBinlogged {
+ // Call Header() to binary log header if it's not already logged.
+ cs.Header()
+ }
+ var recvInfo *payloadInfo
+ if cs.binlog != nil {
+ recvInfo = &payloadInfo{}
+ }
+ err := cs.withRetry(func(a *csAttempt) error {
+ return a.recvMsg(m, recvInfo)
+ }, cs.commitAttemptLocked)
+ if cs.binlog != nil && err == nil {
+ cs.binlog.Log(&binarylog.ServerMessage{
+ OnClientSide: true,
+ Message: recvInfo.uncompressedBytes,
+ })
+ }
+ if err != nil || !cs.desc.ServerStreams {
+ // err != nil or non-server-streaming indicates end of stream.
+ cs.finish(err)
+
+ if cs.binlog != nil {
+ // finish will not log Trailer. Log Trailer here.
+ logEntry := &binarylog.ServerTrailer{
+ OnClientSide: true,
+ Trailer: cs.Trailer(),
+ Err: err,
+ }
+ if logEntry.Err == io.EOF {
+ logEntry.Err = nil
+ }
+ if peer, ok := peer.FromContext(cs.Context()); ok {
+ logEntry.PeerAddr = peer.Addr
+ }
+ cs.binlog.Log(logEntry)
+ }
+ }
+ return err
+}
+
+func (cs *clientStream) CloseSend() error {
+ if cs.sentLast {
+ // TODO: return an error and finish the stream instead, due to API misuse?
+ return nil
+ }
+ cs.sentLast = true
+ op := func(a *csAttempt) error {
+ a.t.Write(a.s, nil, nil, &transport.Options{Last: true})
+ // Always return nil; io.EOF is the only error that might make sense
+ // instead, but there is no need to signal the client to call RecvMsg
+ // as the only use left for the stream after CloseSend is to call
+ // RecvMsg. This also matches historical behavior.
+ return nil
+ }
+ cs.withRetry(op, func() { cs.bufferForRetryLocked(0, op) })
+ if cs.binlog != nil {
+ cs.binlog.Log(&binarylog.ClientHalfClose{
+ OnClientSide: true,
+ })
+ }
+ // We never returned an error here for reasons.
+ return nil
+}
+
+func (cs *clientStream) finish(err error) {
+ if err == io.EOF {
+ // Ending a stream with EOF indicates a success.
+ err = nil
+ }
+ cs.mu.Lock()
+ if cs.finished {
+ cs.mu.Unlock()
+ return
+ }
+ cs.finished = true
+ cs.commitAttemptLocked()
+ cs.mu.Unlock()
+ // For binary logging. only log cancel in finish (could be caused by RPC ctx
+ // canceled or ClientConn closed). Trailer will be logged in RecvMsg.
+ //
+ // Only one of cancel or trailer needs to be logged. In the cases where
+ // users don't call RecvMsg, users must have already canceled the RPC.
+ if cs.binlog != nil && status.Code(err) == codes.Canceled {
+ cs.binlog.Log(&binarylog.Cancel{
+ OnClientSide: true,
+ })
+ }
+ if err == nil {
+ cs.retryThrottler.successfulRPC()
+ }
+ if channelz.IsOn() {
+ if err != nil {
+ cs.cc.incrCallsFailed()
+ } else {
+ cs.cc.incrCallsSucceeded()
+ }
+ }
+ if cs.attempt != nil {
+ cs.attempt.finish(err)
+ }
+ // after functions all rely upon having a stream.
+ if cs.attempt.s != nil {
+ for _, o := range cs.opts {
+ o.after(cs.callInfo)
+ }
+ }
+ cs.cancel()
+}
+
+func (a *csAttempt) sendMsg(m interface{}, hdr, payld, data []byte) error {
+ cs := a.cs
+ if EnableTracing {
+ a.mu.Lock()
+ if a.trInfo.tr != nil {
+ a.trInfo.tr.LazyLog(&payload{sent: true, msg: m}, true)
+ }
+ a.mu.Unlock()
+ }
+ if err := a.t.Write(a.s, hdr, payld, &transport.Options{Last: !cs.desc.ClientStreams}); err != nil {
+ if !cs.desc.ClientStreams {
+ // For non-client-streaming RPCs, we return nil instead of EOF on error
+ // because the generated code requires it. finish is not called; RecvMsg()
+ // will call it with the stream's status independently.
+ return nil
+ }
+ return io.EOF
+ }
+ if a.statsHandler != nil {
+ a.statsHandler.HandleRPC(cs.ctx, outPayload(true, m, data, payld, time.Now()))
+ }
+ if channelz.IsOn() {
+ a.t.IncrMsgSent()
+ }
+ return nil
+}
+
+func (a *csAttempt) recvMsg(m interface{}, payInfo *payloadInfo) (err error) {
+ cs := a.cs
+ if a.statsHandler != nil && payInfo == nil {
+ payInfo = &payloadInfo{}
+ }
+
+ if !a.decompSet {
+ // Block until we receive headers containing received message encoding.
+ if ct := a.s.RecvCompress(); ct != "" && ct != encoding.Identity {
+ if a.dc == nil || a.dc.Type() != ct {
+ // No configured decompressor, or it does not match the incoming
+ // message encoding; attempt to find a registered compressor that does.
+ a.dc = nil
+ a.decomp = encoding.GetCompressor(ct)
+ }
+ } else {
+ // No compression is used; disable our decompressor.
+ a.dc = nil
+ }
+ // Only initialize this state once per stream.
+ a.decompSet = true
+ }
+ err = recv(a.p, cs.codec, a.s, a.dc, m, *cs.callInfo.maxReceiveMessageSize, payInfo, a.decomp)
+ if err != nil {
+ if err == io.EOF {
+ if statusErr := a.s.Status().Err(); statusErr != nil {
+ return statusErr
+ }
+ return io.EOF // indicates successful end of stream.
+ }
+ return toRPCErr(err)
+ }
+ if EnableTracing {
+ a.mu.Lock()
+ if a.trInfo.tr != nil {
+ a.trInfo.tr.LazyLog(&payload{sent: false, msg: m}, true)
+ }
+ a.mu.Unlock()
+ }
+ if a.statsHandler != nil {
+ a.statsHandler.HandleRPC(cs.ctx, &stats.InPayload{
+ Client: true,
+ RecvTime: time.Now(),
+ Payload: m,
+ // TODO truncate large payload.
+ Data: payInfo.uncompressedBytes,
+ Length: len(payInfo.uncompressedBytes),
+ })
+ }
+ if channelz.IsOn() {
+ a.t.IncrMsgRecv()
+ }
+ if cs.desc.ServerStreams {
+ // Subsequent messages should be received by subsequent RecvMsg calls.
+ return nil
+ }
+ // Special handling for non-server-stream rpcs.
+ // This recv expects EOF or errors, so we don't collect inPayload.
+ err = recv(a.p, cs.codec, a.s, a.dc, m, *cs.callInfo.maxReceiveMessageSize, nil, a.decomp)
+ if err == nil {
+ return toRPCErr(errors.New("grpc: client streaming protocol violation: get <nil>, want <EOF>"))
+ }
+ if err == io.EOF {
+ return a.s.Status().Err() // non-server streaming Recv returns nil on success
+ }
+ return toRPCErr(err)
+}
+
+func (a *csAttempt) finish(err error) {
+ a.mu.Lock()
+ if a.finished {
+ a.mu.Unlock()
+ return
+ }
+ a.finished = true
+ if err == io.EOF {
+ // Ending a stream with EOF indicates a success.
+ err = nil
+ }
+ if a.s != nil {
+ a.t.CloseStream(a.s, err)
+ }
+
+ if a.done != nil {
+ br := false
+ var tr metadata.MD
+ if a.s != nil {
+ br = a.s.BytesReceived()
+ tr = a.s.Trailer()
+ }
+ a.done(balancer.DoneInfo{
+ Err: err,
+ Trailer: tr,
+ BytesSent: a.s != nil,
+ BytesReceived: br,
+ })
+ }
+ if a.statsHandler != nil {
+ end := &stats.End{
+ Client: true,
+ BeginTime: a.cs.beginTime,
+ EndTime: time.Now(),
+ Error: err,
+ }
+ a.statsHandler.HandleRPC(a.cs.ctx, end)
+ }
+ if a.trInfo.tr != nil {
+ if err == nil {
+ a.trInfo.tr.LazyPrintf("RPC: [OK]")
+ } else {
+ a.trInfo.tr.LazyPrintf("RPC: [%v]", err)
+ a.trInfo.tr.SetError()
+ }
+ a.trInfo.tr.Finish()
+ a.trInfo.tr = nil
+ }
+ a.mu.Unlock()
+}
+
+func (ac *addrConn) newClientStream(ctx context.Context, desc *StreamDesc, method string, t transport.ClientTransport, opts ...CallOption) (_ ClientStream, err error) {
+ ac.mu.Lock()
+ if ac.transport != t {
+ ac.mu.Unlock()
+ return nil, status.Error(codes.Canceled, "the provided transport is no longer valid to use")
+ }
+ // transition to CONNECTING state when an attempt starts
+ if ac.state != connectivity.Connecting {
+ ac.updateConnectivityState(connectivity.Connecting)
+ ac.cc.handleSubConnStateChange(ac.acbw, ac.state)
+ }
+ ac.mu.Unlock()
+
+ if t == nil {
+ // TODO: return RPC error here?
+ return nil, errors.New("transport provided is nil")
+ }
+ // defaultCallInfo contains unnecessary info(i.e. failfast, maxRetryRPCBufferSize), so we just initialize an empty struct.
+ c := &callInfo{}
+
+ for _, o := range opts {
+ if err := o.before(c); err != nil {
+ return nil, toRPCErr(err)
+ }
+ }
+ c.maxReceiveMessageSize = getMaxSize(nil, c.maxReceiveMessageSize, defaultClientMaxReceiveMessageSize)
+ c.maxSendMessageSize = getMaxSize(nil, c.maxSendMessageSize, defaultServerMaxSendMessageSize)
+
+ // Possible context leak:
+ // The cancel function for the child context we create will only be called
+ // when RecvMsg returns a non-nil error, if the ClientConn is closed, or if
+ // an error is generated by SendMsg.
+ // https://github.com/grpc/grpc-go/issues/1818.
+ ctx, cancel := context.WithCancel(ctx)
+ defer func() {
+ if err != nil {
+ cancel()
+ }
+ }()
+
+ if err := setCallInfoCodec(c); err != nil {
+ return nil, err
+ }
+
+ callHdr := &transport.CallHdr{
+ Host: ac.cc.authority,
+ Method: method,
+ ContentSubtype: c.contentSubtype,
+ }
+
+ // Set our outgoing compression according to the UseCompressor CallOption, if
+ // set. In that case, also find the compressor from the encoding package.
+ // Otherwise, use the compressor configured by the WithCompressor DialOption,
+ // if set.
+ var cp Compressor
+ var comp encoding.Compressor
+ if ct := c.compressorType; ct != "" {
+ callHdr.SendCompress = ct
+ if ct != encoding.Identity {
+ comp = encoding.GetCompressor(ct)
+ if comp == nil {
+ return nil, status.Errorf(codes.Internal, "grpc: Compressor is not installed for requested grpc-encoding %q", ct)
+ }
+ }
+ } else if ac.cc.dopts.cp != nil {
+ callHdr.SendCompress = ac.cc.dopts.cp.Type()
+ cp = ac.cc.dopts.cp
+ }
+ if c.creds != nil {
+ callHdr.Creds = c.creds
+ }
+
+ as := &addrConnStream{
+ callHdr: callHdr,
+ ac: ac,
+ ctx: ctx,
+ cancel: cancel,
+ opts: opts,
+ callInfo: c,
+ desc: desc,
+ codec: c.codec,
+ cp: cp,
+ comp: comp,
+ t: t,
+ }
+
+ as.callInfo.stream = as
+ s, err := as.t.NewStream(as.ctx, as.callHdr)
+ if err != nil {
+ err = toRPCErr(err)
+ return nil, err
+ }
+ as.s = s
+ as.p = &parser{r: s}
+ ac.incrCallsStarted()
+ if desc != unaryStreamDesc {
+ // Listen on cc and stream contexts to cleanup when the user closes the
+ // ClientConn or cancels the stream context. In all other cases, an error
+ // should already be injected into the recv buffer by the transport, which
+ // the client will eventually receive, and then we will cancel the stream's
+ // context in clientStream.finish.
+ go func() {
+ select {
+ case <-ac.ctx.Done():
+ as.finish(status.Error(codes.Canceled, "grpc: the SubConn is closing"))
+ case <-ctx.Done():
+ as.finish(toRPCErr(ctx.Err()))
+ }
+ }()
+ }
+ return as, nil
+}
+
+type addrConnStream struct {
+ s *transport.Stream
+ ac *addrConn
+ callHdr *transport.CallHdr
+ cancel context.CancelFunc
+ opts []CallOption
+ callInfo *callInfo
+ t transport.ClientTransport
+ ctx context.Context
+ sentLast bool
+ desc *StreamDesc
+ codec baseCodec
+ cp Compressor
+ comp encoding.Compressor
+ decompSet bool
+ dc Decompressor
+ decomp encoding.Compressor
+ p *parser
+ done func(balancer.DoneInfo)
+ mu sync.Mutex
+ finished bool
+}
+
+func (as *addrConnStream) Header() (metadata.MD, error) {
+ m, err := as.s.Header()
+ if err != nil {
+ as.finish(toRPCErr(err))
+ }
+ return m, err
+}
+
+func (as *addrConnStream) Trailer() metadata.MD {
+ return as.s.Trailer()
+}
+
+func (as *addrConnStream) CloseSend() error {
+ if as.sentLast {
+ // TODO: return an error and finish the stream instead, due to API misuse?
+ return nil
+ }
+ as.sentLast = true
+
+ as.t.Write(as.s, nil, nil, &transport.Options{Last: true})
+ // Always return nil; io.EOF is the only error that might make sense
+ // instead, but there is no need to signal the client to call RecvMsg
+ // as the only use left for the stream after CloseSend is to call
+ // RecvMsg. This also matches historical behavior.
+ return nil
+}
+
+func (as *addrConnStream) Context() context.Context {
+ return as.s.Context()
+}
+
+func (as *addrConnStream) SendMsg(m interface{}) (err error) {
+ defer func() {
+ if err != nil && err != io.EOF {
+ // Call finish on the client stream for errors generated by this SendMsg
+ // call, as these indicate problems created by this client. (Transport
+ // errors are converted to an io.EOF error in csAttempt.sendMsg; the real
+ // error will be returned from RecvMsg eventually in that case, or be
+ // retried.)
+ as.finish(err)
+ }
+ }()
+ if as.sentLast {
+ return status.Errorf(codes.Internal, "SendMsg called after CloseSend")
+ }
+ if !as.desc.ClientStreams {
+ as.sentLast = true
+ }
+ data, err := encode(as.codec, m)
+ if err != nil {
+ return err
+ }
+ compData, err := compress(data, as.cp, as.comp)
+ if err != nil {
+ return err
+ }
+ hdr, payld := msgHeader(data, compData)
+ // TODO(dfawley): should we be checking len(data) instead?
+ if len(payld) > *as.callInfo.maxSendMessageSize {
+ return status.Errorf(codes.ResourceExhausted, "trying to send message larger than max (%d vs. %d)", len(payld), *as.callInfo.maxSendMessageSize)
+ }
+
+ if err := as.t.Write(as.s, hdr, payld, &transport.Options{Last: !as.desc.ClientStreams}); err != nil {
+ if !as.desc.ClientStreams {
+ // For non-client-streaming RPCs, we return nil instead of EOF on error
+ // because the generated code requires it. finish is not called; RecvMsg()
+ // will call it with the stream's status independently.
+ return nil
+ }
+ return io.EOF
+ }
+
+ if channelz.IsOn() {
+ as.t.IncrMsgSent()
+ }
+ return nil
+}
+
+func (as *addrConnStream) RecvMsg(m interface{}) (err error) {
+ defer func() {
+ if err != nil || !as.desc.ServerStreams {
+ // err != nil or non-server-streaming indicates end of stream.
+ as.finish(err)
+ }
+ }()
+
+ if !as.decompSet {
+ // Block until we receive headers containing received message encoding.
+ if ct := as.s.RecvCompress(); ct != "" && ct != encoding.Identity {
+ if as.dc == nil || as.dc.Type() != ct {
+ // No configured decompressor, or it does not match the incoming
+ // message encoding; attempt to find a registered compressor that does.
+ as.dc = nil
+ as.decomp = encoding.GetCompressor(ct)
+ }
+ } else {
+ // No compression is used; disable our decompressor.
+ as.dc = nil
+ }
+ // Only initialize this state once per stream.
+ as.decompSet = true
+ }
+ err = recv(as.p, as.codec, as.s, as.dc, m, *as.callInfo.maxReceiveMessageSize, nil, as.decomp)
+ if err != nil {
+ if err == io.EOF {
+ if statusErr := as.s.Status().Err(); statusErr != nil {
+ return statusErr
+ }
+ return io.EOF // indicates successful end of stream.
+ }
+ return toRPCErr(err)
+ }
+
+ if channelz.IsOn() {
+ as.t.IncrMsgRecv()
+ }
+ if as.desc.ServerStreams {
+ // Subsequent messages should be received by subsequent RecvMsg calls.
+ return nil
+ }
+
+ // Special handling for non-server-stream rpcs.
+ // This recv expects EOF or errors, so we don't collect inPayload.
+ err = recv(as.p, as.codec, as.s, as.dc, m, *as.callInfo.maxReceiveMessageSize, nil, as.decomp)
+ if err == nil {
+ return toRPCErr(errors.New("grpc: client streaming protocol violation: get <nil>, want <EOF>"))
+ }
+ if err == io.EOF {
+ return as.s.Status().Err() // non-server streaming Recv returns nil on success
+ }
+ return toRPCErr(err)
+}
+
+func (as *addrConnStream) finish(err error) {
+ as.mu.Lock()
+ if as.finished {
+ as.mu.Unlock()
+ return
+ }
+ as.finished = true
+ if err == io.EOF {
+ // Ending a stream with EOF indicates a success.
+ err = nil
+ }
+ if as.s != nil {
+ as.t.CloseStream(as.s, err)
+ }
+
+ if err != nil {
+ as.ac.incrCallsFailed()
+ } else {
+ as.ac.incrCallsSucceeded()
+ }
+ as.cancel()
+ as.mu.Unlock()
+}
+
+// ServerStream defines the server-side behavior of a streaming RPC.
+//
+// All errors returned from ServerStream methods are compatible with the
+// status package.
+type ServerStream interface {
+ // SetHeader sets the header metadata. It may be called multiple times.
+ // When call multiple times, all the provided metadata will be merged.
+ // All the metadata will be sent out when one of the following happens:
+ // - ServerStream.SendHeader() is called;
+ // - The first response is sent out;
+ // - An RPC status is sent out (error or success).
+ SetHeader(metadata.MD) error
+ // SendHeader sends the header metadata.
+ // The provided md and headers set by SetHeader() will be sent.
+ // It fails if called multiple times.
+ SendHeader(metadata.MD) error
+ // SetTrailer sets the trailer metadata which will be sent with the RPC status.
+ // When called more than once, all the provided metadata will be merged.
+ SetTrailer(metadata.MD)
+ // Context returns the context for this stream.
+ Context() context.Context
+ // SendMsg sends a message. On error, SendMsg aborts the stream and the
+ // error is returned directly.
+ //
+ // SendMsg blocks until:
+ // - There is sufficient flow control to schedule m with the transport, or
+ // - The stream is done, or
+ // - The stream breaks.
+ //
+ // SendMsg does not wait until the message is received by the client. An
+ // untimely stream closure may result in lost messages.
+ //
+ // It is safe to have a goroutine calling SendMsg and another goroutine
+ // calling RecvMsg on the same stream at the same time, but it is not safe
+ // to call SendMsg on the same stream in different goroutines.
+ SendMsg(m interface{}) error
+ // RecvMsg blocks until it receives a message into m or the stream is
+ // done. It returns io.EOF when the client has performed a CloseSend. On
+ // any non-EOF error, the stream is aborted and the error contains the
+ // RPC status.
+ //
+ // It is safe to have a goroutine calling SendMsg and another goroutine
+ // calling RecvMsg on the same stream at the same time, but it is not
+ // safe to call RecvMsg on the same stream in different goroutines.
+ RecvMsg(m interface{}) error
+}
+
+// serverStream implements a server side Stream.
+type serverStream struct {
+ ctx context.Context
+ t transport.ServerTransport
+ s *transport.Stream
+ p *parser
+ codec baseCodec
+
+ cp Compressor
+ dc Decompressor
+ comp encoding.Compressor
+ decomp encoding.Compressor
+
+ maxReceiveMessageSize int
+ maxSendMessageSize int
+ trInfo *traceInfo
+
+ statsHandler stats.Handler
+
+ binlog *binarylog.MethodLogger
+ // serverHeaderBinlogged indicates whether server header has been logged. It
+ // will happen when one of the following two happens: stream.SendHeader(),
+ // stream.Send().
+ //
+ // It's only checked in send and sendHeader, doesn't need to be
+ // synchronized.
+ serverHeaderBinlogged bool
+
+ mu sync.Mutex // protects trInfo.tr after the service handler runs.
+}
+
+func (ss *serverStream) Context() context.Context {
+ return ss.ctx
+}
+
+func (ss *serverStream) SetHeader(md metadata.MD) error {
+ if md.Len() == 0 {
+ return nil
+ }
+ return ss.s.SetHeader(md)
+}
+
+func (ss *serverStream) SendHeader(md metadata.MD) error {
+ err := ss.t.WriteHeader(ss.s, md)
+ if ss.binlog != nil && !ss.serverHeaderBinlogged {
+ h, _ := ss.s.Header()
+ ss.binlog.Log(&binarylog.ServerHeader{
+ Header: h,
+ })
+ ss.serverHeaderBinlogged = true
+ }
+ return err
+}
+
+func (ss *serverStream) SetTrailer(md metadata.MD) {
+ if md.Len() == 0 {
+ return
+ }
+ ss.s.SetTrailer(md)
+}
+
+func (ss *serverStream) SendMsg(m interface{}) (err error) {
+ defer func() {
+ if ss.trInfo != nil {
+ ss.mu.Lock()
+ if ss.trInfo.tr != nil {
+ if err == nil {
+ ss.trInfo.tr.LazyLog(&payload{sent: true, msg: m}, true)
+ } else {
+ ss.trInfo.tr.LazyLog(&fmtStringer{"%v", []interface{}{err}}, true)
+ ss.trInfo.tr.SetError()
+ }
+ }
+ ss.mu.Unlock()
+ }
+ if err != nil && err != io.EOF {
+ st, _ := status.FromError(toRPCErr(err))
+ ss.t.WriteStatus(ss.s, st)
+ // Non-user specified status was sent out. This should be an error
+ // case (as a server side Cancel maybe).
+ //
+ // This is not handled specifically now. User will return a final
+ // status from the service handler, we will log that error instead.
+ // This behavior is similar to an interceptor.
+ }
+ if channelz.IsOn() && err == nil {
+ ss.t.IncrMsgSent()
+ }
+ }()
+ data, err := encode(ss.codec, m)
+ if err != nil {
+ return err
+ }
+ compData, err := compress(data, ss.cp, ss.comp)
+ if err != nil {
+ return err
+ }
+ hdr, payload := msgHeader(data, compData)
+ // TODO(dfawley): should we be checking len(data) instead?
+ if len(payload) > ss.maxSendMessageSize {
+ return status.Errorf(codes.ResourceExhausted, "trying to send message larger than max (%d vs. %d)", len(payload), ss.maxSendMessageSize)
+ }
+ if err := ss.t.Write(ss.s, hdr, payload, &transport.Options{Last: false}); err != nil {
+ return toRPCErr(err)
+ }
+ if ss.binlog != nil {
+ if !ss.serverHeaderBinlogged {
+ h, _ := ss.s.Header()
+ ss.binlog.Log(&binarylog.ServerHeader{
+ Header: h,
+ })
+ ss.serverHeaderBinlogged = true
+ }
+ ss.binlog.Log(&binarylog.ServerMessage{
+ Message: data,
+ })
+ }
+ if ss.statsHandler != nil {
+ ss.statsHandler.HandleRPC(ss.s.Context(), outPayload(false, m, data, payload, time.Now()))
+ }
+ return nil
+}
+
+func (ss *serverStream) RecvMsg(m interface{}) (err error) {
+ defer func() {
+ if ss.trInfo != nil {
+ ss.mu.Lock()
+ if ss.trInfo.tr != nil {
+ if err == nil {
+ ss.trInfo.tr.LazyLog(&payload{sent: false, msg: m}, true)
+ } else if err != io.EOF {
+ ss.trInfo.tr.LazyLog(&fmtStringer{"%v", []interface{}{err}}, true)
+ ss.trInfo.tr.SetError()
+ }
+ }
+ ss.mu.Unlock()
+ }
+ if err != nil && err != io.EOF {
+ st, _ := status.FromError(toRPCErr(err))
+ ss.t.WriteStatus(ss.s, st)
+ // Non-user specified status was sent out. This should be an error
+ // case (as a server side Cancel maybe).
+ //
+ // This is not handled specifically now. User will return a final
+ // status from the service handler, we will log that error instead.
+ // This behavior is similar to an interceptor.
+ }
+ if channelz.IsOn() && err == nil {
+ ss.t.IncrMsgRecv()
+ }
+ }()
+ var payInfo *payloadInfo
+ if ss.statsHandler != nil || ss.binlog != nil {
+ payInfo = &payloadInfo{}
+ }
+ if err := recv(ss.p, ss.codec, ss.s, ss.dc, m, ss.maxReceiveMessageSize, payInfo, ss.decomp); err != nil {
+ if err == io.EOF {
+ if ss.binlog != nil {
+ ss.binlog.Log(&binarylog.ClientHalfClose{})
+ }
+ return err
+ }
+ if err == io.ErrUnexpectedEOF {
+ err = status.Errorf(codes.Internal, io.ErrUnexpectedEOF.Error())
+ }
+ return toRPCErr(err)
+ }
+ if ss.statsHandler != nil {
+ ss.statsHandler.HandleRPC(ss.s.Context(), &stats.InPayload{
+ RecvTime: time.Now(),
+ Payload: m,
+ // TODO truncate large payload.
+ Data: payInfo.uncompressedBytes,
+ Length: len(payInfo.uncompressedBytes),
+ })
+ }
+ if ss.binlog != nil {
+ ss.binlog.Log(&binarylog.ClientMessage{
+ Message: payInfo.uncompressedBytes,
+ })
+ }
+ return nil
+}
+
+// MethodFromServerStream returns the method string for the input stream.
+// The returned string is in the format of "/service/method".
+func MethodFromServerStream(stream ServerStream) (string, bool) {
+ return Method(stream.Context())
+}
diff --git a/vendor/google.golang.org/grpc/tap/tap.go b/vendor/google.golang.org/grpc/tap/tap.go
new file mode 100644
index 000000000..584360f68
--- /dev/null
+++ b/vendor/google.golang.org/grpc/tap/tap.go
@@ -0,0 +1,51 @@
+/*
+ *
+ * Copyright 2016 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// Package tap defines the function handles which are executed on the transport
+// layer of gRPC-Go and related information. Everything here is EXPERIMENTAL.
+package tap
+
+import (
+ "context"
+)
+
+// Info defines the relevant information needed by the handles.
+type Info struct {
+ // FullMethodName is the string of grpc method (in the format of
+ // /package.service/method).
+ FullMethodName string
+ // TODO: More to be added.
+}
+
+// ServerInHandle defines the function which runs before a new stream is created
+// on the server side. If it returns a non-nil error, the stream will not be
+// created and a RST_STREAM will be sent back to the client with REFUSED_STREAM.
+// The client will receive an RPC error "code = Unavailable, desc = stream
+// terminated by RST_STREAM with error code: REFUSED_STREAM".
+//
+// It's intended to be used in situations where you don't want to waste the
+// resources to accept the new stream (e.g. rate-limiting). And the content of
+// the error will be ignored and won't be sent back to the client. For other
+// general usages, please use interceptors.
+//
+// Note that it is executed in the per-connection I/O goroutine(s) instead of
+// per-RPC goroutine. Therefore, users should NOT have any
+// blocking/time-consuming work in this handle. Otherwise all the RPCs would
+// slow down. Also, for the same reason, this handle won't be called
+// concurrently by gRPC.
+type ServerInHandle func(ctx context.Context, info *Info) (context.Context, error)
diff --git a/vendor/google.golang.org/grpc/trace.go b/vendor/google.golang.org/grpc/trace.go
new file mode 100644
index 000000000..c1c96dedc
--- /dev/null
+++ b/vendor/google.golang.org/grpc/trace.go
@@ -0,0 +1,113 @@
+/*
+ *
+ * Copyright 2015 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package grpc
+
+import (
+ "bytes"
+ "fmt"
+ "io"
+ "net"
+ "strings"
+ "time"
+
+ "golang.org/x/net/trace"
+)
+
+// EnableTracing controls whether to trace RPCs using the golang.org/x/net/trace package.
+// This should only be set before any RPCs are sent or received by this program.
+var EnableTracing bool
+
+// methodFamily returns the trace family for the given method.
+// It turns "/pkg.Service/GetFoo" into "pkg.Service".
+func methodFamily(m string) string {
+ m = strings.TrimPrefix(m, "/") // remove leading slash
+ if i := strings.Index(m, "/"); i >= 0 {
+ m = m[:i] // remove everything from second slash
+ }
+ if i := strings.LastIndex(m, "."); i >= 0 {
+ m = m[i+1:] // cut down to last dotted component
+ }
+ return m
+}
+
+// traceInfo contains tracing information for an RPC.
+type traceInfo struct {
+ tr trace.Trace
+ firstLine firstLine
+}
+
+// firstLine is the first line of an RPC trace.
+type firstLine struct {
+ client bool // whether this is a client (outgoing) RPC
+ remoteAddr net.Addr
+ deadline time.Duration // may be zero
+}
+
+func (f *firstLine) String() string {
+ var line bytes.Buffer
+ io.WriteString(&line, "RPC: ")
+ if f.client {
+ io.WriteString(&line, "to")
+ } else {
+ io.WriteString(&line, "from")
+ }
+ fmt.Fprintf(&line, " %v deadline:", f.remoteAddr)
+ if f.deadline != 0 {
+ fmt.Fprint(&line, f.deadline)
+ } else {
+ io.WriteString(&line, "none")
+ }
+ return line.String()
+}
+
+const truncateSize = 100
+
+func truncate(x string, l int) string {
+ if l > len(x) {
+ return x
+ }
+ return x[:l]
+}
+
+// payload represents an RPC request or response payload.
+type payload struct {
+ sent bool // whether this is an outgoing payload
+ msg interface{} // e.g. a proto.Message
+ // TODO(dsymonds): add stringifying info to codec, and limit how much we hold here?
+}
+
+func (p payload) String() string {
+ if p.sent {
+ return truncate(fmt.Sprintf("sent: %v", p.msg), truncateSize)
+ }
+ return truncate(fmt.Sprintf("recv: %v", p.msg), truncateSize)
+}
+
+type fmtStringer struct {
+ format string
+ a []interface{}
+}
+
+func (f *fmtStringer) String() string {
+ return fmt.Sprintf(f.format, f.a...)
+}
+
+type stringer string
+
+func (s stringer) String() string { return string(s) }
diff --git a/vendor/google.golang.org/grpc/version.go b/vendor/google.golang.org/grpc/version.go
new file mode 100644
index 000000000..260f27c88
--- /dev/null
+++ b/vendor/google.golang.org/grpc/version.go
@@ -0,0 +1,22 @@
+/*
+ *
+ * Copyright 2018 gRPC authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package grpc
+
+// Version is the current grpc version.
+const Version = "1.17.0"
diff --git a/vendor/google.golang.org/grpc/vet.sh b/vendor/google.golang.org/grpc/vet.sh
new file mode 100755
index 000000000..94d3d54e2
--- /dev/null
+++ b/vendor/google.golang.org/grpc/vet.sh
@@ -0,0 +1,136 @@
+#!/bin/bash
+
+if [[ `uname -a` = *"Darwin"* ]]; then
+ echo "It seems you are running on Mac. This script does not work on Mac. See https://github.com/grpc/grpc-go/issues/2047"
+ exit 1
+fi
+
+set -ex # Exit on error; debugging enabled.
+set -o pipefail # Fail a pipe if any sub-command fails.
+
+die() {
+ echo "$@" >&2
+ exit 1
+}
+
+# Check to make sure it's safe to modify the user's git repo.
+if git status --porcelain | read; then
+ die "Uncommitted or untracked files found; commit changes first"
+fi
+
+if [[ -d "${GOPATH}/src" ]]; then
+ die "\${GOPATH}/src (${GOPATH}/src) exists; this script will delete it."
+fi
+
+# Undo any edits made by this script.
+cleanup() {
+ rm -rf "${GOPATH}/src"
+ git reset --hard HEAD
+}
+trap cleanup EXIT
+
+fail_on_output() {
+ tee /dev/stderr | (! read)
+}
+
+PATH="${GOPATH}/bin:${GOROOT}/bin:${PATH}"
+
+if [[ "$1" = "-install" ]]; then
+ # Check for module support
+ if go help mod >& /dev/null; then
+ go install \
+ golang.org/x/lint/golint \
+ golang.org/x/tools/cmd/goimports \
+ honnef.co/go/tools/cmd/staticcheck \
+ github.com/client9/misspell/cmd/misspell \
+ github.com/golang/protobuf/protoc-gen-go
+ else
+ # Ye olde `go get` incantation.
+ # Note: this gets the latest version of all tools (vs. the pinned versions
+ # with Go modules).
+ go get -u \
+ golang.org/x/lint/golint \
+ golang.org/x/tools/cmd/goimports \
+ honnef.co/go/tools/cmd/staticcheck \
+ github.com/client9/misspell/cmd/misspell \
+ github.com/golang/protobuf/protoc-gen-go
+ fi
+ if [[ -z "${VET_SKIP_PROTO}" ]]; then
+ if [[ "${TRAVIS}" = "true" ]]; then
+ PROTOBUF_VERSION=3.3.0
+ PROTOC_FILENAME=protoc-${PROTOBUF_VERSION}-linux-x86_64.zip
+ pushd /home/travis
+ wget https://github.com/google/protobuf/releases/download/v${PROTOBUF_VERSION}/${PROTOC_FILENAME}
+ unzip ${PROTOC_FILENAME}
+ bin/protoc --version
+ popd
+ elif ! which protoc > /dev/null; then
+ die "Please install protoc into your path"
+ fi
+ fi
+ exit 0
+elif [[ "$#" -ne 0 ]]; then
+ die "Unknown argument(s): $*"
+fi
+
+# - Ensure all source files contain a copyright message.
+git ls-files "*.go" | xargs grep -L "\(Copyright [0-9]\{4,\} gRPC authors\)\|DO NOT EDIT" 2>&1 | fail_on_output
+
+# - Do not import math/rand for real library code. Use internal/grpcrand for
+# thread safety.
+git ls-files "*.go" | xargs grep -l '"math/rand"' 2>&1 | (! grep -v '^examples\|^stress\|grpcrand')
+
+# - Ensure all ptypes proto packages are renamed when importing.
+git ls-files "*.go" | (! xargs grep "\(import \|^\s*\)\"github.com/golang/protobuf/ptypes/")
+
+# - Check imports that are illegal in appengine (until Go 1.11).
+# TODO: Remove when we drop Go 1.10 support
+go list -f {{.Dir}} ./... | xargs go run test/go_vet/vet.go
+
+# - gofmt, goimports, golint (with exceptions for generated code), go vet.
+gofmt -s -d -l . 2>&1 | fail_on_output
+goimports -l . 2>&1 | fail_on_output
+golint ./... 2>&1 | (! grep -vE "(_mock|\.pb)\.go:")
+go tool vet -all .
+
+# - Check that generated proto files are up to date.
+if [[ -z "${VET_SKIP_PROTO}" ]]; then
+ PATH="/home/travis/bin:${PATH}" make proto && \
+ git status --porcelain 2>&1 | fail_on_output || \
+ (git status; git --no-pager diff; exit 1)
+fi
+
+# - Check that our module is tidy.
+if go help mod >& /dev/null; then
+ go mod tidy && \
+ git status --porcelain 2>&1 | fail_on_output || \
+ (git status; git --no-pager diff; exit 1)
+fi
+
+# - Collection of static analysis checks
+### HACK HACK HACK: Remove once staticcheck works with modules.
+# Make a symlink in ${GOPATH}/src to its ${GOPATH}/pkg/mod equivalent for every package we use.
+for x in $(find "${GOPATH}/pkg/mod" -name '*@*' | grep -v \/mod\/cache\/); do
+ pkg="$(echo ${x#"${GOPATH}/pkg/mod/"} | cut -f1 -d@)";
+ # If multiple versions exist, just use the existing one.
+ if [[ -L "${GOPATH}/src/${pkg}" ]]; then continue; fi
+ mkdir -p "$(dirname "${GOPATH}/src/${pkg}")";
+ ln -s $x "${GOPATH}/src/${pkg}";
+done
+### END HACK HACK HACK
+
+# TODO(menghanl): fix errors in transport_test.
+staticcheck -ignore '
+balancer.go:SA1019
+balancer_test.go:SA1019
+clientconn_test.go:SA1019
+balancer/roundrobin/roundrobin_test.go:SA1019
+benchmark/benchmain/main.go:SA1019
+internal/transport/handler_server.go:SA1019
+internal/transport/handler_server_test.go:SA1019
+internal/transport/transport_test.go:SA2002
+stats/stats_test.go:SA1019
+test/channelz_test.go:SA1019
+test/end2end_test.go:SA1019
+' ./...
+misspell -error .
diff --git a/vendor/vendor.json b/vendor/vendor.json
index f6aeac022..f5794d5fd 100644
--- a/vendor/vendor.json
+++ b/vendor/vendor.json
@@ -21,6 +21,42 @@
"revisionTime": "2016-08-11T21:22:31Z"
},
{
+ "checksumSHA1": "JA71FmiLUk0b8JLcARcCdTE/m50=",
+ "path": "cloud.google.com/go/iam",
+ "revision": "e3bff73569d16ed16f9436985fd6e823ca72ad5d",
+ "revisionTime": "2018-12-05T23:08:53Z"
+ },
+ {
+ "checksumSHA1": "6NC37PKwhqaQ8EOZBfVgaEvTGyw=",
+ "path": "cloud.google.com/go/internal",
+ "revision": "e3bff73569d16ed16f9436985fd6e823ca72ad5d",
+ "revisionTime": "2018-12-05T23:08:53Z"
+ },
+ {
+ "checksumSHA1": "wQ4uGuRwMb24vG16pPQDOOCPkFo=",
+ "path": "cloud.google.com/go/internal/optional",
+ "revision": "e3bff73569d16ed16f9436985fd6e823ca72ad5d",
+ "revisionTime": "2018-12-05T23:08:53Z"
+ },
+ {
+ "checksumSHA1": "C4dSGIP7BWaqX/uK38jrmbo6cUE=",
+ "path": "cloud.google.com/go/internal/trace",
+ "revision": "e3bff73569d16ed16f9436985fd6e823ca72ad5d",
+ "revisionTime": "2018-12-05T23:08:53Z"
+ },
+ {
+ "checksumSHA1": "oIsDazjda0HX8LUfgnW/USVYx/k=",
+ "path": "cloud.google.com/go/internal/version",
+ "revision": "e3bff73569d16ed16f9436985fd6e823ca72ad5d",
+ "revisionTime": "2018-12-05T23:08:53Z"
+ },
+ {
+ "checksumSHA1": "RnZ8lmOfTvLgQwnWJbdN5iwI05I=",
+ "path": "cloud.google.com/go/storage",
+ "revision": "e3bff73569d16ed16f9436985fd6e823ca72ad5d",
+ "revisionTime": "2018-12-05T23:08:53Z"
+ },
+ {
"checksumSHA1": "z+M6FYl9EKsoZZMLcT0Ktwfk8pI=",
"path": "github.com/Azure/azure-pipeline-go/pipeline",
"revision": "7571e8eb0876932ab505918ff7ed5107773e5ee2",
@@ -247,10 +283,10 @@
"revisionTime": "2017-07-10T16:04:46Z"
},
{
- "checksumSHA1": "yqF125xVSkmfLpIVGrLlfE05IUk=",
+ "checksumSHA1": "Y2MOwzNZfl4NRNDbLCZa6sgx7O0=",
"path": "github.com/golang/protobuf/proto",
- "revision": "748d386b5c1ea99658fd69fe9f03991ce86a90c1",
- "revisionTime": "2017-07-26T21:28:29Z"
+ "revision": "1d3f30b51784bec5aad268e59fd3c2fc1c2fe73f",
+ "revisionTime": "2018-11-28T19:23:52Z"
},
{
"checksumSHA1": "Z1gJ3PKzwBpOoPnTSEM5yd0zHYA=",
@@ -259,12 +295,48 @@
"revisionTime": "2017-07-26T21:28:29Z"
},
{
+ "checksumSHA1": "/s0InJhSrxhTpqw5FIKgSMknCfM=",
+ "path": "github.com/golang/protobuf/ptypes",
+ "revision": "b4deda0973fb4c70b50d226b1af49f3da59f5265",
+ "revisionTime": "2018-04-30T18:52:41Z"
+ },
+ {
+ "checksumSHA1": "2/Xg4L9IVGQRJB8zCELZx7/Z4HU=",
+ "path": "github.com/golang/protobuf/ptypes/any",
+ "revision": "1d3f30b51784bec5aad268e59fd3c2fc1c2fe73f",
+ "revisionTime": "2018-11-28T19:23:52Z"
+ },
+ {
+ "checksumSHA1": "RE9rLveNHapyMKQC8p10tbkUE9w=",
+ "path": "github.com/golang/protobuf/ptypes/duration",
+ "revision": "1d3f30b51784bec5aad268e59fd3c2fc1c2fe73f",
+ "revisionTime": "2018-11-28T19:23:52Z"
+ },
+ {
+ "checksumSHA1": "seEwY2xETpK9yHJ9+bHqkLZ0VMU=",
+ "path": "github.com/golang/protobuf/ptypes/timestamp",
+ "revision": "1d3f30b51784bec5aad268e59fd3c2fc1c2fe73f",
+ "revisionTime": "2018-11-28T19:23:52Z"
+ },
+ {
"checksumSHA1": "p/8vSviYF91gFflhrt5vkyksroo=",
"path": "github.com/golang/snappy",
"revision": "553a641470496b2327abcac10b36396bd98e45c9",
"revisionTime": "2017-02-15T23:32:05Z"
},
{
+ "checksumSHA1": "XoHDymqY0JxO8QKdNQGknWAihDc=",
+ "path": "github.com/googleapis/gax-go",
+ "revision": "a2f8411585aeae89985ca40e3be2984a82a2bcc7",
+ "revisionTime": "2018-12-05T19:19:52Z"
+ },
+ {
+ "checksumSHA1": "ix3YlIoJkMRSZbpi3AZV8t9vlHY=",
+ "path": "github.com/googleapis/gax-go/v2",
+ "revision": "a2f8411585aeae89985ca40e3be2984a82a2bcc7",
+ "revisionTime": "2018-12-05T19:19:52Z"
+ },
+ {
"checksumSHA1": "d9PxF1XQGLMJZRct2R8qVM/eYlE=",
"path": "github.com/hashicorp/golang-lru",
"revision": "0a025b7e63adc15a622f29b0b2c4c3848243bbf6",
@@ -319,7 +391,7 @@
"revisionTime": "2016-12-24T10:41:01Z"
},
{
- "checksumSHA1": "6tNwbL5tUS0dxYzADKVZtI2d/lE=",
+ "checksumSHA1": "Op+vCwiOTLgCMDFrTO98Hwum6hg=",
"path": "github.com/influxdata/influxdb/client",
"revision": "a55dd0f50edd14c9c798d3564189eb4f53914309",
"revisionTime": "2017-10-09T17:24:46Z"
@@ -381,7 +453,7 @@
"revisionTime": "2018-08-30T10:17:45Z"
},
{
- "checksumSHA1": "MNkKJyk2TazKMJYbal5wFHybpyA=",
+ "checksumSHA1": "KGCifxxR5cm2gz94i2iha+RIZlk=",
"path": "github.com/mattn/go-runewidth",
"revision": "ce7b0b5c7b45a81508558cd1dba6bb1e4ddb51bb",
"revisionTime": "2018-04-08T05:53:51Z"
@@ -723,6 +795,90 @@
"revisionTime": "2018-06-15T20:27:29Z"
},
{
+ "checksumSHA1": "C9EIZQEMR5q5zVZCo1OtPWSV39I=",
+ "path": "go.opencensus.io",
+ "revision": "aab39bd6a98b853ab66c8a564f5d6cfcad59ce8a",
+ "revisionTime": "2018-12-04T02:35:38Z"
+ },
+ {
+ "checksumSHA1": "TA3C6+5PM7V2zbsnLMp13Efy/BA=",
+ "path": "go.opencensus.io/exemplar",
+ "revision": "aab39bd6a98b853ab66c8a564f5d6cfcad59ce8a",
+ "revisionTime": "2018-12-04T02:35:38Z"
+ },
+ {
+ "checksumSHA1": "uEGNDh56bViSqI19kj5uQbcTUOQ=",
+ "path": "go.opencensus.io/internal",
+ "revision": "aab39bd6a98b853ab66c8a564f5d6cfcad59ce8a",
+ "revisionTime": "2018-12-04T02:35:38Z"
+ },
+ {
+ "checksumSHA1": "Vcwr4P/uIN4haoJPglU7liURepM=",
+ "path": "go.opencensus.io/internal/tagencoding",
+ "revision": "aab39bd6a98b853ab66c8a564f5d6cfcad59ce8a",
+ "revisionTime": "2018-12-04T02:35:38Z"
+ },
+ {
+ "checksumSHA1": "kxVcsHl3DWhTdSZkterTpRFQRIs=",
+ "path": "go.opencensus.io/plugin/ochttp",
+ "revision": "aab39bd6a98b853ab66c8a564f5d6cfcad59ce8a",
+ "revisionTime": "2018-12-04T02:35:38Z"
+ },
+ {
+ "checksumSHA1": "0OVZlXVUMGzf8ddlnjg2yMZI4ao=",
+ "path": "go.opencensus.io/plugin/ochttp/propagation/b3",
+ "revision": "aab39bd6a98b853ab66c8a564f5d6cfcad59ce8a",
+ "revisionTime": "2018-12-04T02:35:38Z"
+ },
+ {
+ "checksumSHA1": "iITJeCEWl7VUPxOB8ThLRAGYTJU=",
+ "path": "go.opencensus.io/stats",
+ "revision": "aab39bd6a98b853ab66c8a564f5d6cfcad59ce8a",
+ "revisionTime": "2018-12-04T02:35:38Z"
+ },
+ {
+ "checksumSHA1": "SEHKoV2p561oIgFTqzQ67a/XU7I=",
+ "path": "go.opencensus.io/stats/internal",
+ "revision": "aab39bd6a98b853ab66c8a564f5d6cfcad59ce8a",
+ "revisionTime": "2018-12-04T02:35:38Z"
+ },
+ {
+ "checksumSHA1": "KVJAD8BjQ045mOPz/mAWbPXMlIU=",
+ "path": "go.opencensus.io/stats/view",
+ "revision": "aab39bd6a98b853ab66c8a564f5d6cfcad59ce8a",
+ "revisionTime": "2018-12-04T02:35:38Z"
+ },
+ {
+ "checksumSHA1": "/xIgvCFhYpV43FT16tNBTbm7MeY=",
+ "path": "go.opencensus.io/tag",
+ "revision": "aab39bd6a98b853ab66c8a564f5d6cfcad59ce8a",
+ "revisionTime": "2018-12-04T02:35:38Z"
+ },
+ {
+ "checksumSHA1": "cqXo2mPFU9tZc7isOQ0aq/oZCdY=",
+ "path": "go.opencensus.io/trace",
+ "revision": "8734d3b4deb5b1369308eb92b16ca7c7dd5ff343",
+ "revisionTime": "2019-03-04T23:49:55Z"
+ },
+ {
+ "checksumSHA1": "0P3BycP6CFnFNRCnF4dTlMEJgEI=",
+ "path": "go.opencensus.io/trace/internal",
+ "revision": "aab39bd6a98b853ab66c8a564f5d6cfcad59ce8a",
+ "revisionTime": "2018-12-04T02:35:38Z"
+ },
+ {
+ "checksumSHA1": "FHJParRi8f1GHO7Cx+lk3bMWBq0=",
+ "path": "go.opencensus.io/trace/propagation",
+ "revision": "aab39bd6a98b853ab66c8a564f5d6cfcad59ce8a",
+ "revisionTime": "2018-12-04T02:35:38Z"
+ },
+ {
+ "checksumSHA1": "UHbxxaMqpEPsubh8kPwzSlyEwqI=",
+ "path": "go.opencensus.io/trace/tracestate",
+ "revision": "aab39bd6a98b853ab66c8a564f5d6cfcad59ce8a",
+ "revisionTime": "2018-12-04T02:35:38Z"
+ },
+ {
"checksumSHA1": "TT1rac6kpQp2vz24m5yDGUNQ/QQ=",
"path": "golang.org/x/crypto/cast5",
"revision": "ff983b9c42bc9fbf91556e191cc8efb585c16908",
@@ -843,6 +999,12 @@
"revisionTime": "2017-03-08T20:54:49Z"
},
{
+ "checksumSHA1": "WHc3uByvGaMcnSoI21fhzYgbOgg=",
+ "path": "golang.org/x/net/context/ctxhttp",
+ "revision": "66aacef3dd8a676686c7ae3716979581e8b03c47",
+ "revisionTime": "2016-09-14T00:11:54Z"
+ },
+ {
"checksumSHA1": "vqc3a+oTUGX8PmD0TS+qQ7gmN8I=",
"path": "golang.org/x/net/html",
"revision": "b4690f45fa1cafc47b1c280c2e75116efe40cc13",
@@ -861,18 +1023,75 @@
"revisionTime": "2017-02-15T08:41:58Z"
},
{
+ "checksumSHA1": "pCY4YtdNKVBYRbNvODjx8hj0hIs=",
+ "path": "golang.org/x/net/http/httpguts",
+ "revision": "351d144fa1fc0bd934e2408202be0c29f25e35a0",
+ "revisionTime": "2018-11-30T00:35:12Z"
+ },
+ {
+ "checksumSHA1": "pMsrfJZ8JwoPT2pBa1loXKhGODQ=",
+ "path": "golang.org/x/net/http2",
+ "revision": "16b79f2e4e95ea23b2bf9903c9809ff7b013ce85",
+ "revisionTime": "2019-03-01T08:36:47Z"
+ },
+ {
+ "checksumSHA1": "KZniwnfpWkaTPhUQDUTvgex/7y0=",
+ "path": "golang.org/x/net/http2/hpack",
+ "revision": "351d144fa1fc0bd934e2408202be0c29f25e35a0",
+ "revisionTime": "2018-11-30T00:35:12Z"
+ },
+ {
"checksumSHA1": "RcrB7tgYS/GMW4QrwVdMOTNqIU8=",
"path": "golang.org/x/net/idna",
"revision": "5ccada7d0a7ba9aeb5d3aca8d3501b4c2a509fec",
"revisionTime": "2018-01-12T01:53:59Z"
},
{
+ "checksumSHA1": "UxahDzW2v4mf/+aFxruuupaoIwo=",
+ "path": "golang.org/x/net/internal/timeseries",
+ "revision": "351d144fa1fc0bd934e2408202be0c29f25e35a0",
+ "revisionTime": "2018-11-30T00:35:12Z"
+ },
+ {
+ "path": "golang.org/x/net/lex/httplex",
+ "revision": ""
+ },
+ {
+ "origin": "golang.org/x/net/lex/httplex",
+ "path": "golang.org/x/net/lex/httplex/.",
+ "revision": ""
+ },
+ {
+ "checksumSHA1": "u/r66lwYfgg682u5hZG7/E7+VCY=",
+ "path": "golang.org/x/net/trace",
+ "revision": "66aacef3dd8a676686c7ae3716979581e8b03c47",
+ "revisionTime": "2016-09-14T00:11:54Z"
+ },
+ {
"checksumSHA1": "7EZyXN0EmZLgGxZxK01IJua4c8o=",
"path": "golang.org/x/net/websocket",
"revision": "b4690f45fa1cafc47b1c280c2e75116efe40cc13",
"revisionTime": "2017-02-15T08:41:58Z"
},
{
+ "checksumSHA1": "5+Wlq4i/9BUFndiLq5QMPvATj4w=",
+ "path": "golang.org/x/oauth2",
+ "revision": "d668ce993890a79bda886613ee587a69dd5da7a6",
+ "revisionTime": "2018-12-02T09:28:16Z"
+ },
+ {
+ "checksumSHA1": "aizsl78eqx16svvpIAr8noIpvSk=",
+ "path": "golang.org/x/oauth2/google",
+ "revision": "d668ce993890a79bda886613ee587a69dd5da7a6",
+ "revisionTime": "2018-12-02T09:28:16Z"
+ },
+ {
+ "checksumSHA1": "DMmcJ2yC1hddfBLeijo9nNkARcU=",
+ "path": "golang.org/x/oauth2/internal",
+ "revision": "d668ce993890a79bda886613ee587a69dd5da7a6",
+ "revisionTime": "2018-12-02T09:28:16Z"
+ },
+ {
"checksumSHA1": "4TEYFKrAUuwBMqExjQBsnf/CgjQ=",
"path": "golang.org/x/sync/syncmap",
"revision": "f52d1811a62927559de87708c8913c1650ce4f26",
@@ -1011,6 +1230,338 @@
"revisionTime": "2016-11-04T18:56:24Z"
},
{
+ "checksumSHA1": "RKvIl9YrICqcUYQFsY5BYBQBH8Y=",
+ "path": "google.golang.org/api/gensupport",
+ "revision": "6142e720c068c6cd71f2258e007ff1991572e1d5",
+ "revisionTime": "2018-12-03T22:14:33Z"
+ },
+ {
+ "checksumSHA1": "xLosGeduDIVpjOZWx7QKvVwQqiE=",
+ "path": "google.golang.org/api/googleapi",
+ "revision": "6142e720c068c6cd71f2258e007ff1991572e1d5",
+ "revisionTime": "2018-12-03T22:14:33Z"
+ },
+ {
+ "checksumSHA1": "1K0JxrUfDqAB3MyRiU1LKjfHyf4=",
+ "path": "google.golang.org/api/googleapi/internal/uritemplates",
+ "revision": "6142e720c068c6cd71f2258e007ff1991572e1d5",
+ "revisionTime": "2018-12-03T22:14:33Z"
+ },
+ {
+ "checksumSHA1": "Mr2fXhMRzlQCgANFm91s536pG7E=",
+ "path": "google.golang.org/api/googleapi/transport",
+ "revision": "6142e720c068c6cd71f2258e007ff1991572e1d5",
+ "revisionTime": "2018-12-03T22:14:33Z"
+ },
+ {
+ "checksumSHA1": "VXjerYDduz0mh+VddRvkpT4MHbM=",
+ "path": "google.golang.org/api/internal",
+ "revision": "6142e720c068c6cd71f2258e007ff1991572e1d5",
+ "revisionTime": "2018-12-03T22:14:33Z"
+ },
+ {
+ "checksumSHA1": "zh9AcT6oNvhnOqb7w7njY48TkvI=",
+ "path": "google.golang.org/api/iterator",
+ "revision": "6142e720c068c6cd71f2258e007ff1991572e1d5",
+ "revisionTime": "2018-12-03T22:14:33Z"
+ },
+ {
+ "checksumSHA1": "7KUvO81yZlWUMXY7Ls8U4QaEji4=",
+ "path": "google.golang.org/api/option",
+ "revision": "6142e720c068c6cd71f2258e007ff1991572e1d5",
+ "revisionTime": "2018-12-03T22:14:33Z"
+ },
+ {
+ "checksumSHA1": "8Svg39MMR6EEf4JOucW0XxgxVOs=",
+ "path": "google.golang.org/api/storage/v1",
+ "revision": "6142e720c068c6cd71f2258e007ff1991572e1d5",
+ "revisionTime": "2018-12-03T22:14:33Z"
+ },
+ {
+ "checksumSHA1": "YiHsb+wC9ua0trHVnqbUlWyvhco=",
+ "path": "google.golang.org/api/transport/http",
+ "revision": "6142e720c068c6cd71f2258e007ff1991572e1d5",
+ "revisionTime": "2018-12-03T22:14:33Z"
+ },
+ {
+ "checksumSHA1": "sJcKCvjPtoysqyelsB2CQzC5oQI=",
+ "path": "google.golang.org/api/transport/http/internal/propagation",
+ "revision": "6142e720c068c6cd71f2258e007ff1991572e1d5",
+ "revisionTime": "2018-12-03T22:14:33Z"
+ },
+ {
+ "checksumSHA1": "YNqziavfZHurG6wrwR5Uf9SnI4s=",
+ "path": "google.golang.org/genproto/googleapis/api/annotations",
+ "revision": "bd91e49a0898e27abb88c339b432fa53d7497ac0",
+ "revisionTime": "2018-12-02T18:38:23Z"
+ },
+ {
+ "checksumSHA1": "PhCTccjTEHHwnwxd8MvQyUdba4Q=",
+ "path": "google.golang.org/genproto/googleapis/iam/v1",
+ "revision": "bd91e49a0898e27abb88c339b432fa53d7497ac0",
+ "revisionTime": "2018-12-02T18:38:23Z"
+ },
+ {
+ "checksumSHA1": "jBEvkhfuMbiqPceCQ5HaWmHmYAM=",
+ "path": "google.golang.org/genproto/googleapis/rpc/code",
+ "revision": "bd91e49a0898e27abb88c339b432fa53d7497ac0",
+ "revisionTime": "2018-12-02T18:38:23Z"
+ },
+ {
+ "checksumSHA1": "oUD15OBRSXt0t4P0s6HMjH/+iQo=",
+ "path": "google.golang.org/genproto/googleapis/rpc/status",
+ "revision": "bd91e49a0898e27abb88c339b432fa53d7497ac0",
+ "revisionTime": "2018-12-02T18:38:23Z"
+ },
+ {
+ "checksumSHA1": "In4+pspSMNg2DrAxUYLLEodXJkc=",
+ "path": "google.golang.org/grpc",
+ "revision": "df014850f6dee74ba2fc94874043a9f3f75fbfd8",
+ "revisionTime": "2018-12-04T23:41:53Z",
+ "version": "v1.17.0",
+ "versionExact": "v1.17.0"
+ },
+ {
+ "checksumSHA1": "CGyaW/0mT8XYzAh/URx+9gSe7yQ=",
+ "path": "google.golang.org/grpc/balancer",
+ "revision": "df014850f6dee74ba2fc94874043a9f3f75fbfd8",
+ "revisionTime": "2018-12-04T23:41:53Z",
+ "version": "v1.17.0",
+ "versionExact": "v1.17.0"
+ },
+ {
+ "checksumSHA1": "+y/3Ubm+jgXNL+HTLPH8s8rPZrU=",
+ "path": "google.golang.org/grpc/balancer/base",
+ "revision": "df014850f6dee74ba2fc94874043a9f3f75fbfd8",
+ "revisionTime": "2018-12-04T23:41:53Z",
+ "version": "v1.17.0",
+ "versionExact": "v1.17.0"
+ },
+ {
+ "checksumSHA1": "nbqOZ9r8jJ6K3PfnhxuR0qqsUmY=",
+ "path": "google.golang.org/grpc/balancer/roundrobin",
+ "revision": "df014850f6dee74ba2fc94874043a9f3f75fbfd8",
+ "revisionTime": "2018-12-04T23:41:53Z",
+ "version": "v1.17.0",
+ "versionExact": "v1.17.0"
+ },
+ {
+ "checksumSHA1": "YyTUFAVju8wgb1s/3azC2CeSbfY=",
+ "path": "google.golang.org/grpc/binarylog/grpc_binarylog_v1",
+ "revision": "df014850f6dee74ba2fc94874043a9f3f75fbfd8",
+ "revisionTime": "2018-12-04T23:41:53Z",
+ "version": "v1.17.0",
+ "versionExact": "v1.17.0"
+ },
+ {
+ "checksumSHA1": "R3tuACGAPyK4lr+oSNt1saUzC0M=",
+ "path": "google.golang.org/grpc/codes",
+ "revision": "df014850f6dee74ba2fc94874043a9f3f75fbfd8",
+ "revisionTime": "2018-12-04T23:41:53Z",
+ "version": "v1.17.0",
+ "versionExact": "v1.17.0"
+ },
+ {
+ "checksumSHA1": "5XXlkpXzzeNtV9I7x+3/UVWRe20=",
+ "path": "google.golang.org/grpc/connectivity",
+ "revision": "df014850f6dee74ba2fc94874043a9f3f75fbfd8",
+ "revisionTime": "2018-12-04T23:41:53Z",
+ "version": "v1.17.0",
+ "versionExact": "v1.17.0"
+ },
+ {
+ "checksumSHA1": "MCTf5N2ZKhqL6vW5AfPXh8bGavg=",
+ "path": "google.golang.org/grpc/credentials",
+ "revision": "df014850f6dee74ba2fc94874043a9f3f75fbfd8",
+ "revisionTime": "2018-12-04T23:41:53Z",
+ "version": "v1.17.0",
+ "versionExact": "v1.17.0"
+ },
+ {
+ "checksumSHA1": "Eqxca59xIMaL4EUNwWsozg7kFkk=",
+ "path": "google.golang.org/grpc/credentials/internal",
+ "revision": "df014850f6dee74ba2fc94874043a9f3f75fbfd8",
+ "revisionTime": "2018-12-04T23:41:53Z",
+ "version": "v1.17.0",
+ "versionExact": "v1.17.0"
+ },
+ {
+ "checksumSHA1": "cfLb+pzWB+Glwp82rgfcEST1mv8=",
+ "path": "google.golang.org/grpc/encoding",
+ "revision": "df014850f6dee74ba2fc94874043a9f3f75fbfd8",
+ "revisionTime": "2018-12-04T23:41:53Z",
+ "version": "v1.17.0",
+ "versionExact": "v1.17.0"
+ },
+ {
+ "checksumSHA1": "LKKkn7EYA+Do9Qwb2/SUKLFNxoo=",
+ "path": "google.golang.org/grpc/encoding/proto",
+ "revision": "df014850f6dee74ba2fc94874043a9f3f75fbfd8",
+ "revisionTime": "2018-12-04T23:41:53Z",
+ "version": "v1.17.0",
+ "versionExact": "v1.17.0"
+ },
+ {
+ "checksumSHA1": "ZPPSFisPDz2ANO4FBZIft+fRxyk=",
+ "path": "google.golang.org/grpc/grpclog",
+ "revision": "df014850f6dee74ba2fc94874043a9f3f75fbfd8",
+ "revisionTime": "2018-12-04T23:41:53Z",
+ "version": "v1.17.0",
+ "versionExact": "v1.17.0"
+ },
+ {
+ "checksumSHA1": "v6AtSbBr/lA1TjWUp4JSHIx8Uxw=",
+ "path": "google.golang.org/grpc/internal",
+ "revision": "df014850f6dee74ba2fc94874043a9f3f75fbfd8",
+ "revisionTime": "2018-12-04T23:41:53Z",
+ "version": "v1.17.0",
+ "versionExact": "v1.17.0"
+ },
+ {
+ "checksumSHA1": "uDJA7QK2iGnEwbd9TPqkLaM+xuU=",
+ "path": "google.golang.org/grpc/internal/backoff",
+ "revision": "df014850f6dee74ba2fc94874043a9f3f75fbfd8",
+ "revisionTime": "2018-12-04T23:41:53Z",
+ "version": "v1.17.0",
+ "versionExact": "v1.17.0"
+ },
+ {
+ "checksumSHA1": "9EzFWJVWPBdOC2kwXX11v9HSLTs=",
+ "path": "google.golang.org/grpc/internal/binarylog",
+ "revision": "df014850f6dee74ba2fc94874043a9f3f75fbfd8",
+ "revisionTime": "2018-12-04T23:41:53Z",
+ "version": "v1.17.0",
+ "versionExact": "v1.17.0"
+ },
+ {
+ "checksumSHA1": "xEom80cbngwXniRakoSDi/mQY7k=",
+ "path": "google.golang.org/grpc/internal/channelz",
+ "revision": "df014850f6dee74ba2fc94874043a9f3f75fbfd8",
+ "revisionTime": "2018-12-04T23:41:53Z",
+ "version": "v1.17.0",
+ "versionExact": "v1.17.0"
+ },
+ {
+ "checksumSHA1": "fuwdjGdxlbyt1scRP7g1AKJo4DQ=",
+ "path": "google.golang.org/grpc/internal/envconfig",
+ "revision": "df014850f6dee74ba2fc94874043a9f3f75fbfd8",
+ "revisionTime": "2018-12-04T23:41:53Z",
+ "version": "v1.17.0",
+ "versionExact": "v1.17.0"
+ },
+ {
+ "checksumSHA1": "70gndc/uHwyAl3D45zqp7vyHWlo=",
+ "path": "google.golang.org/grpc/internal/grpcrand",
+ "revision": "df014850f6dee74ba2fc94874043a9f3f75fbfd8",
+ "revisionTime": "2018-12-04T23:41:53Z",
+ "version": "v1.17.0",
+ "versionExact": "v1.17.0"
+ },
+ {
+ "checksumSHA1": "psHSfNyU2y9L9zRK+s41e7ScTf4=",
+ "path": "google.golang.org/grpc/internal/grpcsync",
+ "revision": "df014850f6dee74ba2fc94874043a9f3f75fbfd8",
+ "revisionTime": "2018-12-04T23:41:53Z",
+ "version": "v1.17.0",
+ "versionExact": "v1.17.0"
+ },
+ {
+ "checksumSHA1": "3LK1XBsYw6P112yilUgf8E8ZZY8=",
+ "path": "google.golang.org/grpc/internal/syscall",
+ "revision": "df014850f6dee74ba2fc94874043a9f3f75fbfd8",
+ "revisionTime": "2018-12-04T23:41:53Z",
+ "version": "v1.17.0",
+ "versionExact": "v1.17.0"
+ },
+ {
+ "checksumSHA1": "kVHeWYXkig3fEAOL/vWC+Vxn18o=",
+ "path": "google.golang.org/grpc/internal/transport",
+ "revision": "df014850f6dee74ba2fc94874043a9f3f75fbfd8",
+ "revisionTime": "2018-12-04T23:41:53Z",
+ "version": "v1.17.0",
+ "versionExact": "v1.17.0"
+ },
+ {
+ "checksumSHA1": "350+v+N+AuknxomqjND19nR969g=",
+ "path": "google.golang.org/grpc/keepalive",
+ "revision": "df014850f6dee74ba2fc94874043a9f3f75fbfd8",
+ "revisionTime": "2018-12-04T23:41:53Z",
+ "version": "v1.17.0",
+ "versionExact": "v1.17.0"
+ },
+ {
+ "checksumSHA1": "0OoJw+Wc7+1Ox5nBbwjgqWW8Xpw=",
+ "path": "google.golang.org/grpc/metadata",
+ "revision": "df014850f6dee74ba2fc94874043a9f3f75fbfd8",
+ "revisionTime": "2018-12-04T23:41:53Z",
+ "version": "v1.17.0",
+ "versionExact": "v1.17.0"
+ },
+ {
+ "checksumSHA1": "AIpS1T2G1el02vW5nhqY1fklbpU=",
+ "path": "google.golang.org/grpc/naming",
+ "revision": "df014850f6dee74ba2fc94874043a9f3f75fbfd8",
+ "revisionTime": "2018-12-04T23:41:53Z",
+ "version": "v1.17.0",
+ "versionExact": "v1.17.0"
+ },
+ {
+ "checksumSHA1": "ltPJN8UyzvWN0H0BvkP2AREujgQ=",
+ "path": "google.golang.org/grpc/peer",
+ "revision": "df014850f6dee74ba2fc94874043a9f3f75fbfd8",
+ "revisionTime": "2018-12-04T23:41:53Z",
+ "version": "v1.17.0",
+ "versionExact": "v1.17.0"
+ },
+ {
+ "checksumSHA1": "GEq6wwE1qWLmkaM02SjxBmmnHDo=",
+ "path": "google.golang.org/grpc/resolver",
+ "revision": "df014850f6dee74ba2fc94874043a9f3f75fbfd8",
+ "revisionTime": "2018-12-04T23:41:53Z",
+ "version": "v1.17.0",
+ "versionExact": "v1.17.0"
+ },
+ {
+ "checksumSHA1": "I9b2MMRa7Sz+hSB0AF/vPFsPOv4=",
+ "path": "google.golang.org/grpc/resolver/dns",
+ "revision": "df014850f6dee74ba2fc94874043a9f3f75fbfd8",
+ "revisionTime": "2018-12-04T23:41:53Z",
+ "version": "v1.17.0",
+ "versionExact": "v1.17.0"
+ },
+ {
+ "checksumSHA1": "zs9M4xE8Lyg4wvuYvR00XoBxmuw=",
+ "path": "google.golang.org/grpc/resolver/passthrough",
+ "revision": "df014850f6dee74ba2fc94874043a9f3f75fbfd8",
+ "revisionTime": "2018-12-04T23:41:53Z",
+ "version": "v1.17.0",
+ "versionExact": "v1.17.0"
+ },
+ {
+ "checksumSHA1": "FJu1DY9s5uP3cGFvuVGCL5bgrqw=",
+ "path": "google.golang.org/grpc/stats",
+ "revision": "df014850f6dee74ba2fc94874043a9f3f75fbfd8",
+ "revisionTime": "2018-12-04T23:41:53Z",
+ "version": "v1.17.0",
+ "versionExact": "v1.17.0"
+ },
+ {
+ "checksumSHA1": "bJSa9mM309wvISy+B6zfc0KAUqs=",
+ "path": "google.golang.org/grpc/status",
+ "revision": "df014850f6dee74ba2fc94874043a9f3f75fbfd8",
+ "revisionTime": "2018-12-04T23:41:53Z",
+ "version": "v1.17.0",
+ "versionExact": "v1.17.0"
+ },
+ {
+ "checksumSHA1": "HGXDrPBB90iBU4NJ7C1N8MJRkI0=",
+ "path": "google.golang.org/grpc/tap",
+ "revision": "df014850f6dee74ba2fc94874043a9f3f75fbfd8",
+ "revisionTime": "2018-12-04T23:41:53Z",
+ "version": "v1.17.0",
+ "versionExact": "v1.17.0"
+ },
+ {
"checksumSHA1": "CEFTYXtWmgSh+3Ik1NmDaJcz4E0=",
"path": "gopkg.in/check.v1",
"revision": "20d25e2804050c1cd24a7eea1e7a6447dd0e74ec",