Last active
November 10, 2021 14:22
-
-
Save kenwebb/3ede7991936fe5281657c494f8a92caf to your computer and use it in GitHub Desktop.
Express - web framework for node
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
Learning Express - web framework for node | |
Experimenting with dragging modules into a running Xholon app, | |
where the module connects to a JavaScript node 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
/** | |
Ken Webb | |
Learning Express. | |
October 25, 2021 | |
see Xholon workbook: Express - web framework for node | |
3ede7991936fe5281657c494f8a92caf | |
(base) ken@ken-HP-ZBook-15-G2:~/nodespace/express01$ node app.js | |
Example app listening at http://localhost:3000 | |
http://localhost:3000/add/1/99 | |
result: 1 + 99 = 100 | |
see also: ~/gwtspace/Xholon/Xholon/module/moduleAvatar2Server.xml | |
Performance | |
----------- | |
see: https://expressjs.com/en/advanced/best-practice-performance.html | |
To set NODE_ENV to “production”, enter this command in the Linux/Ubuntu terminal window, before running node: | |
export NODE_ENV=production | |
This is temporary, and is only active for that terminal window. | |
*/ | |
const express = require('express') | |
const cors = require('cors') // KSW added this | |
const {ftest, random, random4, random8, nesw} = require('./functions') // Procedural Memory | |
const {stest, sinsert, squery} = require('./storage') // Declarative Memory | |
const app = express() | |
const port = 3000 | |
// enable CORS for all origins | |
app.use(cors()); | |
app.use(express.json()) // for parsing application/json | |
app.get('/', (req, res) => { | |
res.send('Hello World!') | |
}) | |
// KSW test | |
app.get('/test1', (req, res) => { | |
res.send('Testing 1.') | |
}) | |
// KSW test | |
app.get('/test2', (req, res) => { | |
res.send('Testing 2.') | |
}) | |
app.get('/test2/:one', (req, res) => { | |
res.send('Testing 2: ' + req.params.one) | |
}) | |
app.get('/add/:one/:two', (req, res) => { | |
res.send(`${req.params.one} + ${req.params.two} = ` + (0 + Number(req.params.one) + Number(req.params.two))) | |
}) | |
/** | |
* Return a random direction for a Xholon agent to move to (0 1 2 3). Grid: (N S E W) or Tree: (parent first next prev). | |
*/ | |
app.get('/moveto', (req, res) => { | |
res.send("" + random4()) | |
}) | |
/** | |
* Working Memory. | |
* @param {Request} req A Perception or similar Request. | |
* @param {Response} res A Motor command or similar Response. | |
*/ | |
app.post('/nesw', (req, res) => { | |
sinsert(req.body) | |
res.send("" + nesw(req.body)) | |
}) | |
app.get("/squery", (req, res) => { | |
res.send(squery()) | |
}) | |
app.listen(port, () => { | |
console.log(`Example app listening at http://localhost:${port}`) | |
console.log(ftest()) | |
console.log(stest()) | |
console.log("NODE_ENV: " + process.env.NODE_ENV) | |
}) |
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
/** | |
Ken Webb | |
October 31, 2021 | |
functions.js | |
Functions for use with app.js | |
Decision Engine - Procedural Long-term Memory | |
*/ | |
const ftest = () => "Hello out there from FTest!" | |
/** | |
* Various functions that generate random integers within specified ranges. | |
*/ | |
const random = max => () => Math.floor(Math.random() * max) | |
const random4 = random(4) | |
const random8 = random(8) | |
/** | |
* Process a NESW JavaScript Object. | |
* @param {Object} obj ex: { me: 'LandCell', n: 'CoastCell', e: 'LandCell', s: 'LandCell', w: 'LandCell' } | |
* @return {Number} A direction to move to a random neighboring non-OceanCell gridCell. | |
*/ | |
const nesw = obj => { | |
const neswArr = Object.entries(obj).reduce((prev, curr) => { | |
if ((curr[0] !== "me") && (curr[1] !== "OceanCell")) { | |
prev.push(curr[0]) | |
} | |
return prev | |
}, []) | |
const moveto = neswArr[random(neswArr.length)()] | |
const movetoNum = moveto === "n" ? 0 | |
: moveto === "e" ? 1 | |
: moveto === "s" ? 2 | |
: 3 | |
//console.log(obj, neswArr, moveto, movetoNum) | |
return movetoNum | |
} | |
module.exports = {ftest, random, random4, random8, nesw}; |
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
{ | |
"me": { | |
"energy": 25, | |
"type": "TestAvatar", | |
"inventory": ["Thorn", "BlackBerry", "Fish", "Vine", "Stick"] | |
}, | |
"parent": { | |
"type": "LandCell", | |
"siblings": "ENTIRE NESTED TREE OF ALL SIBLINGS OF me, or use environment.local, or use siblings" | |
}, | |
"environment": { | |
"layout": "grid", | |
"local": {"maybe": "OR USE parent.siblings"}, | |
"neighborhood": { | |
"n": "OceanCell", | |
"e": "CoastCell", | |
"s": "LandCell", | |
"w": "LandCell", | |
"OPTIONAL DIAGONAL NEIGHBORS": { | |
"ne": "LandCell", | |
"se": "LandCell", | |
"sw": "LandCell", | |
"nw": "LandCell" | |
} | |
} | |
}, | |
"ISLANDGAME DISPLAY": [ | |
"{ timestep : 7637 , state : LandCell (Castaway (PricklyFruit Thorn)) , energy : 98165 }", | |
"{ timestep : 7699 , state : LandCell (GreenTree (Fruit*10 JuicyBerry*10 Stick*10) Castaway (PricklyFruit Thorn)) , energy : 98160 }", | |
"{ timestep : 7905 , state : LandCell (RedTree (PricklyFruit*10 Thorn*10 Vine*9) Castaway (PricklyFruit Thorn Vine Stick)) , energy : 98156 }", | |
"{ timestep : 8200 , state : LandCell (Двенадцать Castaway (PricklyFruit Thorn Vine)) , energy : 98137 }", | |
"{ timestep : 8399 , state : LandCell (Spring (FreshWater*100) Castaway (PricklyFruit Thorn Vine)) , energy : 98125 }", | |
"{ timestep : 8442 , state : LandCell (Spring (FreshWater*98) Castaway (PricklyFruit Thorn Vine FreshWater FreshWater)) , energy : 98124 }", | |
"{ timestep : 8977 , state : CoastCell (Castaway (PricklyFruit Thorn Vine FreshWater FreshWater) Fish) , energy : 98107 }", | |
"{ timestep : 9106 , state : CoastCell (TreasureChest (Stick*1 Vine*1 Thorn*1 CatTreat*10 Wilson*1) Castaway (PricklyFruit Thorn Vine FreshWater FreshWater)) , energy : 98061 }", | |
"{ timestep : 9179 , state : CoastCell (Ottawa (Carleton (Library (Starbucks (IslandControlCentre (SecretProjects (ElDorado) Troll) Ken Jen)) Baker) Oh So Good (Westboro Branch (Able))) Castaway (PricklyFruit Thorn Vine FreshWater FreshWater)) , energy : 98038 }", | |
], | |
"rules RECIPE": [ | |
"FishingRod = Stick+Vine+Thorn", | |
"Hut = Stick+Stick+Stick+Vine+Vine+Vine", | |
"Basket = Vine+Vine", | |
"YokeCarrier = Basket+Basket+Stick", | |
"Backpack = Basket+Vine", | |
"Canoe = Stick+Stick+Stick+Stick+Stick+Vine+Vine+Vine+Vine+Vine", | |
"Paddle = Stick+Stick+Vine", | |
"NOTE: rules are also found in the Avatar Key Mappings" | |
], | |
"COMMENTS": [ | |
"maybe use GraphQL?", | |
"" | |
] | |
} | |
{ | |
"before": "LandCell", | |
"direction": "n", | |
"now": "LandCell", | |
"n": "OceanCell", | |
"e": "CoastCell", | |
"s": "LandCell", | |
"w": "LandCell" | |
} |
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
<?xml version="1.0" encoding="UTF-8"?> | |
<!-- | |
Xholon Avatar that talks to a NPM Express (or any other) Server. | |
Ken Webb | |
November 3, 2021 | |
~/gwtspace/Xholon/Xholon/module/ava2srv/mAva2SrvPostNeswV2.xml | |
based on mAva2SrvPostNesw.xml | |
See Xholon workbook: Express - web framework for node | |
Copy and paste, or drag, this entire text into a running Xholon app. | |
--> | |
<XholonModule> | |
<XholonMap> | |
<Attribute_String roleName="ih"><![CDATA[ | |
<_-.XholonClass> | |
<NeswAvatar superClass="Avatar"/> | |
<Talk2ServerNesw superClass="Script"/> | |
<Talk2Robot superClass="Script"/> | |
</_-.XholonClass> | |
]]></Attribute_String> | |
<Attribute_String roleName="cd"><![CDATA[ | |
<xholonClassDetails> | |
<NeswAvatar><Color>purple</Color></NeswAvatar> | |
<Talk2ServerNesw><DefaultContent> | |
const REQ_REMOTE = true; | |
var me, ava, request, beh = { | |
postConfigure: function() { | |
me = this.cnode; | |
ava = me.parent().parent(); | |
if (!ava["subtrees"]) { | |
ava.action("param subtrees true"); | |
} | |
ava.action("param transcript false"); | |
const url = ["http://127.0.0.1:3000/nesw", "http://192.168.0.39:3000/nesw"]; | |
request = new Request(url[0]); | |
me.msg(101, "Sending me ..."); | |
}, | |
processReceivedMessage(msg) { | |
this.doRequest(this.prepData(ava.parent())); | |
}, | |
prepData: function(pava) { | |
return { | |
me: pava.xhc().name(), | |
n: pava.port(0).xhc().name(), | |
e: pava.port(1).xhc().name(), | |
s: pava.port(2).xhc().name(), | |
w: pava.port(3).xhc().name() | |
} | |
}, | |
doRequest: function(jso) { | |
if (REQ_REMOTE) { | |
this.doRequestRemote(jso); | |
} | |
else { | |
this.doRequestLocal(jso); | |
} | |
}, | |
doRequestRemote: function(jso) { | |
fetch(request, { | |
method: 'POST', | |
headers: { | |
'Content-Type': 'application/json' | |
}, | |
body: JSON.stringify(jso) | |
}) | |
.then((res) => res.text()) | |
.then((responseText) => { | |
this.moveto(responseText); | |
me.msg(101, "Sending me againR ..."); | |
return null; | |
}); | |
}, | |
doRequestLocal: function(obj) { | |
// this is the same code used in the Server functions.js | |
const neswArr = Object.entries(obj).reduce((prev, curr) => { | |
if ((curr[0] !== "me") && (curr[1] !== "OceanCell")) { | |
prev.push(curr[0]) | |
} | |
return prev | |
}, []) | |
const random = max => () => Math.floor(Math.random() * max) | |
const moveto = neswArr[random(neswArr.length)()] | |
const movetoNum = moveto === "n" ? 0 | |
: moveto === "e" ? 1 | |
: moveto === "s" ? 2 | |
: 3 | |
this.moveto(movetoNum); | |
me.msg(101, "Sending me againL ..."); | |
}, | |
moveto: function(direction) { | |
ava.action("go " + direction); // go 0|1|2|3 OK | |
} | |
} | |
//# sourceURL=Talk2ServerNeswbehavior.js | |
</DefaultContent></Talk2ServerNesw> | |
<!-- R O B O T | |
see: https://www.primordion.com/Xholon/gwt/wb/editwb.html?app=96da9e285876f9acc88625c962854df9&src=gist | |
- Python Robot - Dash | |
see: my notebook July 16 2021 | |
--> | |
<Talk2Robot><DefaultContent> | |
const RACTIVE = true; | |
function reqListener () { | |
$wnd.console.log(this.responseText); | |
} | |
var me, ava, oReq, pcell, beh = { | |
postConfigure: function() { | |
me = this.cnode.parent(); | |
console.log(me.name()); // behaviorsST_10652 | |
ava = me.parent(); //.parent(); | |
console.log(ava.name()); // neswAvatar_10651 | |
pcell = ava.parent(); | |
console.log(pcell.name()); // landCell_5989 | |
me.msg(101, "Sending me ...", me); | |
if (RACTIVE) { | |
oReq = new $wnd.XMLHttpRequest(); | |
oReq.addEventListener("load", reqListener); | |
//oReq.open("GET", "http://127.0.0.1:8887/robot"); | |
//oReq.send(); | |
me.println("Dash started ..."); | |
} | |
}, | |
act: function() { | |
if (RACTIVE) { | |
const pcellNow = ava.parent(); | |
//me.println("acting: " + me.name() + " " + pcellNow.name()); | |
if (pcellNow !== pcell) { | |
// the Avatar has moved | |
const action = pcellNow.id() < pcell.id() ? "fd" | |
: pcellNow.id() > pcell.id() ? "bk" | |
: "turn" | |
pcell = pcellNow; | |
oReq.open("GET", "http://127.0.0.1:8887/" + action); // http://127.0.0.1:8887/bk | |
oReq.send(); | |
//me.println("Dash is doing a " + action); | |
} | |
} | |
}, | |
processReceivedMessage(msg) { | |
//this.doRequest(this.prepData(ava.parent())); | |
console.log(`msg ${msg.signal} ${msg.data} ${msg.sender ? msg.sender.name() : "no sender"}`); | |
} | |
} | |
//# sourceURL=Talk2Robotbehavior.js | |
</DefaultContent></Talk2Robot> | |
</xholonClassDetails> | |
]]></Attribute_String> | |
<Attribute_String roleName="csh"><![CDATA[ | |
<_-.csh> | |
<!-- I can create additional instances of NeswAvatar, by dragging in just the following subtree --> | |
<NeswAvatar> | |
<BehaviorsST> | |
<Talk2ServerNesw/> | |
<Talk2Robot/> | |
</BehaviorsST> | |
</NeswAvatar> | |
</_-.csh> | |
]]></Attribute_String> | |
</XholonMap> | |
</XholonModule> |
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
<?xml version="1.0" encoding="UTF-8"?> | |
<!-- | |
Xholon Avatar that talks to a NPM Express (or any other) Server. | |
October 27, 2021 | |
~/gwtspace/Xholon/Xholon/module/moduleAvatar2Server.xml | |
See Xholon workbook: Express - web framework for node | |
Copy and paste, or drag, this entire text into a running Xholon app. | |
I was able to drag this module into the PhysicalSystem node of the running Express application. | |
- it worked! | |
It also works if I drag this module to the Castaway's current Cell, in: | |
https://www.primordion.com/Xholon/gwt/Xholon.html?app=24a2abddbdc3eb068d6f5d9f59af9964&src=gist&gui=none | |
Island B5 | |
TestAvatar moves around randomly. | |
See also: | |
- my notebook: October 21/25, 2021 | |
- Xholon workbook: Express - web framework for node 3ede7991936fe5281657c494f8a92caf | |
- NPM Express project: ~/nodespace/express01$ node app.js | |
--> | |
<XholonModule> | |
<XholonMap> | |
<Attribute_String roleName="ih"><![CDATA[ | |
<_-.XholonClass> | |
<Ten/> | |
<Eleven/> | |
<Twelve/> | |
<TestAvatar superClass="Avatar"/> | |
<Talk2Server superClass="Script"/> | |
</_-.XholonClass> | |
]]></Attribute_String> | |
<Attribute_String roleName="cd"><![CDATA[ | |
<xholonClassDetails> | |
<Ten><Color>red</Color></Ten> | |
<Eleven><Color>orange</Color></Eleven> | |
<Twelve><Color>yellow</Color></Twelve> | |
<TestAvatar><Color>blue</Color></TestAvatar> | |
<Talk2Server><DefaultContent> | |
var me, ava, request, beh = { | |
postConfigure: function() { | |
me = this.cnode; | |
ava = me.parent().parent(); | |
if (!ava["subtrees"]) { | |
ava.action("param subtrees true"); | |
} | |
const url = ["http://localhost:3000/moveto", "http://192.168.0.39:3000/moveto"]; | |
request = new Request(url[1], {method: 'GET'}); | |
}, | |
act: function() { | |
//me.println(me.name() + " " + ava.name() + " " + ava.parent().name()); | |
fetch(request) | |
.then((res) => res.text()) | |
.then((responseText) => this.moveto(responseText)); | |
}, | |
moveto: function(direction) { | |
//me.println(me.name() + " " + direction); | |
ava.action("go " + direction); // go 0|1|2|3 OK | |
//ava.action("go port" + direction); | |
} | |
} | |
//# sourceURL=Talk2Serverbehavior.js | |
</DefaultContent></Talk2Server> | |
</xholonClassDetails> | |
]]></Attribute_String> | |
<Attribute_String roleName="csh"><![CDATA[ | |
<_-.csh> | |
<Ten roleName="Десять" energy="10"/> | |
<Eleven roleName="Одиннадцать" energy="11"/> | |
<Twelve roleName="Двенадцать" energy="12"/> | |
<!-- I can create additional instances of TestAvatar, by dragging in just the following subtree --> | |
<TestAvatar> | |
<BehaviorsST> | |
<Talk2Server/> | |
</BehaviorsST> | |
</TestAvatar> | |
</_-.csh> | |
]]></Attribute_String> | |
</XholonMap> | |
</XholonModule> |
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
{ | |
"name": "express01", | |
"version": "1.0.0", | |
"description": "Simple Hello World server for use with Xholon app Express - web framework for node", | |
"main": "app.js", | |
"scripts": { | |
"test": "echo \"Error: no test specified\" && exit 1" | |
}, | |
"author": "Ken Webb", | |
"license": "ISC", | |
"dependencies": { | |
"cors": "^2.8.5", | |
"express": "^4.17.1" | |
} | |
} |
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
/** | |
Ken Webb | |
November 1, 2021 | |
storage.js | |
Storage for use with app.js | |
Declarative Long-term Memory | |
TODO maybe | |
- keep track of nesw+me JSOs: content+count | |
- me n e s w | |
- (L)andCell (C)oastCell (O)ceanCell | |
- example of one record in a neighborhoods JSO: | |
{ | |
L_LLLL: 1, | |
C_OLLC: 3 | |
} | |
*/ | |
const stest = () => "Hello from mighty STest!" | |
// storage, database | |
const neighborhoods = { | |
//{"L_LLLL":77865,"L_LLCL":2878,"C_LCOC":1421,"L_LLCC":447,"C_LCOO":123,"C_OOOC":23,"C_OCCC":62,"C_OCCL":44,"C_CCOC":43,"L_CCCL":302,"C_LCOL":735,"C_OOLC":161,"C_OCLC":1347,"L_CLCL":234,"L_CLLL":3574,"L_LCCL":3665,"C_LOOL":917,"C_COOC":123,"C_OCLO":838,"L_CLLC":3103,"C_LOOC":483,"C_LLOC":144,"C_OLLC":1199,"C_OLLO":643,"L_CCLL":777,"C_OOLL":113,"L_LCLL":1556,"C_LOLL":45,"C_OCLL":273,"C_COCL":347,"C_OOCL":73,"C_COLL":134,"C_LOCL":482,"C_LCLL":87,"C_CCLC":106,"C_COOL":388,"C_LCCL":330,"C_OOCC":155,"C_OLCO":129,"C_CLCO":978,"L_LLLC":1621,"C_CLOO":96,"C_CCLL":107,"L_CCLC":90,"C_OLLL":57,"C_CLLO":178,"C_OOLO":24,"C_LLOO":20,"L_LCLC":28,"C_LLCO":94} | |
} | |
/** | |
* ex: { me: 'LandCell', n: 'CoastCell', e: 'LandCell', s: 'LandCell', w: 'LandCell' } to "L_CLLL" | |
*/ | |
const jso2recname = jso => { | |
return `${jso.me.substring(0,1)}_${jso.n.substring(0,1)}${jso.e.substring(0,1)}${jso.s.substring(0,1)}${jso.w.substring(0,1)}` | |
} | |
const sinsert = nhood => { | |
const recname = jso2recname(nhood) | |
if (neighborhoods[recname]) { | |
neighborhoods[recname]++ | |
} | |
else { | |
neighborhoods[recname] = 1 | |
} | |
return true | |
} | |
// example of returned data: {"X_XXXX":42,"Y_YYYY":21,"Z_ZZZZ":1} | |
// {"C_LLOC":14,"L_LLCC":10,"L_LLCL":21,"C_LCOO":5,"L_LLLL":60,"C_LCOC":12} | |
// {"L_LLLL":540,"L_CLLC":4,"L_LLLC":3,"C_OLLO":2,"L_LCCL":18,"O_OOOC":1,"C_COOL":2,"C_LOOL":6,"C_LOCL":7,"O_OOOO":2,"L_LCLL":2} | |
// {"L_LLLL":2023,"L_CLLC":30,"L_LLLC":32,"C_OLLO":10,"L_LCCL":113,"O_OOOC":11,"C_COOL":9,"C_LOOL":26,"C_LOCL":23,"O_OOOO":206,"L_LCLL":54,"C_CLLO":5,"C_OLCO":14,"C_CLCO":22,"O_COOC":11,"L_LLCL":72,"C_LCOC":48,"O_COOO":4,"C_LOOC":5,"C_LCOL":14,"C_OCLO":4,"C_OOCC":10,"C_COCL":22,"L_CCLC":1,"L_LCLC":7,"C_CCLL":13,"O_OCCC":2,"C_OLLC":3,"L_CLLL":23,"C_LLCO":4,"O_OCOO":1,"L_LLCC":1,"C_LCCL":2,"O_OCCO":16,"C_COOC":2,"O_OOCO":21,"C_OOOC":4,"C_OCCC":6,"C_OCCL":6,"L_CCCL":3} | |
const squery = () => neighborhoods | |
module.exports = {stest, sinsert, squery}; |
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
<?xml version="1.0" encoding="UTF-8"?> | |
<!--Xholon Workbook http://www.primordion.com/Xholon/gwt/ MIT License, Copyright (C) Ken Webb, Fri Oct 29 2021 11:51:43 GMT-0400 (Eastern Daylight Time)--> | |
<XholonWorkbook> | |
<Notes><![CDATA[ | |
Xholon | |
------ | |
Title: Express - web framework for node | |
Description: | |
Url: http://www.primordion.com/Xholon/gwt/ | |
InternalName: 3ede7991936fe5281657c494f8a92caf | |
Keywords: express | |
My Notes | |
-------- | |
October 25, 2021 | |
In this workbook, I learn about and experiment with Xholon apps that use Express to write special-purpose servers that can run on localhost or on the Internet. | |
I previously used a Python server to control my Dash robot from a Xholon app. [ref 3] | |
I also wrote an app that downloads sets of pictures from flickr. [ref 5] | |
I previously learned about Express in the coursera course: Course 4, Week 1, Full-Stack Web Development with React Specialization | |
- see my notes and sample code | |
github | |
------ | |
https://gist.github.com/kenwebb/3ede7991936fe5281657c494f8a92caf | |
primordion.com URLs | |
------------------- | |
https://www.primordion.com/Xholon/gwt/wb/editwb.html?app=Express+-+web+framework+for+node&src=lstr | |
https://www.primordion.com/Xholon/gwt/Xholon.html?app=Express - web framework for node&src=lstr&gui=clsc | |
localhost URLs | |
-------------- | |
http://127.0.0.1:8080/war/wb/editwb.html?app=Express+-+web+framework+for+node&src=lstr | |
http://127.0.0.1:8080/war/Xholon.html?app=Express+-+web+framework+for+node&src=lstr&gui=clsc | |
to create a simple Hello World express server app (see ref 4) | |
------------------------------------------------- | |
cd ~/nodespace | |
mkdir express01 | |
cd express01 | |
npm init | |
"main": "app.js", | |
npm install express --save | |
- add JS content to app.js (from ref 4) | |
node app.js | |
(base) ken@ken-HP-ZBook-15-G2:~/nodespace/express01$ node app.js | |
Example app listening at http://localhost:3000 | |
- this works; the web page shows Hello World! | |
TODO create an express server app that will work with the Xholon app | |
---- | |
OK | |
CORS | |
---- | |
npm install cors | |
- edit app.js | |
To run this client + server app on localhost: | |
------ | |
1. start express server (in a terminal window) based on the simple app in ref 4 | |
cd ~/nodespace/express01 | |
node app.js | |
2. start http-server (in another terminal window) | |
cd ~/gwtspace/Xholon/Xholon | |
http-server OR npx http-server | |
Starting up http-server, serving ./ | |
Available on: | |
http://127.0.0.1:8080 | |
http://192.168.0.39:8080 | |
Hit CTRL-C to stop the server | |
3. start Xholon app | |
http://127.0.0.1:8080/war/ | |
http://127.0.0.1:8080/war/Xholon.html?app=Express+-+web+framework+for+node&src=lstr&gui=clsc | |
CORS error | |
---------- | |
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://127.0.0.1:3000/. (Reason: CORS header “Access-Control-Allow-Origin” missing). | |
See ref 3 and ref 6 for solution | |
app.js | |
------ | |
//The following is the JavaScript text of the Express app.js file: | |
const express = require('express') | |
const cors = require('cors') // KSW added this | |
const app = express() | |
const port = 3000 | |
// enable CORS for all origins | |
app.use(cors()); // KSW added this | |
app.get('/', (req, res) => { | |
res.send('Hello World!') | |
}) | |
app.listen(port, () => { | |
console.log(`Example app listening at http://localhost:${port}`) | |
}) | |
see also | |
-------- | |
see also: ~/gwtspace/Xholon/Xholon/module/moduleAvatar2Server.xml | |
- it incorporates what I have learned in this workbook | |
Client-Server using my home LAN | |
=============================== | |
HP Server | |
--------- | |
$ cd ~/nodespace/express01/ | |
$ node app.js | |
Example app listening at http://localhost:3000 | |
Lenovo Client | |
------------- | |
1. open the following URL for "Island B5", in the Firefox browser: | |
https://www.primordion.com/Xholon/gwt/Xholon.html?app=24a2abddbdc3eb068d6f5d9f59af9964&src=gist&gui=none | |
2. select an island, take Elixir, eat Elixir, and move the Castaway (Avatar) around a bit to expose some of the land | |
3. open the following file in a text editor: | |
~/gwtspace/Xholon/Xholon/module/moduleAvatar2Server.xml | |
it assumes that the URL for LAN access is http://192.168.0.39:3000/moveto | |
4. drag the cintents of that file into the cell (LandCell or CoastCell) that the Castaway is currently in | |
5. you should see: | |
- various new nodes in the cell, one of which is a new blue Avatar that moves around randomly | |
- a lot of messages in the out tab informing us as the new Avatar moves around | |
References | |
---------- | |
(1) http://expressjs.com/ | |
(2) https://www.npmjs.com/package/express | |
Fast, unopinionated, minimalist web framework for Node.js | |
(3) Python Robot - Dash: Xholon workbook, gist.github | |
96da9e285876f9acc88625c962854df9 | |
uses XMLHttpRequest | |
(4) http://expressjs.com/en/starter/hello-world.html | |
(5) Ramda-based Web Client | |
9eb896384969b169d43bfdea79743cb3 | |
has 3 versions: fetch (doesn't work), jquery, fetch-jsonp | |
(6) https://origin.geeksforgeeks.org/how-to-deal-with-cors-error-in-express-node-js-project/ | |
CORS solution | |
(7) https://developer.mozilla.org/en-US/docs/Web/API/fetch | |
https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API | |
]]></Notes> | |
<_-.XholonClass> | |
<PhysicalSystem/> | |
<Client/> | |
</_-.XholonClass> | |
<xholonClassDetails> | |
</xholonClassDetails> | |
<PhysicalSystem> | |
<Client aaa="2" bbb="99"/> | |
</PhysicalSystem> | |
<Clientbehavior implName="org.primordion.xholon.base.Behavior_gwtjs"><![CDATA[ | |
function reqListener () { | |
me.println("listening"); | |
me.println(this.responseText); | |
} | |
var me, oReq, request, beh = { | |
postConfigure: function() { | |
me = this.cnode.parent(); | |
request = new Request(`http://localhost:3000/add/${me.aaa}/${me.bbb}`, {method: 'GET'}); | |
me.println(request.url); | |
me.println(request.method); | |
oReq = new $wnd.XMLHttpRequest(); | |
oReq.addEventListener("load", reqListener); | |
oReq.open("GET", "http://127.0.0.1:3000"); // http://localhost:3000 | |
oReq.send(); | |
me.println("Client post configuring ..."); | |
}, | |
act: function() { | |
// both the Xhr and Fetch functions work | |
//this.actXhr(); | |
this.actFetch(); | |
}, | |
actXhr: function() { | |
me.println(me.name()); | |
//oReq.open("GET", "http://127.0.0.1:3000"); | |
//oReq.open("GET", `http://localhost:3000/add/${me.aaa}/${me.bbb}`); | |
oReq.open(request.method, request.url); | |
oReq.send(); | |
me.println("Client acting ..."); | |
}, | |
actFetch: function() { | |
//fetch(`http://localhost:3000/add/${me.aaa}/${me.bbb}`) | |
fetch(request) | |
.then((res) => res.text()) | |
.then((responseText) => me.println(responseText)); | |
fetch(`http://localhost:3000/moveto`) | |
.then((res) => res.text()) | |
.then((responseText) => me.println(responseText)); | |
} | |
} | |
//# sourceURL=Clientbehavior.js | |
]]></Clientbehavior> | |
<SvgClient><Attribute_String roleName="svgUri"><![CDATA[data:image/svg+xml, | |
<svg width="100" height="50" xmlns="http://www.w3.org/2000/svg"> | |
<g> | |
<title>Client</title> | |
<rect id="PhysicalSystem/Client" fill="#98FB98" height="50" width="50" x="25" y="0"/> | |
</g> | |
</svg> | |
]]></Attribute_String><Attribute_String roleName="setup">${MODELNAME_DEFAULT},${SVGURI_DEFAULT}</Attribute_String></SvgClient> | |
</XholonWorkbook> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment