Skip to content

Commit

Permalink
fix: make form the default POST body
Browse files Browse the repository at this point in the history
Turns out that while the Reddit api can return JSON repsonses, it
really only accepts x-www-form-urlencoded. Whoops!
  • Loading branch information
thislooksfun committed Mar 14, 2021
1 parent 1e8735f commit 8a80eac
Show file tree
Hide file tree
Showing 11 changed files with 70 additions and 47 deletions.
23 changes: 23 additions & 0 deletions src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,29 @@ export default class Client {
}
}

/**
* Perform a json-formatted POST request to the reddit api.
*
* You shouldn't ever have to use this directly.
*
* @template T The type to cast the response to.
*
* @param path The path of the endpoint.
* @param data The data to POST.
* @param query Any query parameters to pass to the endpoint.
*
* @returns The JSON response from the endpoint.
*
* @throws If the endpoint returns an error.
*/
async postJson<T>(path: string, data: Data, query: Query = {}): Promise<T> {
if (this.creds) {
return oauth.postJson(await this.oAuth(), path, data, query);
} else {
return anon.postJson(this.userAgent, path, data, query);
}
}

protected async updateAccessToken(): Promise<void> {
if (!this.creds) throw "No creds";

Expand Down
4 changes: 2 additions & 2 deletions src/helper/accessToken.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { Auth } from "../client";
import type { Data } from "./types";
import type { Credentials } from "./api/creds";
import { postForm } from "./api/creds";
import { post } from "./api/creds";
import { camelCaseKeys } from "./util";

export interface Token {
Expand Down Expand Up @@ -40,7 +40,7 @@ export default async function updateAccessToken(
grant.grant_type = "client_credentials";
}

const raw: Data = await postForm(
const raw: Data = await post(
creds,
userAgent,
"api/v1/access_token",
Expand Down
10 changes: 5 additions & 5 deletions src/helper/api/anon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,17 @@ export async function get<T>(
export async function post<T>(
userAgent: string,
path: string,
json: Data,
form: Data,
query: Query = {}
): Promise<T> {
return core.post(endpoint, `${path}.json`, json, query, userAgent);
return core.post(endpoint, `${path}.json`, form, query, userAgent);
}

export async function postForm<T>(
export async function postJson<T>(
userAgent: string,
path: string,
form: Data,
json: Data,
query: Query = {}
): Promise<T> {
return core.postForm(endpoint, `${path}.json`, form, query, userAgent);
return core.postJson(endpoint, `${path}.json`, json, query, userAgent);
}
10 changes: 5 additions & 5 deletions src/helper/api/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,27 +112,27 @@ export async function get<T>(
export async function post<T>(
endpoint: string,
path: string,
json: Data,
form: Data,
query: Query = {},
userAgent: string,
auth?: Auth
): Promise<T> {
return await _post(path, {
...opts(endpoint, userAgent, query, auth),
json: { api_type: "json", ...json },
form: { api_type: "json", ...form },
});
}

export async function postForm<T>(
export async function postJson<T>(
endpoint: string,
path: string,
form: Data,
json: Data,
query: Query = {},
userAgent: string,
auth?: Auth
): Promise<T> {
return await _post(path, {
...opts(endpoint, userAgent, query, auth),
form,
json: { api_type: "json", ...json },
});
}
10 changes: 5 additions & 5 deletions src/helper/api/creds.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,20 +45,20 @@ export async function post<T>(
creds: Credentials,
userAgent: string,
path: string,
json: Data,
form: Data,
query: Query = {}
): Promise<T> {
const auth: BasicAuth = { user: creds.clientId, pass: creds.clientSecret };
return core.post(endpoint, `${path}.json`, json, query, userAgent, auth);
return core.post(endpoint, `${path}.json`, form, query, userAgent, auth);
}

export async function postForm<T>(
export async function postJson<T>(
creds: Credentials,
userAgent: string,
path: string,
form: Data,
json: Data,
query: Query = {}
): Promise<T> {
const auth: BasicAuth = { user: creds.clientId, pass: creds.clientSecret };
return core.postForm(endpoint, `${path}.json`, form, query, userAgent, auth);
return core.postJson(endpoint, `${path}.json`, json, query, userAgent, auth);
}
10 changes: 5 additions & 5 deletions src/helper/api/oauth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,19 @@ export async function get<T>(
export async function post<T>(
opts: OauthOpts,
path: string,
json: Data,
form: Data,
query: Query = {}
): Promise<T> {
const auth: BearerAuth = { bearer: opts.token };
return core.post(endpoint, path, json, query, opts.userAgent, auth);
return core.post(endpoint, path, form, query, opts.userAgent, auth);
}

export async function postForm<T>(
export async function postJson<T>(
opts: OauthOpts,
path: string,
form: Data,
json: Data,
query: Query = {}
): Promise<T> {
const auth: BearerAuth = { bearer: opts.token };
return core.postForm(endpoint, path, form, query, opts.userAgent, auth);
return core.postJson(endpoint, path, json, query, opts.userAgent, auth);
}
10 changes: 5 additions & 5 deletions test/helper/accessToken.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import updateAccessToken from "../../src/helper/accessToken";
// Mocking
import * as creds from "../../src/helper/api/creds";
jest.mock("../../src/helper/api/creds");
const postForm = creds.postForm as jest.Mock;
const post = creds.post as jest.Mock;

// Just in case something slips through, don't actually ping reddit.
beforeAll(() => nock.disableNetConnect());
Expand Down Expand Up @@ -38,10 +38,10 @@ describe("updateAccessToken()", () => {
fcutil.creds(),
fc.string(),
async (tkn, auth, creds, agent) => {
postForm.mockReset();
post.mockReset();
const prms = updateAccessToken(agent, tkn, creds, auth);
await expect(prms).resolves.toStrictEqual(tkn);
expect(postForm).not.toBeCalled();
expect(post).not.toBeCalled();
}
)
);
Expand All @@ -56,10 +56,10 @@ describe("updateAccessToken()", () => {
tknResponse(),
fc.string(),
async (tkn, auth, creds, newTkn, agent) => {
postForm.mockReset().mockReturnValue(newTkn);
post.mockReset().mockReturnValue(newTkn);

const prms = await updateAccessToken(agent, tkn, creds, auth);
expect(postForm).toBeCalled();
expect(post).toBeCalled();

expect(prms.access).toEqual(newTkn.accessToken);
expect(prms.expiration).toBeGreaterThan(Date.now());
Expand Down
10 changes: 5 additions & 5 deletions test/helper/api/anon.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,13 +116,13 @@ describe("post()", () => {
});
});

describe("postForm()", () => {
describe("postJson()", () => {
it("should pass common values", async () => {
const n = nock("https://www.reddit.com")
.post("/foo/bar.json?api_type=json&raw_json=1")
.reply(200, { bim: "bom" });

await anon.postForm("baz", "foo/bar", { bar: "foo" }, {});
await anon.postJson("baz", "foo/bar", { bar: "foo" }, {});

// TODO: Add tests for body and user agent.
// BODY: Pending https://github.com/nock/nock/issues/2171.
Expand All @@ -134,7 +134,7 @@ describe("postForm()", () => {
.post("/foo/bar.json?api_type=json&raw_json=1")
.reply(200, { bim: "bom" });

const req = anon.postForm("baz", "foo/bar", { bar: "foo" }, {});
const req = anon.postJson("baz", "foo/bar", { bar: "foo" }, {});
await expect(req).resolves.toStrictEqual({ bim: "bom" });

n.done();
Expand All @@ -146,7 +146,7 @@ describe("postForm()", () => {
.post("/foo/bar.json?api_type=json&raw_json=1")
.reply(200, { error: "whoops" });

const req = anon.postForm("baz", "foo/bar", { bar: "foo" }, {});
const req = anon.postJson("baz", "foo/bar", { bar: "foo" }, {});
const err = new Error("Reddit returned an error: whoops");
await expect(req).rejects.toStrictEqual(err);

Expand All @@ -161,7 +161,7 @@ describe("postForm()", () => {
error_description: "something went wrong :(",
});

const req = anon.postForm("baz", "foo/bar", { bar: "foo" }, {});
const req = anon.postJson("baz", "foo/bar", { bar: "foo" }, {});
const err = new Error(
"Reddit returned an error: whoops: something went wrong :("
);
Expand Down
10 changes: 5 additions & 5 deletions test/helper/api/core.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,13 +117,13 @@ describe("post()", () => {
});
});

describe("postForm()", () => {
describe("postJson()", () => {
it("should pass common values", async () => {
const n = nock(domain)
.post("/foo/bar?api_type=json&raw_json=1")
.reply(200, { bim: "bom" });

await core.postForm(domain, "foo/bar", { bar: "foo" }, {}, "baz");
await core.postJson(domain, "foo/bar", { bar: "foo" }, {}, "baz");

// TODO: Add tests for body and user agent.
// BODY: Pending https://github.com/nock/nock/issues/2171.
Expand All @@ -135,7 +135,7 @@ describe("postForm()", () => {
.post("/foo/bar?api_type=json&raw_json=1")
.reply(200, { bim: "bom" });

const req = core.postForm(domain, "foo/bar", { bar: "foo" }, {}, "baz");
const req = core.postJson(domain, "foo/bar", { bar: "foo" }, {}, "baz");
await expect(req).resolves.toStrictEqual({ bim: "bom" });

n.done();
Expand All @@ -147,7 +147,7 @@ describe("postForm()", () => {
.post("/foo/bar?api_type=json&raw_json=1")
.reply(200, { error: "whoops" });

const req = core.postForm(domain, "foo/bar", { bar: "foo" }, {}, "baz");
const req = core.postJson(domain, "foo/bar", { bar: "foo" }, {}, "baz");
const err = new Error("Reddit returned an error: whoops");
await expect(req).rejects.toStrictEqual(err);

Expand All @@ -162,7 +162,7 @@ describe("postForm()", () => {
error_description: "something went wrong :(",
});

const req = core.postForm(domain, "foo/bar", { bar: "foo" }, {}, "baz");
const req = core.postJson(domain, "foo/bar", { bar: "foo" }, {}, "baz");
const err = new Error(
"Reddit returned an error: whoops: something went wrong :("
);
Expand Down
10 changes: 5 additions & 5 deletions test/helper/api/creds.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,14 +124,14 @@ describe("post()", () => {
});
});

describe("postForm()", () => {
describe("postJson()", () => {
it("should pass common values", async () => {
const n = nock("https://www.reddit.com")
.post("/foo/bar.json?api_type=json&raw_json=1")
.reply(200, { bim: "bom" });

const c = { clientId: "cid", clientSecret: "csec" };
await creds.postForm(c, "baz", "foo/bar", { bar: "foo" }, {});
await creds.postJson(c, "baz", "foo/bar", { bar: "foo" }, {});

// TODO: Add tests for body, user agent, and auth.
// BODY: Pending https://github.com/nock/nock/issues/2171.
Expand All @@ -144,7 +144,7 @@ describe("postForm()", () => {
.reply(200, { bim: "bom" });

const c = { clientId: "cid", clientSecret: "csec" };
const req = creds.postForm(c, "baz", "foo/bar", { bar: "foo" }, {});
const req = creds.postJson(c, "baz", "foo/bar", { bar: "foo" }, {});
await expect(req).resolves.toStrictEqual({ bim: "bom" });

n.done();
Expand All @@ -157,7 +157,7 @@ describe("postForm()", () => {
.reply(200, { error: "whoops" });

const c = { clientId: "cid", clientSecret: "csec" };
const req = creds.postForm(c, "baz", "foo/bar", { bar: "foo" }, {});
const req = creds.postJson(c, "baz", "foo/bar", { bar: "foo" }, {});
const err = new Error("Reddit returned an error: whoops");
await expect(req).rejects.toStrictEqual(err);

Expand All @@ -173,7 +173,7 @@ describe("postForm()", () => {
});

const c = { clientId: "cid", clientSecret: "csec" };
const req = creds.postForm(c, "baz", "foo/bar", { bar: "foo" }, {});
const req = creds.postJson(c, "baz", "foo/bar", { bar: "foo" }, {});
const err = new Error(
"Reddit returned an error: whoops: something went wrong :("
);
Expand Down
10 changes: 5 additions & 5 deletions test/helper/api/oauth.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,14 +124,14 @@ describe("post()", () => {
});
});

describe("postForm()", () => {
describe("postJson()", () => {
it("should pass common values", async () => {
const n = nock("https://oauth.reddit.com")
.post("/foo/bar?api_type=json&raw_json=1")
.reply(200, { bim: "bom" });

const oo = { token: "sometkn", userAgent: "baz" };
await oauth.postForm(oo, "foo/bar", { bar: "foo" }, {});
await oauth.postJson(oo, "foo/bar", { bar: "foo" }, {});

// TODO: Add tests for body, user agent, and auth.
// BODY: Pending https://github.com/nock/nock/issues/2171.
Expand All @@ -144,7 +144,7 @@ describe("postForm()", () => {
.reply(200, { bim: "bom" });

const oo = { token: "sometkn", userAgent: "baz" };
const req = oauth.postForm(oo, "foo/bar", { bar: "foo" }, {});
const req = oauth.postJson(oo, "foo/bar", { bar: "foo" }, {});
await expect(req).resolves.toStrictEqual({ bim: "bom" });

n.done();
Expand All @@ -157,7 +157,7 @@ describe("postForm()", () => {
.reply(200, { error: "whoops" });

const oo = { token: "sometkn", userAgent: "baz" };
const req = oauth.postForm(oo, "foo/bar", { bar: "foo" }, {});
const req = oauth.postJson(oo, "foo/bar", { bar: "foo" }, {});
const err = new Error("Reddit returned an error: whoops");
await expect(req).rejects.toStrictEqual(err);

Expand All @@ -173,7 +173,7 @@ describe("postForm()", () => {
});

const oo = { token: "sometkn", userAgent: "baz" };
const req = oauth.postForm(oo, "foo/bar", { bar: "foo" }, {});
const req = oauth.postJson(oo, "foo/bar", { bar: "foo" }, {});
const err = new Error(
"Reddit returned an error: whoops: something went wrong :("
);
Expand Down

0 comments on commit 8a80eac

Please sign in to comment.