-
Notifications
You must be signed in to change notification settings - Fork 239
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add http middleware and websocket upgrade on existing listener #755
- Loading branch information
1 parent
e515f6c
commit 5954fc3
Showing
20 changed files
with
941 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
node_modules |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
# Moddable http bridge example | ||
|
||
This example shows how to use the http bridge components. | ||
|
||
It starts a bi-directional websocket between the Moddable server and a browser. If you start another browser instance, changes on one browser reflect in the other. | ||
|
||
### build the zip file | ||
``` | ||
cd site | ||
npm install | ||
npm run build | ||
``` | ||
|
||
### build moddable | ||
From the site folder: | ||
``` | ||
npm run mcconfig | ||
``` | ||
|
||
This will build the `site.zip` and launch the simulator | ||
|
||
open browser `http://localhost` | ||
|
||
### front end development | ||
``` | ||
`npm run dev` | ||
or | ||
`wmr` | ||
open browser `http://localhost:8080` | ||
Edit any ts or css file, and on save the browser will auto-update with changes, and the `websocket` is connected to the simulator Modable server | ||
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
/* | ||
* Copyright (c) 2016-2021 Moddable Tech, Inc. | ||
* Copyright (c) Wilberforce | ||
* | ||
* This file is part of the Moddable SDK. | ||
* | ||
* This work is licensed under the | ||
* Creative Commons Attribution 4.0 International License. | ||
* To view a copy of this license, visit | ||
* <http://creativecommons.org/licenses/by/4.0>. | ||
* or send a letter to Creative Commons, PO Box 1866, | ||
* Mountain View, CA 94042, USA. | ||
* | ||
*/ | ||
import { WebServer as HTTPServer } from "bridge/webserver"; | ||
import { BridgeWebsocket } from "bridge/websocket"; | ||
import { BridgeHttpZip } from "bridge/httpzip"; | ||
import Preference from "preference"; | ||
|
||
const http = new HTTPServer({ | ||
port: 80, | ||
}); | ||
|
||
let ws = http.use(new BridgeWebsocket("/api")); | ||
http.use(new BridgeHttpZip("site.zip")); | ||
|
||
class App { | ||
#preference_domain = "bridge"; | ||
#model; | ||
|
||
constructor(m) { | ||
this.#model = m; | ||
} | ||
|
||
get model() { | ||
return this.#model; | ||
} | ||
|
||
set model(m) { | ||
this.#model = m; | ||
} | ||
|
||
minus(value) { | ||
this.model.satisfaction = Math.max(0, this.model.satisfaction - 1); | ||
return this.model; | ||
} | ||
plus(value) { | ||
this.model.satisfaction = Math.min(10, this.model.satisfaction + 1); | ||
return this.model; | ||
} | ||
shutdown() { | ||
ws.close(); | ||
http.close(); | ||
} | ||
language() { | ||
this.model.language = value.language; | ||
return this.model; | ||
} | ||
restore() { | ||
let keys = Preference.keys(this.#preference_domain); | ||
for (let key of keys) { | ||
let pref_settings = Preference.get(this.#preference_domain, key); | ||
if (pref_settings) { | ||
Object.assign(this.model, JSON.parse(pref_settings)); | ||
} | ||
} | ||
return this.model; | ||
} | ||
save() { | ||
Preference.set( | ||
this.#preference_domain, | ||
"settings", | ||
JSON.stringify(this.model) | ||
); | ||
} | ||
} | ||
|
||
import { _model } from "model"; | ||
const app = new App({ ..._model }); | ||
app.restore(); | ||
|
||
ws.callback = function cb(websock, message, value) { | ||
switch (message) { | ||
case BridgeWebsocket.connect: | ||
break; | ||
|
||
case BridgeWebsocket.handshake: | ||
websock.broadcast(app.model); | ||
break; | ||
|
||
case BridgeWebsocket.receive: | ||
try { | ||
trace(`Main WebSocket receive: ${value}\n`); | ||
value = JSON.parse(value); | ||
|
||
let action = value?.action; | ||
|
||
if (typeof app[action] === "function") { | ||
value = app[action](value); | ||
} else { | ||
if (value.hasOwnProperty('language')) { | ||
Object.assign(app.model,value) | ||
} else { | ||
trace("No matching action found\n"); | ||
} | ||
} | ||
if (value) websock.broadcast(value); | ||
} catch (e) { | ||
trace(`WebSocket parse received data error: ${e}\n`); | ||
} | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
{ | ||
"include": [ | ||
"$(MODDABLE)/examples/manifest_base.json", | ||
"$(MODDABLE)/examples/manifest_net.json", | ||
"$(MODULES)/network/http/manifest.json", | ||
"$(MODULES)/network/websocket/manifest.json", | ||
"$(MODULES)/files/zip/manifest.json", | ||
"$(MODULES)/files/preference/manifest.json" | ||
], | ||
"modules": { | ||
"*": [ | ||
"./main" | ||
], | ||
"bridge/*": "$(MODDABLE)/contributed/httpbridge/modules/*", | ||
"model":"site/public/model" | ||
}, | ||
"preload": [ | ||
"model", | ||
"bridge/httpzip" | ||
], | ||
"data": { | ||
"*": "./site/dist/site" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
/* | ||
* Copyright (c) 2016-2021 Moddable Tech, Inc. | ||
* Copyright (c) Wilberforce | ||
* | ||
* This file is part of the Moddable SDK. | ||
* | ||
* This work is licensed under the | ||
* Creative Commons Attribution 4.0 International License. | ||
* To view a copy of this license, visit | ||
* <http://creativecommons.org/licenses/by/4.0>. | ||
* or send a letter to Creative Commons, PO Box 1866, | ||
* Mountain View, CA 94042, USA. | ||
* | ||
*/ | ||
|
||
import { Bridge, HTTPServer } from "bridge/webserver"; | ||
import Net from "net" | ||
|
||
const hotspot = new Map; | ||
|
||
// iOS 8/9 | ||
hotspot.set("/library/test/success.html",{status: 302,body: "Success"}); | ||
hotspot.set("/hotspot-detect.html",{status: 302,body: "Success"}); | ||
|
||
// Windows | ||
hotspot.set("/ncsi.txt",{status: 302,body: "Microsoft NCSI"}); | ||
hotspot.set("/connecttest.txt",{status: 302,body: "Microsoft Connect Test"}); | ||
hotspot.set("/redirect",{status: 302,body: ""}); // Win 10 | ||
|
||
// Android | ||
hotspot.set("/mobile/status.php", {status:302}); // Android 8.0 (Samsung s9+) | ||
hotspot.set("/generate_204", {status:302}); // Android actual redirect | ||
hotspot.set("/gen_204", {status:204}); // Android 9.0 | ||
|
||
export class BridgeHotspot extends Bridge { | ||
constructor() { | ||
super(); | ||
} | ||
handler(req, message, value, etc) { | ||
switch (message) { | ||
case HTTPServer.status: | ||
|
||
req.redirect=hotspot.get(value); // value is path | ||
if ( req.redirect) return; // Hotspot url match | ||
delete req.redirect; | ||
return this.next?.handler(req, message, value, etc); | ||
case HTTPServer.header: { | ||
if ( "host" === value ) { | ||
req.host=etc; | ||
trace(`BridgeHotspot: http://${req.host}${req.path}\n`); | ||
} | ||
return this.next?.handler(req, message, value, etc); | ||
} | ||
case HTTPServer.prepareResponse: | ||
|
||
if( req.redirect) { | ||
let apIP=Net.get("IP", "ap"); | ||
let redirect={ | ||
headers: [ "Content-type", "text/plain", "Location",`http://${apIP}`], | ||
...req.redirect | ||
}; | ||
trace(`Hotspot match: http://${req.host}${req.path}\n`); | ||
trace(JSON.stringify(redirect),'\n'); | ||
|
||
return redirect; | ||
} | ||
} | ||
return this.next?.handler(req, message, value, etc); | ||
} | ||
} | ||
Object.freeze(hotspot); | ||
|
||
/* TO DO | ||
add dns constructor flag. then becomes self contained. | ||
*/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
/* | ||
* Copyright (c) 2016-2021 Moddable Tech, Inc. | ||
* Copyright (c) Wilberforce | ||
* | ||
* This file is part of the Moddable SDK. | ||
* | ||
* This work is licensed under the | ||
* Creative Commons Attribution 4.0 International License. | ||
* To view a copy of this license, visit | ||
* <http://creativecommons.org/licenses/by/4.0>. | ||
* or send a letter to Creative Commons, PO Box 1866, | ||
* Mountain View, CA 94042, USA. | ||
* | ||
*/ | ||
|
||
import { Bridge, HTTPServer } from "bridge/webserver"; | ||
import Resource from "Resource"; | ||
import {ZIP} from "zip" | ||
|
||
const mime = new Map; | ||
mime.set("js", "application/javascript"); | ||
mime.set("css", "text/css"); | ||
mime.set("ico", "image/vnd.microsoft.icon"); | ||
mime.set("txt", "text/plain"); | ||
mime.set("htm", "text/html"); | ||
mime.set("html", "text/html"); | ||
mime.set("svg", "image/svg+xml"); | ||
mime.set("png", "image/png"); | ||
mime.set("gif", "image/gif"); | ||
mime.set("webp", "image/webp"); | ||
mime.set("jpg", "image/jpeg"); | ||
mime.set("jpeg", "image/jpeg"); | ||
|
||
export class BridgeHttpZip extends Bridge { | ||
constructor(resource) { | ||
super(); | ||
|
||
this.archive = new ZIP(new Resource(resource)); | ||
} | ||
|
||
handler(req, message, value, etc) { | ||
switch (message) { | ||
case HTTPServer.status: | ||
// redirect home page | ||
if (value === '/') value='/index.html'; | ||
req.path = value; | ||
try { | ||
req.data = this.archive.file(req.path.slice(1)); // drop leading / to match zip content | ||
req.etag = "mod-" + req.data.crc.toString(16); | ||
} | ||
catch { | ||
delete req.data; | ||
delete req.etag; | ||
return this.next?.handler(req, message, value, etc); | ||
} | ||
break; | ||
|
||
case HTTPServer.header: | ||
req.match ||= ("if-none-match" === value) && (req.etag === etc); | ||
return this.next?.handler(req, message, value, etc); | ||
|
||
case HTTPServer.prepareResponse: | ||
if (req.match) { | ||
return { | ||
status: 304, | ||
headers: [ | ||
"ETag", req.etag, | ||
] | ||
}; | ||
} | ||
if (!req.data) { | ||
trace(`prepareResponse: missing file ${req.path}\n`); | ||
|
||
return this.next?.handler(req, message, value, etc); | ||
} | ||
|
||
req.data.current = 0; | ||
const result = { | ||
headers: [ | ||
"Content-type", mime.get(req.path.split('.').pop()) ?? "text/plain", | ||
"Content-length", req.data.length, | ||
"ETag", req.etag, | ||
"Cache-Control", "max-age=60" | ||
], | ||
body: true | ||
} | ||
if (8 === req.data.method) // Compression Method | ||
result.headers.push("Content-Encoding", "deflate"); | ||
return result; | ||
|
||
case HTTPServer.responseFragment: | ||
if (req.data.current >= req.data.length) | ||
return; | ||
|
||
const chunk = req.data.read(ArrayBuffer, (value > 1536) ? 1536 : value); | ||
req.data.current += chunk.byteLength; | ||
return chunk; | ||
} | ||
} | ||
} | ||
|
||
Object.freeze(mime); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
{ | ||
"include": [ | ||
"$(MODDABLE)/examples/manifest_base.json", | ||
"$(MODDABLE)/examples/manifest_net.json", | ||
"$(MODULES)/network/http/manifest.json", | ||
"$(MODULES)/network/websocket/manifest.json", | ||
"$(MODULES)/files/zip/manifest.json" | ||
], | ||
"modules": { | ||
"*": [ | ||
"$(MODULES)/files/resource/*" | ||
], | ||
"dns/server": "$(MODULES)/network/dns/dnsserver" | ||
}, | ||
"preload": [ | ||
"http", | ||
"dns/server", | ||
"websocket/websocket", | ||
"base64", | ||
"hex", | ||
"logical", | ||
"resource", | ||
"zip" | ||
] | ||
} |
Oops, something went wrong.