# rpc middleware
# Install and use
The rpc middleware is an independent middleware and needs to be installed and used separately
npm i sener-rpc
import { RPC } from 'sener-rpc';
new RPC();
# Basic usage
The rpc middleware is used for remote call support, internally compatible with server and client requests, and supports both server and client.
import { Sener, Router } from 'sener';
import { RPC } from 'sener-rpc';
const router = new Router({
'/demo': async ({ col, rpc }) => {
const data = await rpc.comment.postReturn('/add', {content: 'xxx'});
return { data: {success: true} };
},
});
new Sener({
middlewares: [router, new RPC({
comment: 'http://localhost:9001/comment', // specify the address of the comment service
})],
});
# Request object
The Request object is an important concept in RPC. The Request object encapsulates some methods for initiating HTTP requests, and supports both the server and the client. The following is the class declaration of the Request object:
interface IRequestConsOptions {
base: string,
headers?: IJson<string>;
traceid?: string;
}
export class Request {
base: string;
headers: IJson<string> = {};
traceid: string = '';
tk = '';
setToken (tk: string) { this.tk = tk; };
static Interceptor: IRPCRequestInterceptor;
static OnResponse: IRPCRequestOnResponse;
constructor (options: IRequestConsOptions);
get<T=any> (url: string, query: IJson = {}): IRequestReturn<T>;
post<T=any> (url: string, body: IJson = {}, form = false): IRequestReturn<T>;
postForm<T=any> (url: string, body: IJson = {}): IRequestReturn<T>;
async request<T> (options: IRequestOptions): IRequestReturn<T>;
async postReturn<T=any> (url: string, body: IJson = {}): IParsedData;
async getReturn<T=any> (url: string, query: IJson = {}): IParsedData;
async requestReturn<T=any> (url: string, data: IJson = {}): IParsedData;
parseResult<T = any> (result: IRouterReturn<T>): IParsedData;
}
# request method
The request method is the basic method for initiating http requests
The parameters and return values are as follows
interface ICommonRequestOptions {
headers?: IJson<string>;
traceid?: string;
}
interface IRequestOptions extends ICommonRequestOptions {
body?: IJson,
query?: IJson,
url: string,
method?: IMethod,
data?: IJson,
form?: boolean,
traceid?: string,
base?: string,
}
type IRequestReturn<T=any> = Promise<IRouterReturn>;
type IRouterReturn<T=any> = ISenerResponse<IRouterData<T>>;
interface ISenerResponse<T = any> {
data: T,
statusCode?: number,
headers?: IJson<string>;
success?: boolean;
}
interface IRouterData<T=any> {
code: number;
data: T;
extra?: any;
msg?: string;
success?: boolean;
}
The post, get, and postForm methods all encapsulate the request method, and the postForm method is used to send formdata data
# parseResult method
The parseResult method is used to parse IRequestReturn data and convert it to IParsedData
interface IBoolResult {
success: boolean;
msg?: string;
}
type IParsedData = IBoolResult & IJson;
The postReturn, getReturn, and requestReturn methods will first call the corresponding request method, and then convert the return value through parseResult and return it.
# Interceptors
Request has two static interceptors, Interceptor and OnResponse
The Interceptor interceptor is used to intercept the request before the request starts, you can modify the request parameters and then continue the request
Or return a response directly, and no more requests will be made
interface IRPCResponse {
success: boolean,
data?: any,
code?: number,
msg: string,
err?: any,
[prop: string]: any,
}
type IRPCRequestInterceptor = (data: IRequestOptions) => void|IRPCResponse;
The OnResponse interceptor is used to modify the result returned by the request after the request is completed. or return a new response directly
type IRPCRequestOnResponse = (data: IRPCResponse) => void|IRPCResponse;
# Custom Request object
We can encapsulate our own service business logic by inheriting the Request object
import { Request } from 'sener-rpc';
interface IUser {
name: string;
age: number;
pwd: string;
}
class UserRequest extends Request {
await regist(data: IUser){
// If you are using ts, you can use generics to get better type support
const data = await this. postReturn<IUser>('/user/regist', data);
// can do some business logic processing
return data;
}
}
# Construction parameters
The construction parameter supports passing in key-value pairs or a function whose return value is IJson<Request|any>, declared as follows:
type IOptions = IJson<string> | ((traceid:string) => IJson<Request|any>);
# Use key-value pairs as parameters
Use key-value pairs to represent the name and service address of a set of remote services, as shown in the following figure
new RPC({
comment: 'http://localhost:9001/comment', // specify the address of the comment service
goods: 'http://localhost:9002', // specify the address of the goods service
//...
})
rpc will construct a Request object through a key-value pair to make a convenient remote call. In the basic example, rpc.comment is a Request object.
# Using functions as parameters
When using a function as a parameter, it is used to pass in a custom Request object. The function accepts a traceid parameter. This parameter is used to ensure that the traceid is consistent when the server is called remotely, and it needs to be used as a construction parameter of the Request. The use of traceid and log middleware can effectively locate the problem
Use as follows
function createServices(traceid) {
return {
user: new UserRequest({
base: 'http://localhost:9001/user',
traceid,
}),
comment: new CommentRequest({
base: 'http://localhost:9002/comment',
traceid,
})
};
}
new RPC(createServices);
# web client use
The client needs to use the WebRPC object
import {WebRPC} from 'sener-rpc/dist/web.umd';
// 1. A single service can pass in the base address
const comment = new WebRPC('http://localhost:3001');
await comment. get('/message', {page: 1});
// 2. Multiple services are passed into the map
const rpc = new WebRPC({
user: 'http://localhost:3000', // access base address of user service
comment: 'http://localhost:3001', // access base address of comment service
});
await rpc.comment.get('/message', {page: 1});
// 3. 使用继承方式
class Comment extends WebRPC {
getList ({ app = 'common', index = 1 }: {
app?: string
index?: number
} = {}) {
return this.get('/message', {
app,
index,
size: 10,
});
}
}
await (new Comment()).getList();
cdn 使用
<script src='https://cdn.jsdelivr.net/npm/sener-rpc'></script>
<script>
SenerRpc.WebRPC
</script>
← mongodb