Skip to content
Snippets Groups Projects
Select Git revision
  • 21028a702c40cd63b5e2c75303a9cd20169347b2
  • master default
2 results

index.ts

Blame
  • index.ts 4.16 KiB
    import URL from 'url';
    import got from '../got';
    
    interface OutgoingHttpHeaders {
      [header: string]: number | string | string[] | undefined;
    }
    
    export interface HttpOptions {
      body?: any;
      auth?: string;
      baseUrl?: string;
      headers?: OutgoingHttpHeaders;
      throwHttpErrors?: boolean;
      useCache?: boolean;
    }
    
    export interface HttpPostOptions extends HttpOptions {
      body: unknown;
    }
    
    export interface InternalHttpOptions extends HttpOptions {
      json?: boolean;
      method?: 'get' | 'post' | 'put' | 'patch' | 'delete' | 'head';
    }
    
    export interface HttpResponse<T = string> {
      body: T;
      headers: any;
    }
    
    export class Http<GetOptions = HttpOptions, PostOptions = HttpPostOptions> {
      constructor(private hostType: string, private options?: HttpOptions) {}
    
      protected async request<T>(
        requestUrl: string | URL,
        httpOptions?: InternalHttpOptions
      ): Promise<HttpResponse<T> | null> {
        let url = requestUrl.toString();
        if (httpOptions?.baseUrl) {
          url = URL.resolve(httpOptions.baseUrl, url);
        }
        // TODO: deep merge in order to merge headers
        const options: any = {
          method: 'get',
          ...this.options,
          hostType: this.hostType,
          ...httpOptions,
        };
        options.hooks = {
          beforeRedirect: [
            (opts: any): void => {
              // Check if request has been redirected to Amazon
              if (opts.search?.includes('X-Amz-Algorithm')) {
                // if there is no port in the redirect URL string, then delete it from the redirect options.
                // This can be evaluated for removal after upgrading to Got v10
                const portInUrl = opts.href.split('/')[2].split(':')[1];
                if (!portInUrl) {
                  // eslint-disable-next-line no-param-reassign
                  delete opts.port; // Redirect will instead use 80 or 443 for HTTP or HTTPS respectively
                }
    
                // registry is hosted on amazon, redirect url includes authentication.
                delete opts.headers.authorization; // eslint-disable-line no-param-reassign
                delete opts.auth; // eslint-disable-line no-param-reassign
              }
            },
          ],
        };
        options.headers = {
          ...options.headers,
          'user-agent':
            process.env.RENOVATE_USER_AGENT ||
            'https://github.com/renovatebot/renovate',
        };
        const res = await got(url, options);
        return { body: res.body, headers: res.headers };
      }
    
      get(url: string, options: HttpOptions = {}): Promise<HttpResponse> {
        return this.request<string>(url, options);
      }
    
      head(url: string, options: HttpOptions = {}): Promise<HttpResponse> {
        return this.request<string>(url, { ...options, method: 'head' });
      }
    
      private async requestJson<T = unknown>(
        url: string,
        options: InternalHttpOptions
      ): Promise<HttpResponse<T>> {
        const res = await this.request<T>(url, { ...options, json: true });
        const body = res.body;
        return { ...res, body };
      }
    
      async getJson<T = unknown>(
        url: string,
        options?: GetOptions
      ): Promise<HttpResponse<T>> {
        return this.requestJson<T>(url, { ...options });
      }
    
      async headJson<T = unknown>(
        url: string,
        options?: GetOptions
      ): Promise<HttpResponse<T>> {
        return this.requestJson<T>(url, { ...options, method: 'head' });
      }
    
      async postJson<T = unknown>(
        url: string,
        options?: PostOptions
      ): Promise<HttpResponse<T>> {
        return this.requestJson<T>(url, { ...options, method: 'post' });
      }
    
      async putJson<T = unknown>(
        url: string,
        options?: PostOptions
      ): Promise<HttpResponse<T>> {
        return this.requestJson<T>(url, { ...options, method: 'put' });
      }
    
      async patchJson<T = unknown>(
        url: string,
        options?: PostOptions
      ): Promise<HttpResponse<T>> {
        return this.requestJson<T>(url, { ...options, method: 'patch' });
      }
    
      async deleteJson<T = unknown>(
        url: string,
        options?: PostOptions
      ): Promise<HttpResponse<T>> {
        return this.requestJson<T>(url, { ...options, method: 'delete' });
      }
    
      stream(url: string, options?: HttpOptions): NodeJS.ReadableStream {
        const combinedOptions: any = {
          method: 'get',
          ...this.options,
          hostType: this.hostType,
          ...options,
        };
        return got.stream(url, combinedOptions);
      }
    }