Trying to use an express server to exchnage SDP for webrtc communication over local network but SDP contains loopback ip 127.0.0.1

I am trying to learn wrtc, i am buiding an electron app with a p2p feature. I want to remotely access another computer on my LAN. I am using the following process:-

  1. Create an offer (local) in chromium on startup, and send it to the main process to store.
  2. Expose an express endpoint listening on 0.0.0.0 from main and expecting the local offer created by same app from foreign computer.
  3. On receiving this foreign local offer main sends the foreign offer to renderer for setting as remoteSDP and then express sends it’s own local offer in response
  4. The foreign computer takes the response and stores it as their remote SDP.

what i find is that express side is able to successfully set its remote connection but the request side fails to set its local description. I just want a confirmation on approach, as well as to know if i understood it correctly…
will update the code shortly..

What code in Github Pages website do I need to generate an editor box like this one I am using in Stack Overflow to post questions and answers?

What JavaScript, or HTML, or other base code do I need, to append an editor box like this I am using in Stack Overflow to post questions that need answers, as well as post answers to questions?

  1. I need blog functionality in the this page. This is part of a website I started with the wonderful WIX no-coding editor.

  2. I’d like to mirror this site to also wonderful Github pages site where I need all HTML, CSS, JS files.

This question is about how to code an editor box to send answers .

In the I admit too verbose previous version of this question some one kindly just mentioned velo. I just started reading if velo would help solving this task. But velo seems to be a no-coding IDE.

So

  1. What code do I add to 1 single web page to show what I guess is also known as a wysiwyg editor box with top buttons bar like this one I am using in Stackoverflow to ask this question and also ised to post answers?

  2. I tried a paid ‘learn to build websites course from 0’

    But 2 months in and all the bills got me was some walking in circles across basic HTML CSS concepts I already knew or are freely available from for instance W3 Schools.

  3. I tried to, I think it’s called ‘code scrapping’, copying code directly from :

    • A Stackoverflow QA page

    • All about circuits forum. Example.

    • Edaboard forum also has a similar editor box. Example.

    So far, at least from what I tried, pruning, cutting, modifying already existing copied code was a complete waste of time.

    Please don’t tell me to scrape harder.

  4. I tried asking Microsoft Copilot but did not understand the answer.

    Yes, I know, keep trying rewording your question to Copilot may work, it may eventually produce some working code.

  5. Does any of the following links contain the needed code to generate the sought editor box? I found these links, tried 5 of them, could not make any of those 5 tried to make them fly.

I tried going through the following list of WYSIWYG editors, but the few I tried, I did not manage to build an editor box.

http://developer.yahoo.com/yui/editor/

Heavyweight editors

Frameworks/Toolkits

More: https://github.com/dandv/comparisons/blob/master/JavaScript-WYSIWYG-editors.md

How can I declare type on mapped elements?

I’m getting an error on the className of mapped elements. I believe TS is throwing the error because the map’s children (MenuItem) don’t have the className type. See the error below.

The mapped elements are part of the headlessui package. I think this is part of the reason I’m having trouble. I’m following this introduction to headlessui: https://headlessui.com/react/menu. This example is the third code sample on that page.

I tried to make the MenuItemProps interface to use on the .map function like this:

links.map((link): MenuButtonInterface => ()

How can I include the className type to the children of the .map function?

ERROR:

Type '{ children: Element; key: string; className: string; }' is not assignable to type 'IntrinsicAttributes & CleanProps<ExoticComponent<{ children?: ReactNode; }>, "disabled" | ItemPropsWeControl> & OurProps<...> & { ...; } & { ...; }'.


Property 'className' does not exist on type 'IntrinsicAttributes & CleanProps<ExoticComponent<{ children?: ReactNode; }>, "disabled" | ItemPropsWeControl> & OurProps<...> & { ...; } & { ...; }'.ts(2322)

import React, { ReactNode } from 'react'
import { Menu, MenuButton, MenuItem, MenuItems } from '@headlessui/react'

const links = [
    {href: '/home', label: 'Home'},
    {href: '/Test', label: 'Test'},
    {href: '/settings', label: 'Settings'}
]

interface MenuItemProps{
    children: any
    className?: any
    key: any
}

export const MyComponent = () => {
    return(
        <Menu>
            <MenuButton className='data-[active]:bg-blue-500'></MenuButton>
            <MenuItems anchor='bottom'>
                {links.map((link) => (
                    <MenuItem key={link.href} className='block data-[focus]:bg-blue-500'>
                        <a href={link.href}>{link.label}</a>
                    </MenuItem>
                ))}
            </MenuItems>
        </Menu>
    )
}

webcam video stream for capturing photo not working

I am trying to get access to webcam and display video stream for capturing photo. I am not even getting consent for camera access i.e. popup message .I searched a lot but couldn’t find anything.
Below is the code for it:

document.addEventListener("DOMContentLoaded", function() {
            console.log("DOM fully loaded and parsed");

            navigator.permissions.query({ name: 'camera' }).then(function(permission) {
                if (permission.state === 'denied') {
                    alert("Camera access is denied. Please allow camera access and reload the page.");
                }
            });

            const video = document.getElementById('video');
            if (!video) {
                console.error("Video element not found");
                return;
            } else {
                console.log("Video element found");
            }

            const canvas = document.getElementById('canvas');
            if (!canvas) {
                console.error("Canvas element not found");
                return;
            } else {
                console.log("Canvas element found");
            }

            const captureButton = document.getElementById('capture');
            if (!captureButton) {
                console.error("Capture button not found");
                return;
            } else {
                console.log("Capture button found");
            }

            const photoData = document.getElementById('photo_data');
            if (!photoData) {
                console.error("Photo data input not found");
                return;
            } else {
                console.log("Photo data input found");
            }
            
    // Get access to the camera
    if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
        navigator.mediaDevices.getUserMedia({ video: true }).then(function(stream) {
            console.log("Camera stream obtained");
            video.srcObject = stream;
            video.play();
        }).catch(function(error) {
            console.log("Error accessing camera: " + error);
            alert("Could not access the camera. Please check permissions.");
        });
    } else {
        alert("getUserMedia is not supported by your browser.");
    }

    // Capture photo
    captureButton.addEventListener("click", function() {
        const context = canvas.getContext('2d');
        context.drawImage(video, 0, 0, 320, 240);
        const dataURL = canvas.toDataURL('image/png');
        photoData.value = dataURL;
        canvas.style.display = 'block';
    });
});

function submitForm() {
    const photoData = document.getElementById('photo_data').value;
    if (!photoData) {
        alert("Please capture a photo before submitting the form.");
        return false;
    }
    return true; // Ensures the form is submitted
}

i tried a lot and searched different articles but couldn’t find anything.Kindly guide me.

Stateful Widget does not receive data passed to its constructor from proceeding Widget | Dart Flutter

I’ve spent around 5 hours debugging the connectivity between two widgets that cease to function at the passthrough point for receiving the data. I’m fairly new to Flutter and this would be my very first project of all time. I’ve looked on stackoverflow and none of the answers worked with the latest build of flutter. How can I get the data to pass between two stateful widgets or more?

// Works
class ClientPortal extends StatefulWidget {
  const ClientPortal({
    super.key,
  });

  @override
  State<ClientPortal> createState() => _ClientPortalState();
}

class _ClientPortalState extends State<ClientPortal> {
  // State Variables
  dynamic userData;
  dynamic dataCount;

  fetchClientPortalData() async {
    final storage = FlutterSecureStorage();
    final storageObj = await storage.readAll();
    var uid = storageObj['uid'];
    var accessToken = storageObj['access_token'];
    var client = storageObj['client'];

    try {
      Response response = await post(
          Uri.parse('http://localhost:3000/api/v1/clients/client_portal'),
          body: {'uid': uid, 'access-token': accessToken, 'client': client});
      print(response.statusCode);
      if (response.statusCode == 200) {
        var clientPortalData = jsonDecode(response.body.toString());
        var responseHeaders = response.headers;
        setState(() {
          dataCount = clientPortalData['dataCount'];
          userData = clientPortalData['userData'];
        });
      }
    } catch (e) {
      print(e);
    }
  }

  late Future<dynamic> _clientPortalData;
  @override
  void initState() {
    _clientPortalData = fetchClientPortalData();
    super.initState();
  }

  Widget build(BuildContext context) {
    return FutureBuilder<dynamic>(
      future: _clientPortalData,
      initialData: {},
      builder: (context, snapshot) {
        List<Widget> children;
        if (snapshot.connectionState == ConnectionState.done) {
          print('INSIDE OF CLIENT PORTAL');
         // works start
            print(userData);
        // works end

           // fails to store data attributes here in widget below
          return PortalNavigator(
              dataCount: dataCount,
              userData: userData);
        } else {
        }
        return Center(
            child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: children,
        ));
      },
    );
  }
}


// THIS WIDGET DOES NOT RECEIVE DATA
class PortalNavigator extends StatefulWidget {
  PortalNavigator(
      {super.key,
              dataCount: dataCount,
              userData: userData});

  @override
  State<PortalNavigator> createState() => _PortalNavigatorState();
}


class _PortalNavigatorState extends State<PortalNavigator> {
  dynamic userData;
  dynamic dataCount;

  @override
  Widget build(BuildContext context) {
    print('NO DATA EXIST FOR VARS ABOVE');
   print(userData);
   print(dataCount);

    return MaterialApp(
      theme: ThemeData(useMaterial3: true),
      home: PortalNavigatorView(
              dataCount: dataCount,
              userData: userData),
      debugShowCheckedModeBanner: false,
    );
  }
}

class PortalNavigator extends StatefulWidget {
  PortalNavigator(
      {super.key,
      dataCount, userData});

  @override
  State<PortalNavigator> createState() => _PortalNavigatorState();
}

I tried to initialize the variables for the faulty widget but received errors further down the line.

Check if time string is in range of start time and end time [duplicate]

I have data for each type separated by start time and end time range like this. Note that the data will not have time overlap and may have more than 2 ranges. Moreover, there is a time range that is from one day to the next day over midnight that must be included in the consideration of the logic.

const type = [
  {
    time_type: 'A',
    start_time: '22:00:01',
    end_time: '09:00:00'
  },
  {
    time_type: 'B',
    start_time: '09:00:01',
    end_time: '22:00:00'
  }
]

It is assumed that the time format used is 00:00:00 to 23:59:59 format (24 hours).

I would like to have a function that can check if an input time (in string) is in range of which type.

Examples:

const input = '09:02:00';
getType(type, input); // gets time_type 'B'

const input = '08:59:59';
getType(type, input); // gets time_type 'A'

I tried using JavaScript Date but it is a mess in many ways.

Getting two copies of the JS files for my LWC component in Chrome

I’m trying to use Chrome local overrides to make debugging JS quicker. But I’m getting two versions of the JS file in my Chrome sources panel.

I created a new LWC named ‘Hello World’. On the first load, there’s one copy, and I can use Chrome overrides as expected. However, on the second load, there’s another copy with a different path and my overridden changes don’t work. Here are the two paths:

https://connect-flow-485-dev-ed.scratch.lightning.force.com/components/c/helloWorld.js
https://connect-flow-485-dev-ed.scratch.lightning.force.com/lightning/r/Account/001O100000OsFayIAF/modules/c/helloWorld.js

They have different content but both have the “meat” of the component as expected. I can override both but only the overrides in one will take effect. Similarly, only breakpoints in one will stop execution. It seems like a caching issue but I have Disable Cache checked on the Network panel.

(https://i.sstatic.net/19IsdcU3.png)](https://i.sstatic.net/M6Pgrm4p.png)

Why is my nextjs server action being treated as a client routine?

I’m trying to add infinite scrolling to NextJS’s gallery template project by following this tutorial. Here is my server action:

// /actions/getImages.ts

'use server'

import { promises as fs } from 'fs';
import sizeOf from 'image-size';
import type { ImageProps } from "../utils/types";

export const getImages = async (offset: number, 
                                limit: number) => {
    try {
        const file = await fs.readFile('./public/data-large.json', 'utf8');
        const data = JSON.parse(file);

        let reducedResults: ImageProps[] = [];

        let i = offset;
        for (let entry of data) {
            const dim = sizeOf('./public/kitties/kitty-' + entry.public_id + '.jpg');
            reducedResults.push({
                id: i,
                height: dim.height,
                width: dim.width,
                public_id: entry.public_id,
                format: entry.format,
            });

            if (i >= limit) {
                break;
            } else {
                i++
            }
        }

        return reducedResults;
    } catch (error: unknown) {
        console.log(error);
        throw new Error(`An error occurred: ${error}`);
    }
}

And here is my Component:

// /components/Gallery.tsx

'use client'

import Image from "next/image";
import Link from "next/link";
import type { ImageProps } from "../utils/types";
import { useState } from "react";
import { getImages } from '../actions/getImages';

const NUMBER_OF_IMAGES_TO_FETCH = 15; 

export default function Gallery({ images }: { images: ImageProps[] }) {
    const [offset, setOffset] = useState(NUMBER_OF_IMAGES_TO_FETCH);
    const [imgs, setImgs] = useState<ImageProps[]>(images);

    const loadMoreImages = async () => {
        const newImages = await getImages(offset, NUMBER_OF_IMAGES_TO_FETCH);
        setImgs(imgs => [...imgs, ...newImages]);
        setOffset(offset => offset + NUMBER_OF_IMAGES_TO_FETCH);
    }

    return (
      <>
        <div className="columns-1 gap-4 sm:columns-2 xl:columns-3 2xl:columns-4">
          {imgs.map(({ id, public_id, format }) => (
            <Link
              key={id}
              href={`/?photoId=${id}`}
              as={`/p/${id}`}
              //ref={id === Number(lastViewedPhoto) ? lastViewedPhotoRef : null}
              shallow
              className="after:content group relative mb-5 block w-full cursor-zoom-in after:pointer-events-none after:absolute after:inset-0 after:rounded-lg after:shadow-highlight"
            >
              <Image
                alt="Image"
                className="transform rounded-lg brightness-90 transition will-change-auto group-hover:brightness-110"
                style={{ transform: "translate3d(0, 0, 0)" }}
                src={`/kitties/kitty-${public_id}.jpg`}
                width={720}
                height={480}
                sizes="(max-width: 640px) 100vw,
                  (max-width: 1280px) 50vw,
                  (max-width: 1536px) 33vw,
                  25vw"
                />
            </Link>
          ))}
        </div>
        <button className="text-white" onClick={loadMoreImages}>Load more</button>
      </>
    )
}

But I am getting the following build error:

 ○ Compiling / ...
 ⨯ ./node_modules/image-size/dist/index.js:4:1
Module not found: Can't resolve 'fs'
  2 | Object.defineProperty(exports, "__esModule", { value: true });
  3 | exports.types = exports.setConcurrency = exports.disableTypes = exports.disableFS = exports.imageSize = void 0;
> 4 | const fs = require("fs");
    | ^
  5 | const path = require("path");
  6 | const queue_1 = require("queue");
  7 | const index_1 = require("./types/index");

https://nextjs.org/docs/messages/module-not-found

Import trace for requested module:
./actions/getImages.ts
./components/Gallery.tsx
./pages/index.tsx

I assume the server action is being incorrectly treated as a client routine, which is why fs can’t be found. But I’m not sure why that is the case because I’m including 'use server' directive in that file. I can’t tell what what I’m missing.

Version info:

$ node -v
v20.18.0

$ npx next --version
Next.js v15.0.3

Electron – Is there a way to run code after throwing an error?

I’m making my first electron app and I’m trying to implement error handling. If I write:

throw new Error('something happened')

A large, convenient error alert modal appears. I’d like to use this and also call app.quit() afterwards to close the app. Of course, calling throw terminates the function, and there’s no promise or anything for the modal alert. Is there a way to make a call to app.quit() after the user clicks “OK” on the error alert?

How to forcefully reload and clean data in Shopify JS?

I’ve trying for a few days to solve this and couldn’t. I need my page to reload and forget about the previously set values in some functions. I tried many ways to do so but none have been working in my Shopify discount.js code.

I tried making the page reload and clear cache, but it didn’t work.

document.addEventListener('DOMContentLoaded', () => {
    // Clean local cache when loading
    sessionStorage.clear();
    localStorage.clear();

    // Call oldPrice to reset prices
    oldPrice();

In the way above it doesn’t work, but when I use a click event and location.reload like below it works fine:

coupon_tag.addEventListener('click', () => {
    location.reload();
    oldPrice();
});

PHP response triggers HEX view in Edge debugger

PHP 8.0 on IIS 10.0.

I am calling a php api through fetch. An exception is triggered due to some issue with an SQL query in the php api, and normally I would get a 500 server error page followed by PHP’s error reporting output.

However, now suddenly I get this HEX view which is not exactly helpful, and I am not sure what triggered it. No settings were changed in either php.ini or IIS config.

hex view

Any hint?
Thanks

How to fix a cross origin request error without having a live server?

I have a folder ‘testTravel’ in which the files for my site are placed.

Theres a js file in testTravel ‘travel_recommendation.js’ where my js code lives, html file is ‘travel_recommendation.html’, and json file with data in it is ‘travel_recommendation_api.json’ among other files such as style.css, etc.

I am trying to fetch data in Javascript using ‘fetch’ from travel_recommendation_api.json and display it on the html site. I keep running into CORS error. From what I understand from research it has to do with me accesing data from different origin than where the html site lives?? I previously worked around it using a live server in VScode. However for the project, this is not possible for certain reasons. I know it’s possible to do it locally without having to run a live server, I’m just not sure where I’m going wrong.

The inspect page for html site
inspect page on chrome

code snippet in js file

function fetchJSONData(callback) {
  fetch('travel_recommendation_api.json')
    .then(response => {
      if (!response.ok) {
        throw new Error("Failed with HTTP code " + response.status);
      }
      return response.json();
    })
    .then(response => {
      // Call the callback function and pass the data
      callback(response);
    })
    .catch(error => {
      console.error("Friend the error is: " + error);
      // You can also call the callback with an error, if needed
      callback(null, error);
    });
}

directory structure
directory structure

Keep jest workers alive for other test suites

Hope y’all doing great. I have a project that uses Sequelize for database connections, and I’m using different test databases for each Jest worker. However, there is significant overhead in re-creating the database connection, associations, and models for every worker. I know that the Sequelize instance is not serializable, so I can’t share it between workers. I was considering keeping the workers alive to reduce the overhead of creating connections, but I’m unsure where to start. I might try a custom runner, or there could be a better approach.

I’d appreciate a second opinion. Thanks!

Unable to iterate to loop properly (JavaScript)

I’m having issues iterating through the loops below in JavaScript:

function calculateDesign() {
    // Retrieve inputs
    const pu = parseFloat(document.getElementById("pu").value);
    const pa = parseFloat(document.getElementById("pa").value);
    const ep1 = parseFloat(document.getElementById("ep1").value);
    const ep2 = parseFloat(document.getElementById("ep2").value);

// Arrays to store design values
let P0_simon = [], P1_simon = [], n_simon = [], n1_simon = [], n2_simon = [];
let r1_simon = [], r_simon = [], ESS_simon = [], PET_simon = [];

const nmax = 60;

for (let n = 2; n <= nmax; n++) {
    for (let n1 = 1; n1 < n; n1++) {
        const n2 = n - n1;

        for (let r1 = 1; r1 <= n1; r1++) {
            let PET_P0 = dbinomCumsum(r1, n1, pu);
            let PET_P1 = dbinomCumsum(r1, n1, pa);

            if (PET_P1 < ep2 && PET_P0 >= (1 - ep1)) {
                for (let r = r1; r <= (n2 + r1); r++) {
                    let add_P0_list = [], add_P1_list = [];
                    for (let l = (r1 + 1); l <= Math.min(n1, r); l++) {
                        if (r - l > 0 && n - r > 0) {
                            let add_P0 = binomial(l, n1, pu) * cumulativeBinomial(r - l, n2, pu);
                            add_P0_list.push(add_P0);

                            let add_P1 = binomial(l, n1, pa) * cumulativeBinomial(r - l, n2, pa);
                            add_P1_list.push(add_P1);
                        }
                    }

                    let PET_P0_final = PET_P0 + sumArray(add_P0_list);
                    let PET_P1_final = PET_P1 + sumArray(add_P1_list);

                    // Reset lists after each iteration
                    add_P0_list = null;
                    add_P1_list = null;

                    if (PET_P0_final > (1 - ep1) && PET_P1_final < ep2 && r1 !== 0) {
                        P0_simon.push(PET_P0_final);
                        P1_simon.push(PET_P1_final);
                        n_simon.push(n);
                        n1_simon.push(n1);
                        n2_simon.push(n2);
                        r1_simon.push(r1);
                        r_simon.push(r);
                        PET_simon.push(PET_P0);
                        ESS_simon.push(n1 + (1 - PET_P0) * n2);
                    }


                }
            }
        }
        add_P1 = null;
        add_P0 = null;
    }
}

// Display all designs in a table
let tableHTML = "<table border='1'><tr><th>P0</th><th>P1</th><th>n</th><th>n1</th><th>n2</th><th>r1</th><th>r</th><th>PET</th><th>ESS</th></tr>";
for (let i = 0; i < P0_simon.length; i++) {
    tableHTML += `<tr>
        <td>${P0_simon[i]}</td>
        <td>${P1_simon[i]}</td>
        <td>${n_simon[i]}</td>
        <td>${n1_simon[i]}</td>
        <td>${n2_simon[i]}</td>
        <td>${r1_simon[i]}</td>
        <td>${r_simon[i]}</td>
        <td>${PET_simon[i]}</td>
        <td>${ESS_simon[i]}</td>
    </tr>`;
}
tableHTML += "</table>";

document.getElementById("results").innerHTML = tableHTML;
}

Unfortunately the code is not matching my R program, which is returns values when r1 = 1 through r1 = 30 when pu = .4, pa = .6, ep1 = .1, and ep2 = .1.
Something appears to be wrong with the looping structures in the code, specifically the range of values that r1 and r can take.

How to use javascript fetch API when using custom schema in JavaFX webview?

I am trying to fetch a resource from a jar file using JavaFX webview but it fails with minimal information. To start I defined a new URLStreamFactoryHandler. (Based off another stackoverflow post). Unfortunately, this requires a fair amount of boilerplate code.

public class ResourceURLStreamHandlerFactory implements URLStreamHandlerFactory
{

  ResourceURLStreamHandlerFactory() {
  }

  @Override
  public URLStreamHandler createURLStreamHandler(String protocol) {
    if (protocol.equals("resource"))
      return new ResourceURLHandler();
    System.out.println("Unknown "+protocol);
    return null;
  }

  public static class ResourceURLHandler extends URLStreamHandler {

    @Override
    protected URLConnection openConnection(URL url) throws IOException {
      return new ResourceURLConnection(url);
    }
  }
}

With the corresponding Handler.

public class ResourceURLConnection extends URLConnection
{

  private byte[] data;

  public ResourceURLConnection(URL url) {
    super(url);
  }

  @Override
  public void connect() throws IOException {
    if (connected)
      return;
    loadURL();
    connected = true;
  }

  @Override
  public String getHeaderField(String name) {
    if ("Content-Type".equalsIgnoreCase(name))
      return getContentType();
    else if ("Content-Length".equalsIgnoreCase(name))
      return "" + getContentLength();
    return null;
  }

  @Override
  public String getContentType() {
    String fileName = getURL().getFile();
    int index = fileName.lastIndexOf('.');
    if (index == -1)
        return "text/html";
      
    String ext = fileName.substring(index+1);
    switch (ext) {
      case "htm":
      case "html":
        return "text/html";
      case "js":
        return "text/javascript";
      case "svg":
        return "image/svg+xml";
      case "json":
        return "application/json";
      case "png":
        return "image/png";
      case "css":
        return "text/css";
    }
    throw new RuntimeException("Unknown file type " + ext);
  }

  @Override
  public int getContentLength() {
    return data.length;
  }

  @Override
  public long getContentLengthLong() {
    return data.length;
  }

  @Override
  public boolean getDoInput() {
    return true;
  }

  @Override
  public InputStream getInputStream() throws IOException {
    connect();
    return new ByteArrayInputStream(data);
  }

  private void loadURL() throws IOException {
    if (data != null)
      return;
    String path = getURL().toExternalForm();
    path = path.startsWith("resource://")
            ? path.substring("resource://".length())
            : path.substring("resource:".length());

    URL resourceUrl = this.getClass().getClassLoader().getResource(HOME + path);
   
    if (resourceUrl != null) {
      try (InputStream is = resourceUrl.openStream()) {
        data = is.readAllBytes();
      }
    }
    else {
      throw new IOException("Resource not found");
    }
  }

  @Override
  public OutputStream getOutputStream() throws IOException {
    return new ByteArrayOutputStream();
  }

  @Override
  public java.security.Permission getPermission() throws IOException {
    return null; // we need no permissions to access this URL
  }
}

I then install the Resource handler in my main.

  static {
    URL.setURLStreamHandlerFactory(new ResourceURLStreamHandlerFactory());
  }

To use it, I call the desired web page using the custom schema.

    webEngine.load("resource:///hello.html");

Everything works with the exception of the Javascript fetch.

  try {
    console.log("Start fetch " + path);
    const response = await fetch(path);
    console.log("Done fetch");
    return;
  } catch (ex)
  {
    console.log("Fail " + ex + " " + path);
  }

All I get is the cryptic error.

TypeError: Load failed my.svg

The expected result if for Javascript to access the resource from the custom Java protocol schema returning the requested resource.

I have tries the XMLHttpRequest API as well with similar results. Thus far I can find nothing to indicate that Javascript ever called back to Java to get the appropriate resource. I have attempted to read thought the JavaFX webkit modules corresponding to the fetch API, but unfortunately it is too opaque for me to see the connection between resource loading and Java.

Have other succeeded in getting this working? Are there any resources on how to debug interactions between webkit and Java?