github.com/devseccon/trivy@v0.47.1-0.20231123133102-bd902a0bd996/rpc/cache/service.twirp.go (about) 1 // Code generated by protoc-gen-twirp v8.1.0, DO NOT EDIT. 2 // source: rpc/cache/service.proto 3 4 package cache 5 6 import context "context" 7 import fmt "fmt" 8 import http "net/http" 9 import ioutil "io/ioutil" 10 import json "encoding/json" 11 import strconv "strconv" 12 import strings "strings" 13 14 import protojson "google.golang.org/protobuf/encoding/protojson" 15 import proto "google.golang.org/protobuf/proto" 16 import twirp "github.com/twitchtv/twirp" 17 import ctxsetters "github.com/twitchtv/twirp/ctxsetters" 18 19 import google_protobuf2 "google.golang.org/protobuf/types/known/emptypb" 20 21 import bytes "bytes" 22 import errors "errors" 23 import io "io" 24 import path "path" 25 import url "net/url" 26 27 // Version compatibility assertion. 28 // If the constant is not defined in the package, that likely means 29 // the package needs to be updated to work with this generated code. 30 // See https://twitchtv.github.io/twirp/docs/version_matrix.html 31 const _ = twirp.TwirpPackageMinVersion_8_1_0 32 33 // =============== 34 // Cache Interface 35 // =============== 36 37 type Cache interface { 38 PutArtifact(context.Context, *PutArtifactRequest) (*google_protobuf2.Empty, error) 39 40 PutBlob(context.Context, *PutBlobRequest) (*google_protobuf2.Empty, error) 41 42 MissingBlobs(context.Context, *MissingBlobsRequest) (*MissingBlobsResponse, error) 43 44 DeleteBlobs(context.Context, *DeleteBlobsRequest) (*google_protobuf2.Empty, error) 45 } 46 47 // ===================== 48 // Cache Protobuf Client 49 // ===================== 50 51 type cacheProtobufClient struct { 52 client HTTPClient 53 urls [4]string 54 interceptor twirp.Interceptor 55 opts twirp.ClientOptions 56 } 57 58 // NewCacheProtobufClient creates a Protobuf client that implements the Cache interface. 59 // It communicates using Protobuf and can be configured with a custom HTTPClient. 60 func NewCacheProtobufClient(baseURL string, client HTTPClient, opts ...twirp.ClientOption) Cache { 61 if c, ok := client.(*http.Client); ok { 62 client = withoutRedirects(c) 63 } 64 65 clientOpts := twirp.ClientOptions{} 66 for _, o := range opts { 67 o(&clientOpts) 68 } 69 70 // Using ReadOpt allows backwards and forwads compatibility with new options in the future 71 literalURLs := false 72 _ = clientOpts.ReadOpt("literalURLs", &literalURLs) 73 var pathPrefix string 74 if ok := clientOpts.ReadOpt("pathPrefix", &pathPrefix); !ok { 75 pathPrefix = "/twirp" // default prefix 76 } 77 78 // Build method URLs: <baseURL>[<prefix>]/<package>.<Service>/<Method> 79 serviceURL := sanitizeBaseURL(baseURL) 80 serviceURL += baseServicePath(pathPrefix, "trivy.cache.v1", "Cache") 81 urls := [4]string{ 82 serviceURL + "PutArtifact", 83 serviceURL + "PutBlob", 84 serviceURL + "MissingBlobs", 85 serviceURL + "DeleteBlobs", 86 } 87 88 return &cacheProtobufClient{ 89 client: client, 90 urls: urls, 91 interceptor: twirp.ChainInterceptors(clientOpts.Interceptors...), 92 opts: clientOpts, 93 } 94 } 95 96 func (c *cacheProtobufClient) PutArtifact(ctx context.Context, in *PutArtifactRequest) (*google_protobuf2.Empty, error) { 97 ctx = ctxsetters.WithPackageName(ctx, "trivy.cache.v1") 98 ctx = ctxsetters.WithServiceName(ctx, "Cache") 99 ctx = ctxsetters.WithMethodName(ctx, "PutArtifact") 100 caller := c.callPutArtifact 101 if c.interceptor != nil { 102 caller = func(ctx context.Context, req *PutArtifactRequest) (*google_protobuf2.Empty, error) { 103 resp, err := c.interceptor( 104 func(ctx context.Context, req interface{}) (interface{}, error) { 105 typedReq, ok := req.(*PutArtifactRequest) 106 if !ok { 107 return nil, twirp.InternalError("failed type assertion req.(*PutArtifactRequest) when calling interceptor") 108 } 109 return c.callPutArtifact(ctx, typedReq) 110 }, 111 )(ctx, req) 112 if resp != nil { 113 typedResp, ok := resp.(*google_protobuf2.Empty) 114 if !ok { 115 return nil, twirp.InternalError("failed type assertion resp.(*google_protobuf2.Empty) when calling interceptor") 116 } 117 return typedResp, err 118 } 119 return nil, err 120 } 121 } 122 return caller(ctx, in) 123 } 124 125 func (c *cacheProtobufClient) callPutArtifact(ctx context.Context, in *PutArtifactRequest) (*google_protobuf2.Empty, error) { 126 out := new(google_protobuf2.Empty) 127 ctx, err := doProtobufRequest(ctx, c.client, c.opts.Hooks, c.urls[0], in, out) 128 if err != nil { 129 twerr, ok := err.(twirp.Error) 130 if !ok { 131 twerr = twirp.InternalErrorWith(err) 132 } 133 callClientError(ctx, c.opts.Hooks, twerr) 134 return nil, err 135 } 136 137 callClientResponseReceived(ctx, c.opts.Hooks) 138 139 return out, nil 140 } 141 142 func (c *cacheProtobufClient) PutBlob(ctx context.Context, in *PutBlobRequest) (*google_protobuf2.Empty, error) { 143 ctx = ctxsetters.WithPackageName(ctx, "trivy.cache.v1") 144 ctx = ctxsetters.WithServiceName(ctx, "Cache") 145 ctx = ctxsetters.WithMethodName(ctx, "PutBlob") 146 caller := c.callPutBlob 147 if c.interceptor != nil { 148 caller = func(ctx context.Context, req *PutBlobRequest) (*google_protobuf2.Empty, error) { 149 resp, err := c.interceptor( 150 func(ctx context.Context, req interface{}) (interface{}, error) { 151 typedReq, ok := req.(*PutBlobRequest) 152 if !ok { 153 return nil, twirp.InternalError("failed type assertion req.(*PutBlobRequest) when calling interceptor") 154 } 155 return c.callPutBlob(ctx, typedReq) 156 }, 157 )(ctx, req) 158 if resp != nil { 159 typedResp, ok := resp.(*google_protobuf2.Empty) 160 if !ok { 161 return nil, twirp.InternalError("failed type assertion resp.(*google_protobuf2.Empty) when calling interceptor") 162 } 163 return typedResp, err 164 } 165 return nil, err 166 } 167 } 168 return caller(ctx, in) 169 } 170 171 func (c *cacheProtobufClient) callPutBlob(ctx context.Context, in *PutBlobRequest) (*google_protobuf2.Empty, error) { 172 out := new(google_protobuf2.Empty) 173 ctx, err := doProtobufRequest(ctx, c.client, c.opts.Hooks, c.urls[1], in, out) 174 if err != nil { 175 twerr, ok := err.(twirp.Error) 176 if !ok { 177 twerr = twirp.InternalErrorWith(err) 178 } 179 callClientError(ctx, c.opts.Hooks, twerr) 180 return nil, err 181 } 182 183 callClientResponseReceived(ctx, c.opts.Hooks) 184 185 return out, nil 186 } 187 188 func (c *cacheProtobufClient) MissingBlobs(ctx context.Context, in *MissingBlobsRequest) (*MissingBlobsResponse, error) { 189 ctx = ctxsetters.WithPackageName(ctx, "trivy.cache.v1") 190 ctx = ctxsetters.WithServiceName(ctx, "Cache") 191 ctx = ctxsetters.WithMethodName(ctx, "MissingBlobs") 192 caller := c.callMissingBlobs 193 if c.interceptor != nil { 194 caller = func(ctx context.Context, req *MissingBlobsRequest) (*MissingBlobsResponse, error) { 195 resp, err := c.interceptor( 196 func(ctx context.Context, req interface{}) (interface{}, error) { 197 typedReq, ok := req.(*MissingBlobsRequest) 198 if !ok { 199 return nil, twirp.InternalError("failed type assertion req.(*MissingBlobsRequest) when calling interceptor") 200 } 201 return c.callMissingBlobs(ctx, typedReq) 202 }, 203 )(ctx, req) 204 if resp != nil { 205 typedResp, ok := resp.(*MissingBlobsResponse) 206 if !ok { 207 return nil, twirp.InternalError("failed type assertion resp.(*MissingBlobsResponse) when calling interceptor") 208 } 209 return typedResp, err 210 } 211 return nil, err 212 } 213 } 214 return caller(ctx, in) 215 } 216 217 func (c *cacheProtobufClient) callMissingBlobs(ctx context.Context, in *MissingBlobsRequest) (*MissingBlobsResponse, error) { 218 out := new(MissingBlobsResponse) 219 ctx, err := doProtobufRequest(ctx, c.client, c.opts.Hooks, c.urls[2], in, out) 220 if err != nil { 221 twerr, ok := err.(twirp.Error) 222 if !ok { 223 twerr = twirp.InternalErrorWith(err) 224 } 225 callClientError(ctx, c.opts.Hooks, twerr) 226 return nil, err 227 } 228 229 callClientResponseReceived(ctx, c.opts.Hooks) 230 231 return out, nil 232 } 233 234 func (c *cacheProtobufClient) DeleteBlobs(ctx context.Context, in *DeleteBlobsRequest) (*google_protobuf2.Empty, error) { 235 ctx = ctxsetters.WithPackageName(ctx, "trivy.cache.v1") 236 ctx = ctxsetters.WithServiceName(ctx, "Cache") 237 ctx = ctxsetters.WithMethodName(ctx, "DeleteBlobs") 238 caller := c.callDeleteBlobs 239 if c.interceptor != nil { 240 caller = func(ctx context.Context, req *DeleteBlobsRequest) (*google_protobuf2.Empty, error) { 241 resp, err := c.interceptor( 242 func(ctx context.Context, req interface{}) (interface{}, error) { 243 typedReq, ok := req.(*DeleteBlobsRequest) 244 if !ok { 245 return nil, twirp.InternalError("failed type assertion req.(*DeleteBlobsRequest) when calling interceptor") 246 } 247 return c.callDeleteBlobs(ctx, typedReq) 248 }, 249 )(ctx, req) 250 if resp != nil { 251 typedResp, ok := resp.(*google_protobuf2.Empty) 252 if !ok { 253 return nil, twirp.InternalError("failed type assertion resp.(*google_protobuf2.Empty) when calling interceptor") 254 } 255 return typedResp, err 256 } 257 return nil, err 258 } 259 } 260 return caller(ctx, in) 261 } 262 263 func (c *cacheProtobufClient) callDeleteBlobs(ctx context.Context, in *DeleteBlobsRequest) (*google_protobuf2.Empty, error) { 264 out := new(google_protobuf2.Empty) 265 ctx, err := doProtobufRequest(ctx, c.client, c.opts.Hooks, c.urls[3], in, out) 266 if err != nil { 267 twerr, ok := err.(twirp.Error) 268 if !ok { 269 twerr = twirp.InternalErrorWith(err) 270 } 271 callClientError(ctx, c.opts.Hooks, twerr) 272 return nil, err 273 } 274 275 callClientResponseReceived(ctx, c.opts.Hooks) 276 277 return out, nil 278 } 279 280 // ================= 281 // Cache JSON Client 282 // ================= 283 284 type cacheJSONClient struct { 285 client HTTPClient 286 urls [4]string 287 interceptor twirp.Interceptor 288 opts twirp.ClientOptions 289 } 290 291 // NewCacheJSONClient creates a JSON client that implements the Cache interface. 292 // It communicates using JSON and can be configured with a custom HTTPClient. 293 func NewCacheJSONClient(baseURL string, client HTTPClient, opts ...twirp.ClientOption) Cache { 294 if c, ok := client.(*http.Client); ok { 295 client = withoutRedirects(c) 296 } 297 298 clientOpts := twirp.ClientOptions{} 299 for _, o := range opts { 300 o(&clientOpts) 301 } 302 303 // Using ReadOpt allows backwards and forwads compatibility with new options in the future 304 literalURLs := false 305 _ = clientOpts.ReadOpt("literalURLs", &literalURLs) 306 var pathPrefix string 307 if ok := clientOpts.ReadOpt("pathPrefix", &pathPrefix); !ok { 308 pathPrefix = "/twirp" // default prefix 309 } 310 311 // Build method URLs: <baseURL>[<prefix>]/<package>.<Service>/<Method> 312 serviceURL := sanitizeBaseURL(baseURL) 313 serviceURL += baseServicePath(pathPrefix, "trivy.cache.v1", "Cache") 314 urls := [4]string{ 315 serviceURL + "PutArtifact", 316 serviceURL + "PutBlob", 317 serviceURL + "MissingBlobs", 318 serviceURL + "DeleteBlobs", 319 } 320 321 return &cacheJSONClient{ 322 client: client, 323 urls: urls, 324 interceptor: twirp.ChainInterceptors(clientOpts.Interceptors...), 325 opts: clientOpts, 326 } 327 } 328 329 func (c *cacheJSONClient) PutArtifact(ctx context.Context, in *PutArtifactRequest) (*google_protobuf2.Empty, error) { 330 ctx = ctxsetters.WithPackageName(ctx, "trivy.cache.v1") 331 ctx = ctxsetters.WithServiceName(ctx, "Cache") 332 ctx = ctxsetters.WithMethodName(ctx, "PutArtifact") 333 caller := c.callPutArtifact 334 if c.interceptor != nil { 335 caller = func(ctx context.Context, req *PutArtifactRequest) (*google_protobuf2.Empty, error) { 336 resp, err := c.interceptor( 337 func(ctx context.Context, req interface{}) (interface{}, error) { 338 typedReq, ok := req.(*PutArtifactRequest) 339 if !ok { 340 return nil, twirp.InternalError("failed type assertion req.(*PutArtifactRequest) when calling interceptor") 341 } 342 return c.callPutArtifact(ctx, typedReq) 343 }, 344 )(ctx, req) 345 if resp != nil { 346 typedResp, ok := resp.(*google_protobuf2.Empty) 347 if !ok { 348 return nil, twirp.InternalError("failed type assertion resp.(*google_protobuf2.Empty) when calling interceptor") 349 } 350 return typedResp, err 351 } 352 return nil, err 353 } 354 } 355 return caller(ctx, in) 356 } 357 358 func (c *cacheJSONClient) callPutArtifact(ctx context.Context, in *PutArtifactRequest) (*google_protobuf2.Empty, error) { 359 out := new(google_protobuf2.Empty) 360 ctx, err := doJSONRequest(ctx, c.client, c.opts.Hooks, c.urls[0], in, out) 361 if err != nil { 362 twerr, ok := err.(twirp.Error) 363 if !ok { 364 twerr = twirp.InternalErrorWith(err) 365 } 366 callClientError(ctx, c.opts.Hooks, twerr) 367 return nil, err 368 } 369 370 callClientResponseReceived(ctx, c.opts.Hooks) 371 372 return out, nil 373 } 374 375 func (c *cacheJSONClient) PutBlob(ctx context.Context, in *PutBlobRequest) (*google_protobuf2.Empty, error) { 376 ctx = ctxsetters.WithPackageName(ctx, "trivy.cache.v1") 377 ctx = ctxsetters.WithServiceName(ctx, "Cache") 378 ctx = ctxsetters.WithMethodName(ctx, "PutBlob") 379 caller := c.callPutBlob 380 if c.interceptor != nil { 381 caller = func(ctx context.Context, req *PutBlobRequest) (*google_protobuf2.Empty, error) { 382 resp, err := c.interceptor( 383 func(ctx context.Context, req interface{}) (interface{}, error) { 384 typedReq, ok := req.(*PutBlobRequest) 385 if !ok { 386 return nil, twirp.InternalError("failed type assertion req.(*PutBlobRequest) when calling interceptor") 387 } 388 return c.callPutBlob(ctx, typedReq) 389 }, 390 )(ctx, req) 391 if resp != nil { 392 typedResp, ok := resp.(*google_protobuf2.Empty) 393 if !ok { 394 return nil, twirp.InternalError("failed type assertion resp.(*google_protobuf2.Empty) when calling interceptor") 395 } 396 return typedResp, err 397 } 398 return nil, err 399 } 400 } 401 return caller(ctx, in) 402 } 403 404 func (c *cacheJSONClient) callPutBlob(ctx context.Context, in *PutBlobRequest) (*google_protobuf2.Empty, error) { 405 out := new(google_protobuf2.Empty) 406 ctx, err := doJSONRequest(ctx, c.client, c.opts.Hooks, c.urls[1], in, out) 407 if err != nil { 408 twerr, ok := err.(twirp.Error) 409 if !ok { 410 twerr = twirp.InternalErrorWith(err) 411 } 412 callClientError(ctx, c.opts.Hooks, twerr) 413 return nil, err 414 } 415 416 callClientResponseReceived(ctx, c.opts.Hooks) 417 418 return out, nil 419 } 420 421 func (c *cacheJSONClient) MissingBlobs(ctx context.Context, in *MissingBlobsRequest) (*MissingBlobsResponse, error) { 422 ctx = ctxsetters.WithPackageName(ctx, "trivy.cache.v1") 423 ctx = ctxsetters.WithServiceName(ctx, "Cache") 424 ctx = ctxsetters.WithMethodName(ctx, "MissingBlobs") 425 caller := c.callMissingBlobs 426 if c.interceptor != nil { 427 caller = func(ctx context.Context, req *MissingBlobsRequest) (*MissingBlobsResponse, error) { 428 resp, err := c.interceptor( 429 func(ctx context.Context, req interface{}) (interface{}, error) { 430 typedReq, ok := req.(*MissingBlobsRequest) 431 if !ok { 432 return nil, twirp.InternalError("failed type assertion req.(*MissingBlobsRequest) when calling interceptor") 433 } 434 return c.callMissingBlobs(ctx, typedReq) 435 }, 436 )(ctx, req) 437 if resp != nil { 438 typedResp, ok := resp.(*MissingBlobsResponse) 439 if !ok { 440 return nil, twirp.InternalError("failed type assertion resp.(*MissingBlobsResponse) when calling interceptor") 441 } 442 return typedResp, err 443 } 444 return nil, err 445 } 446 } 447 return caller(ctx, in) 448 } 449 450 func (c *cacheJSONClient) callMissingBlobs(ctx context.Context, in *MissingBlobsRequest) (*MissingBlobsResponse, error) { 451 out := new(MissingBlobsResponse) 452 ctx, err := doJSONRequest(ctx, c.client, c.opts.Hooks, c.urls[2], in, out) 453 if err != nil { 454 twerr, ok := err.(twirp.Error) 455 if !ok { 456 twerr = twirp.InternalErrorWith(err) 457 } 458 callClientError(ctx, c.opts.Hooks, twerr) 459 return nil, err 460 } 461 462 callClientResponseReceived(ctx, c.opts.Hooks) 463 464 return out, nil 465 } 466 467 func (c *cacheJSONClient) DeleteBlobs(ctx context.Context, in *DeleteBlobsRequest) (*google_protobuf2.Empty, error) { 468 ctx = ctxsetters.WithPackageName(ctx, "trivy.cache.v1") 469 ctx = ctxsetters.WithServiceName(ctx, "Cache") 470 ctx = ctxsetters.WithMethodName(ctx, "DeleteBlobs") 471 caller := c.callDeleteBlobs 472 if c.interceptor != nil { 473 caller = func(ctx context.Context, req *DeleteBlobsRequest) (*google_protobuf2.Empty, error) { 474 resp, err := c.interceptor( 475 func(ctx context.Context, req interface{}) (interface{}, error) { 476 typedReq, ok := req.(*DeleteBlobsRequest) 477 if !ok { 478 return nil, twirp.InternalError("failed type assertion req.(*DeleteBlobsRequest) when calling interceptor") 479 } 480 return c.callDeleteBlobs(ctx, typedReq) 481 }, 482 )(ctx, req) 483 if resp != nil { 484 typedResp, ok := resp.(*google_protobuf2.Empty) 485 if !ok { 486 return nil, twirp.InternalError("failed type assertion resp.(*google_protobuf2.Empty) when calling interceptor") 487 } 488 return typedResp, err 489 } 490 return nil, err 491 } 492 } 493 return caller(ctx, in) 494 } 495 496 func (c *cacheJSONClient) callDeleteBlobs(ctx context.Context, in *DeleteBlobsRequest) (*google_protobuf2.Empty, error) { 497 out := new(google_protobuf2.Empty) 498 ctx, err := doJSONRequest(ctx, c.client, c.opts.Hooks, c.urls[3], in, out) 499 if err != nil { 500 twerr, ok := err.(twirp.Error) 501 if !ok { 502 twerr = twirp.InternalErrorWith(err) 503 } 504 callClientError(ctx, c.opts.Hooks, twerr) 505 return nil, err 506 } 507 508 callClientResponseReceived(ctx, c.opts.Hooks) 509 510 return out, nil 511 } 512 513 // ==================== 514 // Cache Server Handler 515 // ==================== 516 517 type cacheServer struct { 518 Cache 519 interceptor twirp.Interceptor 520 hooks *twirp.ServerHooks 521 pathPrefix string // prefix for routing 522 jsonSkipDefaults bool // do not include unpopulated fields (default values) in the response 523 jsonCamelCase bool // JSON fields are serialized as lowerCamelCase rather than keeping the original proto names 524 } 525 526 // NewCacheServer builds a TwirpServer that can be used as an http.Handler to handle 527 // HTTP requests that are routed to the right method in the provided svc implementation. 528 // The opts are twirp.ServerOption modifiers, for example twirp.WithServerHooks(hooks). 529 func NewCacheServer(svc Cache, opts ...interface{}) TwirpServer { 530 serverOpts := newServerOpts(opts) 531 532 // Using ReadOpt allows backwards and forwads compatibility with new options in the future 533 jsonSkipDefaults := false 534 _ = serverOpts.ReadOpt("jsonSkipDefaults", &jsonSkipDefaults) 535 jsonCamelCase := false 536 _ = serverOpts.ReadOpt("jsonCamelCase", &jsonCamelCase) 537 var pathPrefix string 538 if ok := serverOpts.ReadOpt("pathPrefix", &pathPrefix); !ok { 539 pathPrefix = "/twirp" // default prefix 540 } 541 542 return &cacheServer{ 543 Cache: svc, 544 hooks: serverOpts.Hooks, 545 interceptor: twirp.ChainInterceptors(serverOpts.Interceptors...), 546 pathPrefix: pathPrefix, 547 jsonSkipDefaults: jsonSkipDefaults, 548 jsonCamelCase: jsonCamelCase, 549 } 550 } 551 552 // writeError writes an HTTP response with a valid Twirp error format, and triggers hooks. 553 // If err is not a twirp.Error, it will get wrapped with twirp.InternalErrorWith(err) 554 func (s *cacheServer) writeError(ctx context.Context, resp http.ResponseWriter, err error) { 555 writeError(ctx, resp, err, s.hooks) 556 } 557 558 // handleRequestBodyError is used to handle error when the twirp server cannot read request 559 func (s *cacheServer) handleRequestBodyError(ctx context.Context, resp http.ResponseWriter, msg string, err error) { 560 if context.Canceled == ctx.Err() { 561 s.writeError(ctx, resp, twirp.NewError(twirp.Canceled, "failed to read request: context canceled")) 562 return 563 } 564 if context.DeadlineExceeded == ctx.Err() { 565 s.writeError(ctx, resp, twirp.NewError(twirp.DeadlineExceeded, "failed to read request: deadline exceeded")) 566 return 567 } 568 s.writeError(ctx, resp, twirp.WrapError(malformedRequestError(msg), err)) 569 } 570 571 // CachePathPrefix is a convenience constant that may identify URL paths. 572 // Should be used with caution, it only matches routes generated by Twirp Go clients, 573 // with the default "/twirp" prefix and default CamelCase service and method names. 574 // More info: https://twitchtv.github.io/twirp/docs/routing.html 575 const CachePathPrefix = "/twirp/trivy.cache.v1.Cache/" 576 577 func (s *cacheServer) ServeHTTP(resp http.ResponseWriter, req *http.Request) { 578 ctx := req.Context() 579 ctx = ctxsetters.WithPackageName(ctx, "trivy.cache.v1") 580 ctx = ctxsetters.WithServiceName(ctx, "Cache") 581 ctx = ctxsetters.WithResponseWriter(ctx, resp) 582 583 var err error 584 ctx, err = callRequestReceived(ctx, s.hooks) 585 if err != nil { 586 s.writeError(ctx, resp, err) 587 return 588 } 589 590 if req.Method != "POST" { 591 msg := fmt.Sprintf("unsupported method %q (only POST is allowed)", req.Method) 592 s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) 593 return 594 } 595 596 // Verify path format: [<prefix>]/<package>.<Service>/<Method> 597 prefix, pkgService, method := parseTwirpPath(req.URL.Path) 598 if pkgService != "trivy.cache.v1.Cache" { 599 msg := fmt.Sprintf("no handler for path %q", req.URL.Path) 600 s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) 601 return 602 } 603 if prefix != s.pathPrefix { 604 msg := fmt.Sprintf("invalid path prefix %q, expected %q, on path %q", prefix, s.pathPrefix, req.URL.Path) 605 s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) 606 return 607 } 608 609 switch method { 610 case "PutArtifact": 611 s.servePutArtifact(ctx, resp, req) 612 return 613 case "PutBlob": 614 s.servePutBlob(ctx, resp, req) 615 return 616 case "MissingBlobs": 617 s.serveMissingBlobs(ctx, resp, req) 618 return 619 case "DeleteBlobs": 620 s.serveDeleteBlobs(ctx, resp, req) 621 return 622 default: 623 msg := fmt.Sprintf("no handler for path %q", req.URL.Path) 624 s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) 625 return 626 } 627 } 628 629 func (s *cacheServer) servePutArtifact(ctx context.Context, resp http.ResponseWriter, req *http.Request) { 630 header := req.Header.Get("Content-Type") 631 i := strings.Index(header, ";") 632 if i == -1 { 633 i = len(header) 634 } 635 switch strings.TrimSpace(strings.ToLower(header[:i])) { 636 case "application/json": 637 s.servePutArtifactJSON(ctx, resp, req) 638 case "application/protobuf": 639 s.servePutArtifactProtobuf(ctx, resp, req) 640 default: 641 msg := fmt.Sprintf("unexpected Content-Type: %q", req.Header.Get("Content-Type")) 642 twerr := badRouteError(msg, req.Method, req.URL.Path) 643 s.writeError(ctx, resp, twerr) 644 } 645 } 646 647 func (s *cacheServer) servePutArtifactJSON(ctx context.Context, resp http.ResponseWriter, req *http.Request) { 648 var err error 649 ctx = ctxsetters.WithMethodName(ctx, "PutArtifact") 650 ctx, err = callRequestRouted(ctx, s.hooks) 651 if err != nil { 652 s.writeError(ctx, resp, err) 653 return 654 } 655 656 d := json.NewDecoder(req.Body) 657 rawReqBody := json.RawMessage{} 658 if err := d.Decode(&rawReqBody); err != nil { 659 s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) 660 return 661 } 662 reqContent := new(PutArtifactRequest) 663 unmarshaler := protojson.UnmarshalOptions{DiscardUnknown: true} 664 if err = unmarshaler.Unmarshal(rawReqBody, reqContent); err != nil { 665 s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) 666 return 667 } 668 669 handler := s.Cache.PutArtifact 670 if s.interceptor != nil { 671 handler = func(ctx context.Context, req *PutArtifactRequest) (*google_protobuf2.Empty, error) { 672 resp, err := s.interceptor( 673 func(ctx context.Context, req interface{}) (interface{}, error) { 674 typedReq, ok := req.(*PutArtifactRequest) 675 if !ok { 676 return nil, twirp.InternalError("failed type assertion req.(*PutArtifactRequest) when calling interceptor") 677 } 678 return s.Cache.PutArtifact(ctx, typedReq) 679 }, 680 )(ctx, req) 681 if resp != nil { 682 typedResp, ok := resp.(*google_protobuf2.Empty) 683 if !ok { 684 return nil, twirp.InternalError("failed type assertion resp.(*google_protobuf2.Empty) when calling interceptor") 685 } 686 return typedResp, err 687 } 688 return nil, err 689 } 690 } 691 692 // Call service method 693 var respContent *google_protobuf2.Empty 694 func() { 695 defer ensurePanicResponses(ctx, resp, s.hooks) 696 respContent, err = handler(ctx, reqContent) 697 }() 698 699 if err != nil { 700 s.writeError(ctx, resp, err) 701 return 702 } 703 if respContent == nil { 704 s.writeError(ctx, resp, twirp.InternalError("received a nil *google_protobuf2.Empty and nil error while calling PutArtifact. nil responses are not supported")) 705 return 706 } 707 708 ctx = callResponsePrepared(ctx, s.hooks) 709 710 marshaler := &protojson.MarshalOptions{UseProtoNames: !s.jsonCamelCase, EmitUnpopulated: !s.jsonSkipDefaults} 711 respBytes, err := marshaler.Marshal(respContent) 712 if err != nil { 713 s.writeError(ctx, resp, wrapInternal(err, "failed to marshal json response")) 714 return 715 } 716 717 ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) 718 resp.Header().Set("Content-Type", "application/json") 719 resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) 720 resp.WriteHeader(http.StatusOK) 721 722 if n, err := resp.Write(respBytes); err != nil { 723 msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) 724 twerr := twirp.NewError(twirp.Unknown, msg) 725 ctx = callError(ctx, s.hooks, twerr) 726 } 727 callResponseSent(ctx, s.hooks) 728 } 729 730 func (s *cacheServer) servePutArtifactProtobuf(ctx context.Context, resp http.ResponseWriter, req *http.Request) { 731 var err error 732 ctx = ctxsetters.WithMethodName(ctx, "PutArtifact") 733 ctx, err = callRequestRouted(ctx, s.hooks) 734 if err != nil { 735 s.writeError(ctx, resp, err) 736 return 737 } 738 739 buf, err := ioutil.ReadAll(req.Body) 740 if err != nil { 741 s.handleRequestBodyError(ctx, resp, "failed to read request body", err) 742 return 743 } 744 reqContent := new(PutArtifactRequest) 745 if err = proto.Unmarshal(buf, reqContent); err != nil { 746 s.writeError(ctx, resp, malformedRequestError("the protobuf request could not be decoded")) 747 return 748 } 749 750 handler := s.Cache.PutArtifact 751 if s.interceptor != nil { 752 handler = func(ctx context.Context, req *PutArtifactRequest) (*google_protobuf2.Empty, error) { 753 resp, err := s.interceptor( 754 func(ctx context.Context, req interface{}) (interface{}, error) { 755 typedReq, ok := req.(*PutArtifactRequest) 756 if !ok { 757 return nil, twirp.InternalError("failed type assertion req.(*PutArtifactRequest) when calling interceptor") 758 } 759 return s.Cache.PutArtifact(ctx, typedReq) 760 }, 761 )(ctx, req) 762 if resp != nil { 763 typedResp, ok := resp.(*google_protobuf2.Empty) 764 if !ok { 765 return nil, twirp.InternalError("failed type assertion resp.(*google_protobuf2.Empty) when calling interceptor") 766 } 767 return typedResp, err 768 } 769 return nil, err 770 } 771 } 772 773 // Call service method 774 var respContent *google_protobuf2.Empty 775 func() { 776 defer ensurePanicResponses(ctx, resp, s.hooks) 777 respContent, err = handler(ctx, reqContent) 778 }() 779 780 if err != nil { 781 s.writeError(ctx, resp, err) 782 return 783 } 784 if respContent == nil { 785 s.writeError(ctx, resp, twirp.InternalError("received a nil *google_protobuf2.Empty and nil error while calling PutArtifact. nil responses are not supported")) 786 return 787 } 788 789 ctx = callResponsePrepared(ctx, s.hooks) 790 791 respBytes, err := proto.Marshal(respContent) 792 if err != nil { 793 s.writeError(ctx, resp, wrapInternal(err, "failed to marshal proto response")) 794 return 795 } 796 797 ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) 798 resp.Header().Set("Content-Type", "application/protobuf") 799 resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) 800 resp.WriteHeader(http.StatusOK) 801 if n, err := resp.Write(respBytes); err != nil { 802 msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) 803 twerr := twirp.NewError(twirp.Unknown, msg) 804 ctx = callError(ctx, s.hooks, twerr) 805 } 806 callResponseSent(ctx, s.hooks) 807 } 808 809 func (s *cacheServer) servePutBlob(ctx context.Context, resp http.ResponseWriter, req *http.Request) { 810 header := req.Header.Get("Content-Type") 811 i := strings.Index(header, ";") 812 if i == -1 { 813 i = len(header) 814 } 815 switch strings.TrimSpace(strings.ToLower(header[:i])) { 816 case "application/json": 817 s.servePutBlobJSON(ctx, resp, req) 818 case "application/protobuf": 819 s.servePutBlobProtobuf(ctx, resp, req) 820 default: 821 msg := fmt.Sprintf("unexpected Content-Type: %q", req.Header.Get("Content-Type")) 822 twerr := badRouteError(msg, req.Method, req.URL.Path) 823 s.writeError(ctx, resp, twerr) 824 } 825 } 826 827 func (s *cacheServer) servePutBlobJSON(ctx context.Context, resp http.ResponseWriter, req *http.Request) { 828 var err error 829 ctx = ctxsetters.WithMethodName(ctx, "PutBlob") 830 ctx, err = callRequestRouted(ctx, s.hooks) 831 if err != nil { 832 s.writeError(ctx, resp, err) 833 return 834 } 835 836 d := json.NewDecoder(req.Body) 837 rawReqBody := json.RawMessage{} 838 if err := d.Decode(&rawReqBody); err != nil { 839 s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) 840 return 841 } 842 reqContent := new(PutBlobRequest) 843 unmarshaler := protojson.UnmarshalOptions{DiscardUnknown: true} 844 if err = unmarshaler.Unmarshal(rawReqBody, reqContent); err != nil { 845 s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) 846 return 847 } 848 849 handler := s.Cache.PutBlob 850 if s.interceptor != nil { 851 handler = func(ctx context.Context, req *PutBlobRequest) (*google_protobuf2.Empty, error) { 852 resp, err := s.interceptor( 853 func(ctx context.Context, req interface{}) (interface{}, error) { 854 typedReq, ok := req.(*PutBlobRequest) 855 if !ok { 856 return nil, twirp.InternalError("failed type assertion req.(*PutBlobRequest) when calling interceptor") 857 } 858 return s.Cache.PutBlob(ctx, typedReq) 859 }, 860 )(ctx, req) 861 if resp != nil { 862 typedResp, ok := resp.(*google_protobuf2.Empty) 863 if !ok { 864 return nil, twirp.InternalError("failed type assertion resp.(*google_protobuf2.Empty) when calling interceptor") 865 } 866 return typedResp, err 867 } 868 return nil, err 869 } 870 } 871 872 // Call service method 873 var respContent *google_protobuf2.Empty 874 func() { 875 defer ensurePanicResponses(ctx, resp, s.hooks) 876 respContent, err = handler(ctx, reqContent) 877 }() 878 879 if err != nil { 880 s.writeError(ctx, resp, err) 881 return 882 } 883 if respContent == nil { 884 s.writeError(ctx, resp, twirp.InternalError("received a nil *google_protobuf2.Empty and nil error while calling PutBlob. nil responses are not supported")) 885 return 886 } 887 888 ctx = callResponsePrepared(ctx, s.hooks) 889 890 marshaler := &protojson.MarshalOptions{UseProtoNames: !s.jsonCamelCase, EmitUnpopulated: !s.jsonSkipDefaults} 891 respBytes, err := marshaler.Marshal(respContent) 892 if err != nil { 893 s.writeError(ctx, resp, wrapInternal(err, "failed to marshal json response")) 894 return 895 } 896 897 ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) 898 resp.Header().Set("Content-Type", "application/json") 899 resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) 900 resp.WriteHeader(http.StatusOK) 901 902 if n, err := resp.Write(respBytes); err != nil { 903 msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) 904 twerr := twirp.NewError(twirp.Unknown, msg) 905 ctx = callError(ctx, s.hooks, twerr) 906 } 907 callResponseSent(ctx, s.hooks) 908 } 909 910 func (s *cacheServer) servePutBlobProtobuf(ctx context.Context, resp http.ResponseWriter, req *http.Request) { 911 var err error 912 ctx = ctxsetters.WithMethodName(ctx, "PutBlob") 913 ctx, err = callRequestRouted(ctx, s.hooks) 914 if err != nil { 915 s.writeError(ctx, resp, err) 916 return 917 } 918 919 buf, err := ioutil.ReadAll(req.Body) 920 if err != nil { 921 s.handleRequestBodyError(ctx, resp, "failed to read request body", err) 922 return 923 } 924 reqContent := new(PutBlobRequest) 925 if err = proto.Unmarshal(buf, reqContent); err != nil { 926 s.writeError(ctx, resp, malformedRequestError("the protobuf request could not be decoded")) 927 return 928 } 929 930 handler := s.Cache.PutBlob 931 if s.interceptor != nil { 932 handler = func(ctx context.Context, req *PutBlobRequest) (*google_protobuf2.Empty, error) { 933 resp, err := s.interceptor( 934 func(ctx context.Context, req interface{}) (interface{}, error) { 935 typedReq, ok := req.(*PutBlobRequest) 936 if !ok { 937 return nil, twirp.InternalError("failed type assertion req.(*PutBlobRequest) when calling interceptor") 938 } 939 return s.Cache.PutBlob(ctx, typedReq) 940 }, 941 )(ctx, req) 942 if resp != nil { 943 typedResp, ok := resp.(*google_protobuf2.Empty) 944 if !ok { 945 return nil, twirp.InternalError("failed type assertion resp.(*google_protobuf2.Empty) when calling interceptor") 946 } 947 return typedResp, err 948 } 949 return nil, err 950 } 951 } 952 953 // Call service method 954 var respContent *google_protobuf2.Empty 955 func() { 956 defer ensurePanicResponses(ctx, resp, s.hooks) 957 respContent, err = handler(ctx, reqContent) 958 }() 959 960 if err != nil { 961 s.writeError(ctx, resp, err) 962 return 963 } 964 if respContent == nil { 965 s.writeError(ctx, resp, twirp.InternalError("received a nil *google_protobuf2.Empty and nil error while calling PutBlob. nil responses are not supported")) 966 return 967 } 968 969 ctx = callResponsePrepared(ctx, s.hooks) 970 971 respBytes, err := proto.Marshal(respContent) 972 if err != nil { 973 s.writeError(ctx, resp, wrapInternal(err, "failed to marshal proto response")) 974 return 975 } 976 977 ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) 978 resp.Header().Set("Content-Type", "application/protobuf") 979 resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) 980 resp.WriteHeader(http.StatusOK) 981 if n, err := resp.Write(respBytes); err != nil { 982 msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) 983 twerr := twirp.NewError(twirp.Unknown, msg) 984 ctx = callError(ctx, s.hooks, twerr) 985 } 986 callResponseSent(ctx, s.hooks) 987 } 988 989 func (s *cacheServer) serveMissingBlobs(ctx context.Context, resp http.ResponseWriter, req *http.Request) { 990 header := req.Header.Get("Content-Type") 991 i := strings.Index(header, ";") 992 if i == -1 { 993 i = len(header) 994 } 995 switch strings.TrimSpace(strings.ToLower(header[:i])) { 996 case "application/json": 997 s.serveMissingBlobsJSON(ctx, resp, req) 998 case "application/protobuf": 999 s.serveMissingBlobsProtobuf(ctx, resp, req) 1000 default: 1001 msg := fmt.Sprintf("unexpected Content-Type: %q", req.Header.Get("Content-Type")) 1002 twerr := badRouteError(msg, req.Method, req.URL.Path) 1003 s.writeError(ctx, resp, twerr) 1004 } 1005 } 1006 1007 func (s *cacheServer) serveMissingBlobsJSON(ctx context.Context, resp http.ResponseWriter, req *http.Request) { 1008 var err error 1009 ctx = ctxsetters.WithMethodName(ctx, "MissingBlobs") 1010 ctx, err = callRequestRouted(ctx, s.hooks) 1011 if err != nil { 1012 s.writeError(ctx, resp, err) 1013 return 1014 } 1015 1016 d := json.NewDecoder(req.Body) 1017 rawReqBody := json.RawMessage{} 1018 if err := d.Decode(&rawReqBody); err != nil { 1019 s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) 1020 return 1021 } 1022 reqContent := new(MissingBlobsRequest) 1023 unmarshaler := protojson.UnmarshalOptions{DiscardUnknown: true} 1024 if err = unmarshaler.Unmarshal(rawReqBody, reqContent); err != nil { 1025 s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) 1026 return 1027 } 1028 1029 handler := s.Cache.MissingBlobs 1030 if s.interceptor != nil { 1031 handler = func(ctx context.Context, req *MissingBlobsRequest) (*MissingBlobsResponse, error) { 1032 resp, err := s.interceptor( 1033 func(ctx context.Context, req interface{}) (interface{}, error) { 1034 typedReq, ok := req.(*MissingBlobsRequest) 1035 if !ok { 1036 return nil, twirp.InternalError("failed type assertion req.(*MissingBlobsRequest) when calling interceptor") 1037 } 1038 return s.Cache.MissingBlobs(ctx, typedReq) 1039 }, 1040 )(ctx, req) 1041 if resp != nil { 1042 typedResp, ok := resp.(*MissingBlobsResponse) 1043 if !ok { 1044 return nil, twirp.InternalError("failed type assertion resp.(*MissingBlobsResponse) when calling interceptor") 1045 } 1046 return typedResp, err 1047 } 1048 return nil, err 1049 } 1050 } 1051 1052 // Call service method 1053 var respContent *MissingBlobsResponse 1054 func() { 1055 defer ensurePanicResponses(ctx, resp, s.hooks) 1056 respContent, err = handler(ctx, reqContent) 1057 }() 1058 1059 if err != nil { 1060 s.writeError(ctx, resp, err) 1061 return 1062 } 1063 if respContent == nil { 1064 s.writeError(ctx, resp, twirp.InternalError("received a nil *MissingBlobsResponse and nil error while calling MissingBlobs. nil responses are not supported")) 1065 return 1066 } 1067 1068 ctx = callResponsePrepared(ctx, s.hooks) 1069 1070 marshaler := &protojson.MarshalOptions{UseProtoNames: !s.jsonCamelCase, EmitUnpopulated: !s.jsonSkipDefaults} 1071 respBytes, err := marshaler.Marshal(respContent) 1072 if err != nil { 1073 s.writeError(ctx, resp, wrapInternal(err, "failed to marshal json response")) 1074 return 1075 } 1076 1077 ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) 1078 resp.Header().Set("Content-Type", "application/json") 1079 resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) 1080 resp.WriteHeader(http.StatusOK) 1081 1082 if n, err := resp.Write(respBytes); err != nil { 1083 msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) 1084 twerr := twirp.NewError(twirp.Unknown, msg) 1085 ctx = callError(ctx, s.hooks, twerr) 1086 } 1087 callResponseSent(ctx, s.hooks) 1088 } 1089 1090 func (s *cacheServer) serveMissingBlobsProtobuf(ctx context.Context, resp http.ResponseWriter, req *http.Request) { 1091 var err error 1092 ctx = ctxsetters.WithMethodName(ctx, "MissingBlobs") 1093 ctx, err = callRequestRouted(ctx, s.hooks) 1094 if err != nil { 1095 s.writeError(ctx, resp, err) 1096 return 1097 } 1098 1099 buf, err := ioutil.ReadAll(req.Body) 1100 if err != nil { 1101 s.handleRequestBodyError(ctx, resp, "failed to read request body", err) 1102 return 1103 } 1104 reqContent := new(MissingBlobsRequest) 1105 if err = proto.Unmarshal(buf, reqContent); err != nil { 1106 s.writeError(ctx, resp, malformedRequestError("the protobuf request could not be decoded")) 1107 return 1108 } 1109 1110 handler := s.Cache.MissingBlobs 1111 if s.interceptor != nil { 1112 handler = func(ctx context.Context, req *MissingBlobsRequest) (*MissingBlobsResponse, error) { 1113 resp, err := s.interceptor( 1114 func(ctx context.Context, req interface{}) (interface{}, error) { 1115 typedReq, ok := req.(*MissingBlobsRequest) 1116 if !ok { 1117 return nil, twirp.InternalError("failed type assertion req.(*MissingBlobsRequest) when calling interceptor") 1118 } 1119 return s.Cache.MissingBlobs(ctx, typedReq) 1120 }, 1121 )(ctx, req) 1122 if resp != nil { 1123 typedResp, ok := resp.(*MissingBlobsResponse) 1124 if !ok { 1125 return nil, twirp.InternalError("failed type assertion resp.(*MissingBlobsResponse) when calling interceptor") 1126 } 1127 return typedResp, err 1128 } 1129 return nil, err 1130 } 1131 } 1132 1133 // Call service method 1134 var respContent *MissingBlobsResponse 1135 func() { 1136 defer ensurePanicResponses(ctx, resp, s.hooks) 1137 respContent, err = handler(ctx, reqContent) 1138 }() 1139 1140 if err != nil { 1141 s.writeError(ctx, resp, err) 1142 return 1143 } 1144 if respContent == nil { 1145 s.writeError(ctx, resp, twirp.InternalError("received a nil *MissingBlobsResponse and nil error while calling MissingBlobs. nil responses are not supported")) 1146 return 1147 } 1148 1149 ctx = callResponsePrepared(ctx, s.hooks) 1150 1151 respBytes, err := proto.Marshal(respContent) 1152 if err != nil { 1153 s.writeError(ctx, resp, wrapInternal(err, "failed to marshal proto response")) 1154 return 1155 } 1156 1157 ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) 1158 resp.Header().Set("Content-Type", "application/protobuf") 1159 resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) 1160 resp.WriteHeader(http.StatusOK) 1161 if n, err := resp.Write(respBytes); err != nil { 1162 msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) 1163 twerr := twirp.NewError(twirp.Unknown, msg) 1164 ctx = callError(ctx, s.hooks, twerr) 1165 } 1166 callResponseSent(ctx, s.hooks) 1167 } 1168 1169 func (s *cacheServer) serveDeleteBlobs(ctx context.Context, resp http.ResponseWriter, req *http.Request) { 1170 header := req.Header.Get("Content-Type") 1171 i := strings.Index(header, ";") 1172 if i == -1 { 1173 i = len(header) 1174 } 1175 switch strings.TrimSpace(strings.ToLower(header[:i])) { 1176 case "application/json": 1177 s.serveDeleteBlobsJSON(ctx, resp, req) 1178 case "application/protobuf": 1179 s.serveDeleteBlobsProtobuf(ctx, resp, req) 1180 default: 1181 msg := fmt.Sprintf("unexpected Content-Type: %q", req.Header.Get("Content-Type")) 1182 twerr := badRouteError(msg, req.Method, req.URL.Path) 1183 s.writeError(ctx, resp, twerr) 1184 } 1185 } 1186 1187 func (s *cacheServer) serveDeleteBlobsJSON(ctx context.Context, resp http.ResponseWriter, req *http.Request) { 1188 var err error 1189 ctx = ctxsetters.WithMethodName(ctx, "DeleteBlobs") 1190 ctx, err = callRequestRouted(ctx, s.hooks) 1191 if err != nil { 1192 s.writeError(ctx, resp, err) 1193 return 1194 } 1195 1196 d := json.NewDecoder(req.Body) 1197 rawReqBody := json.RawMessage{} 1198 if err := d.Decode(&rawReqBody); err != nil { 1199 s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) 1200 return 1201 } 1202 reqContent := new(DeleteBlobsRequest) 1203 unmarshaler := protojson.UnmarshalOptions{DiscardUnknown: true} 1204 if err = unmarshaler.Unmarshal(rawReqBody, reqContent); err != nil { 1205 s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) 1206 return 1207 } 1208 1209 handler := s.Cache.DeleteBlobs 1210 if s.interceptor != nil { 1211 handler = func(ctx context.Context, req *DeleteBlobsRequest) (*google_protobuf2.Empty, error) { 1212 resp, err := s.interceptor( 1213 func(ctx context.Context, req interface{}) (interface{}, error) { 1214 typedReq, ok := req.(*DeleteBlobsRequest) 1215 if !ok { 1216 return nil, twirp.InternalError("failed type assertion req.(*DeleteBlobsRequest) when calling interceptor") 1217 } 1218 return s.Cache.DeleteBlobs(ctx, typedReq) 1219 }, 1220 )(ctx, req) 1221 if resp != nil { 1222 typedResp, ok := resp.(*google_protobuf2.Empty) 1223 if !ok { 1224 return nil, twirp.InternalError("failed type assertion resp.(*google_protobuf2.Empty) when calling interceptor") 1225 } 1226 return typedResp, err 1227 } 1228 return nil, err 1229 } 1230 } 1231 1232 // Call service method 1233 var respContent *google_protobuf2.Empty 1234 func() { 1235 defer ensurePanicResponses(ctx, resp, s.hooks) 1236 respContent, err = handler(ctx, reqContent) 1237 }() 1238 1239 if err != nil { 1240 s.writeError(ctx, resp, err) 1241 return 1242 } 1243 if respContent == nil { 1244 s.writeError(ctx, resp, twirp.InternalError("received a nil *google_protobuf2.Empty and nil error while calling DeleteBlobs. nil responses are not supported")) 1245 return 1246 } 1247 1248 ctx = callResponsePrepared(ctx, s.hooks) 1249 1250 marshaler := &protojson.MarshalOptions{UseProtoNames: !s.jsonCamelCase, EmitUnpopulated: !s.jsonSkipDefaults} 1251 respBytes, err := marshaler.Marshal(respContent) 1252 if err != nil { 1253 s.writeError(ctx, resp, wrapInternal(err, "failed to marshal json response")) 1254 return 1255 } 1256 1257 ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) 1258 resp.Header().Set("Content-Type", "application/json") 1259 resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) 1260 resp.WriteHeader(http.StatusOK) 1261 1262 if n, err := resp.Write(respBytes); err != nil { 1263 msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) 1264 twerr := twirp.NewError(twirp.Unknown, msg) 1265 ctx = callError(ctx, s.hooks, twerr) 1266 } 1267 callResponseSent(ctx, s.hooks) 1268 } 1269 1270 func (s *cacheServer) serveDeleteBlobsProtobuf(ctx context.Context, resp http.ResponseWriter, req *http.Request) { 1271 var err error 1272 ctx = ctxsetters.WithMethodName(ctx, "DeleteBlobs") 1273 ctx, err = callRequestRouted(ctx, s.hooks) 1274 if err != nil { 1275 s.writeError(ctx, resp, err) 1276 return 1277 } 1278 1279 buf, err := ioutil.ReadAll(req.Body) 1280 if err != nil { 1281 s.handleRequestBodyError(ctx, resp, "failed to read request body", err) 1282 return 1283 } 1284 reqContent := new(DeleteBlobsRequest) 1285 if err = proto.Unmarshal(buf, reqContent); err != nil { 1286 s.writeError(ctx, resp, malformedRequestError("the protobuf request could not be decoded")) 1287 return 1288 } 1289 1290 handler := s.Cache.DeleteBlobs 1291 if s.interceptor != nil { 1292 handler = func(ctx context.Context, req *DeleteBlobsRequest) (*google_protobuf2.Empty, error) { 1293 resp, err := s.interceptor( 1294 func(ctx context.Context, req interface{}) (interface{}, error) { 1295 typedReq, ok := req.(*DeleteBlobsRequest) 1296 if !ok { 1297 return nil, twirp.InternalError("failed type assertion req.(*DeleteBlobsRequest) when calling interceptor") 1298 } 1299 return s.Cache.DeleteBlobs(ctx, typedReq) 1300 }, 1301 )(ctx, req) 1302 if resp != nil { 1303 typedResp, ok := resp.(*google_protobuf2.Empty) 1304 if !ok { 1305 return nil, twirp.InternalError("failed type assertion resp.(*google_protobuf2.Empty) when calling interceptor") 1306 } 1307 return typedResp, err 1308 } 1309 return nil, err 1310 } 1311 } 1312 1313 // Call service method 1314 var respContent *google_protobuf2.Empty 1315 func() { 1316 defer ensurePanicResponses(ctx, resp, s.hooks) 1317 respContent, err = handler(ctx, reqContent) 1318 }() 1319 1320 if err != nil { 1321 s.writeError(ctx, resp, err) 1322 return 1323 } 1324 if respContent == nil { 1325 s.writeError(ctx, resp, twirp.InternalError("received a nil *google_protobuf2.Empty and nil error while calling DeleteBlobs. nil responses are not supported")) 1326 return 1327 } 1328 1329 ctx = callResponsePrepared(ctx, s.hooks) 1330 1331 respBytes, err := proto.Marshal(respContent) 1332 if err != nil { 1333 s.writeError(ctx, resp, wrapInternal(err, "failed to marshal proto response")) 1334 return 1335 } 1336 1337 ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) 1338 resp.Header().Set("Content-Type", "application/protobuf") 1339 resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) 1340 resp.WriteHeader(http.StatusOK) 1341 if n, err := resp.Write(respBytes); err != nil { 1342 msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) 1343 twerr := twirp.NewError(twirp.Unknown, msg) 1344 ctx = callError(ctx, s.hooks, twerr) 1345 } 1346 callResponseSent(ctx, s.hooks) 1347 } 1348 1349 func (s *cacheServer) ServiceDescriptor() ([]byte, int) { 1350 return twirpFileDescriptor0, 0 1351 } 1352 1353 func (s *cacheServer) ProtocGenTwirpVersion() string { 1354 return "v8.1.0" 1355 } 1356 1357 // PathPrefix returns the base service path, in the form: "/<prefix>/<package>.<Service>/" 1358 // that is everything in a Twirp route except for the <Method>. This can be used for routing, 1359 // for example to identify the requests that are targeted to this service in a mux. 1360 func (s *cacheServer) PathPrefix() string { 1361 return baseServicePath(s.pathPrefix, "trivy.cache.v1", "Cache") 1362 } 1363 1364 // ===== 1365 // Utils 1366 // ===== 1367 1368 // HTTPClient is the interface used by generated clients to send HTTP requests. 1369 // It is fulfilled by *(net/http).Client, which is sufficient for most users. 1370 // Users can provide their own implementation for special retry policies. 1371 // 1372 // HTTPClient implementations should not follow redirects. Redirects are 1373 // automatically disabled if *(net/http).Client is passed to client 1374 // constructors. See the withoutRedirects function in this file for more 1375 // details. 1376 type HTTPClient interface { 1377 Do(req *http.Request) (*http.Response, error) 1378 } 1379 1380 // TwirpServer is the interface generated server structs will support: they're 1381 // HTTP handlers with additional methods for accessing metadata about the 1382 // service. Those accessors are a low-level API for building reflection tools. 1383 // Most people can think of TwirpServers as just http.Handlers. 1384 type TwirpServer interface { 1385 http.Handler 1386 1387 // ServiceDescriptor returns gzipped bytes describing the .proto file that 1388 // this service was generated from. Once unzipped, the bytes can be 1389 // unmarshalled as a 1390 // google.golang.org/protobuf/types/descriptorpb.FileDescriptorProto. 1391 // 1392 // The returned integer is the index of this particular service within that 1393 // FileDescriptorProto's 'Service' slice of ServiceDescriptorProtos. This is a 1394 // low-level field, expected to be used for reflection. 1395 ServiceDescriptor() ([]byte, int) 1396 1397 // ProtocGenTwirpVersion is the semantic version string of the version of 1398 // twirp used to generate this file. 1399 ProtocGenTwirpVersion() string 1400 1401 // PathPrefix returns the HTTP URL path prefix for all methods handled by this 1402 // service. This can be used with an HTTP mux to route Twirp requests. 1403 // The path prefix is in the form: "/<prefix>/<package>.<Service>/" 1404 // that is, everything in a Twirp route except for the <Method> at the end. 1405 PathPrefix() string 1406 } 1407 1408 func newServerOpts(opts []interface{}) *twirp.ServerOptions { 1409 serverOpts := &twirp.ServerOptions{} 1410 for _, opt := range opts { 1411 switch o := opt.(type) { 1412 case twirp.ServerOption: 1413 o(serverOpts) 1414 case *twirp.ServerHooks: // backwards compatibility, allow to specify hooks as an argument 1415 twirp.WithServerHooks(o)(serverOpts) 1416 case nil: // backwards compatibility, allow nil value for the argument 1417 continue 1418 default: 1419 panic(fmt.Sprintf("Invalid option type %T, please use a twirp.ServerOption", o)) 1420 } 1421 } 1422 return serverOpts 1423 } 1424 1425 // WriteError writes an HTTP response with a valid Twirp error format (code, msg, meta). 1426 // Useful outside of the Twirp server (e.g. http middleware), but does not trigger hooks. 1427 // If err is not a twirp.Error, it will get wrapped with twirp.InternalErrorWith(err) 1428 func WriteError(resp http.ResponseWriter, err error) { 1429 writeError(context.Background(), resp, err, nil) 1430 } 1431 1432 // writeError writes Twirp errors in the response and triggers hooks. 1433 func writeError(ctx context.Context, resp http.ResponseWriter, err error, hooks *twirp.ServerHooks) { 1434 // Convert to a twirp.Error. Non-twirp errors are converted to internal errors. 1435 var twerr twirp.Error 1436 if !errors.As(err, &twerr) { 1437 twerr = twirp.InternalErrorWith(err) 1438 } 1439 1440 statusCode := twirp.ServerHTTPStatusFromErrorCode(twerr.Code()) 1441 ctx = ctxsetters.WithStatusCode(ctx, statusCode) 1442 ctx = callError(ctx, hooks, twerr) 1443 1444 respBody := marshalErrorToJSON(twerr) 1445 1446 resp.Header().Set("Content-Type", "application/json") // Error responses are always JSON 1447 resp.Header().Set("Content-Length", strconv.Itoa(len(respBody))) 1448 resp.WriteHeader(statusCode) // set HTTP status code and send response 1449 1450 _, writeErr := resp.Write(respBody) 1451 if writeErr != nil { 1452 // We have three options here. We could log the error, call the Error 1453 // hook, or just silently ignore the error. 1454 // 1455 // Logging is unacceptable because we don't have a user-controlled 1456 // logger; writing out to stderr without permission is too rude. 1457 // 1458 // Calling the Error hook would confuse users: it would mean the Error 1459 // hook got called twice for one request, which is likely to lead to 1460 // duplicated log messages and metrics, no matter how well we document 1461 // the behavior. 1462 // 1463 // Silently ignoring the error is our least-bad option. It's highly 1464 // likely that the connection is broken and the original 'err' says 1465 // so anyway. 1466 _ = writeErr 1467 } 1468 1469 callResponseSent(ctx, hooks) 1470 } 1471 1472 // sanitizeBaseURL parses the the baseURL, and adds the "http" scheme if needed. 1473 // If the URL is unparsable, the baseURL is returned unchaged. 1474 func sanitizeBaseURL(baseURL string) string { 1475 u, err := url.Parse(baseURL) 1476 if err != nil { 1477 return baseURL // invalid URL will fail later when making requests 1478 } 1479 if u.Scheme == "" { 1480 u.Scheme = "http" 1481 } 1482 return u.String() 1483 } 1484 1485 // baseServicePath composes the path prefix for the service (without <Method>). 1486 // e.g.: baseServicePath("/twirp", "my.pkg", "MyService") 1487 // 1488 // returns => "/twirp/my.pkg.MyService/" 1489 // 1490 // e.g.: baseServicePath("", "", "MyService") 1491 // 1492 // returns => "/MyService/" 1493 func baseServicePath(prefix, pkg, service string) string { 1494 fullServiceName := service 1495 if pkg != "" { 1496 fullServiceName = pkg + "." + service 1497 } 1498 return path.Join("/", prefix, fullServiceName) + "/" 1499 } 1500 1501 // parseTwirpPath extracts path components form a valid Twirp route. 1502 // Expected format: "[<prefix>]/<package>.<Service>/<Method>" 1503 // e.g.: prefix, pkgService, method := parseTwirpPath("/twirp/pkg.Svc/MakeHat") 1504 func parseTwirpPath(path string) (string, string, string) { 1505 parts := strings.Split(path, "/") 1506 if len(parts) < 2 { 1507 return "", "", "" 1508 } 1509 method := parts[len(parts)-1] 1510 pkgService := parts[len(parts)-2] 1511 prefix := strings.Join(parts[0:len(parts)-2], "/") 1512 return prefix, pkgService, method 1513 } 1514 1515 // getCustomHTTPReqHeaders retrieves a copy of any headers that are set in 1516 // a context through the twirp.WithHTTPRequestHeaders function. 1517 // If there are no headers set, or if they have the wrong type, nil is returned. 1518 func getCustomHTTPReqHeaders(ctx context.Context) http.Header { 1519 header, ok := twirp.HTTPRequestHeaders(ctx) 1520 if !ok || header == nil { 1521 return nil 1522 } 1523 copied := make(http.Header) 1524 for k, vv := range header { 1525 if vv == nil { 1526 copied[k] = nil 1527 continue 1528 } 1529 copied[k] = make([]string, len(vv)) 1530 copy(copied[k], vv) 1531 } 1532 return copied 1533 } 1534 1535 // newRequest makes an http.Request from a client, adding common headers. 1536 func newRequest(ctx context.Context, url string, reqBody io.Reader, contentType string) (*http.Request, error) { 1537 req, err := http.NewRequest("POST", url, reqBody) 1538 if err != nil { 1539 return nil, err 1540 } 1541 req = req.WithContext(ctx) 1542 if customHeader := getCustomHTTPReqHeaders(ctx); customHeader != nil { 1543 req.Header = customHeader 1544 } 1545 req.Header.Set("Accept", contentType) 1546 req.Header.Set("Content-Type", contentType) 1547 req.Header.Set("Twirp-Version", "v8.1.0") 1548 return req, nil 1549 } 1550 1551 // JSON serialization for errors 1552 type twerrJSON struct { 1553 Code string `json:"code"` 1554 Msg string `json:"msg"` 1555 Meta map[string]string `json:"meta,omitempty"` 1556 } 1557 1558 // marshalErrorToJSON returns JSON from a twirp.Error, that can be used as HTTP error response body. 1559 // If serialization fails, it will use a descriptive Internal error instead. 1560 func marshalErrorToJSON(twerr twirp.Error) []byte { 1561 // make sure that msg is not too large 1562 msg := twerr.Msg() 1563 if len(msg) > 1e6 { 1564 msg = msg[:1e6] 1565 } 1566 1567 tj := twerrJSON{ 1568 Code: string(twerr.Code()), 1569 Msg: msg, 1570 Meta: twerr.MetaMap(), 1571 } 1572 1573 buf, err := json.Marshal(&tj) 1574 if err != nil { 1575 buf = []byte("{\"type\": \"" + twirp.Internal + "\", \"msg\": \"There was an error but it could not be serialized into JSON\"}") // fallback 1576 } 1577 1578 return buf 1579 } 1580 1581 // errorFromResponse builds a twirp.Error from a non-200 HTTP response. 1582 // If the response has a valid serialized Twirp error, then it's returned. 1583 // If not, the response status code is used to generate a similar twirp 1584 // error. See twirpErrorFromIntermediary for more info on intermediary errors. 1585 func errorFromResponse(resp *http.Response) twirp.Error { 1586 statusCode := resp.StatusCode 1587 statusText := http.StatusText(statusCode) 1588 1589 if isHTTPRedirect(statusCode) { 1590 // Unexpected redirect: it must be an error from an intermediary. 1591 // Twirp clients don't follow redirects automatically, Twirp only handles 1592 // POST requests, redirects should only happen on GET and HEAD requests. 1593 location := resp.Header.Get("Location") 1594 msg := fmt.Sprintf("unexpected HTTP status code %d %q received, Location=%q", statusCode, statusText, location) 1595 return twirpErrorFromIntermediary(statusCode, msg, location) 1596 } 1597 1598 respBodyBytes, err := ioutil.ReadAll(resp.Body) 1599 if err != nil { 1600 return wrapInternal(err, "failed to read server error response body") 1601 } 1602 1603 var tj twerrJSON 1604 dec := json.NewDecoder(bytes.NewReader(respBodyBytes)) 1605 dec.DisallowUnknownFields() 1606 if err := dec.Decode(&tj); err != nil || tj.Code == "" { 1607 // Invalid JSON response; it must be an error from an intermediary. 1608 msg := fmt.Sprintf("Error from intermediary with HTTP status code %d %q", statusCode, statusText) 1609 return twirpErrorFromIntermediary(statusCode, msg, string(respBodyBytes)) 1610 } 1611 1612 errorCode := twirp.ErrorCode(tj.Code) 1613 if !twirp.IsValidErrorCode(errorCode) { 1614 msg := "invalid type returned from server error response: " + tj.Code 1615 return twirp.InternalError(msg).WithMeta("body", string(respBodyBytes)) 1616 } 1617 1618 twerr := twirp.NewError(errorCode, tj.Msg) 1619 for k, v := range tj.Meta { 1620 twerr = twerr.WithMeta(k, v) 1621 } 1622 return twerr 1623 } 1624 1625 // twirpErrorFromIntermediary maps HTTP errors from non-twirp sources to twirp errors. 1626 // The mapping is similar to gRPC: https://github.com/grpc/grpc/blob/master/doc/http-grpc-status-mapping.md. 1627 // Returned twirp Errors have some additional metadata for inspection. 1628 func twirpErrorFromIntermediary(status int, msg string, bodyOrLocation string) twirp.Error { 1629 var code twirp.ErrorCode 1630 if isHTTPRedirect(status) { // 3xx 1631 code = twirp.Internal 1632 } else { 1633 switch status { 1634 case 400: // Bad Request 1635 code = twirp.Internal 1636 case 401: // Unauthorized 1637 code = twirp.Unauthenticated 1638 case 403: // Forbidden 1639 code = twirp.PermissionDenied 1640 case 404: // Not Found 1641 code = twirp.BadRoute 1642 case 429: // Too Many Requests 1643 code = twirp.ResourceExhausted 1644 case 502, 503, 504: // Bad Gateway, Service Unavailable, Gateway Timeout 1645 code = twirp.Unavailable 1646 default: // All other codes 1647 code = twirp.Unknown 1648 } 1649 } 1650 1651 twerr := twirp.NewError(code, msg) 1652 twerr = twerr.WithMeta("http_error_from_intermediary", "true") // to easily know if this error was from intermediary 1653 twerr = twerr.WithMeta("status_code", strconv.Itoa(status)) 1654 if isHTTPRedirect(status) { 1655 twerr = twerr.WithMeta("location", bodyOrLocation) 1656 } else { 1657 twerr = twerr.WithMeta("body", bodyOrLocation) 1658 } 1659 return twerr 1660 } 1661 1662 func isHTTPRedirect(status int) bool { 1663 return status >= 300 && status <= 399 1664 } 1665 1666 // wrapInternal wraps an error with a prefix as an Internal error. 1667 // The original error cause is accessible by github.com/pkg/errors.Cause. 1668 func wrapInternal(err error, prefix string) twirp.Error { 1669 return twirp.InternalErrorWith(&wrappedError{prefix: prefix, cause: err}) 1670 } 1671 1672 type wrappedError struct { 1673 prefix string 1674 cause error 1675 } 1676 1677 func (e *wrappedError) Error() string { return e.prefix + ": " + e.cause.Error() } 1678 func (e *wrappedError) Unwrap() error { return e.cause } // for go1.13 + errors.Is/As 1679 func (e *wrappedError) Cause() error { return e.cause } // for github.com/pkg/errors 1680 1681 // ensurePanicResponses makes sure that rpc methods causing a panic still result in a Twirp Internal 1682 // error response (status 500), and error hooks are properly called with the panic wrapped as an error. 1683 // The panic is re-raised so it can be handled normally with middleware. 1684 func ensurePanicResponses(ctx context.Context, resp http.ResponseWriter, hooks *twirp.ServerHooks) { 1685 if r := recover(); r != nil { 1686 // Wrap the panic as an error so it can be passed to error hooks. 1687 // The original error is accessible from error hooks, but not visible in the response. 1688 err := errFromPanic(r) 1689 twerr := &internalWithCause{msg: "Internal service panic", cause: err} 1690 // Actually write the error 1691 writeError(ctx, resp, twerr, hooks) 1692 // If possible, flush the error to the wire. 1693 f, ok := resp.(http.Flusher) 1694 if ok { 1695 f.Flush() 1696 } 1697 1698 panic(r) 1699 } 1700 } 1701 1702 // errFromPanic returns the typed error if the recovered panic is an error, otherwise formats as error. 1703 func errFromPanic(p interface{}) error { 1704 if err, ok := p.(error); ok { 1705 return err 1706 } 1707 return fmt.Errorf("panic: %v", p) 1708 } 1709 1710 // internalWithCause is a Twirp Internal error wrapping an original error cause, 1711 // but the original error message is not exposed on Msg(). The original error 1712 // can be checked with go1.13+ errors.Is/As, and also by (github.com/pkg/errors).Unwrap 1713 type internalWithCause struct { 1714 msg string 1715 cause error 1716 } 1717 1718 func (e *internalWithCause) Unwrap() error { return e.cause } // for go1.13 + errors.Is/As 1719 func (e *internalWithCause) Cause() error { return e.cause } // for github.com/pkg/errors 1720 func (e *internalWithCause) Error() string { return e.msg + ": " + e.cause.Error() } 1721 func (e *internalWithCause) Code() twirp.ErrorCode { return twirp.Internal } 1722 func (e *internalWithCause) Msg() string { return e.msg } 1723 func (e *internalWithCause) Meta(key string) string { return "" } 1724 func (e *internalWithCause) MetaMap() map[string]string { return nil } 1725 func (e *internalWithCause) WithMeta(key string, val string) twirp.Error { return e } 1726 1727 // malformedRequestError is used when the twirp server cannot unmarshal a request 1728 func malformedRequestError(msg string) twirp.Error { 1729 return twirp.NewError(twirp.Malformed, msg) 1730 } 1731 1732 // badRouteError is used when the twirp server cannot route a request 1733 func badRouteError(msg string, method, url string) twirp.Error { 1734 err := twirp.NewError(twirp.BadRoute, msg) 1735 err = err.WithMeta("twirp_invalid_route", method+" "+url) 1736 return err 1737 } 1738 1739 // withoutRedirects makes sure that the POST request can not be redirected. 1740 // The standard library will, by default, redirect requests (including POSTs) if it gets a 302 or 1741 // 303 response, and also 301s in go1.8. It redirects by making a second request, changing the 1742 // method to GET and removing the body. This produces very confusing error messages, so instead we 1743 // set a redirect policy that always errors. This stops Go from executing the redirect. 1744 // 1745 // We have to be a little careful in case the user-provided http.Client has its own CheckRedirect 1746 // policy - if so, we'll run through that policy first. 1747 // 1748 // Because this requires modifying the http.Client, we make a new copy of the client and return it. 1749 func withoutRedirects(in *http.Client) *http.Client { 1750 copy := *in 1751 copy.CheckRedirect = func(req *http.Request, via []*http.Request) error { 1752 if in.CheckRedirect != nil { 1753 // Run the input's redirect if it exists, in case it has side effects, but ignore any error it 1754 // returns, since we want to use ErrUseLastResponse. 1755 err := in.CheckRedirect(req, via) 1756 _ = err // Silly, but this makes sure generated code passes errcheck -blank, which some people use. 1757 } 1758 return http.ErrUseLastResponse 1759 } 1760 return © 1761 } 1762 1763 // doProtobufRequest makes a Protobuf request to the remote Twirp service. 1764 func doProtobufRequest(ctx context.Context, client HTTPClient, hooks *twirp.ClientHooks, url string, in, out proto.Message) (_ context.Context, err error) { 1765 reqBodyBytes, err := proto.Marshal(in) 1766 if err != nil { 1767 return ctx, wrapInternal(err, "failed to marshal proto request") 1768 } 1769 reqBody := bytes.NewBuffer(reqBodyBytes) 1770 if err = ctx.Err(); err != nil { 1771 return ctx, wrapInternal(err, "aborted because context was done") 1772 } 1773 1774 req, err := newRequest(ctx, url, reqBody, "application/protobuf") 1775 if err != nil { 1776 return ctx, wrapInternal(err, "could not build request") 1777 } 1778 ctx, err = callClientRequestPrepared(ctx, hooks, req) 1779 if err != nil { 1780 return ctx, err 1781 } 1782 1783 req = req.WithContext(ctx) 1784 resp, err := client.Do(req) 1785 if err != nil { 1786 return ctx, wrapInternal(err, "failed to do request") 1787 } 1788 1789 defer func() { 1790 cerr := resp.Body.Close() 1791 if err == nil && cerr != nil { 1792 err = wrapInternal(cerr, "failed to close response body") 1793 } 1794 }() 1795 1796 if err = ctx.Err(); err != nil { 1797 return ctx, wrapInternal(err, "aborted because context was done") 1798 } 1799 1800 if resp.StatusCode != 200 { 1801 return ctx, errorFromResponse(resp) 1802 } 1803 1804 respBodyBytes, err := ioutil.ReadAll(resp.Body) 1805 if err != nil { 1806 return ctx, wrapInternal(err, "failed to read response body") 1807 } 1808 if err = ctx.Err(); err != nil { 1809 return ctx, wrapInternal(err, "aborted because context was done") 1810 } 1811 1812 if err = proto.Unmarshal(respBodyBytes, out); err != nil { 1813 return ctx, wrapInternal(err, "failed to unmarshal proto response") 1814 } 1815 return ctx, nil 1816 } 1817 1818 // doJSONRequest makes a JSON request to the remote Twirp service. 1819 func doJSONRequest(ctx context.Context, client HTTPClient, hooks *twirp.ClientHooks, url string, in, out proto.Message) (_ context.Context, err error) { 1820 marshaler := &protojson.MarshalOptions{UseProtoNames: true} 1821 reqBytes, err := marshaler.Marshal(in) 1822 if err != nil { 1823 return ctx, wrapInternal(err, "failed to marshal json request") 1824 } 1825 if err = ctx.Err(); err != nil { 1826 return ctx, wrapInternal(err, "aborted because context was done") 1827 } 1828 1829 req, err := newRequest(ctx, url, bytes.NewReader(reqBytes), "application/json") 1830 if err != nil { 1831 return ctx, wrapInternal(err, "could not build request") 1832 } 1833 ctx, err = callClientRequestPrepared(ctx, hooks, req) 1834 if err != nil { 1835 return ctx, err 1836 } 1837 1838 req = req.WithContext(ctx) 1839 resp, err := client.Do(req) 1840 if err != nil { 1841 return ctx, wrapInternal(err, "failed to do request") 1842 } 1843 1844 defer func() { 1845 cerr := resp.Body.Close() 1846 if err == nil && cerr != nil { 1847 err = wrapInternal(cerr, "failed to close response body") 1848 } 1849 }() 1850 1851 if err = ctx.Err(); err != nil { 1852 return ctx, wrapInternal(err, "aborted because context was done") 1853 } 1854 1855 if resp.StatusCode != 200 { 1856 return ctx, errorFromResponse(resp) 1857 } 1858 1859 d := json.NewDecoder(resp.Body) 1860 rawRespBody := json.RawMessage{} 1861 if err := d.Decode(&rawRespBody); err != nil { 1862 return ctx, wrapInternal(err, "failed to unmarshal json response") 1863 } 1864 unmarshaler := protojson.UnmarshalOptions{DiscardUnknown: true} 1865 if err = unmarshaler.Unmarshal(rawRespBody, out); err != nil { 1866 return ctx, wrapInternal(err, "failed to unmarshal json response") 1867 } 1868 if err = ctx.Err(); err != nil { 1869 return ctx, wrapInternal(err, "aborted because context was done") 1870 } 1871 return ctx, nil 1872 } 1873 1874 // Call twirp.ServerHooks.RequestReceived if the hook is available 1875 func callRequestReceived(ctx context.Context, h *twirp.ServerHooks) (context.Context, error) { 1876 if h == nil || h.RequestReceived == nil { 1877 return ctx, nil 1878 } 1879 return h.RequestReceived(ctx) 1880 } 1881 1882 // Call twirp.ServerHooks.RequestRouted if the hook is available 1883 func callRequestRouted(ctx context.Context, h *twirp.ServerHooks) (context.Context, error) { 1884 if h == nil || h.RequestRouted == nil { 1885 return ctx, nil 1886 } 1887 return h.RequestRouted(ctx) 1888 } 1889 1890 // Call twirp.ServerHooks.ResponsePrepared if the hook is available 1891 func callResponsePrepared(ctx context.Context, h *twirp.ServerHooks) context.Context { 1892 if h == nil || h.ResponsePrepared == nil { 1893 return ctx 1894 } 1895 return h.ResponsePrepared(ctx) 1896 } 1897 1898 // Call twirp.ServerHooks.ResponseSent if the hook is available 1899 func callResponseSent(ctx context.Context, h *twirp.ServerHooks) { 1900 if h == nil || h.ResponseSent == nil { 1901 return 1902 } 1903 h.ResponseSent(ctx) 1904 } 1905 1906 // Call twirp.ServerHooks.Error if the hook is available 1907 func callError(ctx context.Context, h *twirp.ServerHooks, err twirp.Error) context.Context { 1908 if h == nil || h.Error == nil { 1909 return ctx 1910 } 1911 return h.Error(ctx, err) 1912 } 1913 1914 func callClientResponseReceived(ctx context.Context, h *twirp.ClientHooks) { 1915 if h == nil || h.ResponseReceived == nil { 1916 return 1917 } 1918 h.ResponseReceived(ctx) 1919 } 1920 1921 func callClientRequestPrepared(ctx context.Context, h *twirp.ClientHooks, req *http.Request) (context.Context, error) { 1922 if h == nil || h.RequestPrepared == nil { 1923 return ctx, nil 1924 } 1925 return h.RequestPrepared(ctx, req) 1926 } 1927 1928 func callClientError(ctx context.Context, h *twirp.ClientHooks, err twirp.Error) { 1929 if h == nil || h.Error == nil { 1930 return 1931 } 1932 h.Error(ctx, err) 1933 } 1934 1935 var twirpFileDescriptor0 = []byte{ 1936 // 830 bytes of a gzipped FileDescriptorProto 1937 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x55, 0xdf, 0x8f, 0xdb, 0x44, 1938 0x10, 0x56, 0x92, 0xbb, 0x4b, 0x32, 0xf9, 0x71, 0xc7, 0x52, 0x5a, 0x37, 0x54, 0x6d, 0x64, 0x40, 1939 0x0a, 0x0f, 0xd8, 0xe2, 0xa0, 0x12, 0x12, 0x02, 0x71, 0xbd, 0x02, 0x8a, 0xd4, 0x8a, 0x63, 0x8b, 1940 0x90, 0xe0, 0x25, 0x38, 0xeb, 0x75, 0xb2, 0x3a, 0xdb, 0xeb, 0xdb, 0x59, 0x07, 0xf2, 0xcc, 0x0b, 1941 0xff, 0x13, 0xff, 0x1c, 0xda, 0xb5, 0x9d, 0xc4, 0x49, 0x7a, 0xa2, 0x2f, 0x91, 0x77, 0xe6, 0x9b, 1942 0x6f, 0x67, 0xbe, 0xf9, 0xec, 0xc0, 0x23, 0x95, 0x31, 0x9f, 0x05, 0x6c, 0xc9, 0x7d, 0xe4, 0x6a, 1943 0x25, 0x18, 0xf7, 0x32, 0x25, 0xb5, 0x24, 0x43, 0xad, 0xc4, 0x6a, 0xed, 0xd9, 0x94, 0xb7, 0xfa, 1944 0x7c, 0xf4, 0x6c, 0x21, 0xe5, 0x22, 0xe6, 0xbe, 0xcd, 0xce, 0xf3, 0xc8, 0xd7, 0x22, 0xe1, 0xa8, 1945 0x83, 0x24, 0x2b, 0x0a, 0x46, 0x8e, 0x65, 0x92, 0x49, 0x22, 0xd3, 0x3a, 0xd5, 0xe8, 0xc3, 0xfd, 1946 0x52, 0x9e, 0x64, 0x7a, 0x5d, 0x24, 0xdd, 0x7f, 0x9a, 0xd0, 0xbf, 0x52, 0x5a, 0x44, 0x01, 0xd3, 1947 0xd3, 0x34, 0x92, 0xe4, 0x13, 0x18, 0x22, 0x5b, 0xf2, 0x24, 0x98, 0xad, 0xb8, 0x42, 0x21, 0x53, 1948 0xa7, 0x31, 0x6e, 0x4c, 0x4e, 0xe9, 0xa0, 0x88, 0xfe, 0x5a, 0x04, 0x89, 0x0b, 0xfd, 0x40, 0xb1, 1949 0xa5, 0xd0, 0x9c, 0xe9, 0x5c, 0x71, 0xa7, 0x39, 0x6e, 0x4c, 0xba, 0xb4, 0x16, 0x23, 0x5f, 0x42, 1950 0x9b, 0x29, 0x1e, 0x68, 0x1e, 0x3a, 0xad, 0x71, 0x63, 0xd2, 0xbb, 0x1c, 0x79, 0x45, 0x2b, 0x5e, 1951 0xd5, 0x8a, 0xf7, 0x4b, 0x35, 0x05, 0xad, 0xa0, 0xa6, 0x81, 0x50, 0xb2, 0x5b, 0xae, 0x36, 0x0d, 1952 0x9c, 0x58, 0xee, 0x41, 0x11, 0xad, 0x1a, 0x18, 0x42, 0x53, 0xa2, 0x73, 0x6a, 0x53, 0x4d, 0x89, 1953 0xe4, 0x3b, 0xb8, 0x58, 0x0a, 0xd4, 0x52, 0xad, 0x67, 0x59, 0xc0, 0x6e, 0x83, 0x05, 0x47, 0xe7, 1954 0x6c, 0xdc, 0x9a, 0xf4, 0x2e, 0x3f, 0xf0, 0x4a, 0x2d, 0xad, 0x38, 0xde, 0x4d, 0x91, 0xa5, 0xe7, 1955 0x25, 0xbc, 0x3c, 0xa3, 0xfb, 0x17, 0x90, 0x9b, 0x5c, 0x57, 0x62, 0x50, 0x7e, 0x97, 0x73, 0xd4, 1956 0xe4, 0x19, 0xf4, 0x82, 0x32, 0x34, 0x13, 0xa1, 0x15, 0xa3, 0x4b, 0xa1, 0x0a, 0x4d, 0x43, 0x72, 1957 0x05, 0x83, 0x2d, 0x20, 0x8d, 0xa4, 0x95, 0xa2, 0x77, 0xf9, 0xc4, 0xab, 0x6f, 0xd0, 0xdb, 0x55, 1958 0xd9, 0x08, 0xb5, 0x3d, 0xb9, 0x7f, 0x9f, 0x42, 0xe7, 0x45, 0x2c, 0xe7, 0xef, 0xb2, 0x80, 0xb1, 1959 0x9d, 0xbf, 0xb8, 0xeb, 0xa2, 0x3e, 0xe1, 0x4f, 0x6f, 0xac, 0x22, 0x5f, 0x01, 0x28, 0x9e, 0x49, 1960 0x14, 0x66, 0x4a, 0xa7, 0x67, 0x91, 0x4e, 0x1d, 0x49, 0x37, 0x79, 0xba, 0x83, 0x25, 0xdf, 0xc2, 1961 0xa0, 0xd4, 0xd0, 0x4e, 0x84, 0x4e, 0xcb, 0x0a, 0xf9, 0xf8, 0xa8, 0x90, 0xc5, 0x3c, 0xd9, 0xf6, 1962 0x80, 0xe4, 0x1b, 0xe8, 0x07, 0x59, 0x16, 0x0b, 0x16, 0x68, 0x21, 0x53, 0x74, 0x4e, 0x8e, 0x95, 1963 0x5f, 0x6d, 0x11, 0xb4, 0x06, 0x27, 0xaf, 0xe0, 0xbd, 0x44, 0x20, 0x93, 0x69, 0x24, 0x16, 0xb9, 1964 0x2a, 0x39, 0xba, 0x96, 0xe3, 0x69, 0x9d, 0xe3, 0xf5, 0x1e, 0x8c, 0x1e, 0x16, 0x9a, 0x05, 0xca, 1965 0x2c, 0xb8, 0xcb, 0xf9, 0x2c, 0x14, 0xca, 0x38, 0xa6, 0x65, 0x16, 0x58, 0x84, 0x5e, 0x0a, 0x85, 1966 0x46, 0xf0, 0x3f, 0x8d, 0x69, 0x65, 0xae, 0x67, 0x91, 0x88, 0x4b, 0xdf, 0x74, 0xe9, 0xa0, 0x8a, 1967 0xfe, 0x60, 0x82, 0xe4, 0x21, 0x9c, 0x85, 0x62, 0xc1, 0x51, 0x3b, 0x6d, 0xeb, 0x81, 0xf2, 0x44, 1968 0x1e, 0x41, 0x3b, 0x14, 0x51, 0x64, 0xcc, 0xd1, 0xa9, 0x12, 0x51, 0x34, 0x0d, 0xc9, 0x8f, 0x70, 1969 0xc1, 0x72, 0xd4, 0x32, 0x99, 0x29, 0x8e, 0x32, 0x57, 0x8c, 0xa3, 0x03, 0x76, 0x8a, 0x27, 0xf5, 1970 0x29, 0xae, 0x2d, 0x8a, 0x96, 0x20, 0x7a, 0xce, 0x6a, 0x67, 0x24, 0x1e, 0xb4, 0x91, 0x33, 0xc5, 1971 0x35, 0x3a, 0x7d, 0x5b, 0xff, 0xa0, 0x5e, 0xff, 0xc6, 0x26, 0x69, 0x05, 0x22, 0xcf, 0xa1, 0x13, 1972 0x0b, 0xc6, 0x53, 0xe4, 0xe8, 0x0c, 0x8e, 0x49, 0xff, 0xaa, 0xc8, 0x9a, 0xb9, 0xe8, 0x06, 0xea, 1973 0xfe, 0x01, 0xc3, 0x9b, 0x5c, 0x1b, 0x1f, 0x56, 0xde, 0xdf, 0x19, 0xad, 0x51, 0x1b, 0xed, 0x39, 1974 0x74, 0xe7, 0xb1, 0x9c, 0x17, 0x7e, 0x6f, 0xd5, 0x9d, 0x55, 0xf9, 0xbd, 0x32, 0x34, 0xed, 0xcc, 1975 0xcb, 0x27, 0xf7, 0x1a, 0x7a, 0x37, 0xb9, 0xa6, 0x1c, 0x33, 0x99, 0x22, 0x2f, 0x2d, 0xdc, 0xb8, 1976 0xc7, 0xc2, 0x04, 0x4e, 0xb8, 0xc4, 0xd8, 0xda, 0xbc, 0x43, 0xed, 0xb3, 0xfb, 0x33, 0xbc, 0xff, 1977 0x5a, 0x20, 0x8a, 0x74, 0x61, 0x6e, 0xc0, 0xff, 0xfd, 0x9e, 0x3e, 0x86, 0x4e, 0xd1, 0x73, 0x68, 1978 0x5e, 0x1b, 0xb3, 0xe0, 0xb6, 0x6d, 0x2c, 0x44, 0xf7, 0x16, 0x1e, 0xd4, 0x29, 0xcb, 0x06, 0x3f, 1979 0x85, 0x8b, 0xa4, 0x88, 0xcf, 0x2a, 0x22, 0x4b, 0xdc, 0xa1, 0xe7, 0x65, 0xbc, 0x7a, 0xa9, 0xc9, 1980 0x64, 0x0b, 0xdd, 0xbb, 0x65, 0x98, 0x6c, 0xa9, 0xcd, 0x65, 0x3e, 0x90, 0x97, 0x3c, 0xe6, 0x9a, 1981 0xd7, 0xda, 0xdf, 0xed, 0xae, 0x51, 0xeb, 0xee, 0xf2, 0xdf, 0x26, 0x9c, 0x5e, 0x1b, 0x55, 0xc9, 1982 0xd4, 0xea, 0xb7, 0xb9, 0xd3, 0xdd, 0x97, 0xfc, 0xf0, 0xf3, 0x35, 0x7a, 0x78, 0xf0, 0xc9, 0xfd, 1983 0xde, 0x7c, 0xfd, 0xc9, 0x15, 0xb4, 0xcb, 0x65, 0x93, 0xa7, 0x47, 0x68, 0x76, 0x5c, 0xf0, 0x56, 1984 0x8a, 0xdf, 0xa0, 0xbf, 0xab, 0x1a, 0xf9, 0x68, 0x9f, 0xe7, 0xc8, 0x9a, 0x46, 0x1f, 0xdf, 0x0f, 1985 0x2a, 0x85, 0x9f, 0x42, 0x6f, 0x47, 0xa3, 0xc3, 0x41, 0x0f, 0x05, 0x7c, 0x5b, 0x97, 0x2f, 0xfc, 1986 0xdf, 0x3f, 0x5b, 0x08, 0xbd, 0xcc, 0xe7, 0xc6, 0x5a, 0x7e, 0x70, 0x97, 0x07, 0xc8, 0x59, 0xae, 1987 0x84, 0x5e, 0xfb, 0x96, 0xd4, 0xdf, 0xfc, 0x03, 0x7f, 0x6d, 0x7f, 0xe7, 0x67, 0x96, 0xe0, 0x8b, 1988 0xff, 0x02, 0x00, 0x00, 0xff, 0xff, 0x82, 0x05, 0x5f, 0x23, 0x9b, 0x07, 0x00, 0x00, 1989 }