Encode JSON-RPC GET request params as JSON
This commit is contained in:
parent
81225b77a8
commit
e2f6c5f798
@ -50,7 +50,7 @@ export function jsonrpc<Context>(
|
||||
service: T,
|
||||
methods: F[],
|
||||
) {
|
||||
const callRpcService = createRpcService(service, methods)
|
||||
const rpcService = createRpcService(service, methods)
|
||||
|
||||
const router = Router()
|
||||
|
||||
@ -76,13 +76,19 @@ export function jsonrpc<Context>(
|
||||
})
|
||||
throw err
|
||||
}
|
||||
callRpcService(req.query, getContext(req))
|
||||
const request = {
|
||||
id: req.query.id,
|
||||
jsonrpc: req.query.jsonrpc,
|
||||
method: req.query.method,
|
||||
params: JSON.parse(req.query.params),
|
||||
}
|
||||
rpcService.invoke(request, getContext(req))
|
||||
.then(response => handleResponse(response, res))
|
||||
.catch(next)
|
||||
})
|
||||
|
||||
router.post('/', (req, res, next) => {
|
||||
callRpcService(req.body, getContext(req))
|
||||
rpcService.invoke(req.body, getContext(req))
|
||||
.then(response => handleResponse(response, res))
|
||||
.catch(next)
|
||||
})
|
||||
|
||||
@ -69,51 +69,57 @@ export function createSuccessResponse<T>(id: number | string, result: T)
|
||||
}
|
||||
}
|
||||
|
||||
export const createRpcService =
|
||||
<T, M extends FunctionPropertyNames<T>>(
|
||||
service: T,
|
||||
methods: M[],
|
||||
) => async <Context>(req: IRequest<M, ArgumentTypes<T[M]>>, context: Context)
|
||||
: Promise<ISuccessResponse<RetType<T[M]>> | null> => {
|
||||
const {id, method, params} = req
|
||||
export const createRpcService = <T, M extends FunctionPropertyNames<T>>(
|
||||
service: T,
|
||||
methods: M[],
|
||||
) => {
|
||||
return {
|
||||
async invoke<Context>(
|
||||
req: IRequest<M, ArgumentTypes<T[M]>>,
|
||||
context: Context,
|
||||
): Promise<ISuccessResponse<RetType<T[M]>> | null> {
|
||||
const {id, method, params} = req
|
||||
|
||||
if (
|
||||
req.jsonrpc !== '2.0' ||
|
||||
typeof method !== 'string' ||
|
||||
!Array.isArray(params)
|
||||
) {
|
||||
throw createError(ERROR_INVALID_REQUEST, {
|
||||
id,
|
||||
data: null,
|
||||
statusCode: 400,
|
||||
})
|
||||
}
|
||||
if (
|
||||
req.jsonrpc !== '2.0' ||
|
||||
typeof method !== 'string' ||
|
||||
!Array.isArray(params)
|
||||
) {
|
||||
console.log(req.jsonrpc, method, params)
|
||||
throw createError(ERROR_INVALID_REQUEST, {
|
||||
id,
|
||||
data: null,
|
||||
statusCode: 400,
|
||||
})
|
||||
}
|
||||
|
||||
const isNotification = req.id === null || req.id === undefined
|
||||
const isNotification = req.id === null || req.id === undefined
|
||||
|
||||
const rpcService = pick(service, methods)
|
||||
const rpcService = pick(service, methods)
|
||||
|
||||
if (
|
||||
!rpcService.hasOwnProperty(method) ||
|
||||
typeof rpcService[method] !== 'function'
|
||||
) {
|
||||
throw createError(ERROR_METHOD_NOT_FOUND, {
|
||||
id,
|
||||
data: null,
|
||||
statusCode: 404,
|
||||
})
|
||||
}
|
||||
if (
|
||||
!rpcService.hasOwnProperty(method) ||
|
||||
typeof rpcService[method] !== 'function'
|
||||
) {
|
||||
throw createError(ERROR_METHOD_NOT_FOUND, {
|
||||
id,
|
||||
data: null,
|
||||
statusCode: 404,
|
||||
})
|
||||
}
|
||||
|
||||
let retValue = (rpcService[method] as any)(...params)
|
||||
let retValue = (rpcService[method] as any)(...params)
|
||||
|
||||
if (typeof retValue === 'function') {
|
||||
retValue = retValue(context)
|
||||
}
|
||||
if (typeof retValue === 'function') {
|
||||
retValue = retValue(context)
|
||||
}
|
||||
|
||||
if (!isPromise(retValue) && isNotification) {
|
||||
return null
|
||||
}
|
||||
if (!isPromise(retValue) && isNotification) {
|
||||
return null
|
||||
}
|
||||
|
||||
retValue = await retValue
|
||||
return createSuccessResponse(req.id as any, retValue)
|
||||
retValue = await retValue
|
||||
return createSuccessResponse(req.id as any, retValue)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@ -15,7 +15,8 @@ describe('remote', () => {
|
||||
|
||||
interface IService {
|
||||
add(a: number, b: number): number
|
||||
fetchItem(id: number): Promise<string>
|
||||
fetchItem(obj1: {a: number}, obj2: {b: number})
|
||||
: Promise<{a: number, b: number}>
|
||||
}
|
||||
const IServiceKeys = keys<IService>()
|
||||
|
||||
@ -23,8 +24,9 @@ describe('remote', () => {
|
||||
add(a: number, b: number) {
|
||||
return a + b
|
||||
}
|
||||
async fetchItem(id: number): Promise<string> {
|
||||
return Promise.resolve('id:' + id)
|
||||
async fetchItem(obj1: {a: number}, obj2: {b: number})
|
||||
: Promise<{a: number, b: number}> {
|
||||
return Promise.resolve({...obj1, ...obj2})
|
||||
}
|
||||
}
|
||||
|
||||
@ -60,8 +62,8 @@ describe('remote', () => {
|
||||
it('creates a proxy for remote service', async () => {
|
||||
const rpc = createRemoteClient<IService>(
|
||||
baseUrl, '/myService', IServiceKeys)
|
||||
const result = await rpc.fetchItem(5)
|
||||
expect(result).toBe('id:5')
|
||||
const result = await rpc.fetchItem({a: 10}, {b: 20})
|
||||
expect(result).toEqual({a: 10, b: 20})
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@ -33,7 +33,9 @@ export function createRemoteClient<T>(
|
||||
id,
|
||||
jsonrpc: '2.0',
|
||||
method,
|
||||
params,
|
||||
params: reqMethod === 'post'
|
||||
? params
|
||||
: JSON.stringify(params),
|
||||
},
|
||||
})
|
||||
if (response.data.error) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user