Skip to content

Commit

Permalink
- Added Http Namespace
Browse files Browse the repository at this point in the history
- Removed fixtures flagged by git-secrets for containing passwords/secrets

Signed-off-by: Theo Truong <theotr@amazon.com>
  • Loading branch information
nhtruong committed Nov 20, 2023
1 parent abf79eb commit cfb6cba
Show file tree
Hide file tree
Showing 10 changed files with 445 additions and 13 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
## [Unreleased]
### Added
- Added deprecation warnings for Index Template APIs ([654](https://github.com/opensearch-project/opensearch-js/pull/645))
- Added Low-level APIs functions ([#649](https://github.com/opensearch-project/opensearch-js/pull/649))
### Dependencies
- Bumps `@aws-sdk/types` from 3.418.0 to 3.433.0
- Bumps `@types/node` from 20.6.5 to 20.9.0
Expand Down Expand Up @@ -194,4 +195,4 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)

### Fixed

- Fix mutability of connection headers ([#291](https://github.com/opensearch-project/opensearch-js/issues/291))
- Fix mutability of connection headers ([#291](https://github.com/opensearch-project/opensearch-js/issues/291))
193 changes: 193 additions & 0 deletions api/api/http.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*
* The OpenSearch Contributors require contributions made to
* this file be licensed under the Apache-2.0 license or a
* compatible open source license.
*
*/

'use strict';

/** @namespace API-HTTP */

const { normalizeArguments, kConfigurationError } = require('../utils');

function HttpApi(transport, ConfigurationError) {
this.transport = transport;
this[kConfigurationError] = ConfigurationError;
}

HttpApi.prototype.request = function (method, params, options, callback) {
[params, options, callback] = normalizeArguments(params, options, callback);
if (Array.isArray(params.body)) {
params.bulkBody = params.body;
delete params.body;
}
options = options || {};
options.headers = params.headers || options.headers;
return this.transport.request({ ...params, method }, options, callback);
};

/**
* Make a customized CONNECT request.
*
* @memberOf API-HTTP
*
* @param {Object} params
* @param {Object} params.path - The URL of the request
* @param {Object} [params.querystring] - The querystring parameters
* @param {Object} [params.headers] - The request headers
* @param {Object} [params.body] - The request body
*
* @param {Object} [options] - Options for {@link Transport#request}
* @param {function} [callback] - Callback that handles errors and response
*
* @returns {{abort: function(), then: function(), catch: function()}|Promise<never>|*}
*/
HttpApi.prototype.connect = function (params, options, callback) {
return this.request('CONNECT', params, options, callback);
};

/**
* Make a customized DELETE request.
*
* @memberOf API-HTTP
*
* @param {Object} params
* @param {Object} params.path - The URL of the request
* @param {Object} [params.querystring] - The querystring parameters
* @param {Object} [params.headers] - The request headers
* @param {Object} [params.body] - The request body
*
* @param {Object} [options] - Options for {@link Transport#request}
* @param {function} [callback] - Callback that handles errors and response
*
* @returns {{abort: function(), then: function(), catch: function()}|Promise<never>|*}
*/
HttpApi.prototype.delete = function (params, options, callback) {
return this.request('DELETE', params, options, callback);
};

/**
* Make a customized GET request.
*
* @memberOf API-HTTP
*
* @param {Object} params
* @param {Object} params.path - The URL of the request
* @param {Object} [params.querystring] - The querystring parameters
* @param {Object} [params.headers] - The request headers
* @param {Object} [params.body] - The request body
*
* @param {Object} [options] - Options for {@link Transport#request}
* @param {function} [callback] - Callback that handles errors and response
*
* @returns {{abort: function(), then: function(), catch: function()}|Promise<never>|*}
*/
HttpApi.prototype.get = function (params, options, callback) {
return this.request('GET', params, options, callback);
};

/**
* Make a customized HEAD request.
*
* @memberOf API-HTTP
*
* @param {Object} params
* @param {Object} params.path - The URL of the request
* @param {Object} [params.querystring] - The querystring parameters
* @param {Object} [params.headers] - The request headers
* @param {Object} [params.body] - The request body
*
* @param {Object} [options] - Options for {@link Transport#request}
* @param {function} [callback] - Callback that handles errors and response
*
* @returns {{abort: function(), then: function(), catch: function()}|Promise<never>|*}
*/
HttpApi.prototype.head = function (params, options, callback) {
return this.request('HEAD', params, options, callback);
};

/**
* Make a customized OPTIONS request.
*
* @memberOf API-HTTP
*
* @param {Object} params
* @param {Object} params.path - The URL of the request
* @param {Object} [params.querystring] - The querystring parameters
* @param {Object} [params.headers] - The request headers
* @param {Object} [params.body] - The request body
*
* @param {Object} [options] - Options for {@link Transport#request}
* @param {function} [callback] - Callback that handles errors and response
*
* @returns {{abort: function(), then: function(), catch: function()}|Promise<never>|*}
*/
HttpApi.prototype.options = function (params, options, callback) {
return this.request('OPTIONS', params, options, callback);
};

/**
* Make a customized POST request.
*
* @memberOf API-HTTP
*
* @param {Object} params
* @param {Object} params.path - The URL of the request
* @param {Object} [params.querystring] - The querystring parameters
* @param {Object} [params.headers] - The request headers
* @param {Object} [params.body] - The request body
*
* @param {Object} [options] - Options for {@link Transport#request}
* @param {function} [callback] - Callback that handles errors and response
*
* @returns {{abort: function(), then: function(), catch: function()}|Promise<never>|*}
*/
HttpApi.prototype.post = function (params, options, callback) {
return this.request('POST', params, options, callback);
};

/**
* Make a customized PUT request.
*
* @memberOf API-HTTP
*
* @param {Object} params
* @param {Object} params.path - The URL of the request
* @param {Object} [params.querystring] - The querystring parameters
* @param {Object} [params.headers] - The request headers
* @param {Object} [params.body] - The request body
*
* @param {Object} [options] - Options for {@link Transport#request}
* @param {function} [callback] - Callback that handles errors and response
*
* @returns {{abort: function(), then: function(), catch: function()}|Promise<never>|*}
*/
HttpApi.prototype.put = function (params, options, callback) {
return this.request('PUT', params, options, callback);
};

/**
* Make a customized TRACE request.
*
* @memberOf API-HTTP
*
* @param {Object} params
* @param {Object} params.path - The URL of the request
* @param {Object} [params.querystring] - The querystring parameters
* @param {Object} [params.headers] - The request headers
* @param {Object} [params.body] - The request body
*
* @param {Object} [options] - Options for {@link Transport#request}
* @param {function} [callback] - Callback that handles errors and response
*
* @returns {{abort: function(), then: function(), catch: function()}|Promise<never>|*}
*/
HttpApi.prototype.trace = function (params, options, callback) {
return this.request('TRACE', params, options, callback);
};

module.exports = HttpApi;
11 changes: 11 additions & 0 deletions api/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ const getScriptApi = require('./api/get_script');
const getScriptContextApi = require('./api/get_script_context');
const getScriptLanguagesApi = require('./api/get_script_languages');
const getSourceApi = require('./api/get_source');
const HttpApi = require('./api/http');
const indexApi = require('./api/index');
const IndicesApi = require('./api/indices');
const infoApi = require('./api/info');
Expand Down Expand Up @@ -89,6 +90,7 @@ const kCat = Symbol('Cat');
const kCluster = Symbol('Cluster');
const kDanglingIndices = Symbol('DanglingIndices');
const kFeatures = Symbol('Features');
const kHttp = Symbol('Http');
const kIndices = Symbol('Indices');
const kIngest = Symbol('Ingest');
const kNodes = Symbol('Nodes');
Expand All @@ -103,6 +105,7 @@ function OpenSearchAPI(opts) {
this[kCluster] = null;
this[kDanglingIndices] = null;
this[kFeatures] = null;
this[kHttp] = null;
this[kIndices] = null;
this[kIngest] = null;
this[kNodes] = null;
Expand Down Expand Up @@ -264,6 +267,14 @@ Object.defineProperties(OpenSearchAPI.prototype, {
return this.getSource;
},
},
http: {
get() {
if (this[kHttp] === null) {
this[kHttp] = new HttpApi(this.transport, this[kConfigurationError]);
}
return this[kHttp];
},
},
indices: {
get() {
if (this[kIndices] === null) {
Expand Down
7 changes: 7 additions & 0 deletions api/requestParams.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -750,6 +750,13 @@ export interface GetSource extends Generic {
version_type?: 'internal' | 'external' | 'external_gte' | 'force';
}

export interface HttpParams extends Generic {
path: string;
querystring?: Record<string, any>;
headers?: Record<string, any>;
body?: Record<string, any> | string | Array<string | Record<string, any>>;
}

export interface Index<T = RequestBody> extends Generic {
id?: string;
index: string;
Expand Down
61 changes: 61 additions & 0 deletions guides/low_level_api.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Low-level API

The OpenSearch client implements many high-level REST DSLs that invoke OpenSearch APIs. However, you may find yourself in a situation that requires you to invoke an API that is not supported by the client. In this case, you can use the low-level API to invoke any OpenSearch API. This guide shows you different ways to make custom API calls using the OpenSearch JS client.

## Setup
First, create a client instance with the following code to interact with an OpenSearch cluster with default security settings:

```javascript
const client = new Client({
ssl: {
rejectUnauthorized: false,
},
node: 'https://localhost:9200',
auth: {
username: 'admin',
password: 'admin',
},
});
```

## The http Namespace
The `http` namespace comes with all functions representing HTTP methods like `http.get`, `http.post`, `http.put`, and `http.delete`.

Let's create in index using `http.put`:
```javascript
await client.http.put({
path: '/movies',
body: {
mappings: {
properties: {
title: { type: 'text' },
director: { type: 'text' },
year: { type: 'integer' },
},
},
},
});
```

Make sure that the index was created successfully using `http.head`:

```javascript
await client.http.head({ path: '/movies' });
```

Add two documents to the index using `http.post` and the bulk endpoint
```javascript
const body = [
{ index: { _index: index } },
{ title: 'The quick brown fox' },
{ index: { _index: index } },
{ title: 'The quick brown fox jumps over the lazy dog' },
];
await client.http.post({ path: `_bulk`, body });
```
Note that while most endpoints accept a JSON body, the bulk endpoint accepts a newline-delimited JSON (NDJSON) body. When you provide these methods with an array as body, they will automatically serialize it to NDJSON.

Delete the index using `http.delete`:
```javascript
await client.http.delete({ path: '/movies' });
```
42 changes: 42 additions & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2073,6 +2073,48 @@ declare class Client {
options: TransportRequestOptions,
callback: callbackFn<TResponse, TContext>
): TransportRequestCallback;
http: {
connect<TResponse = Record<string, any>, TContext = Context>(
params: RequestParams.HttpParams,
options?: TransportRequestOptions,
callback?: callbackFn<TResponse, TContext>
): TransportRequestPromise<ApiResponse<TResponse, TContext>>;
delete<TResponse = Record<string, any>, TContext = Context>(
params: RequestParams.HttpParams,
options?: TransportRequestOptions,
callback?: callbackFn<TResponse, TContext>
): TransportRequestPromise<ApiResponse<TResponse, TContext>>;
get<TResponse = Record<string, any>, TContext = Context>(
params: RequestParams.HttpParams,
options?: TransportRequestOptions,
callback?: callbackFn<TResponse, TContext>
): TransportRequestPromise<ApiResponse<TResponse, TContext>>;
head<TResponse = Record<string, any>, TContext = Context>(
params: RequestParams.HttpParams,
options?: TransportRequestOptions,
callback?: callbackFn<TResponse, TContext>
): TransportRequestPromise<ApiResponse<TResponse, TContext>>;
options<TResponse = Record<string, any>, TContext = Context>(
params: RequestParams.HttpParams,
options?: TransportRequestOptions,
callback?: callbackFn<TResponse, TContext>
): TransportRequestPromise<ApiResponse<TResponse, TContext>>;
post<TResponse = Record<string, any>, TContext = Context>(
params: RequestParams.HttpParams,
options?: TransportRequestOptions,
callback?: callbackFn<TResponse, TContext>
): TransportRequestPromise<ApiResponse<TResponse, TContext>>;
put<TResponse = Record<string, any>, TContext = Context>(
params: RequestParams.HttpParams,
options?: TransportRequestOptions,
callback?: callbackFn<TResponse, TContext>
): TransportRequestPromise<ApiResponse<TResponse, TContext>>;
trace<TResponse = Record<string, any>, TContext = Context>(
params: RequestParams.HttpParams,
options?: TransportRequestOptions,
callback?: callbackFn<TResponse, TContext>
): TransportRequestPromise<ApiResponse<TResponse, TContext>>;
};
index<
TResponse = Record<string, any>,
TRequestBody extends RequestBody = Record<string, any>,
Expand Down
Loading

0 comments on commit cfb6cba

Please sign in to comment.