diff --git a/blahd/src/lib.rs b/blahd/src/lib.rs index 906c890..fa71ccf 100644 --- a/blahd/src/lib.rs +++ b/blahd/src/lib.rs @@ -129,7 +129,7 @@ impl AppState { type ArcState = State>; pub fn router(st: Arc) -> Router { - Router::new() + let router = Router::new() .route("/ws", get(handle_ws)) .route("/user/me", get(user_get).post(user_register)) .route("/room", get(room_list)) @@ -153,7 +153,8 @@ pub fn router(st: Arc) -> Router { HeaderName::from_static(X_BLAH_DIFFICULTY), ]), ) - .with_state(st) + .with_state(st); + Router::new().nest("/_blah", router) } type RE = R; diff --git a/blahd/tests/socket_activate.rs b/blahd/tests/socket_activate.rs index ce843bb..b7f4713 100644 --- a/blahd/tests/socket_activate.rs +++ b/blahd/tests/socket_activate.rs @@ -95,8 +95,9 @@ fn socket_activate() { } let resp = rt.block_on(async { + let url = format!("http://127.0.0.1:{local_port}/_blah/room?filter=public"); let fut = async { - reqwest::get(format!("http://127.0.0.1:{local_port}/room?filter=public")) + reqwest::get(url) .await .unwrap() .error_for_status() diff --git a/blahd/tests/webapi.rs b/blahd/tests/webapi.rs index 37c7b02..2f15aa4 100644 --- a/blahd/tests/webapi.rs +++ b/blahd/tests/webapi.rs @@ -130,7 +130,11 @@ struct Server { impl Server { 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 + use<'_> { @@ -881,7 +885,7 @@ async fn register(server: Server) { register_fast(&req) .await .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) .await diff --git a/docs/webapi.yaml b/docs/webapi.yaml index df1a44b..3e2b10d 100644 --- a/docs/webapi.yaml +++ b/docs/webapi.yaml @@ -6,7 +6,7 @@ info: paths: # OAPI does not support WebSocket interface definitions. # See: https://github.com/OAI/OpenAPI-Specification/issues/55#issuecomment-929382279 - /ws: + /_blah/ws: get: summary: WebSocket endpoint description: | @@ -46,7 +46,7 @@ paths: schema: $ref: '#/components/schemas/WSServerToClient' - /user/me: + /_blah/user/me: get: summary: Check registration status of the current user parameters: @@ -131,7 +131,7 @@ paths: schema: $ref: '#/components/schemas/ApiError' - /room: + /_blah/room: get: summary: List rooms parameters: @@ -190,7 +190,7 @@ paths: schema: $ref: '#/components/schemas/ApiError' - /room/create: + /_blah/room/create: post: summary: Create a room @@ -238,7 +238,7 @@ paths: schema: $ref: '#/components/schemas/ApiError' - /room/{rid}: + /_blah/room/{rid}: get: summary: Get room metadata parameters: @@ -264,7 +264,7 @@ paths: schema: $ref: '#/components/schemas/ApiError' - /room/{rid}/admin: + /_blah/room/{rid}/admin: post: summary: Room management @@ -295,7 +295,7 @@ paths: schema: $ref: '#/components/schemas/ApiError' - /room/{rid}/feed.json: + /_blah/room/{rid}/feed.json: get: summary: Get JSON feed of room description: | @@ -316,7 +316,7 @@ paths: schema: $ref: '#/components/schemas/ApiError' - /room/{rid}/msg: + /_blah/room/{rid}/msg: get: summary: List messages in a room description: | @@ -395,7 +395,7 @@ paths: schema: $ref: '#/components/schemas/ApiError' - /room/{rid}/msg/{cid}/seen: + /_blah/room/{rid}/msg/{cid}/seen: post: summary: Mark a message seen description: | diff --git a/test-frontend/main.js b/test-frontend/main.js index 05254be..c272524 100644 --- a/test-frontend/main.js +++ b/test-frontend/main.js @@ -6,7 +6,7 @@ const roomsInput = document.querySelector('#rooms'); const joinNewRoomInput = document.querySelector('#join-new-room'); const chatInput = document.querySelector('#chat'); -let serverUrl = null; +let apiUrl = null; let curRoom = null; let ws = null; let keypair = null; @@ -117,19 +117,19 @@ async function register() { const idUrl = prompt('id_url:', defaultConfig.id_url || ''); if (idUrl === null) return; - const getResp = await fetch(`${serverUrl}/user/me`, { + const getResp = await fetch(`${apiUrl}/user/me`, { cache: 'no-store' }) console.log(getResp.headers); const challenge = getResp.headers.get('x-blah-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. challenge_nonce: parseInt(challenge), id_key: getIdPubkey(), id_url: norm(idUrl), - server_url: norm(serverUrl), + server_url: norm(apiUrl), typ: 'user_register', }) 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; 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 ([status, json]) => { if (status !== 200) throw new Error(`status ${status}: ${json.error.message}`); @@ -230,7 +230,7 @@ async function enterRoom(rid) { }); 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 ([status, json]) => { if (status !== 200) throw new Error(`status ${status}: ${json.error.message}`); @@ -256,7 +256,7 @@ async function connectServer(newServerUrl) { log(`invalid url: ${e}`); return; } - serverUrl = newServerUrl; + apiUrl = wsUrl.toString() + '_blah'; if (ws !== null) { ws.close(); @@ -264,12 +264,12 @@ async function connectServer(newServerUrl) { log('connecting server'); wsUrl.protocol = wsUrl.protocol == 'http:' ? 'ws:' : 'wss:'; - wsUrl.pathname += wsUrl.pathname.endsWith('/') ? 'ws' : '/ws'; + wsUrl.pathname += '_blah/ws'; ws = new WebSocket(wsUrl); ws.onopen = async (_) => { const auth = await signData({ typ: 'auth' }); await ws.send(auth); - log(`listening events on server: ${serverUrl}`); + log(`listening events on server: ${newServerUrl}`); } ws.onclose = (e) => { console.error(e); @@ -310,7 +310,7 @@ async function loadRoomList(autoJoin) { targetEl.value = ''; 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() 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) { @@ -343,7 +343,7 @@ async function loadRoomList(autoJoin) { async function joinRoom(rid) { try { joinNewRoomInput.disabled = true; - await signAndPost(`${serverUrl}/room/${rid}/admin`, { + await signAndPost(`${apiUrl}/room/${rid}/admin`, { // sorted fields. permission: 1, // POST_CHAT room: rid, @@ -363,7 +363,7 @@ async function joinRoom(rid) { async function leaveRoom() { try { - await signAndPost(`${serverUrl}/room/${curRoom}/admin`, { + await signAndPost(`${apiUrl}/room/${curRoom}/admin`, { room: curRoom, typ: 'remove_member', user: await getActPubkey(), @@ -428,7 +428,7 @@ async function postChat(text) { } else { richText = [text]; } - await signAndPost(`${serverUrl}/room/${curRoom}/msg`, { + await signAndPost(`${apiUrl}/room/${curRoom}/msg`, { // sorted fields. rich_text: richText, room: curRoom, @@ -445,7 +445,7 @@ async function postChat(text) { async function markSeen() { try { - const resp = await fetch(`${serverUrl}/room/${curRoom}/msg/${lastCid}/seen`, { + const resp = await fetch(`${apiUrl}/room/${curRoom}/msg/${lastCid}/seen`, { method: 'POST', headers: (await genAuthHeader()).headers, })