Skip to content

Commit

Permalink
use bearer authorization instead of cookie
Browse files Browse the repository at this point in the history
  • Loading branch information
k2d222 committed Oct 26, 2024
1 parent c018927 commit e0952c3
Show file tree
Hide file tree
Showing 10 changed files with 124 additions and 166 deletions.
39 changes: 13 additions & 26 deletions client/src/server/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,6 @@ type ListenFn<K extends RecvKey> = (resp: Recv[K]) => unknown

export interface Options {
timeout?: number
http: boolean
}

const defaultSendOptions: Options = {
http: false
}

export interface Server {
Expand Down Expand Up @@ -96,7 +91,7 @@ export class WebSocketServer extends EventDispatcher<Recv> implements Server {

history: History

private token: string | null = null
token: string | null = null

constructor(cfg:ServerConfig) {
super()
Expand All @@ -122,8 +117,15 @@ export class WebSocketServer extends EventDispatcher<Recv> implements Server {
this.errorListener = fn
}

fetch(path: string, init: RequestInit = {}) {
init.headers = {
...init.headers,
...(this.token && { 'Authorization': 'Bearer ' + this.token })
}
return fetch(`${this.httpUrl}/${path}`, init)
}

query<K extends SendKey>(type: K, content: Send[K], options: Partial<Options> = {}): Promise<Resp[K]> {
const http = options.http || this.socket.readyState !== WebSocket.OPEN
let timeoutID = -1
let id = this.generateID()

Expand Down Expand Up @@ -161,23 +163,7 @@ export class WebSocketServer extends EventDispatcher<Recv> implements Server {
// we predict an ok response from the server and dispatch right away.
this.dispatch(type as any, content, promise.then())

if (http) {
fetch(this.httpUrl + '/http', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: "include",
body: message,
})
.then(async (resp) => {
const data = await resp.json() as RespPacket<SendKey>
this.handleResp(data)
}, async (resp) => {
const data = await resp.json() as RespPacket<SendKey>
this.handleResp(data)
})
} else {
this.socket.send(message)
}
this.socket.send(message)

return promise
}
Expand All @@ -193,10 +179,11 @@ export class WebSocketServer extends EventDispatcher<Recv> implements Server {
}

private handleMessage(data: RespPacket<SendKey> | RecvPacket<RecvKey>) {
if ('id' in data) {
if ('token' in data) {
this.token = data['token'] as string
} else if ('id' in data) {
const ops = this.history.resp(data)
if (ops) for (const [type, content] of ops) this.dispatch(type, content)

this.handleResp(data)
} else if ('err' in data) {
this.errorListener.call(undefined, data.err)
Expand Down
1 change: 0 additions & 1 deletion client/src/ui/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ export async function saveMap() {
export async function downloadMap() {
const rmap_ = get(rmap)
const server_ = get(server)

const httpUrl = server_.httpUrl
download(`${httpUrl}/maps/${rmap_.map.name}`, `${rmap_.map.name}.map`)
}
Expand Down
2 changes: 1 addition & 1 deletion client/src/ui/lib/editLayer.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@
const url = externalImageUrl(e.detail)
const embed = await showInfo('Do you wish to embed this image?', 'yesno')
if (embed) {
const resp = await fetch(url, { credentials: 'include' })
const resp = await $server.fetch(url)
const file = await resp.blob()
const name = e.detail
uploadImageAndPick(file, name)
Expand Down
3 changes: 1 addition & 2 deletions client/src/ui/lib/editSharing.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
let resp = await fetch(httpUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: "include",
body: JSON.stringify(json),
})
if (!resp.ok) throw await resp.text()
Expand All @@ -40,7 +39,7 @@
async function stopBridge(): Promise<void> {
const httpUrl = serverHttpUrl($serverCfg) + '/bridge_close'
await fetch(httpUrl, { credentials: 'include' })
await fetch(httpUrl)
}
function onToggleSharing() {
Expand Down
41 changes: 15 additions & 26 deletions client/src/ui/lib/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ export type Ctor<T> = new (...args: any[]) => T
export type FormEvent<T> = Event & { currentTarget: EventTarget & T }
export type FormInputEvent = FormEvent<HTMLInputElement>

export async function download(file: string, name: string) {
export async function download(path: string, name: string) {
const id = showInfo(`Downloading '${name}'…`, 'none')
try {
const resp = await fetch(file, { credentials: 'include' })
const resp = await fetch(path)
const data = await resp.blob()
const url = URL.createObjectURL(data)

Expand All @@ -43,35 +43,25 @@ export async function download(file: string, name: string) {
}
}

export async function uploadMap(httpRoot: string, name: string, file: Blob) {
const resp = await fetch(`${httpRoot}/maps/${name}`, {
export async function uploadMap(url: string, name: string, file: Blob) {
const resp = await fetch(`${url}/maps/${name}`, {
method: 'PUT',
credentials: 'include',
body: file,
})

if (!resp.ok) throw await resp.text()
}

export async function createMap(httpRoot: string, name: string, create: MapCreation) {
const resp = await fetch(`${httpRoot}/maps/${name}`, {
export async function createMap(url: string, name: string, create: MapCreation) {
const resp = await fetch(`${url}/maps/${name}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
body: JSON.stringify(create),
})

if (!resp.ok) throw await resp.text()
}

// export async function uploadImage(httpRoot: string, mapName: string, imageName: string, file: Blob) {
// await fetch(`${httpRoot}/maps/${mapName}/images/${imageName}`, {
// method: 'POST',
// credentials: 'include',
// body: file
// })
// }

export async function decodePng(file: Blob): Promise<ImageData> {
return new Promise<ImageData>((resolve, reject) => {
const img = document.createElement('img')
Expand All @@ -97,52 +87,51 @@ export function externalImageUrl(name: string) {
return '/mapres/' + name + '.png'
}

export async function queryMaps(httpRoot: string): Promise<MapDetail[]> {
export async function queryMaps(url: string): Promise<MapDetail[]> {
function sortMaps(maps: MapDetail[]): MapDetail[] {
return maps.sort((a, b) => {
if (a.users === b.users) return a.name.localeCompare(b.name)
else return b.users - a.users
})
}

const resp = await fetch(`${httpRoot}/maps`, { credentials: 'include' })
const resp = await fetch(`${url}/maps`)
const maps: MapDetail[] = await resp.json()
sortMaps(maps)
return maps
}

export async function queryConfig(httpRoot: string, mapName: string): Promise<Config> {
const resp = await fetch(`${httpRoot}/maps/${mapName}/config`, { credentials: 'include' })
export async function queryConfig(server: WebSocketServer, mapName: string): Promise<Config> {
const resp = await server.fetch(`maps/${mapName}/config`)
const config: Config = await resp.json()
return config
}

export async function queryMap(httpRoot: string, mapName: string): Promise<Map> {
const resp = await fetch(`${httpRoot}/maps/${mapName}`, { credentials: 'include' })
export async function queryMap(server: WebSocketServer, mapName: string): Promise<Map> {
const resp = await server.fetch(`maps/${mapName}`)
const data = await resp.arrayBuffer()
const map = new Map()
map.load(mapName, data)
return map
}

export async function queryImageData(
httpRoot: string,
server: WebSocketServer,
mapName: string,
imageIndex: number
): Promise<ImageData> {
const resp = await fetch(`${httpRoot}/maps/${mapName}/images/${imageIndex}`, { credentials: 'include' })
const resp = await server.fetch(`maps/${mapName}/images/${imageIndex}`)
const data = await resp.blob()
const image = await decodePng(data)
return image
}

export async function queryImage(
server: WebSocketServer,
httpRoot: string,
mapName: string,
imageIndex: number
): Promise<Image> {
const data = await queryImageData(httpRoot, mapName, imageIndex)
const data = await queryImageData(server, mapName, imageIndex)
const img = new Image()
const images = await server.query('get/images', undefined)
img.loadEmbedded(data)
Expand Down
3 changes: 1 addition & 2 deletions client/src/ui/routes/edit.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@
reset()
await $server.query('join', { name, password })
const httpUrl = $server.httpUrl
const map_ = await queryMap(httpUrl, name)
const map_ = await queryMap($server, name)
const ams = await $server.query('get/automappers', undefined)
$automappers = Object.fromEntries(ams.map(am => [am.name, am]))
$map = map_
Expand Down
1 change: 0 additions & 1 deletion client/src/ui/routes/lobby.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,6 @@
try {
let resp = await fetch(`${httpUrl}/maps/${mapName}`, {
method: 'DELETE',
credentials: "include",
})
if (!resp.ok) {
throw await resp.text()
Expand Down
12 changes: 11 additions & 1 deletion server/src/protocol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use serde_with::{
use twmap::{AutomapperConfig, EnvPoint, Position, Volume};
use vek::{Extent2, Rect, Rgba, Uv, Vec2};

use crate::{base64::Base64, error::Error};
use crate::{base64::Base64, error::Error, util::timestamp_now};

// Some documentation about the communication between clients and the server:
// ----------
Expand Down Expand Up @@ -533,5 +533,15 @@ pub struct Packet<T> {
pub content: T,
}

impl<T> Packet<T> {
pub fn new(id: Option<u32>, content: T) -> Self {
Self {
timestamp: timestamp_now(),
id,
content,
}
}
}

pub type SendPacket = Packet<Message>;
pub type RecvPacket = Packet<Request>;
Loading

0 comments on commit e0952c3

Please sign in to comment.