Skip to content

Commit

Permalink
fix: getUri stringify url
Browse files Browse the repository at this point in the history
  • Loading branch information
Rexer Wang committed May 2, 2023
1 parent 23bff55 commit dc59161
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 89 deletions.
14 changes: 13 additions & 1 deletion src/core/Requete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,18 @@ export interface IRequest extends Omit<RequestConfig, 'verbose'> {
*/
method?: Method
/** A string or object to set querystring of url */
params?: string | Record<string, string | number | boolean>
params?:
| string
| URLSearchParams
| Record<
string,
| string
| number
| boolean
| null
| undefined
| Array<string | number | boolean>
>
/** request`s body */
data?: RequestBody
/**
Expand Down Expand Up @@ -138,6 +149,7 @@ export class Requete {
headers: {
Accept: 'application/json, text/plain, */*',
},
verbose: 1,
toJSON: (text: string | null | undefined) => {
if (text) return JSON.parse(text)
},
Expand Down
3 changes: 3 additions & 0 deletions src/core/__tests__/requete-middleware.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { FetchAdapter } from 'requete/adapter'
import { toAny } from 'test/utils'

import { Requete } from '../Requete'

Expand Down Expand Up @@ -82,6 +83,8 @@ describe('Requete middleware specs', () => {
})

it('should throws when call next() duplicated', async () => {
vi.spyOn(console, 'error').mockImplementation(toAny(vi.fn()))

const requete = new Requete()
requete.use(async (ctx, next) => {
await next()
Expand Down
6 changes: 4 additions & 2 deletions src/core/__tests__/requete-request.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,11 @@ describe('Requete request configs', () => {
expect(ctx.request.url).toBe('https://api.mock.com/api/v2/do-mock?id=1')

ctx = await requete.get('do-mock?id=1', { params: { id: '2' } })
expect(ctx.request.url).toBe('https://api.mock.com/api/v1/do-mock?id=2')
expect(ctx.request.url).toBe(
'https://api.mock.com/api/v1/do-mock?id=1&id=2'
)

ctx = await requete.get('do-mock?id=1', { params: 'id=2' })
ctx = await requete.get('do-mock', { params: 'id=2' })
expect(ctx.request.url).toBe('https://api.mock.com/api/v1/do-mock?id=2')
})
})
127 changes: 50 additions & 77 deletions src/shared/__tests__/getUri.test.ts
Original file line number Diff line number Diff line change
@@ -1,118 +1,91 @@
import { toAny } from 'test/utils'

import { getUri } from '../getUri'

describe('getUri specs', () => {
it('should not join when given a absolute url', () => {
expect(
getUri(
toAny({
baseURL: 'https://requete.com',
url: 'https://api.com/api/v1/posts',
})
)
getUri({
baseURL: 'https://requete.com',
url: 'https://api.com/api/v1/posts',
})
).toBe('https://api.com/api/v1/posts')

expect(
getUri(
toAny({
baseURL: 'https://requete.com',
url: '//api.com/api/v1/posts',
})
)
getUri({
baseURL: 'https://requete.com',
url: '//api.com/api/v1/posts',
})
).toBe('//api.com/api/v1/posts')
})

it('should not join when baseURL is falsy', () => {
expect(
getUri(
toAny({
baseURL: undefined,
url: '/api/v1/posts',
})
)
getUri({
baseURL: undefined,
url: '/api/v1/posts',
})
).toBe('/api/v1/posts')

expect(
getUri(
toAny({
baseURL: '',
url: '/api/v1/posts',
})
)
getUri({
baseURL: '',
url: '/api/v1/posts',
})
).toBe('/api/v1/posts')
})

it('should join with baseURL with separator', () => {
expect(
getUri(
toAny({
baseURL: 'https://requete.com/',
url: '/api/v1/posts',
})
)
getUri({
baseURL: 'https://requete.com/',
url: '/api/v1/posts#t=1',
})
).toBe('https://requete.com/api/v1/posts')

expect(
getUri(
toAny({
baseURL: 'https://requete.com//',
url: '/api/v1/posts/',
})
)
getUri({
baseURL: 'https://requete.com//',
url: '/api/v1/posts/',
})
).toBe('https://requete.com/api/v1/posts/')
})

it('should join url with query-string when given string params', () => {
expect(
getUri(
toAny({
url: 'https://requete.com/api/v1/posts',
params: 'a=1',
})
)
getUri({
url: 'https://requete.com/api/v1/posts',
params: 'a=1',
})
).toBe('https://requete.com/api/v1/posts?a=1')

expect(
getUri(
toAny({
url: 'https://requete.com/api/v1/posts',
params: '?a=1',
})
)
).toBe('https://requete.com/api/v1/posts?a=1')
getUri({
url: 'https://requete.com/api/v1/posts?t=123',
params: '?a=1',
})
).toBe('https://requete.com/api/v1/posts?t=123&a=1')
})

it('should join url with query-string when given object params', () => {
expect(
getUri(
toAny({
url: 'https://requete.com/api/v1/posts',
params: { a: 1, b: 2 },
})
)
).toBe('https://requete.com/api/v1/posts?a=1&b=2')
getUri({
url: 'https://requete.com/api/v1/posts',
params: {
a: '1+1',
b: '2 1',
c: null,
d: undefined,
arr: [1, 2, 3],
},
})
).toBe('https://requete.com/api/v1/posts?a=1%2B1&b=2+1&arr=1&arr=2&arr=3')
})

it('should join url with query-string when given url with params & config.params', () => {
it('should join url with query-string when given the URLSearchParams', () => {
expect(
getUri(
toAny({
url: 'https://requete.com/api/v1/posts?c=3',
params: { a: 1, b: 2 },
})
)
).toBe('https://requete.com/api/v1/posts?c=3&a=1&b=2')
})

it('should overwrite origin url params when given same keys in params', () => {
expect(
getUri(
toAny({
url: 'https://requete.com/api/v1/posts?a=3',
params: { a: 1, b: 2, c: 4 },
})
)
).toBe('https://requete.com/api/v1/posts?a=1&b=2&c=4')
getUri({
url: 'https://requete.com/api/v1/posts',
params: new URLSearchParams({ a: '1', b: '2' }),
})
).toBe('https://requete.com/api/v1/posts?a=1&b=2')
})
})
26 changes: 17 additions & 9 deletions src/shared/getUri.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,24 @@
import type { IRequest } from 'requete'

function stringifyUrl(target: string, query: NonNullable<IRequest['params']>) {
const [url, search] = target.split('?')
const searchParams = new URLSearchParams(search)
if (typeof query === 'string') {
new URLSearchParams(query).forEach((value, key) => {
searchParams.set(key, value)
})
function stringifyUrl(url: string, query: NonNullable<IRequest['params']>) {
let searchParams: URLSearchParams

if (query instanceof URLSearchParams) {
searchParams = query
} else if (typeof query === 'string' || Array.isArray(query)) {
searchParams = new URLSearchParams(query)
} else {
searchParams = new URLSearchParams()
Object.entries(query).forEach(([key, value]) => {
searchParams.set(key, encodeURIComponent(value))
if (Array.isArray(value)) {
value.forEach((val) => searchParams.append(key, val.toString()))
} else if (value != null) {
searchParams.set(key, value.toString())
}
})
}

return url + '?' + searchParams.toString()
return url + (url.indexOf('?') === -1 ? '?' : '&') + searchParams.toString()
}

function isAbsolute(url: string) {
Expand All @@ -23,6 +28,9 @@ function isAbsolute(url: string) {
export function getUri(config: IRequest) {
let url = config.url

const hashIndex = url.indexOf('#')
if (hashIndex > -1) url = url.slice(0, hashIndex)

if (!isAbsolute(url) && config.baseURL) {
url = config.baseURL.replace(/\/+$/, '') + '/' + url.replace(/^\/+/, '')
}
Expand Down

0 comments on commit dc59161

Please sign in to comment.