Skip to content

Commit

Permalink
fix: Use Rails formed URL search params
Browse files Browse the repository at this point in the history
  • Loading branch information
neet committed Nov 12, 2022
1 parent 9799eba commit ff5daad
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 16 deletions.
13 changes: 7 additions & 6 deletions src/http/base-http.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { MastoConfig } from '../config';
import { MimeType, Serializer } from '../serializers';
import { MimeType } from '../serializers';
import { railsQueryString } from '../serializers/rails-querystring';
import { Data, Headers, Http, Request, Response } from './http';

export abstract class BaseHttp implements Http {
abstract readonly config: MastoConfig;
abstract readonly serializer: Serializer;

abstract request<T>(request: Request): Promise<Response<T>>;

Expand All @@ -19,11 +19,12 @@ export abstract class BaseHttp implements Http {
return headers;
}

encodeParams(params: Data = {}) {
return railsQueryString.stringify(params);
}

resolveUrl(path: string, params: Data = {}) {
const searchParams = this.serializer.serialize(
'application/x-www-form-urlencoded',
params,
);
const searchParams = this.encodeParams(params);

return `${this.config.url}${path}${
searchParams !== '' ? `?${searchParams}` : ''
Expand Down
6 changes: 1 addition & 5 deletions src/http/http-axios-impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,7 @@ export class HttpAxiosImpl extends BaseHttp implements Http {
return this.serializer.deserialize(contentType, data);
},
paramsSerializer: {
serialize: (params) =>
this.serializer.serialize(
'application/x-www-form-urlencoded',
params,
) as string,
serialize: (params) => this.encodeParams(params),
},
});
}
Expand Down
37 changes: 37 additions & 0 deletions src/serializers/rails-querystring.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { railsQueryString } from './rails-querystring';

describe('railsQueryString', () => {
it('encodes null', () => {
const result = railsQueryString.stringify(null);
expect(result).toBe('');
});

it('encodes an empty object', () => {
const result = railsQueryString.stringify({});
expect(result).toBe('');
});

it('encodes a basic record', () => {
const result = railsQueryString.stringify({ key: 'value' });
expect(result).toBe('key=value');
});

it('encodes a record with multiple values', () => {
const result = railsQueryString.stringify({
key1: 'value1',
key2: 'value2',
});
expect(result).toBe('key1=value1&key2=value2');
});

it('encodes an array inside a record', () => {
const result = railsQueryString.stringify({
key1: 'value1',
key2: 'value2',
key3: ['apple', 'facebook', 'microsoft'],
});
expect(result).toBe(
'key1=value1&key2=value2&key3[]=apple&key3[]=facebook&key3[]=microsoft',
);
});
});
30 changes: 30 additions & 0 deletions src/serializers/rails-querystring.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { isObject } from './is-object';

/**
* Encodes URI in Rails format
*/
const stringify = (object?: unknown): string => {
if (object == null) {
return '';
}
if (!isObject(object)) {
return '';
}

const values = Object.entries(object)
.reduce<string[]>((prev, [k, v]) => {
if (Array.isArray(v)) {
const xs = v.map((x) => `${k}[]=${x}`);
return prev.concat(...xs);
}
if (isObject(v)) {
throw new TypeError('Encoding nested object is not supported');
}
return prev.concat(`${k}=${v}`);
}, [])
.join('&');

return values;
};

export const railsQueryString = { stringify };
7 changes: 2 additions & 5 deletions src/ws/base-ws.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import semver from 'semver';

import { MastoConfig } from '../config';
import { Serializer } from '../serializers';
import { railsQueryString } from '../serializers/rails-querystring';
import { Ws, WsEvents } from './ws';

export abstract class BaseWs implements Ws {
Expand Down Expand Up @@ -30,11 +31,7 @@ export abstract class BaseWs implements Ws {
if (!this.supportsSecureToken()) {
params.accessToken = this.config.accessToken;
}

const query = this.serializer.serialize(
'application/x-www-form-urlencoded',
params,
);
const query = railsQueryString.stringify(params);

return this.baseUrl + path + (query !== '' ? `?${query}` : '');
}
Expand Down

0 comments on commit ff5daad

Please sign in to comment.