mirror of
https://github.com/ether/etherpad-lite.git
synced 2025-04-23 17:06:16 -04:00
Restructured rest api
This commit is contained in:
parent
08f199178d
commit
644cb9b39f
5 changed files with 113 additions and 11 deletions
|
@ -82,6 +82,12 @@
|
|||
"expressCreateServer": "ep_etherpad-lite/node/hooks/express/errorhandling"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "restApi",
|
||||
"hooks": {
|
||||
"expressCreateServer": "ep_etherpad-lite/node/handler/RestAPI"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "socketio",
|
||||
"hooks": {
|
||||
|
|
|
@ -24,10 +24,10 @@ import {MapArrayType} from "../types/MapType";
|
|||
const api = require('../db/API');
|
||||
const padManager = require('../db/PadManager');
|
||||
import createHTTPError from 'http-errors';
|
||||
import {Http2ServerRequest, Http2ServerResponse} from "node:http2";
|
||||
import {Http2ServerRequest} from "node:http2";
|
||||
import {publicKeyExported} from "../security/OAuth2Provider";
|
||||
import {jwtVerify} from "jose";
|
||||
import {apikey} from './APIKeyHandler'
|
||||
import {APIFields, apikey} from './APIKeyHandler'
|
||||
// a list of all functions
|
||||
const version:MapArrayType<any> = {};
|
||||
|
||||
|
@ -141,6 +141,13 @@ version['1.3.0'] = {
|
|||
setText: ['padID', 'text', 'authorId'],
|
||||
};
|
||||
|
||||
|
||||
version['2.2.2'] = {
|
||||
...version['1.3.0'],
|
||||
|
||||
}
|
||||
|
||||
|
||||
// set the latest available API version here
|
||||
exports.latestApiVersion = '1.3.0';
|
||||
|
||||
|
@ -148,13 +155,6 @@ exports.latestApiVersion = '1.3.0';
|
|||
exports.version = version;
|
||||
|
||||
|
||||
type APIFields = {
|
||||
apikey: string;
|
||||
api_key: string;
|
||||
padID: string;
|
||||
padName: string;
|
||||
authorization: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles an HTTP API call
|
||||
|
|
|
@ -7,6 +7,16 @@ const settings = require('../utils/Settings');
|
|||
|
||||
const apiHandlerLogger = log4js.getLogger('APIHandler');
|
||||
|
||||
|
||||
|
||||
export type APIFields = {
|
||||
apikey: string;
|
||||
api_key: string;
|
||||
padID: string;
|
||||
padName: string;
|
||||
authorization: string;
|
||||
}
|
||||
|
||||
// ensure we have an apikey
|
||||
export let apikey:string|null = null;
|
||||
const apikeyFilename = absolutePaths.makeAbsolute(argv.apikey || './APIKEY.txt');
|
||||
|
|
84
src/node/handler/RestAPI.ts
Normal file
84
src/node/handler/RestAPI.ts
Normal file
|
@ -0,0 +1,84 @@
|
|||
import {ArgsExpressType} from "../types/ArgsExpressType";
|
||||
import {MapArrayType} from "../types/MapType";
|
||||
import {IncomingForm} from "formidable";
|
||||
import {ErrorCaused} from "../types/ErrorCaused";
|
||||
import createHTTPError from "http-errors";
|
||||
const apiHandler = require('./APIHandler')
|
||||
|
||||
type RestAPIMapping = {
|
||||
apiVersion: string;
|
||||
functionName: string
|
||||
}
|
||||
|
||||
|
||||
const mapping = new Map<string, Record<string,RestAPIMapping>>
|
||||
|
||||
|
||||
export const expressCreateServer = async (hookName: string, {app}: ArgsExpressType) => {
|
||||
mapping.set('GET', {})
|
||||
mapping.set('POST', {})
|
||||
mapping.set('PUT', {})
|
||||
mapping.set('DELETE', {})
|
||||
mapping.set('PATCH', {})
|
||||
|
||||
// Version 1
|
||||
mapping.get('POST')!["/groups"] = {apiVersion: '1', functionName: 'createGroup'}
|
||||
mapping.get('GET')!["/pads"] = {apiVersion: '1', functionName: 'listPads'}
|
||||
mapping.get('POST')!["/groups/createIfNotExistsFor"] = {apiVersion: '1', functionName: 'createGroupIfNotExistsFor'};
|
||||
|
||||
app.use('/api/2', async (req, res, next) => {
|
||||
const method = req.method
|
||||
const pathToFunction = req.path
|
||||
// parse fields from request
|
||||
const {headers, params, query} = req;
|
||||
|
||||
// read form data if method was POST
|
||||
let formData: MapArrayType<any> = {};
|
||||
if (method === 'post') {
|
||||
const form = new IncomingForm();
|
||||
formData = (await form.parse(req))[0];
|
||||
for (const k of Object.keys(formData)) {
|
||||
if (formData[k] instanceof Array) {
|
||||
formData[k] = formData[k][0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const fields = Object.assign({}, headers, params, query, formData);
|
||||
|
||||
if (mapping.has(method) && pathToFunction in mapping.get(method)!) {
|
||||
const {apiVersion, functionName} = mapping.get(method)![pathToFunction]!
|
||||
// pass to api handler
|
||||
let data;
|
||||
try {
|
||||
data = await apiHandler.handle(apiVersion, functionName, fields, req, res);
|
||||
} catch (err) {
|
||||
const errCaused = err as ErrorCaused
|
||||
// convert all errors to http errors
|
||||
if (createHTTPError.isHttpError(err)) {
|
||||
// pass http errors thrown by handler forward
|
||||
throw err;
|
||||
} else if (errCaused.name === 'apierror') {
|
||||
// parameters were wrong and the api stopped execution, pass the error
|
||||
// convert to http error
|
||||
throw new createHTTPError.BadRequest(errCaused.message);
|
||||
} else {
|
||||
// an unknown error happened
|
||||
// log it and throw internal error
|
||||
console.error(errCaused.stack || errCaused.toString());
|
||||
throw new createHTTPError.InternalServerError('internal error');
|
||||
}
|
||||
}
|
||||
|
||||
// return in common format
|
||||
const response = {code: 0, message: 'ok', data: data || null};
|
||||
|
||||
console.debug(`RESPONSE, ${functionName}, ${JSON.stringify(response)}`);
|
||||
|
||||
// return the response data
|
||||
res.json(response);
|
||||
} else {
|
||||
res.json({code: 1, message: 'not found'});
|
||||
}
|
||||
})
|
||||
}
|
|
@ -1,5 +1,7 @@
|
|||
import {Express} from "express";
|
||||
|
||||
export type ArgsExpressType = {
|
||||
app:any,
|
||||
app:Express,
|
||||
io: any,
|
||||
server:any
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue