Skip to content

How to register a custom scheme in wry #705

@aeraer21

Description

@aeraer21

`mod args;
mod game_data;
mod hasher;
mod model;
mod dir;
mod listen_msg;

use std::{borrow::Cow, fs, path::PathBuf};

use rust_embed::RustEmbed;
use tao::{event::Event, event_loop::{ControlFlow, EventLoop}, window::WindowBuilder};
use wry::{http::Response, Error as WryError, WebView, WebViewBuilder};

use crate::{args::get_args, dir::get_base_dir, game_data::get_game_data_path, hasher::verify_and_cache_assets, listen_msg::listen_for_asset_ready_messages};

#[derive(RustEmbed)]
#[folder = "assets/"]
struct Asset;

//런처 보안 구조
/**일렉트론이 게임 시작하면 game_id, package_id 제공 -> 런처는 manifest기반 정보로 압축해제된 파일을 즉시 열고 해시 후 캐싱하고 바로 삭제
-> 동적으로 다운로드된 다른 파일들도 전부 적용 -> 그럼 한번만 보안검사 하고 더이상 보안검사 필요없음
-> 유저가 게임을 종료해도 어차피 게임을 다시 시작하면 또 동적 다운로드 및 검사 시작
*/
fn main() -> wry::Result<()> {
let (game_id, package_id) = match get_args() {
Some((game_id, package_id)) => (game_id, package_id),
None => {
eprintln!("❌ 실행 시 --game-id 와 --package-id 인자를 넘겨야 합니다.");
std::process::exit(1);
}
};
let asset_dir = get_base_dir()
.join(game_id.clone())
.join(package_id.clone());

let cache = verify_and_cache_assets(&asset_dir)
    .map_err(|e| wry::Error::from(std::io::Error::new(std::io::ErrorKind::Other, e)))?;
// 2. index.html 경로 구성 
let game_path = get_game_data_path(&game_id, &package_id);
let index_path = game_path.join("index.html");

// 3. HTML 파일 읽기
let html_content = fs::read_to_string(&index_path).unwrap_or_else(|err| {
    eprintln!("❌ index.html 로드 실패: {}\n 경로 : {}", err, &index_path.to_string_lossy());
    std::process::exit(1);
});

std::thread::spawn(move || {
    listen_for_asset_ready_messages();
});

// 4. WebView 초기화
let event_loop = EventLoop::new();
let window = WindowBuilder::new().with_title("Rust Game Launcher").build(&event_loop).expect("윈도우 생성 실패");

let _webview: WebView = WebViewBuilder::new(&window)
    .with_html(&html_content)
    .with_custom_protocol("game".to_string(), move |request| {
        print!("aaaa");
        let uri: String = request.uri().to_string().replace("game://", "");
        let file_path = PathBuf::from(&uri);

        if let Some(buffer) = cache.get(&uri) {
            let content_type = if uri.ends_with("./js") {
                "application/javascript"
            } else {
                "application/octet-stream"
            };
            
            Response::builder()
                .status(200)
                .header("Content-Type", content_type)
                .header(
                    wry::http::header::ACCESS_CONTROL_ALLOW_ORIGIN,
                    wry::http::HeaderValue::from_static("*"),
                )
                .body(Cow::Owned(buffer.clone()))
                .expect("failed to build cached response")
        } else {
            let full_path = asset_dir.join(file_path);
            let content = fs::read(&full_path).unwrap_or_else(|_| b"Not Found".to_vec());

            let content_type = if uri.ends_with(".glb") {
                "model/gltf-binary"
            } else {
                "application/octet-stream"
            };

            let status = if content == b"Not Found".to_vec() { 404 } else { 200 };

            Response::builder()
                .status(status)
                .header("Content-Type", content_type)
                .header(
                    wry::http::header::ACCESS_CONTROL_ALLOW_ORIGIN,
                    wry::http::HeaderValue::from_static("*"),
                )
                .body(Cow::Owned(content))
                .expect("failed to build disk file response")
                }
    })
    .build()?;

// 5. 이벤트 루프 실행
event_loop.run(move |event, _, control_flow| {
    *control_flow = ControlFlow::Wait;
    if let Event::WindowEvent { .. } = event {
        // 여기서 ESC나 윈도우 종료 감지해도 됨
    }
});

}`
This is my code, but I have tried many different methods and I get this error over and over again: net::ERR_UNKNOWN_URL_SCHEME. I can't find a solution on the internet

Metadata

Metadata

Assignees

No one assigned

    Labels

    question질문으로 사용될 이슈

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions