Skip to content

Commit

Permalink
Merge pull request #1322 from cosmos/rm-http-tests
Browse files Browse the repository at this point in the history
Pull out function http and deduplicate tests
  • Loading branch information
webmaster128 committed Nov 14, 2022
2 parents 46ae68e + c3c5517 commit 00035fd
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 162 deletions.
63 changes: 63 additions & 0 deletions packages/tendermint-rpc/src/rpcclients/http.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/* eslint-disable @typescript-eslint/naming-convention */
import { createJsonRpcRequest } from "../jsonrpc";
import { defaultInstance, pendingWithoutTendermint } from "../testutil.spec";
import { http } from "./http";

function pendingWithoutHttpServer(): void {
if (!process.env.HTTPSERVER_ENABLED) {
pending("Set HTTPSERVER_ENABLED to enable HTTP tests");
}
}

const tendermintUrl = defaultInstance.url;
const echoUrl = "http://localhost:5555/echo_headers";

describe("http", () => {
it("can send a health request", async () => {
pendingWithoutTendermint();
const response = await http("POST", `http://${tendermintUrl}`, undefined, createJsonRpcRequest("health"));
expect(response).toEqual(jasmine.objectContaining({ jsonrpc: "2.0" }));
});

it("errors for non-open port", async () => {
await expectAsync(
http("POST", `http://localhost:56745`, undefined, createJsonRpcRequest("health")),
).toBeRejectedWithError(/(ECONNREFUSED|Failed to fetch)/i);
});

it("can send custom headers", async () => {
pendingWithoutHttpServer();
// Without custom headers
const response1 = await http("POST", echoUrl, undefined, createJsonRpcRequest("health"));
expect(response1).toEqual({
request_headers: jasmine.objectContaining({
// Basic headers from http client
Accept: jasmine.any(String),
"Content-Length": jasmine.any(String),
"Content-Type": "application/json",
Host: jasmine.any(String),
"User-Agent": jasmine.any(String),
}),
});

// With custom headers
const response2 = await http(
"POST",
echoUrl,
{ foo: "bar123", Authorization: "Basic Z3Vlc3Q6bm9QYXNzMTIz" },
createJsonRpcRequest("health"),
);
expect(response2).toEqual({
request_headers: jasmine.objectContaining({
// Basic headers from http client
"Content-Length": jasmine.any(String),
"Content-Type": "application/json",
Host: jasmine.any(String),
"User-Agent": jasmine.any(String),
// Custom headers
foo: "bar123",
Authorization: "Basic Z3Vlc3Q6bm9QYXNzMTIz",
}),
});
});
});
44 changes: 44 additions & 0 deletions packages/tendermint-rpc/src/rpcclients/http.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import axios from "axios";

// Global symbols in some environments
// https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch
declare const fetch: any | undefined;

function filterBadStatus(res: any): any {
if (res.status >= 400) {
throw new Error(`Bad status on response: ${res.status}`);
}
return res;
}

/**
* Helper to work around missing CORS support in Tendermint (https://github.com/tendermint/tendermint/pull/2800)
*
* For some reason, fetch does not complain about missing server-side CORS support.
*/
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
export async function http(
method: "POST",
url: string,
headers: Record<string, string> | undefined,
request?: any,
): Promise<any> {
if (typeof fetch !== "undefined") {
const settings = {
method: method,
body: request ? JSON.stringify(request) : undefined,
headers: {
// eslint-disable-next-line @typescript-eslint/naming-convention
"Content-Type": "application/json",
...headers,
},
};
return fetch(url, settings)
.then(filterBadStatus)
.then((res: any) => res.json());
} else {
return axios
.request({ url: url, method: method, data: request, headers: headers })
.then((res) => res.data);
}
}
58 changes: 0 additions & 58 deletions packages/tendermint-rpc/src/rpcclients/httpbatchclient.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,72 +2,14 @@
import { createJsonRpcRequest } from "../jsonrpc";
import { defaultInstance } from "../testutil.spec";
import { HttpBatchClient } from "./httpbatchclient";
import { http } from "./httpclient";

function pendingWithoutTendermint(): void {
if (!process.env.TENDERMINT_ENABLED) {
pending("Set TENDERMINT_ENABLED to enable Tendermint RPC tests");
}
}

function pendingWithoutHttpServer(): void {
if (!process.env.HTTPSERVER_ENABLED) {
pending("Set HTTPSERVER_ENABLED to enable HTTP tests");
}
}

const tendermintUrl = defaultInstance.url;
const echoUrl = "http://localhost:5555/echo_headers";

describe("http", () => {
it("can send a health request", async () => {
pendingWithoutTendermint();
const response = await http("POST", `http://${tendermintUrl}`, undefined, createJsonRpcRequest("health"));
expect(response).toEqual(jasmine.objectContaining({ jsonrpc: "2.0" }));
});

it("errors for non-open port", async () => {
await expectAsync(
http("POST", `http://localhost:56745`, undefined, createJsonRpcRequest("health")),
).toBeRejectedWithError(/(ECONNREFUSED|Failed to fetch)/i);
});

it("can send custom headers", async () => {
pendingWithoutHttpServer();
// Without custom headers
const response1 = await http("POST", echoUrl, undefined, createJsonRpcRequest("health"));
expect(response1).toEqual({
request_headers: jasmine.objectContaining({
// Basic headers from http client
Accept: jasmine.any(String),
"Content-Length": jasmine.any(String),
"Content-Type": "application/json",
Host: jasmine.any(String),
"User-Agent": jasmine.any(String),
}),
});

// With custom headers
const response2 = await http(
"POST",
echoUrl,
{ foo: "bar123", Authorization: "Basic Z3Vlc3Q6bm9QYXNzMTIz" },
createJsonRpcRequest("health"),
);
expect(response2).toEqual({
request_headers: jasmine.objectContaining({
// Basic headers from http client
"Content-Length": jasmine.any(String),
"Content-Type": "application/json",
Host: jasmine.any(String),
"User-Agent": jasmine.any(String),
// Custom headers
foo: "bar123",
Authorization: "Basic Z3Vlc3Q6bm9QYXNzMTIz",
}),
});
});
});

describe("HttpBatchClient", () => {
it("can make a simple call", async () => {
Expand Down
3 changes: 2 additions & 1 deletion packages/tendermint-rpc/src/rpcclients/httpbatchclient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import {
parseJsonRpcResponse,
} from "@cosmjs/json-rpc";

import { http, HttpEndpoint } from "./httpclient";
import { http } from "./http";
import { HttpEndpoint } from "./httpclient";
import { hasProtocol, RpcClient } from "./rpcclient";

export interface HttpBatchClientOptions {
Expand Down
60 changes: 1 addition & 59 deletions packages/tendermint-rpc/src/rpcclients/httpclient.spec.ts
Original file line number Diff line number Diff line change
@@ -1,72 +1,14 @@
/* eslint-disable @typescript-eslint/naming-convention */
import { createJsonRpcRequest } from "../jsonrpc";
import { defaultInstance } from "../testutil.spec";
import { http, HttpClient } from "./httpclient";
import { HttpClient } from "./httpclient";

function pendingWithoutTendermint(): void {
if (!process.env.TENDERMINT_ENABLED) {
pending("Set TENDERMINT_ENABLED to enable Tendermint RPC tests");
}
}

function pendingWithoutHttpServer(): void {
if (!process.env.HTTPSERVER_ENABLED) {
pending("Set HTTPSERVER_ENABLED to enable HTTP tests");
}
}

const tendermintUrl = defaultInstance.url;
const echoUrl = "http://localhost:5555/echo_headers";

describe("http", () => {
it("can send a health request", async () => {
pendingWithoutTendermint();
const response = await http("POST", `http://${tendermintUrl}`, undefined, createJsonRpcRequest("health"));
expect(response).toEqual(jasmine.objectContaining({ jsonrpc: "2.0" }));
});

it("errors for non-open port", async () => {
await expectAsync(
http("POST", `http://localhost:56745`, undefined, createJsonRpcRequest("health")),
).toBeRejectedWithError(/(ECONNREFUSED|Failed to fetch)/i);
});

it("can send custom headers", async () => {
pendingWithoutHttpServer();
// Without custom headers
const response1 = await http("POST", echoUrl, undefined, createJsonRpcRequest("health"));
expect(response1).toEqual({
request_headers: jasmine.objectContaining({
// Basic headers from http client
Accept: jasmine.any(String),
"Content-Length": jasmine.any(String),
"Content-Type": "application/json",
Host: jasmine.any(String),
"User-Agent": jasmine.any(String),
}),
});

// With custom headers
const response2 = await http(
"POST",
echoUrl,
{ foo: "bar123", Authorization: "Basic Z3Vlc3Q6bm9QYXNzMTIz" },
createJsonRpcRequest("health"),
);
expect(response2).toEqual({
request_headers: jasmine.objectContaining({
// Basic headers from http client
"Content-Length": jasmine.any(String),
"Content-Type": "application/json",
Host: jasmine.any(String),
"User-Agent": jasmine.any(String),
// Custom headers
foo: "bar123",
Authorization: "Basic Z3Vlc3Q6bm9QYXNzMTIz",
}),
});
});
});

describe("HttpClient", () => {
it("can make a simple call", async () => {
Expand Down
45 changes: 1 addition & 44 deletions packages/tendermint-rpc/src/rpcclients/httpclient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,53 +4,10 @@ import {
JsonRpcSuccessResponse,
parseJsonRpcResponse,
} from "@cosmjs/json-rpc";
import axios from "axios";

import { http } from "./http";
import { hasProtocol, RpcClient } from "./rpcclient";

// Global symbols in some environments
// https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch
declare const fetch: any | undefined;

function filterBadStatus(res: any): any {
if (res.status >= 400) {
throw new Error(`Bad status on response: ${res.status}`);
}
return res;
}

/**
* Helper to work around missing CORS support in Tendermint (https://github.com/tendermint/tendermint/pull/2800)
*
* For some reason, fetch does not complain about missing server-side CORS support.
*/
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
export async function http(
method: "POST",
url: string,
headers: Record<string, string> | undefined,
request?: any,
): Promise<any> {
if (typeof fetch !== "undefined") {
const settings = {
method: method,
body: request ? JSON.stringify(request) : undefined,
headers: {
// eslint-disable-next-line @typescript-eslint/naming-convention
"Content-Type": "application/json",
...headers,
},
};
return fetch(url, settings)
.then(filterBadStatus)
.then((res: any) => res.json());
} else {
return axios
.request({ url: url, method: method, data: request, headers: headers })
.then((res) => res.data);
}
}

export interface HttpEndpoint {
/**
* The URL of the HTTP endpoint.
Expand Down

0 comments on commit 00035fd

Please sign in to comment.