Feat: protobuf support (#831)
* feat: protobuf support * Wuxiaworld (#31) * wuxiaworld * cleanup * make .proto smaller * add status * fix date and partial freechapter * fetchrpoto * no more JSON.parse * fix typeerrors * fetchProto as type * final draft * cleanup summary --------- Co-authored-by: K1ngfish3r <trulyihu@gmail.com>
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
import { parse as parseProto } from 'protobufjs';
|
||||
|
||||
type FetchInit = {
|
||||
headers?: Record<string, string | undefined> | Headers;
|
||||
method?: string;
|
||||
@@ -106,3 +108,51 @@ export const fetchText = async function (
|
||||
return "";
|
||||
}
|
||||
};
|
||||
|
||||
interface ProtoRequestInit {
|
||||
// merged .proto file
|
||||
proto: string;
|
||||
requestType: string;
|
||||
requestData?: any;
|
||||
responseType: string;
|
||||
}
|
||||
|
||||
const BYTE_MARK = BigInt((1 << 8) - 1);
|
||||
|
||||
export const fetchProto = async function<ReturnType> (
|
||||
protoInit: ProtoRequestInit,
|
||||
url: string,
|
||||
init?: FetchInit,
|
||||
) {
|
||||
const protoRoot = parseProto(protoInit.proto).root;
|
||||
const RequestMessge = protoRoot.lookupType(protoInit.requestType);
|
||||
if (RequestMessge.verify(protoInit.requestData)){
|
||||
throw new Error('Invalid Proto');
|
||||
}
|
||||
// encode request data
|
||||
const encodedrequest = RequestMessge.encode(protoInit.requestData).finish();
|
||||
const requestLength = BigInt(encodedrequest.length);
|
||||
const headers = new Uint8Array(
|
||||
Array(5).fill(0).map((v, idx) => {
|
||||
if(idx === 0) return 0;
|
||||
return Number((requestLength >> BigInt(8 * (5 - idx - 1))) & BYTE_MARK);
|
||||
})
|
||||
);
|
||||
init = await makeInit(init);
|
||||
const bodyArray = new Uint8Array(headers.length + encodedrequest.length)
|
||||
bodyArray.set(headers, 0)
|
||||
bodyArray.set(encodedrequest, headers.length)
|
||||
return fetch(url, {
|
||||
method: 'POST',
|
||||
...init,
|
||||
body: bodyArray
|
||||
} as RequestInit
|
||||
).then(r => r.arrayBuffer())
|
||||
.then(arr => {
|
||||
// decode response data
|
||||
const payload = new Uint8Array(arr);
|
||||
const length = Number(BigInt(payload[1] << 24) | BigInt(payload[2] << 16) | BigInt(payload[3] << 8) | BigInt(payload[4]));
|
||||
const ResponseMessage = protoRoot.lookupType(protoInit.responseType);
|
||||
return ResponseMessage.decode(payload.slice(5, 5 + length));
|
||||
}) as ReturnType
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user