github.com/devseccon/trivy@v0.47.1-0.20231123133102-bd902a0bd996/rpc/scanner/service.twirp.go (about) 1 // Code generated by protoc-gen-twirp v8.1.0, DO NOT EDIT. 2 // source: rpc/scanner/service.proto 3 4 package scanner 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 bytes "bytes" 20 import errors "errors" 21 import io "io" 22 import path "path" 23 import url "net/url" 24 25 // Version compatibility assertion. 26 // If the constant is not defined in the package, that likely means 27 // the package needs to be updated to work with this generated code. 28 // See https://twitchtv.github.io/twirp/docs/version_matrix.html 29 const _ = twirp.TwirpPackageMinVersion_8_1_0 30 31 // ================= 32 // Scanner Interface 33 // ================= 34 35 type Scanner interface { 36 Scan(context.Context, *ScanRequest) (*ScanResponse, error) 37 } 38 39 // ======================= 40 // Scanner Protobuf Client 41 // ======================= 42 43 type scannerProtobufClient struct { 44 client HTTPClient 45 urls [1]string 46 interceptor twirp.Interceptor 47 opts twirp.ClientOptions 48 } 49 50 // NewScannerProtobufClient creates a Protobuf client that implements the Scanner interface. 51 // It communicates using Protobuf and can be configured with a custom HTTPClient. 52 func NewScannerProtobufClient(baseURL string, client HTTPClient, opts ...twirp.ClientOption) Scanner { 53 if c, ok := client.(*http.Client); ok { 54 client = withoutRedirects(c) 55 } 56 57 clientOpts := twirp.ClientOptions{} 58 for _, o := range opts { 59 o(&clientOpts) 60 } 61 62 // Using ReadOpt allows backwards and forwads compatibility with new options in the future 63 literalURLs := false 64 _ = clientOpts.ReadOpt("literalURLs", &literalURLs) 65 var pathPrefix string 66 if ok := clientOpts.ReadOpt("pathPrefix", &pathPrefix); !ok { 67 pathPrefix = "/twirp" // default prefix 68 } 69 70 // Build method URLs: <baseURL>[<prefix>]/<package>.<Service>/<Method> 71 serviceURL := sanitizeBaseURL(baseURL) 72 serviceURL += baseServicePath(pathPrefix, "trivy.scanner.v1", "Scanner") 73 urls := [1]string{ 74 serviceURL + "Scan", 75 } 76 77 return &scannerProtobufClient{ 78 client: client, 79 urls: urls, 80 interceptor: twirp.ChainInterceptors(clientOpts.Interceptors...), 81 opts: clientOpts, 82 } 83 } 84 85 func (c *scannerProtobufClient) Scan(ctx context.Context, in *ScanRequest) (*ScanResponse, error) { 86 ctx = ctxsetters.WithPackageName(ctx, "trivy.scanner.v1") 87 ctx = ctxsetters.WithServiceName(ctx, "Scanner") 88 ctx = ctxsetters.WithMethodName(ctx, "Scan") 89 caller := c.callScan 90 if c.interceptor != nil { 91 caller = func(ctx context.Context, req *ScanRequest) (*ScanResponse, error) { 92 resp, err := c.interceptor( 93 func(ctx context.Context, req interface{}) (interface{}, error) { 94 typedReq, ok := req.(*ScanRequest) 95 if !ok { 96 return nil, twirp.InternalError("failed type assertion req.(*ScanRequest) when calling interceptor") 97 } 98 return c.callScan(ctx, typedReq) 99 }, 100 )(ctx, req) 101 if resp != nil { 102 typedResp, ok := resp.(*ScanResponse) 103 if !ok { 104 return nil, twirp.InternalError("failed type assertion resp.(*ScanResponse) when calling interceptor") 105 } 106 return typedResp, err 107 } 108 return nil, err 109 } 110 } 111 return caller(ctx, in) 112 } 113 114 func (c *scannerProtobufClient) callScan(ctx context.Context, in *ScanRequest) (*ScanResponse, error) { 115 out := new(ScanResponse) 116 ctx, err := doProtobufRequest(ctx, c.client, c.opts.Hooks, c.urls[0], in, out) 117 if err != nil { 118 twerr, ok := err.(twirp.Error) 119 if !ok { 120 twerr = twirp.InternalErrorWith(err) 121 } 122 callClientError(ctx, c.opts.Hooks, twerr) 123 return nil, err 124 } 125 126 callClientResponseReceived(ctx, c.opts.Hooks) 127 128 return out, nil 129 } 130 131 // =================== 132 // Scanner JSON Client 133 // =================== 134 135 type scannerJSONClient struct { 136 client HTTPClient 137 urls [1]string 138 interceptor twirp.Interceptor 139 opts twirp.ClientOptions 140 } 141 142 // NewScannerJSONClient creates a JSON client that implements the Scanner interface. 143 // It communicates using JSON and can be configured with a custom HTTPClient. 144 func NewScannerJSONClient(baseURL string, client HTTPClient, opts ...twirp.ClientOption) Scanner { 145 if c, ok := client.(*http.Client); ok { 146 client = withoutRedirects(c) 147 } 148 149 clientOpts := twirp.ClientOptions{} 150 for _, o := range opts { 151 o(&clientOpts) 152 } 153 154 // Using ReadOpt allows backwards and forwads compatibility with new options in the future 155 literalURLs := false 156 _ = clientOpts.ReadOpt("literalURLs", &literalURLs) 157 var pathPrefix string 158 if ok := clientOpts.ReadOpt("pathPrefix", &pathPrefix); !ok { 159 pathPrefix = "/twirp" // default prefix 160 } 161 162 // Build method URLs: <baseURL>[<prefix>]/<package>.<Service>/<Method> 163 serviceURL := sanitizeBaseURL(baseURL) 164 serviceURL += baseServicePath(pathPrefix, "trivy.scanner.v1", "Scanner") 165 urls := [1]string{ 166 serviceURL + "Scan", 167 } 168 169 return &scannerJSONClient{ 170 client: client, 171 urls: urls, 172 interceptor: twirp.ChainInterceptors(clientOpts.Interceptors...), 173 opts: clientOpts, 174 } 175 } 176 177 func (c *scannerJSONClient) Scan(ctx context.Context, in *ScanRequest) (*ScanResponse, error) { 178 ctx = ctxsetters.WithPackageName(ctx, "trivy.scanner.v1") 179 ctx = ctxsetters.WithServiceName(ctx, "Scanner") 180 ctx = ctxsetters.WithMethodName(ctx, "Scan") 181 caller := c.callScan 182 if c.interceptor != nil { 183 caller = func(ctx context.Context, req *ScanRequest) (*ScanResponse, error) { 184 resp, err := c.interceptor( 185 func(ctx context.Context, req interface{}) (interface{}, error) { 186 typedReq, ok := req.(*ScanRequest) 187 if !ok { 188 return nil, twirp.InternalError("failed type assertion req.(*ScanRequest) when calling interceptor") 189 } 190 return c.callScan(ctx, typedReq) 191 }, 192 )(ctx, req) 193 if resp != nil { 194 typedResp, ok := resp.(*ScanResponse) 195 if !ok { 196 return nil, twirp.InternalError("failed type assertion resp.(*ScanResponse) when calling interceptor") 197 } 198 return typedResp, err 199 } 200 return nil, err 201 } 202 } 203 return caller(ctx, in) 204 } 205 206 func (c *scannerJSONClient) callScan(ctx context.Context, in *ScanRequest) (*ScanResponse, error) { 207 out := new(ScanResponse) 208 ctx, err := doJSONRequest(ctx, c.client, c.opts.Hooks, c.urls[0], in, out) 209 if err != nil { 210 twerr, ok := err.(twirp.Error) 211 if !ok { 212 twerr = twirp.InternalErrorWith(err) 213 } 214 callClientError(ctx, c.opts.Hooks, twerr) 215 return nil, err 216 } 217 218 callClientResponseReceived(ctx, c.opts.Hooks) 219 220 return out, nil 221 } 222 223 // ====================== 224 // Scanner Server Handler 225 // ====================== 226 227 type scannerServer struct { 228 Scanner 229 interceptor twirp.Interceptor 230 hooks *twirp.ServerHooks 231 pathPrefix string // prefix for routing 232 jsonSkipDefaults bool // do not include unpopulated fields (default values) in the response 233 jsonCamelCase bool // JSON fields are serialized as lowerCamelCase rather than keeping the original proto names 234 } 235 236 // NewScannerServer builds a TwirpServer that can be used as an http.Handler to handle 237 // HTTP requests that are routed to the right method in the provided svc implementation. 238 // The opts are twirp.ServerOption modifiers, for example twirp.WithServerHooks(hooks). 239 func NewScannerServer(svc Scanner, opts ...interface{}) TwirpServer { 240 serverOpts := newServerOpts(opts) 241 242 // Using ReadOpt allows backwards and forwads compatibility with new options in the future 243 jsonSkipDefaults := false 244 _ = serverOpts.ReadOpt("jsonSkipDefaults", &jsonSkipDefaults) 245 jsonCamelCase := false 246 _ = serverOpts.ReadOpt("jsonCamelCase", &jsonCamelCase) 247 var pathPrefix string 248 if ok := serverOpts.ReadOpt("pathPrefix", &pathPrefix); !ok { 249 pathPrefix = "/twirp" // default prefix 250 } 251 252 return &scannerServer{ 253 Scanner: svc, 254 hooks: serverOpts.Hooks, 255 interceptor: twirp.ChainInterceptors(serverOpts.Interceptors...), 256 pathPrefix: pathPrefix, 257 jsonSkipDefaults: jsonSkipDefaults, 258 jsonCamelCase: jsonCamelCase, 259 } 260 } 261 262 // writeError writes an HTTP response with a valid Twirp error format, and triggers hooks. 263 // If err is not a twirp.Error, it will get wrapped with twirp.InternalErrorWith(err) 264 func (s *scannerServer) writeError(ctx context.Context, resp http.ResponseWriter, err error) { 265 writeError(ctx, resp, err, s.hooks) 266 } 267 268 // handleRequestBodyError is used to handle error when the twirp server cannot read request 269 func (s *scannerServer) handleRequestBodyError(ctx context.Context, resp http.ResponseWriter, msg string, err error) { 270 if context.Canceled == ctx.Err() { 271 s.writeError(ctx, resp, twirp.NewError(twirp.Canceled, "failed to read request: context canceled")) 272 return 273 } 274 if context.DeadlineExceeded == ctx.Err() { 275 s.writeError(ctx, resp, twirp.NewError(twirp.DeadlineExceeded, "failed to read request: deadline exceeded")) 276 return 277 } 278 s.writeError(ctx, resp, twirp.WrapError(malformedRequestError(msg), err)) 279 } 280 281 // ScannerPathPrefix is a convenience constant that may identify URL paths. 282 // Should be used with caution, it only matches routes generated by Twirp Go clients, 283 // with the default "/twirp" prefix and default CamelCase service and method names. 284 // More info: https://twitchtv.github.io/twirp/docs/routing.html 285 const ScannerPathPrefix = "/twirp/trivy.scanner.v1.Scanner/" 286 287 func (s *scannerServer) ServeHTTP(resp http.ResponseWriter, req *http.Request) { 288 ctx := req.Context() 289 ctx = ctxsetters.WithPackageName(ctx, "trivy.scanner.v1") 290 ctx = ctxsetters.WithServiceName(ctx, "Scanner") 291 ctx = ctxsetters.WithResponseWriter(ctx, resp) 292 293 var err error 294 ctx, err = callRequestReceived(ctx, s.hooks) 295 if err != nil { 296 s.writeError(ctx, resp, err) 297 return 298 } 299 300 if req.Method != "POST" { 301 msg := fmt.Sprintf("unsupported method %q (only POST is allowed)", req.Method) 302 s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) 303 return 304 } 305 306 // Verify path format: [<prefix>]/<package>.<Service>/<Method> 307 prefix, pkgService, method := parseTwirpPath(req.URL.Path) 308 if pkgService != "trivy.scanner.v1.Scanner" { 309 msg := fmt.Sprintf("no handler for path %q", req.URL.Path) 310 s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) 311 return 312 } 313 if prefix != s.pathPrefix { 314 msg := fmt.Sprintf("invalid path prefix %q, expected %q, on path %q", prefix, s.pathPrefix, req.URL.Path) 315 s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) 316 return 317 } 318 319 switch method { 320 case "Scan": 321 s.serveScan(ctx, resp, req) 322 return 323 default: 324 msg := fmt.Sprintf("no handler for path %q", req.URL.Path) 325 s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) 326 return 327 } 328 } 329 330 func (s *scannerServer) serveScan(ctx context.Context, resp http.ResponseWriter, req *http.Request) { 331 header := req.Header.Get("Content-Type") 332 i := strings.Index(header, ";") 333 if i == -1 { 334 i = len(header) 335 } 336 switch strings.TrimSpace(strings.ToLower(header[:i])) { 337 case "application/json": 338 s.serveScanJSON(ctx, resp, req) 339 case "application/protobuf": 340 s.serveScanProtobuf(ctx, resp, req) 341 default: 342 msg := fmt.Sprintf("unexpected Content-Type: %q", req.Header.Get("Content-Type")) 343 twerr := badRouteError(msg, req.Method, req.URL.Path) 344 s.writeError(ctx, resp, twerr) 345 } 346 } 347 348 func (s *scannerServer) serveScanJSON(ctx context.Context, resp http.ResponseWriter, req *http.Request) { 349 var err error 350 ctx = ctxsetters.WithMethodName(ctx, "Scan") 351 ctx, err = callRequestRouted(ctx, s.hooks) 352 if err != nil { 353 s.writeError(ctx, resp, err) 354 return 355 } 356 357 d := json.NewDecoder(req.Body) 358 rawReqBody := json.RawMessage{} 359 if err := d.Decode(&rawReqBody); err != nil { 360 s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) 361 return 362 } 363 reqContent := new(ScanRequest) 364 unmarshaler := protojson.UnmarshalOptions{DiscardUnknown: true} 365 if err = unmarshaler.Unmarshal(rawReqBody, reqContent); err != nil { 366 s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) 367 return 368 } 369 370 handler := s.Scanner.Scan 371 if s.interceptor != nil { 372 handler = func(ctx context.Context, req *ScanRequest) (*ScanResponse, error) { 373 resp, err := s.interceptor( 374 func(ctx context.Context, req interface{}) (interface{}, error) { 375 typedReq, ok := req.(*ScanRequest) 376 if !ok { 377 return nil, twirp.InternalError("failed type assertion req.(*ScanRequest) when calling interceptor") 378 } 379 return s.Scanner.Scan(ctx, typedReq) 380 }, 381 )(ctx, req) 382 if resp != nil { 383 typedResp, ok := resp.(*ScanResponse) 384 if !ok { 385 return nil, twirp.InternalError("failed type assertion resp.(*ScanResponse) when calling interceptor") 386 } 387 return typedResp, err 388 } 389 return nil, err 390 } 391 } 392 393 // Call service method 394 var respContent *ScanResponse 395 func() { 396 defer ensurePanicResponses(ctx, resp, s.hooks) 397 respContent, err = handler(ctx, reqContent) 398 }() 399 400 if err != nil { 401 s.writeError(ctx, resp, err) 402 return 403 } 404 if respContent == nil { 405 s.writeError(ctx, resp, twirp.InternalError("received a nil *ScanResponse and nil error while calling Scan. nil responses are not supported")) 406 return 407 } 408 409 ctx = callResponsePrepared(ctx, s.hooks) 410 411 marshaler := &protojson.MarshalOptions{UseProtoNames: !s.jsonCamelCase, EmitUnpopulated: !s.jsonSkipDefaults} 412 respBytes, err := marshaler.Marshal(respContent) 413 if err != nil { 414 s.writeError(ctx, resp, wrapInternal(err, "failed to marshal json response")) 415 return 416 } 417 418 ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) 419 resp.Header().Set("Content-Type", "application/json") 420 resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) 421 resp.WriteHeader(http.StatusOK) 422 423 if n, err := resp.Write(respBytes); err != nil { 424 msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) 425 twerr := twirp.NewError(twirp.Unknown, msg) 426 ctx = callError(ctx, s.hooks, twerr) 427 } 428 callResponseSent(ctx, s.hooks) 429 } 430 431 func (s *scannerServer) serveScanProtobuf(ctx context.Context, resp http.ResponseWriter, req *http.Request) { 432 var err error 433 ctx = ctxsetters.WithMethodName(ctx, "Scan") 434 ctx, err = callRequestRouted(ctx, s.hooks) 435 if err != nil { 436 s.writeError(ctx, resp, err) 437 return 438 } 439 440 buf, err := ioutil.ReadAll(req.Body) 441 if err != nil { 442 s.handleRequestBodyError(ctx, resp, "failed to read request body", err) 443 return 444 } 445 reqContent := new(ScanRequest) 446 if err = proto.Unmarshal(buf, reqContent); err != nil { 447 s.writeError(ctx, resp, malformedRequestError("the protobuf request could not be decoded")) 448 return 449 } 450 451 handler := s.Scanner.Scan 452 if s.interceptor != nil { 453 handler = func(ctx context.Context, req *ScanRequest) (*ScanResponse, error) { 454 resp, err := s.interceptor( 455 func(ctx context.Context, req interface{}) (interface{}, error) { 456 typedReq, ok := req.(*ScanRequest) 457 if !ok { 458 return nil, twirp.InternalError("failed type assertion req.(*ScanRequest) when calling interceptor") 459 } 460 return s.Scanner.Scan(ctx, typedReq) 461 }, 462 )(ctx, req) 463 if resp != nil { 464 typedResp, ok := resp.(*ScanResponse) 465 if !ok { 466 return nil, twirp.InternalError("failed type assertion resp.(*ScanResponse) when calling interceptor") 467 } 468 return typedResp, err 469 } 470 return nil, err 471 } 472 } 473 474 // Call service method 475 var respContent *ScanResponse 476 func() { 477 defer ensurePanicResponses(ctx, resp, s.hooks) 478 respContent, err = handler(ctx, reqContent) 479 }() 480 481 if err != nil { 482 s.writeError(ctx, resp, err) 483 return 484 } 485 if respContent == nil { 486 s.writeError(ctx, resp, twirp.InternalError("received a nil *ScanResponse and nil error while calling Scan. nil responses are not supported")) 487 return 488 } 489 490 ctx = callResponsePrepared(ctx, s.hooks) 491 492 respBytes, err := proto.Marshal(respContent) 493 if err != nil { 494 s.writeError(ctx, resp, wrapInternal(err, "failed to marshal proto response")) 495 return 496 } 497 498 ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) 499 resp.Header().Set("Content-Type", "application/protobuf") 500 resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) 501 resp.WriteHeader(http.StatusOK) 502 if n, err := resp.Write(respBytes); err != nil { 503 msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) 504 twerr := twirp.NewError(twirp.Unknown, msg) 505 ctx = callError(ctx, s.hooks, twerr) 506 } 507 callResponseSent(ctx, s.hooks) 508 } 509 510 func (s *scannerServer) ServiceDescriptor() ([]byte, int) { 511 return twirpFileDescriptor0, 0 512 } 513 514 func (s *scannerServer) ProtocGenTwirpVersion() string { 515 return "v8.1.0" 516 } 517 518 // PathPrefix returns the base service path, in the form: "/<prefix>/<package>.<Service>/" 519 // that is everything in a Twirp route except for the <Method>. This can be used for routing, 520 // for example to identify the requests that are targeted to this service in a mux. 521 func (s *scannerServer) PathPrefix() string { 522 return baseServicePath(s.pathPrefix, "trivy.scanner.v1", "Scanner") 523 } 524 525 // ===== 526 // Utils 527 // ===== 528 529 // HTTPClient is the interface used by generated clients to send HTTP requests. 530 // It is fulfilled by *(net/http).Client, which is sufficient for most users. 531 // Users can provide their own implementation for special retry policies. 532 // 533 // HTTPClient implementations should not follow redirects. Redirects are 534 // automatically disabled if *(net/http).Client is passed to client 535 // constructors. See the withoutRedirects function in this file for more 536 // details. 537 type HTTPClient interface { 538 Do(req *http.Request) (*http.Response, error) 539 } 540 541 // TwirpServer is the interface generated server structs will support: they're 542 // HTTP handlers with additional methods for accessing metadata about the 543 // service. Those accessors are a low-level API for building reflection tools. 544 // Most people can think of TwirpServers as just http.Handlers. 545 type TwirpServer interface { 546 http.Handler 547 548 // ServiceDescriptor returns gzipped bytes describing the .proto file that 549 // this service was generated from. Once unzipped, the bytes can be 550 // unmarshalled as a 551 // google.golang.org/protobuf/types/descriptorpb.FileDescriptorProto. 552 // 553 // The returned integer is the index of this particular service within that 554 // FileDescriptorProto's 'Service' slice of ServiceDescriptorProtos. This is a 555 // low-level field, expected to be used for reflection. 556 ServiceDescriptor() ([]byte, int) 557 558 // ProtocGenTwirpVersion is the semantic version string of the version of 559 // twirp used to generate this file. 560 ProtocGenTwirpVersion() string 561 562 // PathPrefix returns the HTTP URL path prefix for all methods handled by this 563 // service. This can be used with an HTTP mux to route Twirp requests. 564 // The path prefix is in the form: "/<prefix>/<package>.<Service>/" 565 // that is, everything in a Twirp route except for the <Method> at the end. 566 PathPrefix() string 567 } 568 569 func newServerOpts(opts []interface{}) *twirp.ServerOptions { 570 serverOpts := &twirp.ServerOptions{} 571 for _, opt := range opts { 572 switch o := opt.(type) { 573 case twirp.ServerOption: 574 o(serverOpts) 575 case *twirp.ServerHooks: // backwards compatibility, allow to specify hooks as an argument 576 twirp.WithServerHooks(o)(serverOpts) 577 case nil: // backwards compatibility, allow nil value for the argument 578 continue 579 default: 580 panic(fmt.Sprintf("Invalid option type %T, please use a twirp.ServerOption", o)) 581 } 582 } 583 return serverOpts 584 } 585 586 // WriteError writes an HTTP response with a valid Twirp error format (code, msg, meta). 587 // Useful outside of the Twirp server (e.g. http middleware), but does not trigger hooks. 588 // If err is not a twirp.Error, it will get wrapped with twirp.InternalErrorWith(err) 589 func WriteError(resp http.ResponseWriter, err error) { 590 writeError(context.Background(), resp, err, nil) 591 } 592 593 // writeError writes Twirp errors in the response and triggers hooks. 594 func writeError(ctx context.Context, resp http.ResponseWriter, err error, hooks *twirp.ServerHooks) { 595 // Convert to a twirp.Error. Non-twirp errors are converted to internal errors. 596 var twerr twirp.Error 597 if !errors.As(err, &twerr) { 598 twerr = twirp.InternalErrorWith(err) 599 } 600 601 statusCode := twirp.ServerHTTPStatusFromErrorCode(twerr.Code()) 602 ctx = ctxsetters.WithStatusCode(ctx, statusCode) 603 ctx = callError(ctx, hooks, twerr) 604 605 respBody := marshalErrorToJSON(twerr) 606 607 resp.Header().Set("Content-Type", "application/json") // Error responses are always JSON 608 resp.Header().Set("Content-Length", strconv.Itoa(len(respBody))) 609 resp.WriteHeader(statusCode) // set HTTP status code and send response 610 611 _, writeErr := resp.Write(respBody) 612 if writeErr != nil { 613 // We have three options here. We could log the error, call the Error 614 // hook, or just silently ignore the error. 615 // 616 // Logging is unacceptable because we don't have a user-controlled 617 // logger; writing out to stderr without permission is too rude. 618 // 619 // Calling the Error hook would confuse users: it would mean the Error 620 // hook got called twice for one request, which is likely to lead to 621 // duplicated log messages and metrics, no matter how well we document 622 // the behavior. 623 // 624 // Silently ignoring the error is our least-bad option. It's highly 625 // likely that the connection is broken and the original 'err' says 626 // so anyway. 627 _ = writeErr 628 } 629 630 callResponseSent(ctx, hooks) 631 } 632 633 // sanitizeBaseURL parses the the baseURL, and adds the "http" scheme if needed. 634 // If the URL is unparsable, the baseURL is returned unchaged. 635 func sanitizeBaseURL(baseURL string) string { 636 u, err := url.Parse(baseURL) 637 if err != nil { 638 return baseURL // invalid URL will fail later when making requests 639 } 640 if u.Scheme == "" { 641 u.Scheme = "http" 642 } 643 return u.String() 644 } 645 646 // baseServicePath composes the path prefix for the service (without <Method>). 647 // e.g.: baseServicePath("/twirp", "my.pkg", "MyService") 648 // 649 // returns => "/twirp/my.pkg.MyService/" 650 // 651 // e.g.: baseServicePath("", "", "MyService") 652 // 653 // returns => "/MyService/" 654 func baseServicePath(prefix, pkg, service string) string { 655 fullServiceName := service 656 if pkg != "" { 657 fullServiceName = pkg + "." + service 658 } 659 return path.Join("/", prefix, fullServiceName) + "/" 660 } 661 662 // parseTwirpPath extracts path components form a valid Twirp route. 663 // Expected format: "[<prefix>]/<package>.<Service>/<Method>" 664 // e.g.: prefix, pkgService, method := parseTwirpPath("/twirp/pkg.Svc/MakeHat") 665 func parseTwirpPath(path string) (string, string, string) { 666 parts := strings.Split(path, "/") 667 if len(parts) < 2 { 668 return "", "", "" 669 } 670 method := parts[len(parts)-1] 671 pkgService := parts[len(parts)-2] 672 prefix := strings.Join(parts[0:len(parts)-2], "/") 673 return prefix, pkgService, method 674 } 675 676 // getCustomHTTPReqHeaders retrieves a copy of any headers that are set in 677 // a context through the twirp.WithHTTPRequestHeaders function. 678 // If there are no headers set, or if they have the wrong type, nil is returned. 679 func getCustomHTTPReqHeaders(ctx context.Context) http.Header { 680 header, ok := twirp.HTTPRequestHeaders(ctx) 681 if !ok || header == nil { 682 return nil 683 } 684 copied := make(http.Header) 685 for k, vv := range header { 686 if vv == nil { 687 copied[k] = nil 688 continue 689 } 690 copied[k] = make([]string, len(vv)) 691 copy(copied[k], vv) 692 } 693 return copied 694 } 695 696 // newRequest makes an http.Request from a client, adding common headers. 697 func newRequest(ctx context.Context, url string, reqBody io.Reader, contentType string) (*http.Request, error) { 698 req, err := http.NewRequest("POST", url, reqBody) 699 if err != nil { 700 return nil, err 701 } 702 req = req.WithContext(ctx) 703 if customHeader := getCustomHTTPReqHeaders(ctx); customHeader != nil { 704 req.Header = customHeader 705 } 706 req.Header.Set("Accept", contentType) 707 req.Header.Set("Content-Type", contentType) 708 req.Header.Set("Twirp-Version", "v8.1.0") 709 return req, nil 710 } 711 712 // JSON serialization for errors 713 type twerrJSON struct { 714 Code string `json:"code"` 715 Msg string `json:"msg"` 716 Meta map[string]string `json:"meta,omitempty"` 717 } 718 719 // marshalErrorToJSON returns JSON from a twirp.Error, that can be used as HTTP error response body. 720 // If serialization fails, it will use a descriptive Internal error instead. 721 func marshalErrorToJSON(twerr twirp.Error) []byte { 722 // make sure that msg is not too large 723 msg := twerr.Msg() 724 if len(msg) > 1e6 { 725 msg = msg[:1e6] 726 } 727 728 tj := twerrJSON{ 729 Code: string(twerr.Code()), 730 Msg: msg, 731 Meta: twerr.MetaMap(), 732 } 733 734 buf, err := json.Marshal(&tj) 735 if err != nil { 736 buf = []byte("{\"type\": \"" + twirp.Internal + "\", \"msg\": \"There was an error but it could not be serialized into JSON\"}") // fallback 737 } 738 739 return buf 740 } 741 742 // errorFromResponse builds a twirp.Error from a non-200 HTTP response. 743 // If the response has a valid serialized Twirp error, then it's returned. 744 // If not, the response status code is used to generate a similar twirp 745 // error. See twirpErrorFromIntermediary for more info on intermediary errors. 746 func errorFromResponse(resp *http.Response) twirp.Error { 747 statusCode := resp.StatusCode 748 statusText := http.StatusText(statusCode) 749 750 if isHTTPRedirect(statusCode) { 751 // Unexpected redirect: it must be an error from an intermediary. 752 // Twirp clients don't follow redirects automatically, Twirp only handles 753 // POST requests, redirects should only happen on GET and HEAD requests. 754 location := resp.Header.Get("Location") 755 msg := fmt.Sprintf("unexpected HTTP status code %d %q received, Location=%q", statusCode, statusText, location) 756 return twirpErrorFromIntermediary(statusCode, msg, location) 757 } 758 759 respBodyBytes, err := ioutil.ReadAll(resp.Body) 760 if err != nil { 761 return wrapInternal(err, "failed to read server error response body") 762 } 763 764 var tj twerrJSON 765 dec := json.NewDecoder(bytes.NewReader(respBodyBytes)) 766 dec.DisallowUnknownFields() 767 if err := dec.Decode(&tj); err != nil || tj.Code == "" { 768 // Invalid JSON response; it must be an error from an intermediary. 769 msg := fmt.Sprintf("Error from intermediary with HTTP status code %d %q", statusCode, statusText) 770 return twirpErrorFromIntermediary(statusCode, msg, string(respBodyBytes)) 771 } 772 773 errorCode := twirp.ErrorCode(tj.Code) 774 if !twirp.IsValidErrorCode(errorCode) { 775 msg := "invalid type returned from server error response: " + tj.Code 776 return twirp.InternalError(msg).WithMeta("body", string(respBodyBytes)) 777 } 778 779 twerr := twirp.NewError(errorCode, tj.Msg) 780 for k, v := range tj.Meta { 781 twerr = twerr.WithMeta(k, v) 782 } 783 return twerr 784 } 785 786 // twirpErrorFromIntermediary maps HTTP errors from non-twirp sources to twirp errors. 787 // The mapping is similar to gRPC: https://github.com/grpc/grpc/blob/master/doc/http-grpc-status-mapping.md. 788 // Returned twirp Errors have some additional metadata for inspection. 789 func twirpErrorFromIntermediary(status int, msg string, bodyOrLocation string) twirp.Error { 790 var code twirp.ErrorCode 791 if isHTTPRedirect(status) { // 3xx 792 code = twirp.Internal 793 } else { 794 switch status { 795 case 400: // Bad Request 796 code = twirp.Internal 797 case 401: // Unauthorized 798 code = twirp.Unauthenticated 799 case 403: // Forbidden 800 code = twirp.PermissionDenied 801 case 404: // Not Found 802 code = twirp.BadRoute 803 case 429: // Too Many Requests 804 code = twirp.ResourceExhausted 805 case 502, 503, 504: // Bad Gateway, Service Unavailable, Gateway Timeout 806 code = twirp.Unavailable 807 default: // All other codes 808 code = twirp.Unknown 809 } 810 } 811 812 twerr := twirp.NewError(code, msg) 813 twerr = twerr.WithMeta("http_error_from_intermediary", "true") // to easily know if this error was from intermediary 814 twerr = twerr.WithMeta("status_code", strconv.Itoa(status)) 815 if isHTTPRedirect(status) { 816 twerr = twerr.WithMeta("location", bodyOrLocation) 817 } else { 818 twerr = twerr.WithMeta("body", bodyOrLocation) 819 } 820 return twerr 821 } 822 823 func isHTTPRedirect(status int) bool { 824 return status >= 300 && status <= 399 825 } 826 827 // wrapInternal wraps an error with a prefix as an Internal error. 828 // The original error cause is accessible by github.com/pkg/errors.Cause. 829 func wrapInternal(err error, prefix string) twirp.Error { 830 return twirp.InternalErrorWith(&wrappedError{prefix: prefix, cause: err}) 831 } 832 833 type wrappedError struct { 834 prefix string 835 cause error 836 } 837 838 func (e *wrappedError) Error() string { return e.prefix + ": " + e.cause.Error() } 839 func (e *wrappedError) Unwrap() error { return e.cause } // for go1.13 + errors.Is/As 840 func (e *wrappedError) Cause() error { return e.cause } // for github.com/pkg/errors 841 842 // ensurePanicResponses makes sure that rpc methods causing a panic still result in a Twirp Internal 843 // error response (status 500), and error hooks are properly called with the panic wrapped as an error. 844 // The panic is re-raised so it can be handled normally with middleware. 845 func ensurePanicResponses(ctx context.Context, resp http.ResponseWriter, hooks *twirp.ServerHooks) { 846 if r := recover(); r != nil { 847 // Wrap the panic as an error so it can be passed to error hooks. 848 // The original error is accessible from error hooks, but not visible in the response. 849 err := errFromPanic(r) 850 twerr := &internalWithCause{msg: "Internal service panic", cause: err} 851 // Actually write the error 852 writeError(ctx, resp, twerr, hooks) 853 // If possible, flush the error to the wire. 854 f, ok := resp.(http.Flusher) 855 if ok { 856 f.Flush() 857 } 858 859 panic(r) 860 } 861 } 862 863 // errFromPanic returns the typed error if the recovered panic is an error, otherwise formats as error. 864 func errFromPanic(p interface{}) error { 865 if err, ok := p.(error); ok { 866 return err 867 } 868 return fmt.Errorf("panic: %v", p) 869 } 870 871 // internalWithCause is a Twirp Internal error wrapping an original error cause, 872 // but the original error message is not exposed on Msg(). The original error 873 // can be checked with go1.13+ errors.Is/As, and also by (github.com/pkg/errors).Unwrap 874 type internalWithCause struct { 875 msg string 876 cause error 877 } 878 879 func (e *internalWithCause) Unwrap() error { return e.cause } // for go1.13 + errors.Is/As 880 func (e *internalWithCause) Cause() error { return e.cause } // for github.com/pkg/errors 881 func (e *internalWithCause) Error() string { return e.msg + ": " + e.cause.Error() } 882 func (e *internalWithCause) Code() twirp.ErrorCode { return twirp.Internal } 883 func (e *internalWithCause) Msg() string { return e.msg } 884 func (e *internalWithCause) Meta(key string) string { return "" } 885 func (e *internalWithCause) MetaMap() map[string]string { return nil } 886 func (e *internalWithCause) WithMeta(key string, val string) twirp.Error { return e } 887 888 // malformedRequestError is used when the twirp server cannot unmarshal a request 889 func malformedRequestError(msg string) twirp.Error { 890 return twirp.NewError(twirp.Malformed, msg) 891 } 892 893 // badRouteError is used when the twirp server cannot route a request 894 func badRouteError(msg string, method, url string) twirp.Error { 895 err := twirp.NewError(twirp.BadRoute, msg) 896 err = err.WithMeta("twirp_invalid_route", method+" "+url) 897 return err 898 } 899 900 // withoutRedirects makes sure that the POST request can not be redirected. 901 // The standard library will, by default, redirect requests (including POSTs) if it gets a 302 or 902 // 303 response, and also 301s in go1.8. It redirects by making a second request, changing the 903 // method to GET and removing the body. This produces very confusing error messages, so instead we 904 // set a redirect policy that always errors. This stops Go from executing the redirect. 905 // 906 // We have to be a little careful in case the user-provided http.Client has its own CheckRedirect 907 // policy - if so, we'll run through that policy first. 908 // 909 // Because this requires modifying the http.Client, we make a new copy of the client and return it. 910 func withoutRedirects(in *http.Client) *http.Client { 911 copy := *in 912 copy.CheckRedirect = func(req *http.Request, via []*http.Request) error { 913 if in.CheckRedirect != nil { 914 // Run the input's redirect if it exists, in case it has side effects, but ignore any error it 915 // returns, since we want to use ErrUseLastResponse. 916 err := in.CheckRedirect(req, via) 917 _ = err // Silly, but this makes sure generated code passes errcheck -blank, which some people use. 918 } 919 return http.ErrUseLastResponse 920 } 921 return © 922 } 923 924 // doProtobufRequest makes a Protobuf request to the remote Twirp service. 925 func doProtobufRequest(ctx context.Context, client HTTPClient, hooks *twirp.ClientHooks, url string, in, out proto.Message) (_ context.Context, err error) { 926 reqBodyBytes, err := proto.Marshal(in) 927 if err != nil { 928 return ctx, wrapInternal(err, "failed to marshal proto request") 929 } 930 reqBody := bytes.NewBuffer(reqBodyBytes) 931 if err = ctx.Err(); err != nil { 932 return ctx, wrapInternal(err, "aborted because context was done") 933 } 934 935 req, err := newRequest(ctx, url, reqBody, "application/protobuf") 936 if err != nil { 937 return ctx, wrapInternal(err, "could not build request") 938 } 939 ctx, err = callClientRequestPrepared(ctx, hooks, req) 940 if err != nil { 941 return ctx, err 942 } 943 944 req = req.WithContext(ctx) 945 resp, err := client.Do(req) 946 if err != nil { 947 return ctx, wrapInternal(err, "failed to do request") 948 } 949 950 defer func() { 951 cerr := resp.Body.Close() 952 if err == nil && cerr != nil { 953 err = wrapInternal(cerr, "failed to close response body") 954 } 955 }() 956 957 if err = ctx.Err(); err != nil { 958 return ctx, wrapInternal(err, "aborted because context was done") 959 } 960 961 if resp.StatusCode != 200 { 962 return ctx, errorFromResponse(resp) 963 } 964 965 respBodyBytes, err := ioutil.ReadAll(resp.Body) 966 if err != nil { 967 return ctx, wrapInternal(err, "failed to read response body") 968 } 969 if err = ctx.Err(); err != nil { 970 return ctx, wrapInternal(err, "aborted because context was done") 971 } 972 973 if err = proto.Unmarshal(respBodyBytes, out); err != nil { 974 return ctx, wrapInternal(err, "failed to unmarshal proto response") 975 } 976 return ctx, nil 977 } 978 979 // doJSONRequest makes a JSON request to the remote Twirp service. 980 func doJSONRequest(ctx context.Context, client HTTPClient, hooks *twirp.ClientHooks, url string, in, out proto.Message) (_ context.Context, err error) { 981 marshaler := &protojson.MarshalOptions{UseProtoNames: true} 982 reqBytes, err := marshaler.Marshal(in) 983 if err != nil { 984 return ctx, wrapInternal(err, "failed to marshal json request") 985 } 986 if err = ctx.Err(); err != nil { 987 return ctx, wrapInternal(err, "aborted because context was done") 988 } 989 990 req, err := newRequest(ctx, url, bytes.NewReader(reqBytes), "application/json") 991 if err != nil { 992 return ctx, wrapInternal(err, "could not build request") 993 } 994 ctx, err = callClientRequestPrepared(ctx, hooks, req) 995 if err != nil { 996 return ctx, err 997 } 998 999 req = req.WithContext(ctx) 1000 resp, err := client.Do(req) 1001 if err != nil { 1002 return ctx, wrapInternal(err, "failed to do request") 1003 } 1004 1005 defer func() { 1006 cerr := resp.Body.Close() 1007 if err == nil && cerr != nil { 1008 err = wrapInternal(cerr, "failed to close response body") 1009 } 1010 }() 1011 1012 if err = ctx.Err(); err != nil { 1013 return ctx, wrapInternal(err, "aborted because context was done") 1014 } 1015 1016 if resp.StatusCode != 200 { 1017 return ctx, errorFromResponse(resp) 1018 } 1019 1020 d := json.NewDecoder(resp.Body) 1021 rawRespBody := json.RawMessage{} 1022 if err := d.Decode(&rawRespBody); err != nil { 1023 return ctx, wrapInternal(err, "failed to unmarshal json response") 1024 } 1025 unmarshaler := protojson.UnmarshalOptions{DiscardUnknown: true} 1026 if err = unmarshaler.Unmarshal(rawRespBody, out); err != nil { 1027 return ctx, wrapInternal(err, "failed to unmarshal json response") 1028 } 1029 if err = ctx.Err(); err != nil { 1030 return ctx, wrapInternal(err, "aborted because context was done") 1031 } 1032 return ctx, nil 1033 } 1034 1035 // Call twirp.ServerHooks.RequestReceived if the hook is available 1036 func callRequestReceived(ctx context.Context, h *twirp.ServerHooks) (context.Context, error) { 1037 if h == nil || h.RequestReceived == nil { 1038 return ctx, nil 1039 } 1040 return h.RequestReceived(ctx) 1041 } 1042 1043 // Call twirp.ServerHooks.RequestRouted if the hook is available 1044 func callRequestRouted(ctx context.Context, h *twirp.ServerHooks) (context.Context, error) { 1045 if h == nil || h.RequestRouted == nil { 1046 return ctx, nil 1047 } 1048 return h.RequestRouted(ctx) 1049 } 1050 1051 // Call twirp.ServerHooks.ResponsePrepared if the hook is available 1052 func callResponsePrepared(ctx context.Context, h *twirp.ServerHooks) context.Context { 1053 if h == nil || h.ResponsePrepared == nil { 1054 return ctx 1055 } 1056 return h.ResponsePrepared(ctx) 1057 } 1058 1059 // Call twirp.ServerHooks.ResponseSent if the hook is available 1060 func callResponseSent(ctx context.Context, h *twirp.ServerHooks) { 1061 if h == nil || h.ResponseSent == nil { 1062 return 1063 } 1064 h.ResponseSent(ctx) 1065 } 1066 1067 // Call twirp.ServerHooks.Error if the hook is available 1068 func callError(ctx context.Context, h *twirp.ServerHooks, err twirp.Error) context.Context { 1069 if h == nil || h.Error == nil { 1070 return ctx 1071 } 1072 return h.Error(ctx, err) 1073 } 1074 1075 func callClientResponseReceived(ctx context.Context, h *twirp.ClientHooks) { 1076 if h == nil || h.ResponseReceived == nil { 1077 return 1078 } 1079 h.ResponseReceived(ctx) 1080 } 1081 1082 func callClientRequestPrepared(ctx context.Context, h *twirp.ClientHooks, req *http.Request) (context.Context, error) { 1083 if h == nil || h.RequestPrepared == nil { 1084 return ctx, nil 1085 } 1086 return h.RequestPrepared(ctx, req) 1087 } 1088 1089 func callClientError(ctx context.Context, h *twirp.ClientHooks, err twirp.Error) { 1090 if h == nil || h.Error == nil { 1091 return 1092 } 1093 h.Error(ctx, err) 1094 } 1095 1096 var twirpFileDescriptor0 = []byte{ 1097 // 665 bytes of a gzipped FileDescriptorProto 1098 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x54, 0xdd, 0x6e, 0xda, 0x4a, 1099 0x10, 0x16, 0x10, 0xc0, 0x0c, 0x47, 0x27, 0x64, 0x75, 0x4e, 0xe4, 0x90, 0xa6, 0x45, 0x5c, 0x54, 1100 0xa8, 0x17, 0xd0, 0x90, 0x56, 0xfd, 0xbb, 0x6a, 0x93, 0xb4, 0x8a, 0xd4, 0x2a, 0xd1, 0x12, 0xf5, 1101 0xa2, 0x37, 0xee, 0xb2, 0x9e, 0xd0, 0x55, 0x8c, 0xed, 0xec, 0xac, 0x91, 0x78, 0x95, 0xbe, 0x57, 1102 0x9f, 0xa0, 0x2f, 0x52, 0x79, 0xbd, 0x46, 0x81, 0x24, 0xbd, 0xb2, 0x67, 0xe6, 0x9b, 0x6f, 0xbe, 1103 0xdd, 0xfd, 0x34, 0xb0, 0xa7, 0x53, 0x39, 0x22, 0x29, 0xe2, 0x18, 0xf5, 0x88, 0x50, 0x2f, 0x94, 1104 0xc4, 0x61, 0xaa, 0x13, 0x93, 0xb0, 0x8e, 0xd1, 0x6a, 0xb1, 0x1c, 0xba, 0xe2, 0x70, 0x71, 0xd8, 1105 0xf5, 0x73, 0xb0, 0x4c, 0xe6, 0xf3, 0x24, 0x5e, 0xc7, 0xf6, 0x7f, 0x56, 0xa0, 0x3d, 0x91, 0x22, 1106 0xe6, 0x78, 0x93, 0x21, 0x19, 0xb6, 0x0b, 0x0d, 0x23, 0xf4, 0x0c, 0x8d, 0x5f, 0xe9, 0x55, 0x06, 1107 0x2d, 0xee, 0x22, 0xf6, 0x04, 0xda, 0x42, 0x1b, 0x75, 0x25, 0xa4, 0x09, 0x54, 0xe8, 0x57, 0x6d, 1108 0x11, 0xca, 0xd4, 0x59, 0xc8, 0xf6, 0xc0, 0x9b, 0x46, 0xc9, 0x34, 0x50, 0x21, 0xf9, 0xb5, 0x5e, 1109 0x6d, 0xd0, 0xe2, 0xcd, 0x3c, 0x3e, 0x0b, 0x89, 0xbd, 0x82, 0x66, 0x92, 0x1a, 0x95, 0xc4, 0xe4, 1110 0x6f, 0xf5, 0x2a, 0x83, 0xf6, 0xf8, 0x60, 0xb8, 0xa9, 0x70, 0x98, 0x6b, 0x38, 0x2f, 0x40, 0xbc, 1111 0x44, 0xf7, 0x7b, 0xe0, 0x7d, 0x56, 0x12, 0x63, 0x42, 0x62, 0xff, 0x41, 0x3d, 0x16, 0x73, 0x24, 1112 0xbf, 0x62, 0xc9, 0x8b, 0xa0, 0xff, 0xbb, 0x5a, 0xc8, 0x77, 0xad, 0x6c, 0x1f, 0x5a, 0x8b, 0x2c, 1113 0x8a, 0x03, 0xb3, 0x4c, 0xd1, 0x21, 0xbd, 0x3c, 0x71, 0xb9, 0x4c, 0x91, 0x75, 0xc1, 0x73, 0x13, 1114 0xc9, 0xaf, 0x16, 0xb5, 0x32, 0x66, 0xcf, 0x60, 0x27, 0x52, 0x64, 0x02, 0x11, 0x45, 0x41, 0x2a, 1115 0xe4, 0xb5, 0x98, 0x61, 0x7e, 0x8e, 0xca, 0xc0, 0xe3, 0xdb, 0x79, 0xe1, 0x7d, 0x14, 0x5d, 0xb8, 1116 0x34, 0x93, 0xc0, 0xa2, 0x42, 0x56, 0x20, 0x85, 0xc1, 0x59, 0xa2, 0x15, 0xe6, 0x47, 0xab, 0x0d, 1117 0xda, 0xe3, 0x17, 0x7f, 0x3d, 0xda, 0xd0, 0x1d, 0xe7, 0x78, 0xd5, 0x76, 0x1a, 0x1b, 0xbd, 0xe4, 1118 0x3b, 0xd1, 0x66, 0x9e, 0x0d, 0xa0, 0xa3, 0x62, 0x19, 0x65, 0x21, 0x06, 0x21, 0x2e, 0x82, 0x10, 1119 0x53, 0xf2, 0xeb, 0x56, 0xcf, 0xbf, 0x2e, 0x7f, 0x82, 0x8b, 0x13, 0x4c, 0xa9, 0xfb, 0x1d, 0x76, 1120 0xef, 0xa7, 0x65, 0x1d, 0xa8, 0x5d, 0xe3, 0xd2, 0xbd, 0x64, 0xfe, 0xcb, 0x9e, 0x43, 0x7d, 0x21, 1121 0xa2, 0x0c, 0xed, 0x03, 0xb6, 0xc7, 0xdd, 0xbb, 0x6a, 0xcb, 0x0b, 0xe7, 0x05, 0xf0, 0x6d, 0xf5, 1122 0x75, 0xa5, 0x1f, 0xc2, 0x3f, 0x85, 0x47, 0x28, 0x4d, 0x62, 0x42, 0xd6, 0x83, 0x6a, 0x42, 0x96, 1123 0xb6, 0x3d, 0xee, 0x38, 0x8a, 0xc2, 0x5d, 0xc3, 0xf3, 0x09, 0xaf, 0x26, 0xc4, 0xc6, 0xd0, 0xd4, 1124 0x48, 0x59, 0x64, 0x0a, 0x33, 0xb4, 0xc7, 0xfe, 0xdd, 0x49, 0xdc, 0x02, 0x78, 0x09, 0xec, 0xff, 1125 0xaa, 0x41, 0xa3, 0xc8, 0x3d, 0xe8, 0xc2, 0x53, 0xd8, 0xce, 0x5f, 0x13, 0xb5, 0x98, 0xaa, 0x48, 1126 0x99, 0xfc, 0xda, 0xab, 0x96, 0x7e, 0x7f, 0x5d, 0xc5, 0xd7, 0x5b, 0xa0, 0x25, 0xdf, 0xec, 0x61, 1127 0x97, 0xb0, 0x33, 0x57, 0x24, 0x93, 0xf8, 0x4a, 0xcd, 0x32, 0x2d, 0x4a, 0x6b, 0xe6, 0x44, 0x4f, 1128 0xd7, 0x89, 0x4e, 0xd0, 0xa0, 0x34, 0x18, 0x7e, 0xd9, 0x80, 0xf3, 0xbb, 0x04, 0xb9, 0x43, 0x65, 1129 0x24, 0x88, 0xfc, 0x86, 0xd5, 0x5c, 0x04, 0x8c, 0xc1, 0x96, 0x35, 0x63, 0xcd, 0x26, 0xed, 0x3f, 1130 0x3b, 0x04, 0x6f, 0xe5, 0xb1, 0xba, 0x1d, 0xfb, 0xff, 0xfa, 0x58, 0x67, 0x35, 0xbe, 0x82, 0xb1, 1131 0x4f, 0xd0, 0x91, 0x19, 0x99, 0x64, 0x1e, 0x68, 0xa4, 0x24, 0xd3, 0x12, 0xc9, 0x6f, 0xda, 0xd6, 1132 0x47, 0xeb, 0xad, 0xc7, 0x16, 0xc5, 0x1d, 0x88, 0x6f, 0xcb, 0xb5, 0x98, 0xd8, 0x4b, 0x68, 0x12, 1133 0x4a, 0x8d, 0x86, 0x7c, 0xef, 0xbe, 0xab, 0x9b, 0xd8, 0xe2, 0x47, 0x15, 0x87, 0x2a, 0x9e, 0xf1, 1134 0x12, 0xcb, 0xde, 0x80, 0xe7, 0x3c, 0x4a, 0x7e, 0xcb, 0xf6, 0x1d, 0xdc, 0x7f, 0x53, 0xce, 0x3f, 1135 0x7c, 0x05, 0x1f, 0x5f, 0x40, 0x73, 0x52, 0xbc, 0x3a, 0x3b, 0x85, 0xad, 0xfc, 0x97, 0x3d, 0xb0, 1136 0x00, 0xdc, 0x12, 0xea, 0x3e, 0x7e, 0xa8, 0x5c, 0xf8, 0xef, 0xc3, 0xd1, 0xb7, 0xc3, 0x99, 0x32, 1137 0x3f, 0xb2, 0x69, 0x3e, 0x7c, 0x24, 0x6e, 0x32, 0x41, 0x28, 0x33, 0xad, 0xcc, 0x72, 0x64, 0x1b, 1138 0x47, 0xb7, 0x76, 0xe3, 0x3b, 0xf7, 0x9d, 0x36, 0xec, 0xc2, 0x3b, 0xfa, 0x13, 0x00, 0x00, 0xff, 1139 0xff, 0x67, 0xa9, 0x8c, 0x3c, 0x39, 0x05, 0x00, 0x00, 1140 }