(ctx context.Context, method, apiURL string, data []byte)
| 546 | } |
| 547 | |
| 548 | func (p *provider) doBotRequest(ctx context.Context, method, apiURL string, data []byte) ([]byte, error) { |
| 549 | const maxRetries = 3 |
| 550 | |
| 551 | for i := 0; i < maxRetries; i++ { |
| 552 | if ctx.Err() != nil { |
| 553 | return nil, ctx.Err() |
| 554 | } |
| 555 | |
| 556 | b, retry, err := func() ([]byte, bool, error) { |
| 557 | req, err := http.NewRequestWithContext(ctx, method, apiURL, bytes.NewReader(data)) |
| 558 | if err != nil { |
| 559 | return nil, false, errors.Wrapf(err, "failed to construct request") |
| 560 | } |
| 561 | |
| 562 | req.Header.Set("Authorization", "Bearer "+p.botToken) |
| 563 | req.Header.Set("Content-Type", "application/json") |
| 564 | |
| 565 | resp, err := p.c.Do(req) |
| 566 | if err != nil { |
| 567 | return nil, false, errors.Wrapf(err, "request failed") |
| 568 | } |
| 569 | defer resp.Body.Close() |
| 570 | |
| 571 | respBody, err := io.ReadAll(resp.Body) |
| 572 | if err != nil { |
| 573 | return nil, false, errors.Wrapf(err, "failed to read response") |
| 574 | } |
| 575 | |
| 576 | if resp.StatusCode == http.StatusUnauthorized { |
| 577 | if err := p.refreshBotToken(ctx); err != nil { |
| 578 | return nil, false, errors.Wrapf(err, "failed to refresh token") |
| 579 | } |
| 580 | return nil, true, nil |
| 581 | } |
| 582 | |
| 583 | if resp.StatusCode < 200 || resp.StatusCode >= 300 { |
| 584 | return nil, false, errors.Errorf("request failed with status %d: %s", resp.StatusCode, string(respBody)) |
| 585 | } |
| 586 | |
| 587 | return respBody, false, nil |
| 588 | }() |
| 589 | |
| 590 | if err != nil { |
| 591 | return nil, err |
| 592 | } |
| 593 | if retry { |
| 594 | continue |
| 595 | } |
| 596 | return b, nil |
| 597 | } |
| 598 | |
| 599 | return nil, errors.Errorf("exceeded max retries for %s %s", method, apiURL) |
| 600 | } |
| 601 | |
| 602 | // Validate validates the Teams configuration by attempting to get a token and look up a user. |
| 603 | func Validate(ctx context.Context, tenantID, clientID, clientSecret, email string) error { |
no test coverage detected