mirror of
https://github.com/Blah-IM/blahrs.git
synced 2025-05-01 08:41:09 +00:00
refactor(webapi)!: put all API under path /_blah
This commit is contained in:
parent
ab756f78ab
commit
0c28c00c3d
5 changed files with 34 additions and 28 deletions
|
@ -129,7 +129,7 @@ impl AppState {
|
||||||
type ArcState = State<Arc<AppState>>;
|
type ArcState = State<Arc<AppState>>;
|
||||||
|
|
||||||
pub fn router(st: Arc<AppState>) -> Router {
|
pub fn router(st: Arc<AppState>) -> Router {
|
||||||
Router::new()
|
let router = Router::new()
|
||||||
.route("/ws", get(handle_ws))
|
.route("/ws", get(handle_ws))
|
||||||
.route("/user/me", get(user_get).post(user_register))
|
.route("/user/me", get(user_get).post(user_register))
|
||||||
.route("/room", get(room_list))
|
.route("/room", get(room_list))
|
||||||
|
@ -153,7 +153,8 @@ pub fn router(st: Arc<AppState>) -> Router {
|
||||||
HeaderName::from_static(X_BLAH_DIFFICULTY),
|
HeaderName::from_static(X_BLAH_DIFFICULTY),
|
||||||
]),
|
]),
|
||||||
)
|
)
|
||||||
.with_state(st)
|
.with_state(st);
|
||||||
|
Router::new().nest("/_blah", router)
|
||||||
}
|
}
|
||||||
|
|
||||||
type RE<T> = R<T, ApiError>;
|
type RE<T> = R<T, ApiError>;
|
||||||
|
|
|
@ -95,8 +95,9 @@ fn socket_activate() {
|
||||||
}
|
}
|
||||||
|
|
||||||
let resp = rt.block_on(async {
|
let resp = rt.block_on(async {
|
||||||
|
let url = format!("http://127.0.0.1:{local_port}/_blah/room?filter=public");
|
||||||
let fut = async {
|
let fut = async {
|
||||||
reqwest::get(format!("http://127.0.0.1:{local_port}/room?filter=public"))
|
reqwest::get(url)
|
||||||
.await
|
.await
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.error_for_status()
|
.error_for_status()
|
||||||
|
|
|
@ -130,7 +130,11 @@ struct Server {
|
||||||
|
|
||||||
impl Server {
|
impl Server {
|
||||||
fn url(&self, rhs: impl fmt::Display) -> String {
|
fn url(&self, rhs: impl fmt::Display) -> String {
|
||||||
format!("http://{}:{}{}", LOCALHOST, self.port, rhs)
|
format!("{}/_blah{}", self.domain(), rhs)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn domain(&self) -> String {
|
||||||
|
format!("http://{}:{}", LOCALHOST, self.port)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rng(&self) -> impl DerefMut<Target = impl RngCore> + use<'_> {
|
fn rng(&self) -> impl DerefMut<Target = impl RngCore> + use<'_> {
|
||||||
|
@ -881,7 +885,7 @@ async fn register(server: Server) {
|
||||||
register_fast(&req)
|
register_fast(&req)
|
||||||
.await
|
.await
|
||||||
.expect_api_err(StatusCode::BAD_REQUEST, "invalid_server_url");
|
.expect_api_err(StatusCode::BAD_REQUEST, "invalid_server_url");
|
||||||
req.server_url = server.url("").parse().unwrap();
|
req.server_url = server.domain().parse().unwrap();
|
||||||
|
|
||||||
register_fast(&req)
|
register_fast(&req)
|
||||||
.await
|
.await
|
||||||
|
|
|
@ -6,7 +6,7 @@ info:
|
||||||
paths:
|
paths:
|
||||||
# OAPI does not support WebSocket interface definitions.
|
# OAPI does not support WebSocket interface definitions.
|
||||||
# See: https://github.com/OAI/OpenAPI-Specification/issues/55#issuecomment-929382279
|
# See: https://github.com/OAI/OpenAPI-Specification/issues/55#issuecomment-929382279
|
||||||
/ws:
|
/_blah/ws:
|
||||||
get:
|
get:
|
||||||
summary: WebSocket endpoint
|
summary: WebSocket endpoint
|
||||||
description: |
|
description: |
|
||||||
|
@ -46,7 +46,7 @@ paths:
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/components/schemas/WSServerToClient'
|
$ref: '#/components/schemas/WSServerToClient'
|
||||||
|
|
||||||
/user/me:
|
/_blah/user/me:
|
||||||
get:
|
get:
|
||||||
summary: Check registration status of the current user
|
summary: Check registration status of the current user
|
||||||
parameters:
|
parameters:
|
||||||
|
@ -131,7 +131,7 @@ paths:
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/components/schemas/ApiError'
|
$ref: '#/components/schemas/ApiError'
|
||||||
|
|
||||||
/room:
|
/_blah/room:
|
||||||
get:
|
get:
|
||||||
summary: List rooms
|
summary: List rooms
|
||||||
parameters:
|
parameters:
|
||||||
|
@ -190,7 +190,7 @@ paths:
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/components/schemas/ApiError'
|
$ref: '#/components/schemas/ApiError'
|
||||||
|
|
||||||
/room/create:
|
/_blah/room/create:
|
||||||
post:
|
post:
|
||||||
summary: Create a room
|
summary: Create a room
|
||||||
|
|
||||||
|
@ -238,7 +238,7 @@ paths:
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/components/schemas/ApiError'
|
$ref: '#/components/schemas/ApiError'
|
||||||
|
|
||||||
/room/{rid}:
|
/_blah/room/{rid}:
|
||||||
get:
|
get:
|
||||||
summary: Get room metadata
|
summary: Get room metadata
|
||||||
parameters:
|
parameters:
|
||||||
|
@ -264,7 +264,7 @@ paths:
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/components/schemas/ApiError'
|
$ref: '#/components/schemas/ApiError'
|
||||||
|
|
||||||
/room/{rid}/admin:
|
/_blah/room/{rid}/admin:
|
||||||
post:
|
post:
|
||||||
summary: Room management
|
summary: Room management
|
||||||
|
|
||||||
|
@ -295,7 +295,7 @@ paths:
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/components/schemas/ApiError'
|
$ref: '#/components/schemas/ApiError'
|
||||||
|
|
||||||
/room/{rid}/feed.json:
|
/_blah/room/{rid}/feed.json:
|
||||||
get:
|
get:
|
||||||
summary: Get JSON feed of room
|
summary: Get JSON feed of room
|
||||||
description: |
|
description: |
|
||||||
|
@ -316,7 +316,7 @@ paths:
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/components/schemas/ApiError'
|
$ref: '#/components/schemas/ApiError'
|
||||||
|
|
||||||
/room/{rid}/msg:
|
/_blah/room/{rid}/msg:
|
||||||
get:
|
get:
|
||||||
summary: List messages in a room
|
summary: List messages in a room
|
||||||
description: |
|
description: |
|
||||||
|
@ -395,7 +395,7 @@ paths:
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/components/schemas/ApiError'
|
$ref: '#/components/schemas/ApiError'
|
||||||
|
|
||||||
/room/{rid}/msg/{cid}/seen:
|
/_blah/room/{rid}/msg/{cid}/seen:
|
||||||
post:
|
post:
|
||||||
summary: Mark a message seen
|
summary: Mark a message seen
|
||||||
description: |
|
description: |
|
||||||
|
|
|
@ -6,7 +6,7 @@ const roomsInput = document.querySelector('#rooms');
|
||||||
const joinNewRoomInput = document.querySelector('#join-new-room');
|
const joinNewRoomInput = document.querySelector('#join-new-room');
|
||||||
const chatInput = document.querySelector('#chat');
|
const chatInput = document.querySelector('#chat');
|
||||||
|
|
||||||
let serverUrl = null;
|
let apiUrl = null;
|
||||||
let curRoom = null;
|
let curRoom = null;
|
||||||
let ws = null;
|
let ws = null;
|
||||||
let keypair = null;
|
let keypair = null;
|
||||||
|
@ -117,19 +117,19 @@ async function register() {
|
||||||
const idUrl = prompt('id_url:', defaultConfig.id_url || '');
|
const idUrl = prompt('id_url:', defaultConfig.id_url || '');
|
||||||
if (idUrl === null) return;
|
if (idUrl === null) return;
|
||||||
|
|
||||||
const getResp = await fetch(`${serverUrl}/user/me`, {
|
const getResp = await fetch(`${apiUrl}/user/me`, {
|
||||||
cache: 'no-store'
|
cache: 'no-store'
|
||||||
})
|
})
|
||||||
console.log(getResp.headers);
|
console.log(getResp.headers);
|
||||||
const challenge = getResp.headers.get('x-blah-nonce');
|
const challenge = getResp.headers.get('x-blah-nonce');
|
||||||
if (challenge === null) throw new Error('cannot get challenge nonce');
|
if (challenge === null) throw new Error('cannot get challenge nonce');
|
||||||
|
|
||||||
const postResp = await signAndPost(`${serverUrl}/user/me`, {
|
const postResp = await signAndPost(`${apiUrl}/user/me`, {
|
||||||
// sorted fields.
|
// sorted fields.
|
||||||
challenge_nonce: parseInt(challenge),
|
challenge_nonce: parseInt(challenge),
|
||||||
id_key: getIdPubkey(),
|
id_key: getIdPubkey(),
|
||||||
id_url: norm(idUrl),
|
id_url: norm(idUrl),
|
||||||
server_url: norm(serverUrl),
|
server_url: norm(apiUrl),
|
||||||
typ: 'user_register',
|
typ: 'user_register',
|
||||||
})
|
})
|
||||||
if (!postResp.ok) throw new Error(`status ${getResp.status}: ${(await getResp.json()).error.message}`);
|
if (!postResp.ok) throw new Error(`status ${getResp.status}: ${(await getResp.json()).error.message}`);
|
||||||
|
@ -219,7 +219,7 @@ async function enterRoom(rid) {
|
||||||
roomsInput.value = rid;
|
roomsInput.value = rid;
|
||||||
|
|
||||||
genAuthHeader()
|
genAuthHeader()
|
||||||
.then(opts => fetch(`${serverUrl}/room/${rid}`, opts))
|
.then(opts => fetch(`${apiUrl}/room/${rid}`, opts))
|
||||||
.then(async (resp) => [resp.status, await resp.json()])
|
.then(async (resp) => [resp.status, await resp.json()])
|
||||||
.then(async ([status, json]) => {
|
.then(async ([status, json]) => {
|
||||||
if (status !== 200) throw new Error(`status ${status}: ${json.error.message}`);
|
if (status !== 200) throw new Error(`status ${status}: ${json.error.message}`);
|
||||||
|
@ -230,7 +230,7 @@ async function enterRoom(rid) {
|
||||||
});
|
});
|
||||||
|
|
||||||
genAuthHeader()
|
genAuthHeader()
|
||||||
.then(opts => fetch(`${serverUrl}/room/${rid}/msg`, opts))
|
.then(opts => fetch(`${apiUrl}/room/${rid}/msg`, opts))
|
||||||
.then(async (resp) => { return [resp.status, await resp.json()]; })
|
.then(async (resp) => { return [resp.status, await resp.json()]; })
|
||||||
.then(async ([status, json]) => {
|
.then(async ([status, json]) => {
|
||||||
if (status !== 200) throw new Error(`status ${status}: ${json.error.message}`);
|
if (status !== 200) throw new Error(`status ${status}: ${json.error.message}`);
|
||||||
|
@ -256,7 +256,7 @@ async function connectServer(newServerUrl) {
|
||||||
log(`invalid url: ${e}`);
|
log(`invalid url: ${e}`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
serverUrl = newServerUrl;
|
apiUrl = wsUrl.toString() + '_blah';
|
||||||
|
|
||||||
if (ws !== null) {
|
if (ws !== null) {
|
||||||
ws.close();
|
ws.close();
|
||||||
|
@ -264,12 +264,12 @@ async function connectServer(newServerUrl) {
|
||||||
|
|
||||||
log('connecting server');
|
log('connecting server');
|
||||||
wsUrl.protocol = wsUrl.protocol == 'http:' ? 'ws:' : 'wss:';
|
wsUrl.protocol = wsUrl.protocol == 'http:' ? 'ws:' : 'wss:';
|
||||||
wsUrl.pathname += wsUrl.pathname.endsWith('/') ? 'ws' : '/ws';
|
wsUrl.pathname += '_blah/ws';
|
||||||
ws = new WebSocket(wsUrl);
|
ws = new WebSocket(wsUrl);
|
||||||
ws.onopen = async (_) => {
|
ws.onopen = async (_) => {
|
||||||
const auth = await signData({ typ: 'auth' });
|
const auth = await signData({ typ: 'auth' });
|
||||||
await ws.send(auth);
|
await ws.send(auth);
|
||||||
log(`listening events on server: ${serverUrl}`);
|
log(`listening events on server: ${newServerUrl}`);
|
||||||
}
|
}
|
||||||
ws.onclose = (e) => {
|
ws.onclose = (e) => {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
|
@ -310,7 +310,7 @@ async function loadRoomList(autoJoin) {
|
||||||
targetEl.value = '';
|
targetEl.value = '';
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const resp = await fetch(`${serverUrl}/room?filter=${filter}`, await genAuthHeader())
|
const resp = await fetch(`${apiUrl}/room?filter=${filter}`, await genAuthHeader())
|
||||||
const json = await resp.json()
|
const json = await resp.json()
|
||||||
if (resp.status !== 200) throw new Error(`status ${resp.status}: ${json.error.message}`);
|
if (resp.status !== 200) throw new Error(`status ${resp.status}: ${json.error.message}`);
|
||||||
for (const { rid, title, attrs, last_msg, last_seen_cid } of json.rooms) {
|
for (const { rid, title, attrs, last_msg, last_seen_cid } of json.rooms) {
|
||||||
|
@ -343,7 +343,7 @@ async function loadRoomList(autoJoin) {
|
||||||
async function joinRoom(rid) {
|
async function joinRoom(rid) {
|
||||||
try {
|
try {
|
||||||
joinNewRoomInput.disabled = true;
|
joinNewRoomInput.disabled = true;
|
||||||
await signAndPost(`${serverUrl}/room/${rid}/admin`, {
|
await signAndPost(`${apiUrl}/room/${rid}/admin`, {
|
||||||
// sorted fields.
|
// sorted fields.
|
||||||
permission: 1, // POST_CHAT
|
permission: 1, // POST_CHAT
|
||||||
room: rid,
|
room: rid,
|
||||||
|
@ -363,7 +363,7 @@ async function joinRoom(rid) {
|
||||||
|
|
||||||
async function leaveRoom() {
|
async function leaveRoom() {
|
||||||
try {
|
try {
|
||||||
await signAndPost(`${serverUrl}/room/${curRoom}/admin`, {
|
await signAndPost(`${apiUrl}/room/${curRoom}/admin`, {
|
||||||
room: curRoom,
|
room: curRoom,
|
||||||
typ: 'remove_member',
|
typ: 'remove_member',
|
||||||
user: await getActPubkey(),
|
user: await getActPubkey(),
|
||||||
|
@ -428,7 +428,7 @@ async function postChat(text) {
|
||||||
} else {
|
} else {
|
||||||
richText = [text];
|
richText = [text];
|
||||||
}
|
}
|
||||||
await signAndPost(`${serverUrl}/room/${curRoom}/msg`, {
|
await signAndPost(`${apiUrl}/room/${curRoom}/msg`, {
|
||||||
// sorted fields.
|
// sorted fields.
|
||||||
rich_text: richText,
|
rich_text: richText,
|
||||||
room: curRoom,
|
room: curRoom,
|
||||||
|
@ -445,7 +445,7 @@ async function postChat(text) {
|
||||||
|
|
||||||
async function markSeen() {
|
async function markSeen() {
|
||||||
try {
|
try {
|
||||||
const resp = await fetch(`${serverUrl}/room/${curRoom}/msg/${lastCid}/seen`, {
|
const resp = await fetch(`${apiUrl}/room/${curRoom}/msg/${lastCid}/seen`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: (await genAuthHeader()).headers,
|
headers: (await genAuthHeader()).headers,
|
||||||
})
|
})
|
||||||
|
|
Loading…
Add table
Reference in a new issue