diff --git a/doc/7/protocols/http/constructor/index.md b/doc/7/protocols/http/constructor/index.md index a1aaddae1..9d4dcdbab 100644 --- a/doc/7/protocols/http/constructor/index.md +++ b/doc/7/protocols/http/constructor/index.md @@ -19,7 +19,7 @@ Http(host, [options]);
| Argument | Type | Description | -| --------- | ----------------- | ---------------------------- | +|-----------|-------------------|------------------------------| | `host` |
string
| Kuzzle server hostname or IP | | `options` |
object
| Http connection options | @@ -27,13 +27,14 @@ Http(host, [options]); Http protocol connection options. -| Property | Type
(default) | Description | -| --------------- | -------------------------------- | ----------------------------------- | -| `port` |
number

(`7512`) | Kuzzle server port | -| `sslConnection` |
boolean

(`false`) | Use SSL to connect to Kuzzle server | -| `ssl` |
boolean

(`false`) | Use SSL to connect to Kuzzle server. Defaults to `true` for ports 443 and 7443. | -| `customRoutes` |
object

(`{}`) | Add custom routes | -| `timeout` |
number

(`0`) | Connection timeout in milliseconds (`0` means no timeout) | +| Property | Type
(default) | Description | +|-----------------|----------------------------------|----------------------------------------------------------------------------------------| +| `customRoutes` |
object

(`{}`) | Add custom routes | +| `headers` |
object

(`{}`) | Default headers sent with each HTTP request | +| `port` |
number

(`7512`) | Kuzzle server port | +| `sslConnection` |
boolean

(`false`) | Use SSL to connect to Kuzzle server | +| `ssl` |
boolean

(`false`) | Use SSL to connect to Kuzzle server. Defaults to `true` for ports 443 and 7443. | +| `timeout` |
number

(`0`) | Connection timeout in milliseconds (`0` means no timeout) | **Note:** diff --git a/doc/7/protocols/http/constructor/snippets/constructor.js b/doc/7/protocols/http/constructor/snippets/constructor.js index b20311b68..35f07816e 100644 --- a/doc/7/protocols/http/constructor/snippets/constructor.js +++ b/doc/7/protocols/http/constructor/snippets/constructor.js @@ -12,8 +12,13 @@ const customRoutes = { } }; +const headers = { + 'Accept-Encoding': 'gzip, deflate' +}; + const options = { customRoutes, + headers, sslConnection: false }; diff --git a/src/protocols/Http.ts b/src/protocols/Http.ts index c4ff8c45c..b7c064e2d 100644 --- a/src/protocols/Http.ts +++ b/src/protocols/Http.ts @@ -14,11 +14,13 @@ export default class HttpProtocol extends KuzzleAbstractProtocol { private _routes: HttpRoutes; private _timeout: number; private _customRoutes: HttpRoutes; + private _defaultHeaders: JSONObject; /** * @param host Kuzzle server hostname or IP * @param options Http connection options * - `customRoutes` Add custom routes + * - `headers` Default headers sent with each HTTP request (default: `{}`) * - `port` Kuzzle server port (default: `7512`) * - `ssl` Use SSL to connect to Kuzzle server. Default `false` unless port is 443 or 7443. * - `timeout` Connection timeout in milliseconds (default: `0`) @@ -33,7 +35,8 @@ export default class HttpProtocol extends KuzzleAbstractProtocol { sslConnection?: boolean; ssl?: boolean; customRoutes?: HttpRoutes; - timeout?: number + timeout?: number, + headers?: JSONObject, } = {} ) { super(host, options, 'http'); @@ -48,6 +51,8 @@ export default class HttpProtocol extends KuzzleAbstractProtocol { this._customRoutes = options.customRoutes || {}; + this._defaultHeaders = options.headers || {}; + for (const controller of Object.keys(this._customRoutes)) { const definition = this._customRoutes[controller]; @@ -113,7 +118,14 @@ export default class HttpProtocol extends KuzzleAbstractProtocol { return Promise.resolve(); } - return this._sendHttpRequest({method: 'GET', path: '/_publicApi'}) + const publicApiRequest = { + method: 'GET', + path: '/_publicApi', + payload: { + headers: this._defaultHeaders, + } + }; + return this._sendHttpRequest(publicApiRequest) .then(({ result, error }) => { if (! error) { this._routes = this._constructRoutes(result); @@ -133,7 +145,14 @@ export default class HttpProtocol extends KuzzleAbstractProtocol { } else if (error.status === 404) { // fallback to server:info route // server:publicApi is only available since Kuzzle 1.9.0 - return this._sendHttpRequest({method: 'GET', path: '/'}) + const serverInfoRequest = { + method: 'GET', + path: '/', + payload: { + headers: this._defaultHeaders, + } + }; + return this._sendHttpRequest(serverInfoRequest) .then(({ result: res, error: err }) => { if (! err) { this._routes = this._constructRoutes(res.serverInfo.kuzzle.api.routes); @@ -207,7 +226,8 @@ export default class HttpProtocol extends KuzzleAbstractProtocol { collection: undefined, controller: undefined, headers: { - 'Content-Type': 'application/json' + 'Content-Type': 'application/json', + ...this._defaultHeaders, }, index: undefined, meta: undefined, @@ -311,11 +331,15 @@ export default class HttpProtocol extends KuzzleAbstractProtocol { if (formattedRequest) { this._sendHttpRequest(formattedRequest) .then(response => this.emit(formattedRequest.payload.requestId, response)) - .catch(error => this.emit(formattedRequest.payload.requestId, {error})); + .catch(error => this.emit(formattedRequest.payload.requestId, { error })); } } - _sendHttpRequest ({method, path, payload = {headers: undefined, body:undefined}}) { + _sendHttpRequest ({ method, path, payload }: { + method: string, + path: string, + payload: JSONObject + }) { if (typeof XMLHttpRequest === 'undefined') { // NodeJS implementation, using http.request: @@ -326,12 +350,12 @@ export default class HttpProtocol extends KuzzleAbstractProtocol { path = `/${path}`; } const url = `${this.protocol}://${this.host}:${this.port}${path}`; - const headers = payload.headers || {}; - headers['Content-Length'] = Buffer.byteLength(payload.body || ''); + const headers = payload && payload.headers || {}; + headers['Content-Length'] = Buffer.byteLength(payload && payload.body || ''); return httpClient.request(url, method, { - headers, - body: payload.body, + body: payload && payload.body, + headers: headers, timeout: this._timeout }) .then(response => { @@ -362,8 +386,8 @@ export default class HttpProtocol extends KuzzleAbstractProtocol { // Authorize the reception of cookies xhr.withCredentials = this.cookieSupport; - for (const header of Object.keys(payload.headers || {})) { - xhr.setRequestHeader(header, payload.headers[header]); + for (const [header, value] of Object.entries(payload && payload.headers || {})) { + xhr.setRequestHeader(header, value as string); } xhr.onload = () => { @@ -376,7 +400,7 @@ export default class HttpProtocol extends KuzzleAbstractProtocol { } }; - xhr.send(payload.body); + xhr.send(payload && payload.body); }); } diff --git a/test/protocol/Http.test.js b/test/protocol/Http.test.js index 01424fce3..6d69d31ee 100644 --- a/test/protocol/Http.test.js +++ b/test/protocol/Http.test.js @@ -828,6 +828,28 @@ describe('HTTP networking module', () => { }); }); + describe('#_formatRequest', () => { + it('should inject default headers', () => { + protocol._routes = { + server: { + now: { verb: 'get', url: '/_now' } + } + }; + protocol._defaultHeaders = { + 'Accept-Encoding': 'gzip, deflate', + }; + const request = { controller: 'server', action: 'now' }; + const formattedRequest = protocol.formatRequest(request); + + should(formattedRequest.payload).match({ + headers: { + 'Accept-Encoding': 'gzip, deflate', + 'Content-Type': 'application/json', + } + }); + }); + }); + describe('#isReady', () => { it('should be ready if the instance is ready', () => { protocol.state = 'ready';