-
Notifications
You must be signed in to change notification settings - Fork 504
Description
- Version:
package.json
{
"name": "test",
"version": "1.0.0",
"license": "Apache-2.0 OR MIT",
"type": "module",
"scripts": {
"start": "node server.js",
"build": "npm run build:pubsub && npm run build:libp2p && npm run build:filter && npm run build:peer-store && npm run build:pubsubPeerDiscovery && npm run build:gossipsub && npm run build:identify",
"build:pubsub": "esbuild ./src/dep-pubsub.js --bundle --sourcemap --format=esm --target=chrome114 --define:global=window --keep-names --outfile=./docs/lib-pubsub.js",
"build:libp2p": "esbuild ./src/dep-libp2p.js --bundle --sourcemap --format=esm --target=chrome114 --define:global=window --keep-names --outfile=./docs/lib-libp2p.js",
"build:filter": "esbuild ./src/dep-filters.js --bundle --sourcemap --format=esm --target=chrome114 --define:global=window --keep-names --outfile=./docs/lib-filters.js",
"build:peer-store": "esbuild ./src/dep-peer-store.js --bundle --sourcemap --format=esm --target=chrome114 --define:global=window --keep-names --outfile=./docs/lib-peer-store.js",
"build:gossipsub": "esbuild ./src/dep-gossipsub.js --bundle --sourcemap --format=esm --target=chrome114 --define:global=window --keep-names --outfile=./docs/lib-gossipsub.js",
"build:pubsubPeerDiscovery": "esbuild ./src/dep-pubsubPeerDiscovery.js --bundle --sourcemap --format=esm --target=chrome114 --define:global=window --keep-names --outfile=./docs/lib-pubsubPeerDiscovery.js",
"build:identify": "esbuild ./src/dep-identify.js --bundle --sourcemap --format=esm --target=chrome114 --define:global=window --keep-names --outfile=./docs/lib-identify.js",
"test:firefox": "npm run build && playwright test --browser=firefox test",
"test:chrome": "npm run build && playwright test test"
},
"dependencies": {
"@chainsafe/libp2p-gossipsub": "^14.1.2",
"@chainsafe/libp2p-noise": "^17.0.0",
"@chainsafe/libp2p-yamux": "^8.0.0",
"@libp2p/autonat": "^3.0.5",
"@libp2p/bootstrap": "^12.0.6",
"@libp2p/circuit-relay-v2": "^4.0.5",
"@libp2p/crypto": "^5.1.12",
"@libp2p/dcutr": "^3.0.5",
"@libp2p/identify": "^4.0.5",
"@libp2p/interface-transport": "^4.0.3",
"@libp2p/kad-dht": "^16.0.5",
"@libp2p/peer-id": "^6.0.3",
"@libp2p/peer-id-factory": "^4.2.4",
"@libp2p/peer-store": "^12.0.5",
"@libp2p/ping": "^3.0.5",
"@libp2p/pubsub-peer-discovery": "^12.0.0",
"@libp2p/tcp": "^11.0.5",
"@libp2p/webrtc": "^6.0.6",
"@libp2p/websockets": "^10.0.6",
"@libp2p/webtransport": "^6.0.7",
"@multiformats/multiaddr": "^13.0.1",
"blockstore-core": "^6.1.1",
"compression": "^1.8.1",
"cors": "^2.8.5",
"datastore-core": "^11.0.2",
"datastore-idb": "^4.0.1",
"dotenv": "^17.2.3",
"express": "^5.1.0",
"express-enqueue": "^1.0.0",
"http-proxy": "^1.18.1",
"libp2p": "^3.0.6",
"peer-id": "^0.16.0",
"protons-runtime": "^5.6.0",
"uint8arrays": "^5.1.0"
},
"devDependencies": {
"esbuild": "^0.25.10",
"test-ipfs-example": "^1.3.3"
}
}
- Platform:
Linux manjaro
- Subsystem:
Not work is packages/transport-websockets
Severity:
Low - Medium
Description:
I built a relay server with an HTTP server.
It worked well. To transfer data to the HTTP server, I passed the webSockets({server}) server transport to the transport.
transports: [
webTransport(),
webSockets({server}),
tcp(),
],
I've now updated all the libraries to the latest versions.
When starting the server, I see the error Only WebSocket connections are supported
I looked in the library interface:
https://libp2p.github.io/js-libp2p/interfaces/_libp2p_websockets.WebSocketsInit.html
interface WebSocketsInit {
bufferedAmountPollInterval?: number;
http?: ServerOptions<typeof IncomingMessage, typeof ServerResponse>;
https?: ServerOptions<typeof IncomingMessage, typeof ServerResponse>;
maxBufferedAmount?: number;
signal?: AbortSignal;
}
I thought I needed to pass a new http parameter, but that didn't work.
Steps to reproduce the error:
This is the code that worked. After the update, it started saying "Only WebSocket connections are supported."
import path from 'path';
import process from "node:process";
import cors from 'cors';
import Enqueue from 'express-enqueue';
import compression from 'compression';
import * as dotenv from 'dotenv';
import express from 'express';
import http from 'http'
/* eslint-disable no-console */
import { privateKeyFromRaw, generateKeyPair, privateKeyToProtobuf, privateKeyFromProtobuf } from '@libp2p/crypto/keys'
import { noise } from '@chainsafe/libp2p-noise'
import { yamux } from '@chainsafe/libp2p-yamux'
import { circuitRelayServer } from '@libp2p/circuit-relay-v2'
import {identify, identifyPush} from '@libp2p/identify'
import { webSockets } from '@libp2p/websockets'
import { createLibp2p } from 'libp2p'
import { tcp } from '@libp2p/tcp'
import * as peerIdLib from '@libp2p/peer-id'
import * as createEd25519PeerId from '@libp2p/peer-id-factory'
import { webTransport } from '@libp2p/webtransport'
import fs from "node:fs";
import { persistentPeerStore } from '@libp2p/peer-store'
import { MemoryDatastore } from 'datastore-core'
import {ping} from "@libp2p/ping";
import { PUBSUB_PEER_DISCOVERY } from './docs/constants.js'
import { gossipsub } from '@chainsafe/libp2p-gossipsub'
let __dirname = process.cwd();
const buffer = fs.readFileSync(__dirname + '/peerId.proto')
const peerId = await createEd25519PeerId.createFromProtobuf(buffer)
dotenv.config();
const port = process.env.PORT
? process.env.PORT
: 4839;
let whitelist = []
let app = express();
const server = http.createServer(app);
async function main () {
app.use(compression());
app.use(express.json());
const queue = new Enqueue({
concurrentWorkers: 4,
maxSize: 200,
timeout: 30000
});
app.use(await cors({credentials: true}));
app.use(queue.getMiddleware());
let corsOptions = {
origin: function (origin, callback) {
console.log('origin', origin);
if (whitelist.indexOf(origin) !== -1) {
callback(null, true);
} else {
callback(new Error('Not allowed by CORS'));
}
}
};
app.use('/pubsub', express.static(path.join(__dirname, '/docs')));
// app.use('/assets', express.static(path.join(__dirname, '/dist/assets')));
app.use('/assets', express.static(path.join(__dirname, '/public')));
app.get(`/env.json`, async (req, res) => {
res.status(200).sendFile(path.join(__dirname, 'env.json'))
})
app.get(`/env.mjs`, async (req, res) => {
res.status(200).sendFile(path.join(__dirname, 'env.mjs'))
})
app.get(`/`, async (req, res) => {
const html = `<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>org browser relay</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=yes" />
<meta
name="description"
content="">
<meta property="og:site_name" content="markdown" />
<meta property="og:locale" content="ru_RU" />
<meta property="og:type" content="contract" />
<meta property="og:title" content="markdown" />
<meta property="og:description" content="markdown" />
<meta property="og:image" content="https://i.imgur.com/pSrPUkJ.jpg" />
<meta property="og:image:width" content="537" />
<meta property="og:image:height" content="240" />
<link rel="shortcut icon"
href="data:image/png;base64, AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbbv+DGW3/mRlt/5kZbf+ZGq6/hIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGa3/ohkt/7/Zbj//2S3/v9lt/6WAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGm5/iRlt/74Zbj//2W4//9luP//Zbf++mi4/i4gIPciGhr24hsb9uwbG/bsGhr24CEh9xoAAAAAAAAAAAAAAABnuP5mZLf+/2W4//9luP//Zbj//2S3/v9muP5yGBj2rhMT9v8TE/b/ExP2/xMT9f8YGPWkAAAAAAAAAAAAAAAAb7z/BGW3/tZluP//Zbj//2W4//9lt/7gJzH3ShMT9f8TE/b/ExP2/xMT9v8TE/b/ExP1/CAg9joAAAAAAAAAAAAAAABmuP5GZLf+6GS3/uhkt/7oZbf+UhgY9YQSEvX/ExP2/xMT9v8TE/b/ExP2/xIS9f8aGvZ8AAAAAD4++gQgIPZ6IiL2hiIi9oYgIPZ8KCj5BAAAAAAtLfgUFBT17BMT9v8TE/b/ExP2/xMT9v8VFfXoLCz4DgAAAAAaGvZqEhL1/xMT9v8TE/b/EhL1/xsb9nIAAAAAAAAAABwc9m4SEvX/ExP2/xMT9v8SEvX/HR32ZAAAAAAnJ/gSFRX16hMT9v8TE/b/ExP2/xMT9v8UFPXuJyf4Fp2xlAKNnqUYLC/mfhYW83ATE/VuFxf1aDc3+gIAAAAAGBj1fhIS9f8TE/b/ExP2/xMT9v8TE/b/ExP1/xkZ9YaGn3yIhZ57/4Wee/+Gn3yKAAAAAAAAAAAAAAAAAAAAACMj9zYTE/X8ExP2/xMT9v8TE/b/ExP2/xMT9f9JUshihZ57+IaffP+Gn3z/hZ579oigfiYAAAAAAAAAAAAAAAAAAAAAGBj1oBIS9f8TE/b/ExP2/xMT9f8YGPWmiKB+PIWee/+Gn3z/hp98/4Wee/+HoH06AAAAAAAAAAAAAAAAAAAAACUl9xgVFfXOExP11BMT9dQUFPXQJib3HgAAAACGn3ymhp98/4affP+Gn3ymAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAiKB+EIihf0CIoX9AiKB+EAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//8AAP//AADg/wAA4MMAAOCBAADggQAA8QEAAOeBAADDwwAAgf8AAIAPAACBDwAAgQ8AAMMPAAD//wAA//8AAA=="
type="image/png">
<style>
.body {
display: flex;
flex-direction: column;
justify-content: center;
text-align: center;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: auto;
}
.body img {
align-self: center;
}
#addr {
display: flex;
flex-direction: row;
gap: 24px;
justify-content: center;
align-items: center;
}
p {
background: #AFAFAF;
padding: 4px;
border-radius: 2px;
width: max-content;
}
</style>
</head>
<body>
<div class="body">
<br>
<img src="./assets/logo.png" alt="org Logo" width="128">
<h2>Relay</h2>
<div id="addr">
You can add this bootstrap list with the address
<p
onclick="(function(self) {
if ('clipboard' in navigator) {
navigator.clipboard.writeText(self.textContent.trim())
.then(() => {
console.log('Text copied');
})
.catch((err) => console.error(err.name, err.message));
} else {
}
})(this)"
>
${pathNode}
</p>
</div>
<div class="container">
<div class="peers">
<button class="get-peers"> get peers</button>
<ul>
</ul>
</div>
</div>
</div>
<script type="module">
let mount = true;
let events;
let timer;
let createEvents = () => {
if(events){
events.close();
}
// Устанавливаем SSE соединение
events = new EventSource('/events');
events.onmessage = (event) => {
console.log('event: ', JSON.parse(event.data))
// if(mount){
// let parsedData = JSON.parse(event.data);
// setTasks(parsedData);
// }
};
events.onerror = (err) => {
console.log('error', err)
// timer = setTimeout(() => {
// createEvents();
// }, 1000);
};
};
createEvents();
const peers = document.querySelector('.get-peers')
peers.addEventListener('click', async () => {
let data = await fetch('/peers')
data = await data.json()
console.log('peers: ', data)
})
</script>
</body>
</html>
`;
res.status(200).send(html);
// res.status(200).sendFile(path.join(__dirname, '/index.html'));
});
app.use(queue.getErrorMiddleware());
let addresses = process.env.PORT
? {
listen: [
`/ip4/0.0.0.0/tcp/${port}/wss`
],
announce: [
`/dns4/${process.env.RENDER_EXTERNAL_HOSTNAME}`,
`/dns4/${process.env.RENDER_EXTERNAL_HOSTNAME}/wss`
]
}
: {
listen: [
`/ip4/0.0.0.0/tcp/${port}/ws`
],
announce: [
`/dns4/localhost/tcp/${port}`,
`/dns4/localhost/tcp/${port}/ws`
]
}
const node = await createLibp2p({
peerId,
addresses: addresses,
transports: [
webTransport(),
webSockets({ server }),
tcp(),
],
connectionEncryption: [
noise()
],
streamMuxers: [yamux()],
services: {
identify: identify(),
identifyPush: identifyPush(),
pubsub: gossipsub(),
// autoNat: autoNAT(),
relay: circuitRelayServer(),
ping: ping()
}
})
node.services.pubsub.subscribe(PUBSUB_PEER_DISCOVERY)
console.log(`Node started with id ${node.peerId.toString()}`)
let pathNode = ''
node.getMultiaddrs().forEach((ma, index) => {
pathNode = ma.toString()
console.log(`${index}::Listening on:`, pathNode)
})
console.log('pid: ', process.pid);
console.log('listening on http://localhost:' + port);
let clients = [];
let todoState = [];
app.get('/state', (req, res) => {
res.json(todoState);
});
app.get('/events', (req, res) => {
const headers = {
'Content-Type': 'text/event-stream',
'Access-Control-Allow-Origin': '*',
'Connection': 'keep-alive',
'Cache-Control': 'no-cache'
};
res.writeHead(200, headers);
const sendData = `data: ${JSON.stringify({
peerId: peerId.toString()
})}\n\n`;
res.write(sendData);
res.flush();
const clientId = genUniqId();
const newClient = {
id: clientId,
res,
};
clients.push(newClient);
console.log(`${clientId} - Connection opened`);
req.on('close', () => {
console.log(`${clientId} - Connection closed`);
clients = clients.filter(client => client.id !== clientId);
});
});
function genUniqId(){
return Date.now() + '-' + Math.floor(Math.random() * 1000000000);
}
function sendToAllUsers() {
for(let i=0; i<clients.length; i++){
clients[i].res.write(`data: ${JSON.stringify(todoState)}\n\n`);
clients[i].res.flush();
}
}
app.get('/clients', (req, res) => {
res.json(clients.map((client) => client.id));
});
app.get('/peers', (req, res) => {
let peers = []
for(let item of node.getPeers()) {
peers.push(item.toString())
}
res.json({
status: true,
peers: peers,
dhtMode: node.services.dht.getMode(),
MA: node.getMultiaddrs()
});
});
app.post('/add-task', (req, res) => {
const addedText = req.body.text;
todoState = [
{ id: genUniqId(), text: addedText, checked: false },
...todoState
];
res.json(null);
sendToAllUsers();
});
app.post('/check-task', (req, res) => {
const id = req.body.id;
const checked = req.body.checked;
todoState = todoState.map((item) => {
if(item.id === id){
return { ...item, checked };
}
else{
return item;
}
});
res.json(null);
sendToAllUsers();
});
app.post('/del-task', (req, res) => {
const id = req.body.id;
todoState = todoState.filter((item) => {
return item.id !== id;
});
res.json(null);
sendToAllUsers();
});
}
main()
How to get the express server back?