diff --git a/clients/algoliasearch-client-javascript/client-search/apis.ts b/clients/algoliasearch-client-javascript/client-search/apis.ts index c69231a7b7..7ce8b4109e 100644 --- a/clients/algoliasearch-client-javascript/client-search/apis.ts +++ b/clients/algoliasearch-client-javascript/client-search/apis.ts @@ -4,6 +4,6 @@ import { SearchApi } from './searchApi'; export class searchClient extends SearchApi {} export * from '../utils/errors'; -export { EchoRequester } from '../utils/EchoRequester'; +export { EchoRequester } from '../utils/requester/EchoRequester'; export const APIS = [SearchApi]; diff --git a/clients/algoliasearch-client-javascript/client-search/searchApi.ts b/clients/algoliasearch-client-javascript/client-search/searchApi.ts index b643e903b3..d3ed1a7730 100644 --- a/clients/algoliasearch-client-javascript/client-search/searchApi.ts +++ b/clients/algoliasearch-client-javascript/client-search/searchApi.ts @@ -1,7 +1,7 @@ import { shuffle } from '../utils/helpers'; import { Transporter } from '../utils/Transporter'; import { Headers, Host, Request, RequestOptions } from '../utils/types'; -import { Requester } from '../utils/Requester'; +import { Requester } from '../utils/requester/Requester'; import { BatchObject } from '../model/batchObject'; import { BatchResponse } from '../model/batchResponse'; @@ -27,22 +27,11 @@ export class SearchApi { appId: new ApiKeyAuth('header', 'X-Algolia-Application-Id'), }; - constructor(appId: string, apiKey: string, requester?: Requester) { + constructor(appId: string, apiKey: string, options?: { requester?: Requester; hosts?: Host[] }) { this.setApiKey(SearchApiApiKeys.appId, appId); this.setApiKey(SearchApiApiKeys.apiKey, apiKey); this.transporter = new Transporter({ - hosts: ( - [ - { url: `${appId}-dsn.algolia.net`, accept: 'read', protocol: 'https' }, - { url: `${appId}.algolia.net`, accept: 'write', protocol: 'https' }, - ] as Host[] - ).concat( - shuffle([ - { url: `${appId}-1.algolianet.com`, accept: 'readWrite', protocol: 'https' }, - { url: `${appId}-2.algolianet.com`, accept: 'readWrite', protocol: 'https' }, - { url: `${appId}-3.algolianet.com`, accept: 'readWrite', protocol: 'https' }, - ]) - ), + hosts: options?.hosts ?? this.getDefaultHosts(appId, apiKey), baseHeaders: { 'content-type': 'application/x-www-form-urlencoded', }, @@ -52,10 +41,33 @@ export class SearchApi { read: 5, write: 30, }, - requester, + requester: options?.requester, }); } + public getDefaultHosts(appId: string, apiKey: string): Host[] { + return ( + [ + { url: `${appId}-dsn.algolia.net`, accept: 'read', protocol: 'https' }, + { url: `${appId}.algolia.net`, accept: 'write', protocol: 'https' }, + ] as Host[] + ).concat( + shuffle([ + { url: `${appId}-1.algolianet.com`, accept: 'readWrite', protocol: 'https' }, + { url: `${appId}-2.algolianet.com`, accept: 'readWrite', protocol: 'https' }, + { url: `${appId}-3.algolianet.com`, accept: 'readWrite', protocol: 'https' }, + ]) + ); + } + + public setRequest(requester: Requester): void { + this.transporter.setRequester(requester); + } + + public setHosts(hosts: Host[]): void { + this.transporter.setHosts(hosts); + } + public setApiKey(key: SearchApiApiKeys, value: string) { this.authentications[SearchApiApiKeys[key]].apiKey = value; } diff --git a/clients/algoliasearch-client-javascript/utils/EchoRequester.ts b/clients/algoliasearch-client-javascript/utils/EchoRequester.ts deleted file mode 100644 index 12c6cd1b25..0000000000 --- a/clients/algoliasearch-client-javascript/utils/EchoRequester.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { EndRequest, Response } from './types'; -import { Requester } from './Requester'; - -export class EchoRequester extends Requester { - async send(request: EndRequest): Promise { - return { - content: JSON.stringify(request), - isTimedOut: false, - status: 200, - }; - } -} diff --git a/clients/algoliasearch-client-javascript/utils/Requester.ts b/clients/algoliasearch-client-javascript/utils/Requester.ts deleted file mode 100644 index 6735a27a34..0000000000 --- a/clients/algoliasearch-client-javascript/utils/Requester.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { EndRequest, Response } from './types'; -export abstract class Requester { - abstract send(request: EndRequest): Promise; -} diff --git a/clients/algoliasearch-client-javascript/utils/Transporter.ts b/clients/algoliasearch-client-javascript/utils/Transporter.ts index 4248c636a3..f7fccad3ff 100644 --- a/clients/algoliasearch-client-javascript/utils/Transporter.ts +++ b/clients/algoliasearch-client-javascript/utils/Transporter.ts @@ -7,8 +7,8 @@ import type { Response, EndRequest, } from './types'; -import { MemoryCache } from './MemoryCache'; -import type { Cache } from './Cache'; +import { MemoryCache } from './cache/MemoryCache'; +import type { Cache } from './cache/Cache'; import { StatefulHost } from './StatefulHost'; import { deserializeFailure, @@ -20,8 +20,8 @@ import { import { Headers } from './types'; import { RetryError } from './errors'; import * as responseUtils from './Response'; -import { Requester } from './Requester'; -import { HttpRequester } from './HttpRequester'; +import { Requester } from './requester/Requester'; +import { HttpRequester } from './requester/HttpRequester'; export class Transporter { private hosts: Host[]; @@ -52,6 +52,15 @@ export class Transporter { this.requester = requester; } + public setHosts(hosts: Host[]): void { + this.hosts = hosts; + this.hostsCache.clear(); + } + + public setRequester(requester: Requester): void { + this.requester = requester; + } + async createRetryableOptions(compatibleHosts: Host[]): Promise<{ hosts: Host[]; getTimeout: (retryCount: number, timeout: number) => number; @@ -169,7 +178,7 @@ export class Transporter { return stackFrame; }; - const response = await this.requester.send(payload); + const response = await this.requester.send(payload, request); if (responseUtils.isRetryable(response)) { pushToStackTrace(response); diff --git a/clients/algoliasearch-client-javascript/utils/Cache.ts b/clients/algoliasearch-client-javascript/utils/cache/Cache.ts similarity index 100% rename from clients/algoliasearch-client-javascript/utils/Cache.ts rename to clients/algoliasearch-client-javascript/utils/cache/Cache.ts diff --git a/clients/algoliasearch-client-javascript/utils/MemoryCache.ts b/clients/algoliasearch-client-javascript/utils/cache/MemoryCache.ts similarity index 100% rename from clients/algoliasearch-client-javascript/utils/MemoryCache.ts rename to clients/algoliasearch-client-javascript/utils/cache/MemoryCache.ts diff --git a/clients/algoliasearch-client-javascript/utils/requester/EchoRequester.ts b/clients/algoliasearch-client-javascript/utils/requester/EchoRequester.ts new file mode 100644 index 0000000000..59db014da0 --- /dev/null +++ b/clients/algoliasearch-client-javascript/utils/requester/EchoRequester.ts @@ -0,0 +1,16 @@ +import { EndRequest, Request, Response } from '../types'; +import { Requester } from './Requester'; + +export class EchoRequester extends Requester { + constructor(private status = 200) { + super(); + } + + async send(request: EndRequest, originalRequest: Request): Promise { + return { + content: JSON.stringify(originalRequest), + isTimedOut: false, + status: this.status, + }; + } +} diff --git a/clients/utils/javascript/HttpRequester.ts b/clients/algoliasearch-client-javascript/utils/requester/HttpRequester.ts similarity index 98% rename from clients/utils/javascript/HttpRequester.ts rename to clients/algoliasearch-client-javascript/utils/requester/HttpRequester.ts index 7105360a44..c99ae70842 100644 --- a/clients/utils/javascript/HttpRequester.ts +++ b/clients/algoliasearch-client-javascript/utils/requester/HttpRequester.ts @@ -1,4 +1,4 @@ -import { EndRequest, Response } from './types'; +import { EndRequest, Response } from '../types'; import * as http from 'http'; import * as https from 'https'; import { Requester } from './Requester'; diff --git a/clients/algoliasearch-client-javascript/utils/requester/Requester.ts b/clients/algoliasearch-client-javascript/utils/requester/Requester.ts new file mode 100644 index 0000000000..c26e08205d --- /dev/null +++ b/clients/algoliasearch-client-javascript/utils/requester/Requester.ts @@ -0,0 +1,4 @@ +import { EndRequest, Request, Response } from '../types'; +export abstract class Requester { + abstract send(request: EndRequest, originalRequest: Request): Promise; +} diff --git a/clients/utils/javascript/EchoRequester.ts b/clients/utils/javascript/EchoRequester.ts deleted file mode 100644 index 12c6cd1b25..0000000000 --- a/clients/utils/javascript/EchoRequester.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { EndRequest, Response } from './types'; -import { Requester } from './Requester'; - -export class EchoRequester extends Requester { - async send(request: EndRequest): Promise { - return { - content: JSON.stringify(request), - isTimedOut: false, - status: 200, - }; - } -} diff --git a/clients/utils/javascript/Requester.ts b/clients/utils/javascript/Requester.ts deleted file mode 100644 index 6735a27a34..0000000000 --- a/clients/utils/javascript/Requester.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { EndRequest, Response } from './types'; -export abstract class Requester { - abstract send(request: EndRequest): Promise; -} diff --git a/clients/utils/javascript/Transporter.ts b/clients/utils/javascript/Transporter.ts index 4248c636a3..f7fccad3ff 100644 --- a/clients/utils/javascript/Transporter.ts +++ b/clients/utils/javascript/Transporter.ts @@ -7,8 +7,8 @@ import type { Response, EndRequest, } from './types'; -import { MemoryCache } from './MemoryCache'; -import type { Cache } from './Cache'; +import { MemoryCache } from './cache/MemoryCache'; +import type { Cache } from './cache/Cache'; import { StatefulHost } from './StatefulHost'; import { deserializeFailure, @@ -20,8 +20,8 @@ import { import { Headers } from './types'; import { RetryError } from './errors'; import * as responseUtils from './Response'; -import { Requester } from './Requester'; -import { HttpRequester } from './HttpRequester'; +import { Requester } from './requester/Requester'; +import { HttpRequester } from './requester/HttpRequester'; export class Transporter { private hosts: Host[]; @@ -52,6 +52,15 @@ export class Transporter { this.requester = requester; } + public setHosts(hosts: Host[]): void { + this.hosts = hosts; + this.hostsCache.clear(); + } + + public setRequester(requester: Requester): void { + this.requester = requester; + } + async createRetryableOptions(compatibleHosts: Host[]): Promise<{ hosts: Host[]; getTimeout: (retryCount: number, timeout: number) => number; @@ -169,7 +178,7 @@ export class Transporter { return stackFrame; }; - const response = await this.requester.send(payload); + const response = await this.requester.send(payload, request); if (responseUtils.isRetryable(response)) { pushToStackTrace(response); diff --git a/clients/utils/javascript/Cache.ts b/clients/utils/javascript/cache/Cache.ts similarity index 100% rename from clients/utils/javascript/Cache.ts rename to clients/utils/javascript/cache/Cache.ts diff --git a/clients/utils/javascript/MemoryCache.ts b/clients/utils/javascript/cache/MemoryCache.ts similarity index 100% rename from clients/utils/javascript/MemoryCache.ts rename to clients/utils/javascript/cache/MemoryCache.ts diff --git a/clients/utils/javascript/requester/EchoRequester.ts b/clients/utils/javascript/requester/EchoRequester.ts new file mode 100644 index 0000000000..59db014da0 --- /dev/null +++ b/clients/utils/javascript/requester/EchoRequester.ts @@ -0,0 +1,16 @@ +import { EndRequest, Request, Response } from '../types'; +import { Requester } from './Requester'; + +export class EchoRequester extends Requester { + constructor(private status = 200) { + super(); + } + + async send(request: EndRequest, originalRequest: Request): Promise { + return { + content: JSON.stringify(originalRequest), + isTimedOut: false, + status: this.status, + }; + } +} diff --git a/clients/algoliasearch-client-javascript/utils/HttpRequester.ts b/clients/utils/javascript/requester/HttpRequester.ts similarity index 98% rename from clients/algoliasearch-client-javascript/utils/HttpRequester.ts rename to clients/utils/javascript/requester/HttpRequester.ts index 7105360a44..c99ae70842 100644 --- a/clients/algoliasearch-client-javascript/utils/HttpRequester.ts +++ b/clients/utils/javascript/requester/HttpRequester.ts @@ -1,4 +1,4 @@ -import { EndRequest, Response } from './types'; +import { EndRequest, Response } from '../types'; import * as http from 'http'; import * as https from 'https'; import { Requester } from './Requester'; diff --git a/clients/utils/javascript/requester/Requester.ts b/clients/utils/javascript/requester/Requester.ts new file mode 100644 index 0000000000..c26e08205d --- /dev/null +++ b/clients/utils/javascript/requester/Requester.ts @@ -0,0 +1,4 @@ +import { EndRequest, Request, Response } from '../types'; +export abstract class Requester { + abstract send(request: EndRequest, originalRequest: Request): Promise; +} diff --git a/templates/javascript/api-all.mustache b/templates/javascript/api-all.mustache index 17bcd356c6..4da3802a3e 100644 --- a/templates/javascript/api-all.mustache +++ b/templates/javascript/api-all.mustache @@ -12,7 +12,7 @@ export * from './{{ classFilename }}Interface' export class searchClient extends SearchApi{} export * from '../utils/errors'; -export { EchoRequester } from '../utils/EchoRequester'; +export { EchoRequester } from '../utils/requester/EchoRequester'; export const APIS = [{{#apis}}{{#operations}}{{ classname }}{{/operations}}{{^-last}}, {{/-last}}{{/apis}}]; {{/apiInfo}} diff --git a/templates/javascript/api-single.mustache b/templates/javascript/api-single.mustache index 9ebb11b699..e8fbb16b70 100644 --- a/templates/javascript/api-single.mustache +++ b/templates/javascript/api-single.mustache @@ -1,7 +1,7 @@ import { shuffle } from '../utils/helpers'; import { Transporter } from '../utils/Transporter'; import { Headers, Host, Request, RequestOptions } from '../utils/types'; -import { Requester } from '../utils/Requester'; +import { Requester } from '../utils/requester/Requester'; {{#imports}} import { {{classname}} } from '{{filename}}'; @@ -37,22 +37,11 @@ export class {{classname}} { {{/hasAuthMethods}} } - constructor(appId: string, apiKey: string, requester?: Requester) { + constructor(appId: string, apiKey: string, options?: {requester?: Requester, hosts?: Host[]}) { this.setApiKey(SearchApiApiKeys.appId, appId); this.setApiKey(SearchApiApiKeys.apiKey, apiKey); this.transporter = new Transporter({ - hosts: ( - [ - { url: `${appId}-dsn.algolia.net`, accept: 'read', protocol: 'https' }, - { url: `${appId}.algolia.net`, accept: 'write', protocol: 'https' }, - ] as Host[] - ).concat( - shuffle([ - { url: `${appId}-1.algolianet.com`, accept: 'readWrite', protocol: 'https' }, - { url: `${appId}-2.algolianet.com`, accept: 'readWrite', protocol: 'https' }, - { url: `${appId}-3.algolianet.com`, accept: 'readWrite', protocol: 'https' }, - ]) - ), + hosts: options?.hosts ?? this.getDefaultHosts(appId, apiKey), baseHeaders: { 'content-type': 'application/x-www-form-urlencoded' }, @@ -62,17 +51,36 @@ export class {{classname}} { read: 5, write: 30, }, - requester, + requester: options?.requester, }); } + public getDefaultHosts(appId: string, apiKey: string): Host[] { + return ( + [ + { url: `${appId}-dsn.algolia.net`, accept: 'read', protocol: 'https' }, + { url: `${appId}.algolia.net`, accept: 'write', protocol: 'https' }, + ] as Host[] + ).concat( + shuffle([ + { url: `${appId}-1.algolianet.com`, accept: 'readWrite', protocol: 'https' }, + { url: `${appId}-2.algolianet.com`, accept: 'readWrite', protocol: 'https' }, + { url: `${appId}-3.algolianet.com`, accept: 'readWrite', protocol: 'https' }, + ]) + ); + } + + public setRequest(requester: Requester): void { + this.transporter.setRequester(requester); + } + + public setHosts(hosts: Host[]): void { + this.transporter.setHosts(hosts); + } + public setApiKey(key: {{classname}}ApiKeys, value: string) { this.authentications[{{classname}}ApiKeys[key]].apiKey = value; } - {{#hasAuthMethods}} - {{#authMethods}} - {{/authMethods}} - {{/hasAuthMethods}} private async sendRequest(request: Request, requestOptions: RequestOptions): Promise { {{#authMethods}}