github.com/argoproj/argo-cd/v3@v3.2.1/ui/src/app/shared/services/requests.ts (about)

     1  import * as path from 'path';
     2  import * as agent from 'superagent';
     3  
     4  import {BehaviorSubject, Observable, Observer} from 'rxjs';
     5  import {filter} from 'rxjs/operators';
     6  
     7  type Callback = (data: any) => void;
     8  
     9  declare class EventSource {
    10      public onopen: Callback;
    11      public onmessage: Callback;
    12      public onerror: Callback;
    13      public readyState: number;
    14      constructor(url: string);
    15      public close(): void;
    16  }
    17  
    18  enum ReadyState {
    19      CONNECTING = 0,
    20      OPEN = 1,
    21      CLOSED = 2,
    22      DONE = 4
    23  }
    24  
    25  let baseHRef = '/';
    26  
    27  const onError = new BehaviorSubject<agent.ResponseError>(null);
    28  
    29  function toAbsURL(val: string): string {
    30      return path.join(baseHRef, val);
    31  }
    32  
    33  function apiRoot(): string {
    34      return toAbsURL('/api/v1');
    35  }
    36  
    37  function initHandlers(req: agent.Request) {
    38      req.on('error', err => onError.next(err));
    39      return req;
    40  }
    41  
    42  export default {
    43      setBaseHRef(val: string) {
    44          baseHRef = val;
    45      },
    46      agent,
    47      toAbsURL,
    48      onError: onError.asObservable().pipe(filter(err => err != null)),
    49      get(url: string) {
    50          return initHandlers(agent.get(`${apiRoot()}${url}`));
    51      },
    52  
    53      post(url: string) {
    54          return initHandlers(agent.post(`${apiRoot()}${url}`)).set('Content-Type', 'application/json');
    55      },
    56  
    57      put(url: string) {
    58          return initHandlers(agent.put(`${apiRoot()}${url}`)).set('Content-Type', 'application/json');
    59      },
    60  
    61      patch(url: string) {
    62          return initHandlers(agent.patch(`${apiRoot()}${url}`)).set('Content-Type', 'application/json');
    63      },
    64  
    65      delete(url: string) {
    66          return initHandlers(agent.del(`${apiRoot()}${url}`)).set('Content-Type', 'application/json');
    67      },
    68  
    69      loadEventSource(url: string): Observable<string> {
    70          return Observable.create((observer: Observer<any>) => {
    71              const fullUrl = `${apiRoot()}${url}`;
    72  
    73              const abortController = new AbortController();
    74  
    75              // If there is an error, show it beforehand
    76              fetch(fullUrl, {signal: abortController.signal})
    77                  .then(response => {
    78                      if (!response.ok) {
    79                          return response.text().then(text => {
    80                              observer.error({status: response.status, statusText: response.statusText, body: text});
    81                          });
    82                      }
    83                  })
    84                  .catch(err => {
    85                      if (err.name === 'AbortError') {
    86                          return;
    87                      }
    88                      observer.error(err);
    89                  });
    90  
    91              let eventSource = new EventSource(fullUrl);
    92              eventSource.onmessage = msg => observer.next(msg.data);
    93              eventSource.onerror = e => () => {
    94                  observer.error(e);
    95                  onError.next(e);
    96              };
    97  
    98              // EventSource does not provide easy way to get notification when connection closed.
    99              // check readyState periodically instead.
   100              const interval = setInterval(() => {
   101                  if (eventSource && eventSource.readyState === ReadyState.CLOSED) {
   102                      observer.error('connection got closed unexpectedly');
   103                  }
   104              }, 500);
   105              return () => {
   106                  clearInterval(interval);
   107                  eventSource.close();
   108                  abortController.abort();
   109                  eventSource = null;
   110              };
   111          });
   112      }
   113  };