SlideShare a Scribd company logo
1 of 69
Download to read offline
Eleanor McHugh


http://slideshare.net/feyeleanor


http://github.com/feyeleanor/TheBrowserEnvironment
The Browser Environment
A Systems Programmer's Perspective


[a rant in diverse movements]
TL;DR
JavaScript Concurrency is a Confused Mess


if you disagree you have serious Stockholm Syndrome
Elric of Melniboné, Michael Moorcock
E
lric sent his mind into twisting tunnels of logic,
across endless plains of ideas, through
mountains of symbolism and endless universes
of alternate truths; he sent his mind out further
and further and as it went he sent with it the words [...] words
that few of his contemporaries would understand...
pay attention!
all code is BSD 2-clause licensed


any resemblance to actual code &
conceptstm, living or dead, is probably
your imagination playing tricks on you


if you can make money from it you're
doing a damn sight better than we are!
In Digital Spaces
•2006 -> present [inidsol.uk]


•13 US patents


•real-time systems


•digital identity


•distributed ledgers


•DNS -> [TCP|UDP] -> HTTP


•Ruby -> Go -> JavaScript
Seeking Identity
Ellie

[physicist]
Romek

[cryptographer]
Since 2009
•http://leanpub.com/GoNotebook


•http://github.com/feyeleanor


•http://slideshare.net/feyeleanor
Abusing Go
HTTP[S]
serving web content with go
package main


import "fmt"


import "io/ioutil"


import "net/http"


import "os"


import "strings"


const LAUNCH_FAILED = 1


const FILE_READ = 2


const ADDRESS = ":3000"


var MESSAGE string


func main() {


s := strings.Split(os.Args[0], "/")


html, e := ioutil.ReadFile(s[len(s) - 1] + ".html")


Abort(FILE_READ, e)


MESSAGE = string(html)


http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {


w.Header().Set("Content-Type", "text/html")


fmt.Fprint(w, MESSAGE)


})


Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil))


}


func Abort(n int, e error) {


if e != nil {


fmt.Println(e)


os.Exit(n)


}	


}


<!DOCTYPE html>


<html>


<head>


<meta charset='UTF-8' />


<title>SERVING HTML</title>


</head>


<body>


<h1>SERVING HTML</h1>


<div>


hello world!


</div>


</body>


</html>
func main() {


s := strings.Split(os.Args[0], "/")


html, e := ioutil.ReadFile(s[len(s) - 1] + ".html")


Abort(FILE_READ, e)


MESSAGE = string(html)


http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {


w.Header().Set("Content-Type", "text/html")


fmt.Fprint(w, MESSAGE)


})


Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil))


}
package main


import "fmt"


import "io/ioutil"


import "net/http"


import "os"


import "strings"


const LAUNCH_FAILED = 1


const FILE_READ = 2


const ADDRESS = ":3000"


var MESSAGE string


func main() {


s := strings.Split(os.Args[0], "/")


html, e := ioutil.ReadFile(s[len(s) - 1] + ".html")


Abort(FILE_READ, e)


MESSAGE = string(html)


http.HandleFunc("/", billboard)


Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil))


}


func billboard(w http.ResponseWriter, r *http.Request) {


w.Header().Set("Content-Type", "text/html")


fmt.Fprint(w, MESSAGE)


}


func Abort(n int, e error) {


if e != nil {


fmt.Println(e)


os.Exit(n)


}	


}


<!DOCTYPE html>


<html>


<head>


<meta charset='UTF-8' />


<title>SERVING HTML</title>


</head>


<body>


<h1>SERVING HTML</h1>


<div>


hello world!


</div>


</body>


</html>
func main() {


s := strings.Split(os.Args[0], "/")


html, e := ioutil.ReadFile(s[len(s) - 1] + ".html")


Abort(FILE_READ, e)


MESSAGE = string(html)


http.HandleFunc("/", billboard)


Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil))


}


func billboard(w http.ResponseWriter, r *http.Request) {


w.Header().Set("Content-Type", "text/html")


fmt.Fprint(w, MESSAGE)


}
package main


import "fmt"


import "io/ioutil"


import "net/http"


import "os"


import "strings"


const LAUNCH_FAILED = 1


const FILE_READ = 2


const ADDRESS = ":3000"


const CERT="cert.pem"


const KEY="key.pem"


var MESSAGE string


func main() {


s := strings.Split(os.Args[0], "/")


html, e := ioutil.ReadFile(s[len(s) - 1] + ".html")


Abort(FILE_READ, e)


MESSAGE = string(html)


http.HandleFunc("/", billboard)


Abort(LAUNCH_FAILED, http.ListenAndServeTLS(ADDRESS, CERT, KEY, nil))


}


func billboard(w http.ResponseWriter, r *http.Request) {


w.Header().Set("Content-Type", "text/html")


fmt.Fprint(w, MESSAGE)


}


func Abort(n int, e error) {


if e != nil {


fmt.Println(e)


os.Exit(n)


}	


}


<!DOCTYPE html>


<html>


<head>


<meta charset='UTF-8' />


<title>SERVING HTML</title>


</head>


<body>


<h1>SERVING HTML</h1>


<div>


hello world!


</div>


</body>


</html>
func main() {


s := strings.Split(os.Args[0], "/")


html, e := ioutil.ReadFile(s[len(s) - 1] + ".html")


Abort(FILE_READ, e)


MESSAGE = string(html)


http.HandleFunc("/", billboard)


Abort(LAUNCH_FAILED, http.ListenAndServeTLS(ADDRESS, CERT, KEY, nil))


}
Microsoft's Gift


to Humanity
the XMLHttpRequest object
aka


AJAX
asynchronous javascript and XML
AJAX
Asynchronous JavaScript and XML
•JavaScript is a single-threaded language


•but browsers are event-driven environments


•so JavaScript runtimes normally have three basic threads


•one to run the main script


•one to run scripts for high priority events


•one to run scripts for low priority events


•and each event can have callbacks de
fi
ned for it
AJAX
Asynchronous JavaScript and XML
•XMLHttpRequest
fi
rst appeared in MSXML


•available in IE5 as an ActiveX component from 1999


•similar functionality in other browsers from 2000 onwards


•fully supported in IE 7 2006


•despite its name it isn't restricted to XML


•most modern uses involve JSON
package main


import "fmt"


import "net/http"


import "os"


import "strings"


import "text/template"


const LAUNCH_FAILED = 1


const FILE_READ = 2


const BAD_TEMPLATE = 3


const ADDRESS = ":3000"


type Commands map[string] func(http.ResponseWriter, *http.Request)


type PageCon
fi
guration struct { Commands }


func main() {


p := PageCon
fi
guration{


Commands{ "A": AJAX_handler("A"), "B": AJAX_handler("B"), "C": AJAX_handler("C") }}


html, e := template.ParseFiles(BaseName() + ".html")


Abort(FILE_READ, e)


http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {


w.Header().Set("Content-Type", "text/html")


Abort(BAD_TEMPLATE, html.Execute(w, p))


})


for c, f := range p.Commands {


http.HandleFunc("/"+c, f)


}


Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil))


}


func Abort(n int, e error) {


if e != nil {


fmt.Println(e)


os.Exit(n)


}


}


func BaseName() string {


s := strings.Split(os.Args[0], "/")


return s[len(s)-1]


}


func AJAX_handler(c string) func(http.ResponseWriter, *http.Request) {


func(w http.ResponseWriter, r *http.Request) {


w.Header().Set("Content-Type", "text/plain")


fmt.Fprint(w, c)


}


}
<!DOCTYPE html>


<html>


<head>


<meta charset='UTF-8' />


<title>AJAX EXAMPLE</title>


<script>


function print(e, m) {


document.getElementById(e).innerHTML += `<div>${m}</div>`;


}


{{range $c, $v := .Commands}}


function {{$c}}() {


var xhttp = new XMLHttpRequest();


xhttp.onreadystatechange = function() {


if (this.readyState == 4 && this.status == 200) {


print("event_log", this.responseText);


}


};


xhttp.open("GET", "{{$c}}", true);


xhttp.send();


}


{{end}}


</script>


</head>


<body>


<h1>AJAX EXAMPLE</h1>


<h2>Known Asynchronous Actions</h2>


<div>


{{range $c, $v := .Commands}}


<span>


<button type="button" onclick="{{$c}}();">{{$c}}</button>


</span>


{{end}}


</div>


<h2>Server Output</h2>


<div id='event_log'></div>


</body>


</html>
package main


import "fmt"


import "net/http"


import "os"


import "strings"


import "text/template"


const LAUNCH_FAILED = 1


const FILE_READ = 2


const BAD_TEMPLATE = 3


const ADDRESS = ":3000"


type Commands map[string] func(http.ResponseWriter, *http.Request)


type PageCon
fi
guration struct { Commands }


func main() {


p := PageCon
fi
guration{


Commands{


"A": AJAX_handler("A"),


"B": AJAX_handler("B"),


"C": AJAX_handler("C") }}


html, e := template.ParseFiles(BaseName() + ".html")


Abort(FILE_READ, e)


http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {


w.Header().Set("Content-Type", "text/html")


Abort(BAD_TEMPLATE, html.Execute(w, p))


})


for c, f := range p.Commands {


http.HandleFunc("/"+c, f)


}


Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil))


}


<!DOCTYPE html>


<html>


<head>


<meta charset='UTF-8' />


<title>AJAX EXAMPLE</title>


<script>


function print(e, m) {


document.getElementById(e).innerHTML += `<div>${m}</div>`;


}


{{range $c, $v := .Commands}}


function {{$c}}() {


var xhttp = new XMLHttpRequest();


xhttp.onreadystatechange = function() {


if (this.readyState == 4 && this.status == 200) {


print("event_log", this.responseText);


}


};


xhttp.open("GET", "{{$c}}", true);


xhttp.send();


}


{{end}}


</script>


</head>


<body>


<h1>AJAX EXAMPLE</h1>


<h2>Known Asynchronous Actions</h2>


<div>


{{range $c, $v := .Commands}}


<span>


<button type="button" onclick="{{$c}}();">{{$c}}</button>


</span>


{{end}}


</div>


<h2>Server Output</h2>


<div id='event_log'></div>


</body>


</html>
{{range $c, $v := .Commands}}


function {{$c}}() {


var xhttp = new XMLHttpRequest();


xhttp.onreadystatechange = function() {


if (this.readyState == 4 && this.status == 200) {


print("event_log", this.responseText);


}


};


xhttp.open("GET", "{{$c}}", true);


xhttp.send();


}


{{end}}


{{range $c, $v := .Commands}}


<span>


<button type="button" onclick="{{$c}}();">{{$c}}


</button>


</span>


{{end}}
{{range $c, $v := .Commands}}


function {{$c}}() {


var xhttp = new XMLHttpRequest();


xhttp.onreadystatechange = function() {


if (this.readyState == 4 && this.status == 200) {


print("event_log", this.responseText);


}


};


xhttp.open("GET", "{{$c}}", true);


xhttp.send();


}


{{end}}
package main


import "fmt"


import "net/http"


import "os"


import "strings"


import "text/template"


const LAUNCH_FAILED = 1


const FILE_READ = 2


const BAD_TEMPLATE = 3


const ADDRESS = ":3000"


type Commands map[string] func(http.ResponseWriter, *http.Request)


type PageCon
fi
guration struct { Commands }


func main() {


p := PageCon
fi
guration{


Commands{ "A": AJAX_handler("A"), "B": AJAX_handler("B"), "C": AJAX_handler("C") }}


html, e := template.ParseFiles(BaseName() + ".html")


Abort(FILE_READ, e)


http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {


w.Header().Set("Content-Type", "text/html")


Abort(BAD_TEMPLATE, html.Execute(w, p))


})


for c, f := range p.Commands {


http.HandleFunc("/"+c, f)


}


Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil))


}


func Abort(n int, e error) {


if e != nil {


fmt.Println(e)


os.Exit(n)


}


}


func BaseName() string {


s := strings.Split(os.Args[0], "/")


return s[len(s)-1]


}


func AJAX_handler(c string) func(http.ResponseWriter, *http.Request) {


func(w http.ResponseWriter, r *http.Request) {


w.Header().Set("Content-Type", "text/plain")


fmt.Fprint(w, c)


}


}
<!DOCTYPE html>


<html>


<head>


<meta charset='UTF-8' />


<title>AJAX EXAMPLE</title>


<script>


function print(e, m) {


document.getElementById(e).innerHTML += `<div>${m}</div>`;


}


{{range $c, $v := .Commands}}


function {{$c}}() {


var xhttp = new XMLHttpRequest();


xhttp.open("GET", "{{$c}}", false);


try {


xhttp.send();


print("event_log", xhttp.responseText);


} catch(err) {


print("event_log", `Request Failed: ${err}`);


}


}


{{end}}


</script>


</head>


<body>


<h1>AJAX EXAMPLE</h1>


<h2>Known Asynchronous Actions</h2>


<div>


{{range $c, $v := .Commands}}


<span>


<button type="button" onclick="{{$c}}();">{{$c}}</button>


</span>


{{end}}


</div>


<h2>Server Output</h2>


<div id='event_log'></div>


</body>


</html>
{{range $c, $v := .Commands}}


function {{$c}}() {


var xhttp = new XMLHttpRequest();


xhttp.open("GET", "{{$c}}", false);


try {


xhttp.send();


print("event_log", xhttp.responseText);


} catch(err) {


print("event_log", `Request Failed: ${err}`);


}


}


{{end}}
fetch
a promise of things to come
package main


import "fmt"


import "net/http"


import "os"


import "strings"


import "text/template"


const LAUNCH_FAILED = 1


const FILE_READ = 2


const BAD_TEMPLATE = 3


const ADDRESS = ":3000"


type Commands map[string] func(http.ResponseWriter, *http.Request)


type PageCon
fi
guration struct { Commands }


func main() {


p := PageCon
fi
guration{


Commands{ "A": AJAX_handler("A"), "B": AJAX_handler("B"), "C": AJAX_handler("C") }}


html, e := template.ParseFiles(BaseName() + ".html")


Abort(FILE_READ, e)


http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {


w.Header().Set("Content-Type", "text/html")


Abort(BAD_TEMPLATE, html.Execute(w, p))


})


for c, f := range p.Commands {


http.HandleFunc("/"+c, f)


}


Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil))


}


func Abort(n int, e error) {


if e != nil {


fmt.Println(e)


os.Exit(n)


}


}


func BaseName() string {


s := strings.Split(os.Args[0], "/")


return s[len(s)-1]


}


func AJAX_handler(c string) func(http.ResponseWriter, *http.Request) {


func(w http.ResponseWriter, r *http.Request) {


w.Header().Set("Content-Type", "text/plain")


fmt.Fprint(w, c)


}


}
<!DOCTYPE html>


<html>


<head>


<meta charset='UTF-8' />


<title>FETCH EXAMPLE</title>


<script>


function print(e, m) {


document.getElementById(e).innerHTML += `<div>${m}</div>`;


}


{{range $c, $v := .Commands}}


async function {{$c}}() {


let response = await fetch("{{$c}}");


if (response.ok) {


let body = await response.text();


print("event_log", body);


} else {


print("event_log", `Request Failed: ${response.status}`);


}


}


{{end}}


</script>


</head>


<body>


<h1>FETCH EXAMPLE</h1>


<h2>Known Asynchronous Actions</h2>


<div>


{{range $c, $v := .Commands}}


<span>


<button type="button" onclick="{{$c}}();">{{$c}}</button>


</span>


{{end}}


</div>


<h2>Server Output</h2>


<div id='event_log'></div>


</body>


</html>
{{range $c, $v := .Commands}}


async function {{$c}}() {


let response = await fetch("{{$c}}");


if (response.ok) {


let body = await response.text();


print("event_log", body);


} else {


print("event_log", `Request Failed: ${response.status}`);


}


}


{{end}}
{{range $c, $v := .Commands}}


async function {{$c}}() {


let response = await fetch("{{$c}}");


if (response.ok) {


let body = await response.text();


print("event_log", body);


} else {


print("event_log", `Request Failed: ${response.status}`);


}


}


{{end}}
{{range $c, $v := .Commands}}


async function {{$c}}() {


fetch("{{$c}}")


.then(response => response.text())


.then(text => print("event_log", text))


.catch(e => print("event_log", `Request Failed: ${e}`));


}


{{end}}
DOM
document object model
package main


import "fmt"


import "io/ioutil"


import "net/http"


import "os"


import "strings"


const LAUNCH_FAILED = 1


const FILE_READ = 2


const ADDRESS = ":3000"


var MESSAGE string


func main() {


s := strings.Split(os.Args[0], "/")


html, e := ioutil.ReadFile(s[len(s)-1] + ".html")


Abort(FILE_READ, e)


MESSAGE = string(html)


http.HandleFunc("/", billboard)


Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil))


}


func billboard(w http.ResponseWriter, r *http.Request) {


w.Header().Set("Content-Type", "text/html")


fmt.Fprint(w, MESSAGE)


}


func Abort(n int, e error) {


if e != nil {


fmt.Println(e)


os.Exit(n)


}


}
<!DOCTYPE html>


<html>


<head>


<meta charset='UTF-8' />


<title>FETCH EXAMPLE</title>


<script>


function print(e, m) {


document.getElementById(e).innerHTML += `<div>${m}</div>`;


}


function hide(...n) {


n.forEach(e => {


document.getElementById(e).innerHTML = "X";


});


}


function show(...n) {


n.forEach(e => {


document.getElementById(e).innerHTML = e;


});


}


function toggle(name) {


print("event_log", name);


hide(name);


switch(name) {


case 'A':


show('B', 'C');


break;


case 'B':


show('A', 'C');


break;


case 'C':


show('A', 'B');


break;


};


}


</script>


</head>


<body>


<h1>FETCH EXAMPLE</h1>


<h2>Known Asynchronous Actions</h2>


<div>


<button id='A' type="button" onclick="toggle('A');">A</button>


<button id='B' type="button" onclick="toggle('B');">B</button>


<button id='C' type="button" onclick="toggle('C');">C</button>


</div>


<h2>Server Output</h2>


<div id='event_log'></div>


</body>


</html>
function hide(...n) {


n.forEach(e => {


document.getElementById(e).innerHTML = "X";


});


}


function show(...n) {


n.forEach(e => {


document.getElementById(e).innerHTML = e;


});


}


function toggle(name) {


print("event_log", name);


hide(name);


switch(name) {


case 'A':


show('B', 'C');


break;


case 'B':


show('A', 'C');


break;


case 'C':


show('A', 'B');


break;


};


}
<body>


<h1>FETCH EXAMPLE</h1>


<h2>Known Asynchronous Actions</h2>


<div>


<button id='A' type="button" onclick="toggle('A');">A</button>


<button id='B' type="button" onclick="toggle('B');">B</button>


<button id='C' type="button" onclick="toggle('C');">C</button>


</div>


<h2>Server Output</h2>


<div id='event_log'></div>


</body>
function hide(...n) {


n.forEach(e => {


document.getElementById(e).innerHTML = "X";


});


}


function show(...n) {


n.forEach(e => {


document.getElementById(e).innerHTML = e;


});


}


function toggle(name) {


print("event_log", name);


hide(name);


switch(name) {


case 'A':


show('B', 'C');


break;


case 'B':


show('A', 'C');


break;


case 'C':


show('A', 'B');


break;


};


}
<body>


<h1>FETCH EXAMPLE</h1>


<h2>Known Asynchronous Actions</h2>


<div>


<button id='A' type="button" onclick="toggle('A');">A</button>


<button id='B' type="button" onclick="toggle('B');">B</button>


<button id='C' type="button" onclick="toggle('C');">C</button>


</div>


<h2>Server Output</h2>


<div id='event_log'></div>


</body>
package main


import "fmt"


import "io/ioutil"


import "net/http"


import "os"


import "strings"


const LAUNCH_FAILED = 1


const FILE_READ = 2


const ADDRESS = ":3000"


var MESSAGE string


func main() {


s := strings.Split(os.Args[0], "/")


html, e := ioutil.ReadFile(s[len(s)-1] + ".html")


Abort(FILE_READ, e)


MESSAGE = string(html)


http.HandleFunc("/", billboard)


Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil))


}


func billboard(w http.ResponseWriter, r *http.Request) {


w.Header().Set("Content-Type", "text/html")


fmt.Fprint(w, MESSAGE)


}


func Abort(n int, e error) {


if e != nil {


fmt.Println(e)


os.Exit(n)


}


}
<!DOCTYPE html>


<html>


<head>


<meta charset='UTF-8' />


<title>DOM EXAMPLE</title>


<script>


function hide(e) {


e.innerHTML = "X";


}


function show(...e) {


e.forEach(e => {


e.innerHTML = e.id;


});


}


var buttons = [];


function toggle(e) {


hide(e);


switch(e.id) {


case 'A':


show(buttons[1], buttons[0]);


break;


case 'B':


show(buttons[2], buttons[0]);


break;


case 'C':


show(buttons[2], buttons[1]);


break;


};


}


function newButton(id) {


let b = document.createElement("BUTTON");


b.id = id;


b.onclick = new Function("toggle(this);");


b.appendChild(document.createTextNode(id));


return b;


}


window.onload = () => {


let button_bar = document.getElementById("action_buttons");


['A', 'B', 'C'].forEach(n => {


buttons.unshift(newButton(n));


button_bar.appendChild(buttons[0]);


});


};


</script>


</head>


<body>


<h1>DOM EXAMPLE</h1>


<h2>Known Actions</h2>


<div id="action_buttons"></div>


</body>


</html>
function hide(...n) {


n.forEach(e => {


document.getElementById(e).innerHTML = "X";


});


}


function show(...n) {


n.forEach(e => {


document.getElementById(e).innerHTML = e;


});


}
function hide(e) {


e.innerHTML = "X";


}


function show(...e) {


e.forEach(e => {


e.innerHTML = e.id;


});


}
function toggle(name) {


print("event_log", name);


hide(name);


switch(name) {


case 'A':


show('B', 'C');


break;


case 'B':


show('A', 'C');


break;


case 'C':


show('A', 'B');


break;


};


}
var buttons = [];


function toggle(e) {


hide(e);


switch(e.id) {


case 'A':


show(buttons[1], buttons[0]);


break;


case 'B':


show(buttons[2], buttons[0]);


break;


case 'C':


show(buttons[2], buttons[1]);


break;


};


}
function newButton(id) {


let b = document.createElement("BUTTON");


b.id = id;


b.onclick = new Function("toggle(this);");


b.appendChild(document.createTextNode(id));


return b;


}


window.onload = () => {


let button_bar = document.getElementById("action_buttons");


['A', 'B', 'C'].forEach(n => {


buttons.unshift(newButton(n));


button_bar.appendChild(buttons[0]);


});


};
<body>


<h1>DOM EXAMPLE</h1>


<h2>Known Actions</h2>


<div id="action_buttons"></div>


</body>
package main


import "fmt"


import "net/http"


import "os"


import "strings"


import "text/template"


const LAUNCH_FAILED = 1


const FILE_READ = 2


const BAD_TEMPLATE = 3


const ADDRESS = ":3000"


type Commands map[string]func(http.ResponseWriter, *http.Request)


type PageCon
fi
guration struct{ Commands }


func main() {


p := PageCon
fi
guration{


Commands{


"A": AJAX_handler("A"), "B": AJAX_handler("B"), "C": AJAX_handler("C") }}


html, e := template.ParseFiles(BaseName() + ".html")


Abort(FILE_READ, e)


http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {


w.Header().Set("Content-Type", "text/html")


Abort(BAD_TEMPLATE, html.Execute(w, p))


})


for c, f := range p.Commands {


http.HandleFunc("/"+c, f)


}


Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil))


}


func Abort(n int, e error) {


if e != nil {


fmt.Println(e)


os.Exit(n)


}


}


func BaseName() string {


s := strings.Split(os.Args[0], "/")


return s[len(s)-1]


}


func AJAX_handler(c string) func(http.ResponseWriter, *http.Request) {


return func(w http.ResponseWriter, r *http.Request) {


w.Header().Set("Content-Type", "text/plain")


fmt.Fprint(w, c)


}


}
<!DOCTYPE html>


<html>


<head>


<meta charset='UTF-8' />


<title>DOM FETCH EXAMPLE</title>


<script>


function print(e, m) {


document.getElementById(e).innerHTML += `<div>${m}</div>`;


}


function doCommand(c) {


fetch(c)


.then(response => response.text())


.then(text => print("event_log", text))


.catch(e => print("event_log", `Request Failed: ${e}`));


}


function newButton(n, c) {


let b = document.createElement("BUTTON");


b.onclick = c;


b.appendChild(document.createTextNode(n));


return b;


}


window.onload = () => {


let button_bar = document.getElementById("action_buttons");


{{range $c, $v := .Commands}}


button_bar.appendChild(


newButton('{{$c}}', () => doCommand('{{$c}}')));


{{end}}


};


</script>


</head>


<body>


<h1>DOM FETCH EXAMPLE</h1>


<h2>Known Asynchronous Actions</h2>


<div id="action_buttons"></div>


<h2>Server Output</h2>


<div id='event_log'></div>


</body>


</html>
window.onload = () => {


let button_bar = document.getElementById("action_buttons");


{{range $c, $v := .Commands}}


button_bar.appendChild(


newButton('{{$c}}', () => doCommand('{{$c}}')));


{{end}}


};
function doCommand(c) {


fetch(c)


.then(response => response.text())


.then(text => print("event_log", text))


.catch(e => print("event_log", `Request Failed: ${e}`));


}


function newButton(n, c) {


let b = document.createElement("BUTTON");


b.onclick = c;


b.appendChild(document.createTextNode(n));


return b;


}


window.onload = () => {


let button_bar = document.getElementById("action_buttons");


{{range $c, $v := .Commands}}


button_bar.appendChild(


newButton('{{$c}}', () => doCommand('{{$c}}')));


{{end}}


};
setInterval
marking time
package main


import "fmt"


import "io/ioutil"


import "net/http"


import "os"


import "strings"


const LAUNCH_FAILED = 1


const FILE_READ = 2


const ADDRESS = ":3000"


var MESSAGE string


func main() {


s := strings.Split(os.Args[0], "/")


html, e := ioutil.ReadFile(s[len(s)-1] + ".html")


Abort(FILE_READ, e)


MESSAGE = string(html)


http.HandleFunc("/", billboard)


Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil))


}


func billboard(w http.ResponseWriter, r *http.Request) {


w.Header().Set("Content-Type", "text/html")


fmt.Fprint(w, MESSAGE)


}


func Abort(n int, e error) {


if e != nil {


fmt.Println(e)


os.Exit(n)


}


}
<!DOCTYPE html>


<html>


<head>


<meta charset='UTF-8' />


<title>TIMER EXAMPLE</title>


<script>


function print(e, m) {


document.getElementById(e).innerHTML += `<div>${m}</div>`;


}


window.onload = () => {


let i = window.setInterval(() => {


print("event_log", "setInterval triggered");


}, 500);


window.setTimeout(() => {


print("event_log", "setTimeout triggered");


window.setTimeout(() => {


window.clearInterval(i);


print("event_log", "setInterval cancelled");


}, 2000);


}, 3000);


}


</script>


</head>


<body>


<h1>TIMER EXAMPLE</h1>


<h2>Timer Events</h2>


<div id='event_log'></div>


</body>


</html>
window.onload = () => {


let i = window.setInterval(() => {


print("event_log", "setInterval triggered");


}, 500);


window.setTimeout(() => {


print("event_log", "setTimeout triggered");


window.setTimeout(() => {


window.clearInterval(i);


print("event_log", "setInterval cancelled");


}, 2000);


}, 3000);


}
window.onload = () => {


let i = window.setInterval(() => {


print("event_log", "setInterval triggered");


}, 500);


window.setTimeout(() => {


print("event_log", "setTimeout triggered");


window.setTimeout(() => {


window.clearInterval(i);


print("event_log", "setInterval cancelled");


}, 2000);


}, 3000);


}
package main


import "fmt"


import "io/ioutil"


import "net/http"


import "os"


import "strings"


const LAUNCH_FAILED = 1


const FILE_READ = 2


const ADDRESS = ":3000"


var MESSAGE string


func main() {


s := strings.Split(os.Args[0], "/")


html, e := ioutil.ReadFile(s[len(s)-1] + ".html")


Abort(FILE_READ, e)


MESSAGE = string(html)


http.HandleFunc("/", billboard)


Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil))


}


func billboard(w http.ResponseWriter, r *http.Request) {


w.Header().Set("Content-Type", "text/html")


fmt.Fprint(w, MESSAGE)


}


func Abort(n int, e error) {


if e != nil {


fmt.Println(e)


os.Exit(n)


}


}
<!DOCTYPE html>


<html>


<head>


<meta charset='UTF-8' />


<title>TIMER EXAMPLE</title>


<script>


function print(e, m) {


document.getElementById(e).innerHTML += `<div>${m}</div>`;


}


const doAfter = (i, f) => { return window.setTimeout(f, i) };


const doEvery = (i, f) => { return window.setInterval(f, i) };


window.onload = () => {


let i = doEvery(500, () => {


print("event_log", "doEvery triggered");


);


doAfter(3000, () => {


print("event_log", "doAfter triggered");


doAfter(2000, () => {


window.clearInterval(i);


print("event_log", "doEvery cancelled");


});


});


}


</script>


</head>


<body>


<h1>TIMER EXAMPLE</h1>


<h2>Timer Events</h2>


<div id='event_log'></div>


</body>


</html>
const doAfter = (i, f) => { return window.setTimeout(f, i) };


const doEvery = (i, f) => { return window.setInterval(f, i) };


window.onload = () => {


let i = doEvery(500, () => {


print("event_log", "doEvery triggered");


});


doAfter(3000, () => {


print("event_log", "doAfter triggered");


doAfter(2000, () => {


window.clearInterval(i);


print("event_log", "doEvery cancelled");


});


});


}
window.onload = () => {


let i = window.setInterval(() => {


print("event_log", "setInterval triggered");


}, 500);


window.setTimeout(() => {


print("event_log", "setTimeout triggered");


window.setTimeout(() => {


window.clearInterval(i);


print("event_log", "setInterval cancelled");


}, 2000);


}, 3000);


}


window.onload = () => {


let i = doEvery(500, () => {


print("event_log", "doEvery triggered");


});


doAfter(3000, () => {


print("event_log", "doAfter triggered");


doAfter(2000, () => {


window.clearInterval(i);


print("event_log", "doEvery cancelled");


});


});


}
package main


import "fmt"


import "net/http"


import "os"


import "strings"


import "text/template"


const LAUNCH_FAILED = 1


const FILE_READ = 2


const BAD_TEMPLATE = 3


const ADDRESS = ":3000"


type Commands map[string]func(http.ResponseWriter, *http.Request)


type PageCon
fi
guration struct{ Commands }


func main() {


p := PageCon
fi
guration{


Commands{


"A": AJAX_handler("A"), "B": AJAX_handler("B"), "C": AJAX_handler("C") }}


html, e := template.ParseFiles(BaseName() + ".html")


Abort(FILE_READ, e)


http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {


w.Header().Set("Content-Type", "text/html")


Abort(BAD_TEMPLATE, html.Execute(w, p))


})


for c, f := range p.Commands {


http.HandleFunc("/"+c, f)


}


Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil))


}


func Abort(n int, e error) {


if e != nil {


fmt.Println(e)


os.Exit(n)


}


}


func BaseName() string {


s := strings.Split(os.Args[0], "/")


return s[len(s)-1]


}


func AJAX_handler(c string) func(http.ResponseWriter, *http.Request) {


return func(w http.ResponseWriter, r *http.Request) {


w.Header().Set("Content-Type", "text/plain")


fmt.Fprint(w, c)


}


}
<!DOCTYPE html>


<html>


<head>


<meta charset='UTF-8' />


<title>TIMER FETCH EXAMPLE</title>


<script>


const print = (e, m) => document.getElementById(e).innerHTML += `<div>${m}</div>`;


const doEvery = (i, f) => { return window.setInterval(f, i) };


var timers = {}


function doCommand(c) {


if (timers[c]) {


print("event_log", `no longer polling ${c}`);


window.clearInterval(timers[c]);


timers[c] = null;


} else {


print("event_log", `polling ${c}`);


timers[c] = doEvery(500, () => {


fetch(c)


.then(response => response.text())


.then(text => print("event_log", text))


.catch(e => print("event_log", `Request Failed: ${e}`));


});


}


}


function newButton(n, c) {


let b = document.createElement("BUTTON");


b.onclick = c;


b.appendChild(document.createTextNode(n));


return b;


}


window.onload = () => {


let button_bar = document.getElementById("action_buttons");


{{range $c, $v := .Commands}}


button_bar.appendChild(


newButton('{{$c}}', () => doCommand('{{$c}}')));


{{end}}


}


</script>


</head>


<body>


<h1>TIMER FETCH EXAMPLE</h1>


<h2>Known Asynchronous Actions</h2>


<div id="action_buttons"></div>


<h2>Server Output</h2>


<div id='event_log'></div>


</body>


</html>
var timers = {}


function doCommand(c) {


if (timers[c]) {


print("event_log", `no longer polling ${c}`);


window.clearInterval(timers[c]);


timers[c] = null;


} else {


print("event_log", `polling ${c}`);


timers[c] = doEvery(500, () => {


fetch(c)


.then(response => response.text())


.then(text => print("event_log", text))


.catch(e => print("event_log", `Request Failed: ${e}`));


});


}


}
var timers = {}


function doCommand(c) {


if (timers[c]) {


print("event_log", `no longer polling ${c}`);


window.clearInterval(timers[c]);


timers[c] = null;


} else {


print("event_log", `polling ${c}`);


timers[c] = doEvery(500, () => {


fetch(c)


.then(response => response.text())


.then(text => print("event_log", text))


.catch(e => print("event_log", `Request Failed: ${e}`));


});


}


}
WebSocket
bidirectional communication
package main


import "fmt"


import "log"


import "net/http"


import "os"


import "strings"


import "text/template"


import "golang.org/x/net/websocket"


const LAUNCH_FAILED = 1


const FILE_READ = 2


const BAD_TEMPLATE = 3


const ADDRESS = ":3000"


type PageCon
fi
guration struct {


URL string


Commands []string


}


func main() {


p := PageCon
fi
guration{"/socket", []string{"A", "B", "C"}}


html, e := template.ParseFiles(BaseName() + ".html")


Abort(FILE_READ, e)


http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {


w.Header().Set("Content-Type", "text/html")


Abort(BAD_TEMPLATE, html.Execute(w, p))


})


http.Handle(p.URL, websocket.Handler(func(ws *websocket.Conn) {


defer func() {


if e := ws.Close(); e != nil {


log.Println(e.Error())


}


}()


var b struct{ Message string }


for {


if e := websocket.JSON.Receive(ws, &b); e == nil {


log.Printf("received: %vn", b.Message)


websocket.JSON.Send(ws, []interface{}{b.Message})


} else {


log.Printf("socket receive error: %vn", e)


break


}


}


}))


Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil))


}


func Abort(n int, e error) {


if e != nil {


fmt.Println(e)


os.Exit(n)


}


}


func BaseName() string {


s := strings.Split(os.Args[0], "/")


return s[len(s)-1]


}
<!DOCTYPE html>


<html>


<head>


<meta charset='UTF-8' />


<title>WebSocket EXAMPLE</title>


<script>


function print(m) {


document.getElementById("event_log").innerHTML += `<div>${m}</div>`;


}


function newButton(n, c) {


let b = document.createElement("BUTTON");


b.onclick = c;


b.appendChild(document.createTextNode(n));


return b;


}


window.onload = () => {


var socket = new WebSocket(`ws://${location.host}{{.URL}}`);


socket.onopen = (e) => print("opening socket: {{.URL}}");


socket.onclose = (e) => print("closing socket: {{.URL}}");


socket.onerror = (e) => print(e.message);


socket.onmessage = (m) => print(JSON.parse(m.data));


let button_bar = document.getElementById("action_buttons");


{{range $c, $v := .Commands}}


button_bar.appendChild(


newButton('{{$v}}', () => socket.send(


JSON.stringify({ Message: '{{$v}}' }))));


{{end}}


}


</script>


</head>


<body>


<h1>WebSocket EXAMPLE</h1>


<h2>Known Asynchronous Actions</h2>


<div id="action_buttons"></div>


<h2>Server Output</h2>


<div id='event_log'></div>


</body>


</html>
import "golang.org/x/net/websocket"


type PageCon
fi
guration struct {


URL string


Commands []string


}


func main() {


p := PageCon
fi
guration{"/socket", []string{"A", "B", "C"}}


html, e := template.ParseFiles(BaseName() + ".html")


Abort(FILE_READ, e)


http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {


w.Header().Set("Content-Type", "text/html")


Abort(BAD_TEMPLATE, html.Execute(w, p))


})


http.Handle(p.URL, websocket.Handler(func(ws *websocket.Conn) {


defer func() {


if e := ws.Close(); e != nil {


log.Println(e.Error())


}


}()


var b struct{ Message string }


for {


if e := websocket.JSON.Receive(ws, &b); e == nil {


log.Printf("received: %vn", b.Message)


websocket.JSON.Send(ws, []interface{}{b.Message})


} else {


log.Printf("socket receive error: %vn", e)


break


}


}


}))


Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil))


}
import "golang.org/x/net/websocket"


type PageCon
fi
guration struct {


URL string


Commands []string


}


func main() {


p := PageCon
fi
guration{"/socket", []string{"A", "B", "C"}}


html, e := template.ParseFiles(BaseName() + ".html")


Abort(FILE_READ, e)


http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {


w.Header().Set("Content-Type", "text/html")


Abort(BAD_TEMPLATE, html.Execute(w, p))


})


http.Handle(p.URL, websocket.Handler(func(ws *websocket.Conn) {


defer func() {


if e := ws.Close(); e != nil {


log.Println(e.Error())


}


}()


var b struct{ Message string }


for {


if e := websocket.JSON.Receive(ws, &b); e == nil {


log.Printf("received: %vn", b.Message)


websocket.JSON.Send(ws, []interface{}{b.Message})


} else {


log.Printf("socket receive error: %vn", e)


break


}


}


}))


Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil))


}
window.onload = () => {


var socket = new WebSocket(`ws://${location.host}{{.URL}}`);


socket.onopen = (e) => print("opening socket: {{.URL}}");


socket.onclose = (e) => print("closing socket: {{.URL}}");


socket.onerror = (e) => print(e.message);


socket.onmessage = (m) => print(JSON.parse(m.data));


let button_bar = document.getElementById("action_buttons");


{{range $c, $v := .Commands}}


button_bar.appendChild(


newButton('{{$v}}', () => socket.send(


JSON.stringify({ Message: '{{$v}}' }))));


{{end}}


}
window.onload = () => {


var socket = new WebSocket(`ws://${location.host}{{.URL}}`);


socket.onopen = (e) => print("opening socket: {{.URL}}");


socket.onclose = (e) => print("closing socket: {{.URL}}");


socket.onerror = (e) => print(e.message);


socket.onmessage = (m) => print(JSON.parse(m.data));


let button_bar = document.getElementById("action_buttons");


{{range $c, $v := .Commands}}


button_bar.appendChild(


newButton('{{$v}}', () => socket.send(


JSON.stringify({ Message: '{{$v}}' }))));


{{end}}


}
package main


import "fmt"


import "log"


import "net/http"


import "os"


import "strings"


import "text/template"


import "golang.org/x/net/websocket"


const LAUNCH_FAILED = 1


const FILE_READ = 2


const BAD_TEMPLATE = 3


const ADDRESS = ":3000"


type PageCon
fi
guration struct {


URL string


Commands []string


}


func main() {


p := PageCon
fi
guration{"/socket", []string{"A", "B", "C"}}


html, e := template.ParseFiles(BaseName() + ".html")


Abort(FILE_READ, e)


http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {


w.Header().Set("Content-Type", "text/html")


Abort(BAD_TEMPLATE, html.Execute(w, p))


})


events := make(chan string, 4096)


var monitors []*websocket.Conn


http.Handle(p.URL, websocket.Handler(func(ws *websocket.Conn) {


i := len(monitors)


monitors = append(monitors, ws)


defer func() {


if e := ws.Close(); e != nil {


log.Println(e.Error())


}


monitors[i] = nil


}()


var b struct{ Message string }


for {


if e := websocket.JSON.Receive(ws, &b); e == nil {


events <- b.Message


} else {


log.Printf("socket receive error: %vn", e)


break


}


}


}))


go func() {


for {


e := <-events


for _, ws := range monitors {


if ws != nil {


go func(ws *websocket.Conn, e string) {


websocket.JSON.Send(ws, []interface{}{e})


	 	 	 	 	
}(ws, e)


}


}


}


}()


Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil))


}


func Abort(n int, e error) {


if e != nil {


fmt.Println(e)


os.Exit(n)


}


}


func BaseName() string {


s := strings.Split(os.Args[0], "/")


return s[len(s)-1]


}


<!DOCTYPE html>


<html>


<head>


<meta charset='UTF-8' />


<title>WebSocket EXAMPLE</title>


<script>


function print(m) {


document.getElementById("event_log").innerHTML += `<div>${m}</div>`;


}


function newButton(n, c) {


let b = document.createElement("BUTTON");


b.onclick = c;


b.appendChild(document.createTextNode(n));


return b;


}


window.onload = () => {


var socket = new WebSocket(`ws://${location.host}{{.URL}}`);


socket.onopen = (e) => print("opening socket: {{.URL}}");


socket.onclose = (e) => print("closing socket: {{.URL}}");


socket.onerror = (e) => print(e.message);


socket.onmessage = (m) => print(JSON.parse(m.data));


let button_bar = document.getElementById("action_buttons");


{{range $c, $v := .Commands}}


button_bar.appendChild(


newButton('{{$v}}', () => socket.send(


JSON.stringify({ Message: '{{$v}}' }))));


{{end}}


}


</script>


</head>


<body>


<h1>WebSocket EXAMPLE</h1>


<h2>Known Asynchronous Actions</h2>


<div id="action_buttons"></div>


<h2>Server Output</h2>


<div id='event_log'></div>


</body>


</html>
func main() {


p := PageCon
fi
guration{"/socket", []string{"A", "B", "C"}}


html, e := template.ParseFiles(BaseName() + ".html")


Abort(FILE_READ, e)


http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {


w.Header().Set("Content-Type", "text/html")


Abort(BAD_TEMPLATE, html.Execute(w, p))


})


events := make(chan string, 4096)


var monitors []*websocket.Conn


http.Handle(p.URL, websocket.Handler(func(ws *websocket.Conn) {


i := len(monitors)


monitors = append(monitors, ws)


defer func() {


if e := ws.Close(); e != nil {


log.Println(e.Error())


}


monitors[i] = nil


}()


var b struct{ Message string }


for {


if e := websocket.JSON.Receive(ws, &b); e == nil {


events <- b.Message


} else {


log.Printf("socket receive error: %vn", e)


break


}


}


}))


go func() {


for {


e := <-events


for _, ws := range monitors {


if ws != nil {


go func(ws *websocket.Conn, e string) {


websocket.JSON.Send(ws, []interface{}{e})


}(ws, e)


}


}


}


}()


Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil))


}
events := make(chan string, 4096)


var monitors []*websocket.Conn


http.Handle(p.URL, websocket.Handler(func(ws *websocket.Conn) {


i := len(monitors)


monitors = append(monitors, ws)


defer func() {


if e := ws.Close(); e != nil {


log.Println(e.Error())


}


monitors[i] = nil


}()


var b struct{ Message string }


for {


if e := websocket.JSON.Receive(ws, &b); e == nil {


events <- b.Message


} else {


log.Printf("socket receive error: %vn", e)


break


}


}


}))
func main() {


p := PageCon
fi
guration{"/socket", []string{"A", "B", "C"}}


html, e := template.ParseFiles(BaseName() + ".html")


Abort(FILE_READ, e)


http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {


w.Header().Set("Content-Type", "text/html")


Abort(BAD_TEMPLATE, html.Execute(w, p))


})


events := make(chan string, 4096)


var monitors []*websocket.Conn


http.Handle(p.URL, websocket.Handler(func(ws *websocket.Conn) {


i := len(monitors)


monitors = append(monitors, ws)


defer func() {


if e := ws.Close(); e != nil {


log.Println(e.Error())


}


monitors[i] = nil


}()


var b struct{ Message string }


for {


if e := websocket.JSON.Receive(ws, &b); e == nil {


events <- b.Message


} else {


log.Printf("socket receive error: %vn", e)


break


}


}


}))


go func() {


for {


e := <-events


for _, ws := range monitors {


if ws != nil {


go func(ws *websocket.Conn, e string) {


websocket.JSON.Send(ws, []interface{}{e})


}(ws, e)


}


}


}


}()


Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil))


}
events := make(chan string, 4096)


var monitors []*websocket.Conn


go func() {


for {


e := <-events


for _, ws := range monitors {


if ws != nil {


go func(ws *websocket.Conn, e string) {


websocket.JSON.Send(ws, []interface{}{e})


}(ws, e)


}


}


}


}()
func main() {


p := PageCon
fi
guration{"/socket", []string{"A", "B", "C"}}


html, e := template.ParseFiles(BaseName() + ".html")


Abort(FILE_READ, e)


http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {


w.Header().Set("Content-Type", "text/html")


Abort(BAD_TEMPLATE, html.Execute(w, p))


})


events := make(chan string, 4096)


var monitors []*websocket.Conn


http.Handle(p.URL, websocket.Handler(func(ws *websocket.Conn) {


i := len(monitors)


monitors = append(monitors, ws)


defer func() {


if e := ws.Close(); e != nil {


log.Println(e.Error())


}


monitors[i] = nil


}()


var b struct{ Message string }


for {


if e := websocket.JSON.Receive(ws, &b); e == nil {


events <- b.Message


} else {


log.Printf("socket receive error: %vn", e)


break


}


}


}))


go func() {


for {


e := <-events


for _, ws := range monitors {


if ws != nil {


go func(ws *websocket.Conn, e string) {


websocket.JSON.Send(ws, []interface{}{e})


}(ws, e)


}


}


}


}()


Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil))


}
events := make(chan string, 4096)


var monitors []*websocket.Conn


http.Handle(p.URL, websocket.Handler(func(ws *websocket.Conn) {


i := len(monitors)


monitors = append(monitors, ws)


defer func() {


if e := ws.Close(); e != nil {


log.Println(e.Error())


}


monitors[i] = nil


}()


var b struct{ Message string }


for {


if e := websocket.JSON.Receive(ws, &b); e == nil {


events <- b.Message


} else {


log.Printf("socket receive error: %vn", e)


break


}


}


}))
func main() {


p := PageCon
fi
guration{"/socket", []string{"A", "B", "C"}}


html, e := template.ParseFiles(BaseName() + ".html")


Abort(FILE_READ, e)


http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {


w.Header().Set("Content-Type", "text/html")


Abort(BAD_TEMPLATE, html.Execute(w, p))


})


events := make(chan string, 4096)


var monitors []*websocket.Conn


http.Handle(p.URL, websocket.Handler(func(ws *websocket.Conn) {


i := len(monitors)


monitors = append(monitors, ws)


defer func() {


if e := ws.Close(); e != nil {


log.Println(e.Error())


}


monitors[i] = nil


}()


var b struct{ Message string }


for {


if e := websocket.JSON.Receive(ws, &b); e == nil {


events <- b.Message


} else {


log.Printf("socket receive error: %vn", e)


break


}


}


}))


go func() {


for {


e := <-events


for _, ws := range monitors {


if ws != nil {


go func(ws *websocket.Conn, e string) {


websocket.JSON.Send(ws, []interface{}{e})


}(ws, e)


}


}


}


}()


Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil))


}
events := make(chan string, 4096)


var monitors []*websocket.Conn


go func() {


for {


e := <-events


for _, ws := range monitors {


if ws != nil {


go func(ws *websocket.Conn, e string) {


websocket.JSON.Send(ws, []interface{}{e})


}(ws, e)


}


}


}


}()
package main


import "log"


import "golang.org/x/net/websocket"


const SERVER = "ws://localhost:3000/socket"


const ADDRESS = "http://localhost/"


func main() {


if ws, e := websocket.Dial(SERVER, "", ADDRESS); e == nil {


var m []interface{}


for {


if e := websocket.JSON.Receive(ws, &m); e == nil {


log.Printf("message: %vn", m)


} else {


log.Fatal(e)


}


}


} else {


log.Fatal(e)


}


}
package main


import "log"


import "golang.org/x/net/websocket"


const SERVER = "ws://localhost:3000/socket"


const ADDRESS = "http://localhost/"


func main() {


if ws, e := websocket.Dial(SERVER, "", ADDRESS); e == nil {


var m []interface{}


for {


if e := websocket.JSON.Receive(ws, &m); e == nil {


log.Printf("message: %vn", m)


} else {


log.Fatal(e)


}


}


} else {


log.Fatal(e)


}


}
package main


import "log"


import "golang.org/x/net/websocket"


const SERVER = "ws://localhost:3000/socket"


const ADDRESS = "http://localhost/"


func main() {


if ws, e := websocket.Dial(SERVER, "", ADDRESS); e == nil {


var m []interface{}


for {


if e := websocket.JSON.Receive(ws, &m); e == nil {


log.Printf("message: %vn", m)


} else {


log.Fatal(e)


}


}


} else {


log.Fatal(e)


}


}
package main


import "log"


import "os"


import "time"


import "golang.org/x/net/websocket"


const SERVER = "ws://localhost:3000/socket"


const ADDRESS = "http://localhost/"


func main() {


if ws, e := websocket.Dial(SERVER, "", ADDRESS); e == nil {


var b struct{ Message string }


for _, v := range os.Args[1:] {


b.Message = v


websocket.JSON.Send(ws, &b)


time.Sleep(1 * time.Second)


}


} else {


log.Fatal(e)


}


}
package main


import "log"


import "os"


import "time"


import "golang.org/x/net/websocket"


const SERVER = "ws://localhost:3000/socket"


const ADDRESS = "http://localhost/"


func main() {


if ws, e := websocket.Dial(SERVER, "", ADDRESS); e == nil {


var b struct{ Message string }


for _, v := range os.Args[1:] {


b.Message = v


websocket.JSON.Send(ws, &b)


time.Sleep(1 * time.Second)


}


} else {


log.Fatal(e)


}


}
package main


import "log"


import "os"


import "time"


import "golang.org/x/net/websocket"


const SERVER = "ws://localhost:3000/socket"


const ADDRESS = "http://localhost/"


func main() {


if ws, e := websocket.Dial(SERVER, "", ADDRESS); e == nil {


var b struct{ Message string }


for _, v := range os.Args[1:] {


b.Message = v


websocket.JSON.Send(ws, &b)


time.Sleep(1 * time.Second)


}


} else {


log.Fatal(e)


}


}

More Related Content

What's hot

"PostgreSQL and Python" Lightning Talk @EuroPython2014
"PostgreSQL and Python" Lightning Talk @EuroPython2014"PostgreSQL and Python" Lightning Talk @EuroPython2014
"PostgreSQL and Python" Lightning Talk @EuroPython2014Henning Jacobs
 
Go ahead, make my day
Go ahead, make my dayGo ahead, make my day
Go ahead, make my dayTor Ivry
 
Kotlin from-scratch 2 - functions
Kotlin from-scratch 2 - functionsKotlin from-scratch 2 - functions
Kotlin from-scratch 2 - functionsFranco Lombardo
 
Go for the paranoid network programmer, 2nd edition
Go for the paranoid network programmer, 2nd editionGo for the paranoid network programmer, 2nd edition
Go for the paranoid network programmer, 2nd editionEleanor McHugh
 
Introducing PHP Latest Updates
Introducing PHP Latest UpdatesIntroducing PHP Latest Updates
Introducing PHP Latest UpdatesIftekhar Eather
 
5. Ввод-вывод, доступ к файловой системе
5. Ввод-вывод, доступ к файловой системе5. Ввод-вывод, доступ к файловой системе
5. Ввод-вывод, доступ к файловой системеDEVTYPE
 
ZeroMQ Is The Answer: DPC 11 Version
ZeroMQ Is The Answer: DPC 11 VersionZeroMQ Is The Answer: DPC 11 Version
ZeroMQ Is The Answer: DPC 11 VersionIan Barber
 
What's New in PHP 5.5
What's New in PHP 5.5What's New in PHP 5.5
What's New in PHP 5.5Corey Ballou
 
Implementing Virtual Machines in Go & C
Implementing Virtual Machines in Go & CImplementing Virtual Machines in Go & C
Implementing Virtual Machines in Go & CEleanor McHugh
 
From Java to Kotlin beyond alt+shift+cmd+k - Kotlin Community Conf Milan
From Java to Kotlin beyond alt+shift+cmd+k - Kotlin Community Conf MilanFrom Java to Kotlin beyond alt+shift+cmd+k - Kotlin Community Conf Milan
From Java to Kotlin beyond alt+shift+cmd+k - Kotlin Community Conf MilanFabio Collini
 
What's new in PHP 5.5
What's new in PHP 5.5What's new in PHP 5.5
What's new in PHP 5.5Tom Corrigan
 
Are we ready to Go?
Are we ready to Go?Are we ready to Go?
Are we ready to Go?Adam Dudczak
 
Snakes for Camels
Snakes for CamelsSnakes for Camels
Snakes for Camelsmiquelruizm
 
Python utan-stodhjul-motorsag
Python utan-stodhjul-motorsagPython utan-stodhjul-motorsag
Python utan-stodhjul-motorsagniklal
 

What's hot (20)

"PostgreSQL and Python" Lightning Talk @EuroPython2014
"PostgreSQL and Python" Lightning Talk @EuroPython2014"PostgreSQL and Python" Lightning Talk @EuroPython2014
"PostgreSQL and Python" Lightning Talk @EuroPython2014
 
Go ahead, make my day
Go ahead, make my dayGo ahead, make my day
Go ahead, make my day
 
Kotlin from-scratch 2 - functions
Kotlin from-scratch 2 - functionsKotlin from-scratch 2 - functions
Kotlin from-scratch 2 - functions
 
Go for the paranoid network programmer, 2nd edition
Go for the paranoid network programmer, 2nd editionGo for the paranoid network programmer, 2nd edition
Go for the paranoid network programmer, 2nd edition
 
Java VS Python
Java VS PythonJava VS Python
Java VS Python
 
The most exciting features of PHP 7.1
The most exciting features of PHP 7.1The most exciting features of PHP 7.1
The most exciting features of PHP 7.1
 
Introducing PHP Latest Updates
Introducing PHP Latest UpdatesIntroducing PHP Latest Updates
Introducing PHP Latest Updates
 
5. Ввод-вывод, доступ к файловой системе
5. Ввод-вывод, доступ к файловой системе5. Ввод-вывод, доступ к файловой системе
5. Ввод-вывод, доступ к файловой системе
 
Having Fun Programming!
Having Fun Programming!Having Fun Programming!
Having Fun Programming!
 
Scala 2 + 2 > 4
Scala 2 + 2 > 4Scala 2 + 2 > 4
Scala 2 + 2 > 4
 
ZeroMQ Is The Answer: DPC 11 Version
ZeroMQ Is The Answer: DPC 11 VersionZeroMQ Is The Answer: DPC 11 Version
ZeroMQ Is The Answer: DPC 11 Version
 
What's New in PHP 5.5
What's New in PHP 5.5What's New in PHP 5.5
What's New in PHP 5.5
 
Implementing Virtual Machines in Go & C
Implementing Virtual Machines in Go & CImplementing Virtual Machines in Go & C
Implementing Virtual Machines in Go & C
 
From Java to Kotlin beyond alt+shift+cmd+k - Kotlin Community Conf Milan
From Java to Kotlin beyond alt+shift+cmd+k - Kotlin Community Conf MilanFrom Java to Kotlin beyond alt+shift+cmd+k - Kotlin Community Conf Milan
From Java to Kotlin beyond alt+shift+cmd+k - Kotlin Community Conf Milan
 
What's new in PHP 5.5
What's new in PHP 5.5What's new in PHP 5.5
What's new in PHP 5.5
 
Are we ready to Go?
Are we ready to Go?Are we ready to Go?
Are we ready to Go?
 
Snakes for Camels
Snakes for CamelsSnakes for Camels
Snakes for Camels
 
Python utan-stodhjul-motorsag
Python utan-stodhjul-motorsagPython utan-stodhjul-motorsag
Python utan-stodhjul-motorsag
 
Introduzione a C#
Introduzione a C#Introduzione a C#
Introduzione a C#
 
Hello Go
Hello GoHello Go
Hello Go
 

Similar to The Browser Environment - A Systems Programmer's Perspective

What can be done with Java, but should better be done with Erlang (@pavlobaron)
What can be done with Java, but should better be done with Erlang (@pavlobaron)What can be done with Java, but should better be done with Erlang (@pavlobaron)
What can be done with Java, but should better be done with Erlang (@pavlobaron)Pavlo Baron
 
TypeScript Introduction
TypeScript IntroductionTypeScript Introduction
TypeScript IntroductionHans Höchtl
 
Introduction to go
Introduction to goIntroduction to go
Introduction to goJaehue Jang
 
Scala presentation by Aleksandar Prokopec
Scala presentation by Aleksandar ProkopecScala presentation by Aleksandar Prokopec
Scala presentation by Aleksandar ProkopecLoïc Descotte
 
Introduction to source{d} Engine and source{d} Lookout
Introduction to source{d} Engine and source{d} Lookout Introduction to source{d} Engine and source{d} Lookout
Introduction to source{d} Engine and source{d} Lookout source{d}
 
Introduction to clojure
Introduction to clojureIntroduction to clojure
Introduction to clojureAbbas Raza
 
Introduction To Scala
Introduction To ScalaIntroduction To Scala
Introduction To ScalaPeter Maas
 
Beyond javascript using the features of tomorrow
Beyond javascript   using the features of tomorrowBeyond javascript   using the features of tomorrow
Beyond javascript using the features of tomorrowAlexander Varwijk
 
Go for the would be network programmer
Go for the would be network programmerGo for the would be network programmer
Go for the would be network programmerEleanor McHugh
 
Building a friendly .NET SDK to connect to Space
Building a friendly .NET SDK to connect to SpaceBuilding a friendly .NET SDK to connect to Space
Building a friendly .NET SDK to connect to SpaceMaarten Balliauw
 
The Rust Programming Language: an Overview
The Rust Programming Language: an OverviewThe Rust Programming Language: an Overview
The Rust Programming Language: an OverviewRoberto Casadei
 

Similar to The Browser Environment - A Systems Programmer's Perspective (20)

Unfiltered Unveiled
Unfiltered UnveiledUnfiltered Unveiled
Unfiltered Unveiled
 
What can be done with Java, but should better be done with Erlang (@pavlobaron)
What can be done with Java, but should better be done with Erlang (@pavlobaron)What can be done with Java, but should better be done with Erlang (@pavlobaron)
What can be done with Java, but should better be done with Erlang (@pavlobaron)
 
TypeScript Introduction
TypeScript IntroductionTypeScript Introduction
TypeScript Introduction
 
ES6 is Nigh
ES6 is NighES6 is Nigh
ES6 is Nigh
 
Introduction to go
Introduction to goIntroduction to go
Introduction to go
 
Scala presentation by Aleksandar Prokopec
Scala presentation by Aleksandar ProkopecScala presentation by Aleksandar Prokopec
Scala presentation by Aleksandar Prokopec
 
Php and MySQL
Php and MySQLPhp and MySQL
Php and MySQL
 
Let's Go-lang
Let's Go-langLet's Go-lang
Let's Go-lang
 
Introduction to source{d} Engine and source{d} Lookout
Introduction to source{d} Engine and source{d} Lookout Introduction to source{d} Engine and source{d} Lookout
Introduction to source{d} Engine and source{d} Lookout
 
Introduction to clojure
Introduction to clojureIntroduction to clojure
Introduction to clojure
 
Introduction To Scala
Introduction To ScalaIntroduction To Scala
Introduction To Scala
 
Beyond javascript using the features of tomorrow
Beyond javascript   using the features of tomorrowBeyond javascript   using the features of tomorrow
Beyond javascript using the features of tomorrow
 
Lettering js
Lettering jsLettering js
Lettering js
 
Go for the would be network programmer
Go for the would be network programmerGo for the would be network programmer
Go for the would be network programmer
 
Building a friendly .NET SDK to connect to Space
Building a friendly .NET SDK to connect to SpaceBuilding a friendly .NET SDK to connect to Space
Building a friendly .NET SDK to connect to Space
 
The Rust Programming Language: an Overview
The Rust Programming Language: an OverviewThe Rust Programming Language: an Overview
The Rust Programming Language: an Overview
 
C# programming
C# programming C# programming
C# programming
 
Rust-lang
Rust-langRust-lang
Rust-lang
 
Elixir cheatsheet
Elixir cheatsheetElixir cheatsheet
Elixir cheatsheet
 
In kor we Trust
In kor we TrustIn kor we Trust
In kor we Trust
 

More from Eleanor McHugh

[2023] Putting the R! in R&D.pdf
[2023] Putting the R! in R&D.pdf[2023] Putting the R! in R&D.pdf
[2023] Putting the R! in R&D.pdfEleanor McHugh
 
Generics, Reflection, and Efficient Collections
Generics, Reflection, and Efficient CollectionsGenerics, Reflection, and Efficient Collections
Generics, Reflection, and Efficient CollectionsEleanor McHugh
 
The Relevance of Liveness - Biometrics and Data Integrity
The Relevance of Liveness - Biometrics and Data IntegrityThe Relevance of Liveness - Biometrics and Data Integrity
The Relevance of Liveness - Biometrics and Data IntegrityEleanor McHugh
 
An introduction to functional programming with Go [redux]
An introduction to functional programming with Go [redux]An introduction to functional programming with Go [redux]
An introduction to functional programming with Go [redux]Eleanor McHugh
 
An introduction to functional programming with go
An introduction to functional programming with goAn introduction to functional programming with go
An introduction to functional programming with goEleanor McHugh
 
Identity & trust in Monitored Spaces
Identity & trust in Monitored SpacesIdentity & trust in Monitored Spaces
Identity & trust in Monitored SpacesEleanor McHugh
 
Don't Ask, Don't Tell - The Virtues of Privacy By Design
Don't Ask, Don't Tell - The Virtues of Privacy By DesignDon't Ask, Don't Tell - The Virtues of Privacy By Design
Don't Ask, Don't Tell - The Virtues of Privacy By DesignEleanor McHugh
 
Don't ask, don't tell the virtues of privacy by design
Don't ask, don't tell   the virtues of privacy by designDon't ask, don't tell   the virtues of privacy by design
Don't ask, don't tell the virtues of privacy by designEleanor McHugh
 
Anonymity, identity, trust
Anonymity, identity, trustAnonymity, identity, trust
Anonymity, identity, trustEleanor McHugh
 
Going Loopy - Adventures in Iteration with Google Go
Going Loopy - Adventures in Iteration with Google GoGoing Loopy - Adventures in Iteration with Google Go
Going Loopy - Adventures in Iteration with Google GoEleanor McHugh
 
Distributed Ledgers: Anonymity & Immutability at Scale
Distributed Ledgers: Anonymity & Immutability at ScaleDistributed Ledgers: Anonymity & Immutability at Scale
Distributed Ledgers: Anonymity & Immutability at ScaleEleanor McHugh
 
Finding a useful outlet for my many Adventures in go
Finding a useful outlet for my many Adventures in goFinding a useful outlet for my many Adventures in go
Finding a useful outlet for my many Adventures in goEleanor McHugh
 
Anonymity, trust, accountability
Anonymity, trust, accountabilityAnonymity, trust, accountability
Anonymity, trust, accountabilityEleanor McHugh
 
Implementing Virtual Machines in Ruby & C
Implementing Virtual Machines in Ruby & CImplementing Virtual Machines in Ruby & C
Implementing Virtual Machines in Ruby & CEleanor McHugh
 
Implementing Software Machines in C and Go
Implementing Software Machines in C and GoImplementing Software Machines in C and Go
Implementing Software Machines in C and GoEleanor McHugh
 
Implementing Software Machines in Go and C
Implementing Software Machines in Go and CImplementing Software Machines in Go and C
Implementing Software Machines in Go and CEleanor McHugh
 
Encrypt all transports
Encrypt all transportsEncrypt all transports
Encrypt all transportsEleanor McHugh
 
Privacy is always a requirement
Privacy is always a requirementPrivacy is always a requirement
Privacy is always a requirementEleanor McHugh
 

More from Eleanor McHugh (20)

[2023] Putting the R! in R&D.pdf
[2023] Putting the R! in R&D.pdf[2023] Putting the R! in R&D.pdf
[2023] Putting the R! in R&D.pdf
 
Generics, Reflection, and Efficient Collections
Generics, Reflection, and Efficient CollectionsGenerics, Reflection, and Efficient Collections
Generics, Reflection, and Efficient Collections
 
The Relevance of Liveness - Biometrics and Data Integrity
The Relevance of Liveness - Biometrics and Data IntegrityThe Relevance of Liveness - Biometrics and Data Integrity
The Relevance of Liveness - Biometrics and Data Integrity
 
An introduction to functional programming with Go [redux]
An introduction to functional programming with Go [redux]An introduction to functional programming with Go [redux]
An introduction to functional programming with Go [redux]
 
An introduction to functional programming with go
An introduction to functional programming with goAn introduction to functional programming with go
An introduction to functional programming with go
 
Identity & trust in Monitored Spaces
Identity & trust in Monitored SpacesIdentity & trust in Monitored Spaces
Identity & trust in Monitored Spaces
 
Don't Ask, Don't Tell - The Virtues of Privacy By Design
Don't Ask, Don't Tell - The Virtues of Privacy By DesignDon't Ask, Don't Tell - The Virtues of Privacy By Design
Don't Ask, Don't Tell - The Virtues of Privacy By Design
 
Don't ask, don't tell the virtues of privacy by design
Don't ask, don't tell   the virtues of privacy by designDon't ask, don't tell   the virtues of privacy by design
Don't ask, don't tell the virtues of privacy by design
 
Anonymity, identity, trust
Anonymity, identity, trustAnonymity, identity, trust
Anonymity, identity, trust
 
Going Loopy - Adventures in Iteration with Google Go
Going Loopy - Adventures in Iteration with Google GoGoing Loopy - Adventures in Iteration with Google Go
Going Loopy - Adventures in Iteration with Google Go
 
Distributed Ledgers: Anonymity & Immutability at Scale
Distributed Ledgers: Anonymity & Immutability at ScaleDistributed Ledgers: Anonymity & Immutability at Scale
Distributed Ledgers: Anonymity & Immutability at Scale
 
Finding a useful outlet for my many Adventures in go
Finding a useful outlet for my many Adventures in goFinding a useful outlet for my many Adventures in go
Finding a useful outlet for my many Adventures in go
 
Anonymity, trust, accountability
Anonymity, trust, accountabilityAnonymity, trust, accountability
Anonymity, trust, accountability
 
Implementing Virtual Machines in Ruby & C
Implementing Virtual Machines in Ruby & CImplementing Virtual Machines in Ruby & C
Implementing Virtual Machines in Ruby & C
 
Implementing Software Machines in C and Go
Implementing Software Machines in C and GoImplementing Software Machines in C and Go
Implementing Software Machines in C and Go
 
Implementing Software Machines in Go and C
Implementing Software Machines in Go and CImplementing Software Machines in Go and C
Implementing Software Machines in Go and C
 
Encrypt all transports
Encrypt all transportsEncrypt all transports
Encrypt all transports
 
Whispered secrets
Whispered secretsWhispered secrets
Whispered secrets
 
Whispered secrets
Whispered secretsWhispered secrets
Whispered secrets
 
Privacy is always a requirement
Privacy is always a requirementPrivacy is always a requirement
Privacy is always a requirement
 

Recently uploaded

Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountPuma Security, LLC
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024BookNet Canada
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsMark Billinghurst
 
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024BookNet Canada
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slidespraypatel2
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 3652toLead Limited
 
Benefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksBenefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksSoftradix Technologies
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationMichael W. Hawkins
 
Azure Monitor & Application Insight to monitor Infrastructure & Application
Azure Monitor & Application Insight to monitor Infrastructure & ApplicationAzure Monitor & Application Insight to monitor Infrastructure & Application
Azure Monitor & Application Insight to monitor Infrastructure & ApplicationAndikSusilo4
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking MenDelhi Call girls
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesSinan KOZAK
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonetsnaman860154
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationSafe Software
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsEnterprise Knowledge
 
How to Remove Document Management Hurdles with X-Docs?
How to Remove Document Management Hurdles with X-Docs?How to Remove Document Management Hurdles with X-Docs?
How to Remove Document Management Hurdles with X-Docs?XfilesPro
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsMemoori
 
Key Features Of Token Development (1).pptx
Key  Features Of Token  Development (1).pptxKey  Features Of Token  Development (1).pptx
Key Features Of Token Development (1).pptxLBM Solutions
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreternaman860154
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 

Recently uploaded (20)

Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR Systems
 
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
 
Benefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksBenefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other Frameworks
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
Azure Monitor & Application Insight to monitor Infrastructure & Application
Azure Monitor & Application Insight to monitor Infrastructure & ApplicationAzure Monitor & Application Insight to monitor Infrastructure & Application
Azure Monitor & Application Insight to monitor Infrastructure & Application
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen Frames
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food Manufacturing
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
How to Remove Document Management Hurdles with X-Docs?
How to Remove Document Management Hurdles with X-Docs?How to Remove Document Management Hurdles with X-Docs?
How to Remove Document Management Hurdles with X-Docs?
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial Buildings
 
Key Features Of Token Development (1).pptx
Key  Features Of Token  Development (1).pptxKey  Features Of Token  Development (1).pptx
Key Features Of Token Development (1).pptx
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 

The Browser Environment - A Systems Programmer's Perspective

  • 1. Eleanor McHugh http://slideshare.net/feyeleanor http://github.com/feyeleanor/TheBrowserEnvironment The Browser Environment A Systems Programmer's Perspective [a rant in diverse movements]
  • 2. TL;DR JavaScript Concurrency is a Confused Mess if you disagree you have serious Stockholm Syndrome
  • 3. Elric of Melniboné, Michael Moorcock E lric sent his mind into twisting tunnels of logic, across endless plains of ideas, through mountains of symbolism and endless universes of alternate truths; he sent his mind out further and further and as it went he sent with it the words [...] words that few of his contemporaries would understand...
  • 4. pay attention! all code is BSD 2-clause licensed any resemblance to actual code & conceptstm, living or dead, is probably your imagination playing tricks on you if you can make money from it you're doing a damn sight better than we are!
  • 5. In Digital Spaces •2006 -> present [inidsol.uk] •13 US patents •real-time systems •digital identity •distributed ledgers •DNS -> [TCP|UDP] -> HTTP •Ruby -> Go -> JavaScript Seeking Identity Ellie [physicist] Romek [cryptographer]
  • 6.
  • 7.
  • 8.
  • 11. package main import "fmt" import "io/ioutil" import "net/http" import "os" import "strings" const LAUNCH_FAILED = 1 const FILE_READ = 2 const ADDRESS = ":3000" var MESSAGE string func main() { s := strings.Split(os.Args[0], "/") html, e := ioutil.ReadFile(s[len(s) - 1] + ".html") Abort(FILE_READ, e) MESSAGE = string(html) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/html") fmt.Fprint(w, MESSAGE) }) Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil)) } func Abort(n int, e error) { if e != nil { fmt.Println(e) os.Exit(n) } } <!DOCTYPE html> <html> <head> <meta charset='UTF-8' /> <title>SERVING HTML</title> </head> <body> <h1>SERVING HTML</h1> <div> hello world! </div> </body> </html>
  • 12. func main() { s := strings.Split(os.Args[0], "/") html, e := ioutil.ReadFile(s[len(s) - 1] + ".html") Abort(FILE_READ, e) MESSAGE = string(html) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/html") fmt.Fprint(w, MESSAGE) }) Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil)) }
  • 13. package main import "fmt" import "io/ioutil" import "net/http" import "os" import "strings" const LAUNCH_FAILED = 1 const FILE_READ = 2 const ADDRESS = ":3000" var MESSAGE string func main() { s := strings.Split(os.Args[0], "/") html, e := ioutil.ReadFile(s[len(s) - 1] + ".html") Abort(FILE_READ, e) MESSAGE = string(html) http.HandleFunc("/", billboard) Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil)) } func billboard(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/html") fmt.Fprint(w, MESSAGE) } func Abort(n int, e error) { if e != nil { fmt.Println(e) os.Exit(n) } } <!DOCTYPE html> <html> <head> <meta charset='UTF-8' /> <title>SERVING HTML</title> </head> <body> <h1>SERVING HTML</h1> <div> hello world! </div> </body> </html>
  • 14. func main() { s := strings.Split(os.Args[0], "/") html, e := ioutil.ReadFile(s[len(s) - 1] + ".html") Abort(FILE_READ, e) MESSAGE = string(html) http.HandleFunc("/", billboard) Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil)) } func billboard(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/html") fmt.Fprint(w, MESSAGE) }
  • 15. package main import "fmt" import "io/ioutil" import "net/http" import "os" import "strings" const LAUNCH_FAILED = 1 const FILE_READ = 2 const ADDRESS = ":3000" const CERT="cert.pem" const KEY="key.pem" var MESSAGE string func main() { s := strings.Split(os.Args[0], "/") html, e := ioutil.ReadFile(s[len(s) - 1] + ".html") Abort(FILE_READ, e) MESSAGE = string(html) http.HandleFunc("/", billboard) Abort(LAUNCH_FAILED, http.ListenAndServeTLS(ADDRESS, CERT, KEY, nil)) } func billboard(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/html") fmt.Fprint(w, MESSAGE) } func Abort(n int, e error) { if e != nil { fmt.Println(e) os.Exit(n) } } <!DOCTYPE html> <html> <head> <meta charset='UTF-8' /> <title>SERVING HTML</title> </head> <body> <h1>SERVING HTML</h1> <div> hello world! </div> </body> </html>
  • 16. func main() { s := strings.Split(os.Args[0], "/") html, e := ioutil.ReadFile(s[len(s) - 1] + ".html") Abort(FILE_READ, e) MESSAGE = string(html) http.HandleFunc("/", billboard) Abort(LAUNCH_FAILED, http.ListenAndServeTLS(ADDRESS, CERT, KEY, nil)) }
  • 17. Microsoft's Gift to Humanity the XMLHttpRequest object
  • 19. AJAX Asynchronous JavaScript and XML •JavaScript is a single-threaded language •but browsers are event-driven environments •so JavaScript runtimes normally have three basic threads •one to run the main script •one to run scripts for high priority events •one to run scripts for low priority events •and each event can have callbacks de fi ned for it
  • 20. AJAX Asynchronous JavaScript and XML •XMLHttpRequest fi rst appeared in MSXML •available in IE5 as an ActiveX component from 1999 •similar functionality in other browsers from 2000 onwards •fully supported in IE 7 2006 •despite its name it isn't restricted to XML •most modern uses involve JSON
  • 21. package main import "fmt" import "net/http" import "os" import "strings" import "text/template" const LAUNCH_FAILED = 1 const FILE_READ = 2 const BAD_TEMPLATE = 3 const ADDRESS = ":3000" type Commands map[string] func(http.ResponseWriter, *http.Request) type PageCon fi guration struct { Commands } func main() { p := PageCon fi guration{ Commands{ "A": AJAX_handler("A"), "B": AJAX_handler("B"), "C": AJAX_handler("C") }} html, e := template.ParseFiles(BaseName() + ".html") Abort(FILE_READ, e) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/html") Abort(BAD_TEMPLATE, html.Execute(w, p)) }) for c, f := range p.Commands { http.HandleFunc("/"+c, f) } Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil)) } func Abort(n int, e error) { if e != nil { fmt.Println(e) os.Exit(n) } } func BaseName() string { s := strings.Split(os.Args[0], "/") return s[len(s)-1] } func AJAX_handler(c string) func(http.ResponseWriter, *http.Request) { func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/plain") fmt.Fprint(w, c) } } <!DOCTYPE html> <html> <head> <meta charset='UTF-8' /> <title>AJAX EXAMPLE</title> <script> function print(e, m) { document.getElementById(e).innerHTML += `<div>${m}</div>`; } {{range $c, $v := .Commands}} function {{$c}}() { var xhttp = new XMLHttpRequest(); xhttp.onreadystatechange = function() { if (this.readyState == 4 && this.status == 200) { print("event_log", this.responseText); } }; xhttp.open("GET", "{{$c}}", true); xhttp.send(); } {{end}} </script> </head> <body> <h1>AJAX EXAMPLE</h1> <h2>Known Asynchronous Actions</h2> <div> {{range $c, $v := .Commands}} <span> <button type="button" onclick="{{$c}}();">{{$c}}</button> </span> {{end}} </div> <h2>Server Output</h2> <div id='event_log'></div> </body> </html>
  • 22. package main import "fmt" import "net/http" import "os" import "strings" import "text/template" const LAUNCH_FAILED = 1 const FILE_READ = 2 const BAD_TEMPLATE = 3 const ADDRESS = ":3000" type Commands map[string] func(http.ResponseWriter, *http.Request) type PageCon fi guration struct { Commands } func main() { p := PageCon fi guration{ Commands{ "A": AJAX_handler("A"), "B": AJAX_handler("B"), "C": AJAX_handler("C") }} html, e := template.ParseFiles(BaseName() + ".html") Abort(FILE_READ, e) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/html") Abort(BAD_TEMPLATE, html.Execute(w, p)) }) for c, f := range p.Commands { http.HandleFunc("/"+c, f) } Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil)) } <!DOCTYPE html> <html> <head> <meta charset='UTF-8' /> <title>AJAX EXAMPLE</title> <script> function print(e, m) { document.getElementById(e).innerHTML += `<div>${m}</div>`; } {{range $c, $v := .Commands}} function {{$c}}() { var xhttp = new XMLHttpRequest(); xhttp.onreadystatechange = function() { if (this.readyState == 4 && this.status == 200) { print("event_log", this.responseText); } }; xhttp.open("GET", "{{$c}}", true); xhttp.send(); } {{end}} </script> </head> <body> <h1>AJAX EXAMPLE</h1> <h2>Known Asynchronous Actions</h2> <div> {{range $c, $v := .Commands}} <span> <button type="button" onclick="{{$c}}();">{{$c}}</button> </span> {{end}} </div> <h2>Server Output</h2> <div id='event_log'></div> </body> </html>
  • 23. {{range $c, $v := .Commands}} function {{$c}}() { var xhttp = new XMLHttpRequest(); xhttp.onreadystatechange = function() { if (this.readyState == 4 && this.status == 200) { print("event_log", this.responseText); } }; xhttp.open("GET", "{{$c}}", true); xhttp.send(); } {{end}} {{range $c, $v := .Commands}} <span> <button type="button" onclick="{{$c}}();">{{$c}} </button> </span> {{end}}
  • 24. {{range $c, $v := .Commands}} function {{$c}}() { var xhttp = new XMLHttpRequest(); xhttp.onreadystatechange = function() { if (this.readyState == 4 && this.status == 200) { print("event_log", this.responseText); } }; xhttp.open("GET", "{{$c}}", true); xhttp.send(); } {{end}}
  • 25. package main import "fmt" import "net/http" import "os" import "strings" import "text/template" const LAUNCH_FAILED = 1 const FILE_READ = 2 const BAD_TEMPLATE = 3 const ADDRESS = ":3000" type Commands map[string] func(http.ResponseWriter, *http.Request) type PageCon fi guration struct { Commands } func main() { p := PageCon fi guration{ Commands{ "A": AJAX_handler("A"), "B": AJAX_handler("B"), "C": AJAX_handler("C") }} html, e := template.ParseFiles(BaseName() + ".html") Abort(FILE_READ, e) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/html") Abort(BAD_TEMPLATE, html.Execute(w, p)) }) for c, f := range p.Commands { http.HandleFunc("/"+c, f) } Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil)) } func Abort(n int, e error) { if e != nil { fmt.Println(e) os.Exit(n) } } func BaseName() string { s := strings.Split(os.Args[0], "/") return s[len(s)-1] } func AJAX_handler(c string) func(http.ResponseWriter, *http.Request) { func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/plain") fmt.Fprint(w, c) } } <!DOCTYPE html> <html> <head> <meta charset='UTF-8' /> <title>AJAX EXAMPLE</title> <script> function print(e, m) { document.getElementById(e).innerHTML += `<div>${m}</div>`; } {{range $c, $v := .Commands}} function {{$c}}() { var xhttp = new XMLHttpRequest(); xhttp.open("GET", "{{$c}}", false); try { xhttp.send(); print("event_log", xhttp.responseText); } catch(err) { print("event_log", `Request Failed: ${err}`); } } {{end}} </script> </head> <body> <h1>AJAX EXAMPLE</h1> <h2>Known Asynchronous Actions</h2> <div> {{range $c, $v := .Commands}} <span> <button type="button" onclick="{{$c}}();">{{$c}}</button> </span> {{end}} </div> <h2>Server Output</h2> <div id='event_log'></div> </body> </html>
  • 26. {{range $c, $v := .Commands}} function {{$c}}() { var xhttp = new XMLHttpRequest(); xhttp.open("GET", "{{$c}}", false); try { xhttp.send(); print("event_log", xhttp.responseText); } catch(err) { print("event_log", `Request Failed: ${err}`); } } {{end}}
  • 27. fetch a promise of things to come
  • 28. package main import "fmt" import "net/http" import "os" import "strings" import "text/template" const LAUNCH_FAILED = 1 const FILE_READ = 2 const BAD_TEMPLATE = 3 const ADDRESS = ":3000" type Commands map[string] func(http.ResponseWriter, *http.Request) type PageCon fi guration struct { Commands } func main() { p := PageCon fi guration{ Commands{ "A": AJAX_handler("A"), "B": AJAX_handler("B"), "C": AJAX_handler("C") }} html, e := template.ParseFiles(BaseName() + ".html") Abort(FILE_READ, e) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/html") Abort(BAD_TEMPLATE, html.Execute(w, p)) }) for c, f := range p.Commands { http.HandleFunc("/"+c, f) } Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil)) } func Abort(n int, e error) { if e != nil { fmt.Println(e) os.Exit(n) } } func BaseName() string { s := strings.Split(os.Args[0], "/") return s[len(s)-1] } func AJAX_handler(c string) func(http.ResponseWriter, *http.Request) { func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/plain") fmt.Fprint(w, c) } } <!DOCTYPE html> <html> <head> <meta charset='UTF-8' /> <title>FETCH EXAMPLE</title> <script> function print(e, m) { document.getElementById(e).innerHTML += `<div>${m}</div>`; } {{range $c, $v := .Commands}} async function {{$c}}() { let response = await fetch("{{$c}}"); if (response.ok) { let body = await response.text(); print("event_log", body); } else { print("event_log", `Request Failed: ${response.status}`); } } {{end}} </script> </head> <body> <h1>FETCH EXAMPLE</h1> <h2>Known Asynchronous Actions</h2> <div> {{range $c, $v := .Commands}} <span> <button type="button" onclick="{{$c}}();">{{$c}}</button> </span> {{end}} </div> <h2>Server Output</h2> <div id='event_log'></div> </body> </html>
  • 29. {{range $c, $v := .Commands}} async function {{$c}}() { let response = await fetch("{{$c}}"); if (response.ok) { let body = await response.text(); print("event_log", body); } else { print("event_log", `Request Failed: ${response.status}`); } } {{end}}
  • 30. {{range $c, $v := .Commands}} async function {{$c}}() { let response = await fetch("{{$c}}"); if (response.ok) { let body = await response.text(); print("event_log", body); } else { print("event_log", `Request Failed: ${response.status}`); } } {{end}}
  • 31. {{range $c, $v := .Commands}} async function {{$c}}() { fetch("{{$c}}") .then(response => response.text()) .then(text => print("event_log", text)) .catch(e => print("event_log", `Request Failed: ${e}`)); } {{end}}
  • 33. package main import "fmt" import "io/ioutil" import "net/http" import "os" import "strings" const LAUNCH_FAILED = 1 const FILE_READ = 2 const ADDRESS = ":3000" var MESSAGE string func main() { s := strings.Split(os.Args[0], "/") html, e := ioutil.ReadFile(s[len(s)-1] + ".html") Abort(FILE_READ, e) MESSAGE = string(html) http.HandleFunc("/", billboard) Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil)) } func billboard(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/html") fmt.Fprint(w, MESSAGE) } func Abort(n int, e error) { if e != nil { fmt.Println(e) os.Exit(n) } } <!DOCTYPE html> <html> <head> <meta charset='UTF-8' /> <title>FETCH EXAMPLE</title> <script> function print(e, m) { document.getElementById(e).innerHTML += `<div>${m}</div>`; } function hide(...n) { n.forEach(e => { document.getElementById(e).innerHTML = "X"; }); } function show(...n) { n.forEach(e => { document.getElementById(e).innerHTML = e; }); } function toggle(name) { print("event_log", name); hide(name); switch(name) { case 'A': show('B', 'C'); break; case 'B': show('A', 'C'); break; case 'C': show('A', 'B'); break; }; } </script> </head> <body> <h1>FETCH EXAMPLE</h1> <h2>Known Asynchronous Actions</h2> <div> <button id='A' type="button" onclick="toggle('A');">A</button> <button id='B' type="button" onclick="toggle('B');">B</button> <button id='C' type="button" onclick="toggle('C');">C</button> </div> <h2>Server Output</h2> <div id='event_log'></div> </body> </html>
  • 34. function hide(...n) { n.forEach(e => { document.getElementById(e).innerHTML = "X"; }); } function show(...n) { n.forEach(e => { document.getElementById(e).innerHTML = e; }); } function toggle(name) { print("event_log", name); hide(name); switch(name) { case 'A': show('B', 'C'); break; case 'B': show('A', 'C'); break; case 'C': show('A', 'B'); break; }; } <body> <h1>FETCH EXAMPLE</h1> <h2>Known Asynchronous Actions</h2> <div> <button id='A' type="button" onclick="toggle('A');">A</button> <button id='B' type="button" onclick="toggle('B');">B</button> <button id='C' type="button" onclick="toggle('C');">C</button> </div> <h2>Server Output</h2> <div id='event_log'></div> </body>
  • 35. function hide(...n) { n.forEach(e => { document.getElementById(e).innerHTML = "X"; }); } function show(...n) { n.forEach(e => { document.getElementById(e).innerHTML = e; }); } function toggle(name) { print("event_log", name); hide(name); switch(name) { case 'A': show('B', 'C'); break; case 'B': show('A', 'C'); break; case 'C': show('A', 'B'); break; }; } <body> <h1>FETCH EXAMPLE</h1> <h2>Known Asynchronous Actions</h2> <div> <button id='A' type="button" onclick="toggle('A');">A</button> <button id='B' type="button" onclick="toggle('B');">B</button> <button id='C' type="button" onclick="toggle('C');">C</button> </div> <h2>Server Output</h2> <div id='event_log'></div> </body>
  • 36. package main import "fmt" import "io/ioutil" import "net/http" import "os" import "strings" const LAUNCH_FAILED = 1 const FILE_READ = 2 const ADDRESS = ":3000" var MESSAGE string func main() { s := strings.Split(os.Args[0], "/") html, e := ioutil.ReadFile(s[len(s)-1] + ".html") Abort(FILE_READ, e) MESSAGE = string(html) http.HandleFunc("/", billboard) Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil)) } func billboard(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/html") fmt.Fprint(w, MESSAGE) } func Abort(n int, e error) { if e != nil { fmt.Println(e) os.Exit(n) } } <!DOCTYPE html> <html> <head> <meta charset='UTF-8' /> <title>DOM EXAMPLE</title> <script> function hide(e) { e.innerHTML = "X"; } function show(...e) { e.forEach(e => { e.innerHTML = e.id; }); } var buttons = []; function toggle(e) { hide(e); switch(e.id) { case 'A': show(buttons[1], buttons[0]); break; case 'B': show(buttons[2], buttons[0]); break; case 'C': show(buttons[2], buttons[1]); break; }; } function newButton(id) { let b = document.createElement("BUTTON"); b.id = id; b.onclick = new Function("toggle(this);"); b.appendChild(document.createTextNode(id)); return b; } window.onload = () => { let button_bar = document.getElementById("action_buttons"); ['A', 'B', 'C'].forEach(n => { buttons.unshift(newButton(n)); button_bar.appendChild(buttons[0]); }); }; </script> </head> <body> <h1>DOM EXAMPLE</h1> <h2>Known Actions</h2> <div id="action_buttons"></div> </body> </html>
  • 37. function hide(...n) { n.forEach(e => { document.getElementById(e).innerHTML = "X"; }); } function show(...n) { n.forEach(e => { document.getElementById(e).innerHTML = e; }); } function hide(e) { e.innerHTML = "X"; } function show(...e) { e.forEach(e => { e.innerHTML = e.id; }); }
  • 38. function toggle(name) { print("event_log", name); hide(name); switch(name) { case 'A': show('B', 'C'); break; case 'B': show('A', 'C'); break; case 'C': show('A', 'B'); break; }; } var buttons = []; function toggle(e) { hide(e); switch(e.id) { case 'A': show(buttons[1], buttons[0]); break; case 'B': show(buttons[2], buttons[0]); break; case 'C': show(buttons[2], buttons[1]); break; }; }
  • 39. function newButton(id) { let b = document.createElement("BUTTON"); b.id = id; b.onclick = new Function("toggle(this);"); b.appendChild(document.createTextNode(id)); return b; } window.onload = () => { let button_bar = document.getElementById("action_buttons"); ['A', 'B', 'C'].forEach(n => { buttons.unshift(newButton(n)); button_bar.appendChild(buttons[0]); }); }; <body> <h1>DOM EXAMPLE</h1> <h2>Known Actions</h2> <div id="action_buttons"></div> </body>
  • 40. package main import "fmt" import "net/http" import "os" import "strings" import "text/template" const LAUNCH_FAILED = 1 const FILE_READ = 2 const BAD_TEMPLATE = 3 const ADDRESS = ":3000" type Commands map[string]func(http.ResponseWriter, *http.Request) type PageCon fi guration struct{ Commands } func main() { p := PageCon fi guration{ Commands{ "A": AJAX_handler("A"), "B": AJAX_handler("B"), "C": AJAX_handler("C") }} html, e := template.ParseFiles(BaseName() + ".html") Abort(FILE_READ, e) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/html") Abort(BAD_TEMPLATE, html.Execute(w, p)) }) for c, f := range p.Commands { http.HandleFunc("/"+c, f) } Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil)) } func Abort(n int, e error) { if e != nil { fmt.Println(e) os.Exit(n) } } func BaseName() string { s := strings.Split(os.Args[0], "/") return s[len(s)-1] } func AJAX_handler(c string) func(http.ResponseWriter, *http.Request) { return func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/plain") fmt.Fprint(w, c) } } <!DOCTYPE html> <html> <head> <meta charset='UTF-8' /> <title>DOM FETCH EXAMPLE</title> <script> function print(e, m) { document.getElementById(e).innerHTML += `<div>${m}</div>`; } function doCommand(c) { fetch(c) .then(response => response.text()) .then(text => print("event_log", text)) .catch(e => print("event_log", `Request Failed: ${e}`)); } function newButton(n, c) { let b = document.createElement("BUTTON"); b.onclick = c; b.appendChild(document.createTextNode(n)); return b; } window.onload = () => { let button_bar = document.getElementById("action_buttons"); {{range $c, $v := .Commands}} button_bar.appendChild( newButton('{{$c}}', () => doCommand('{{$c}}'))); {{end}} }; </script> </head> <body> <h1>DOM FETCH EXAMPLE</h1> <h2>Known Asynchronous Actions</h2> <div id="action_buttons"></div> <h2>Server Output</h2> <div id='event_log'></div> </body> </html>
  • 41. window.onload = () => { let button_bar = document.getElementById("action_buttons"); {{range $c, $v := .Commands}} button_bar.appendChild( newButton('{{$c}}', () => doCommand('{{$c}}'))); {{end}} };
  • 42. function doCommand(c) { fetch(c) .then(response => response.text()) .then(text => print("event_log", text)) .catch(e => print("event_log", `Request Failed: ${e}`)); } function newButton(n, c) { let b = document.createElement("BUTTON"); b.onclick = c; b.appendChild(document.createTextNode(n)); return b; } window.onload = () => { let button_bar = document.getElementById("action_buttons"); {{range $c, $v := .Commands}} button_bar.appendChild( newButton('{{$c}}', () => doCommand('{{$c}}'))); {{end}} };
  • 44. package main import "fmt" import "io/ioutil" import "net/http" import "os" import "strings" const LAUNCH_FAILED = 1 const FILE_READ = 2 const ADDRESS = ":3000" var MESSAGE string func main() { s := strings.Split(os.Args[0], "/") html, e := ioutil.ReadFile(s[len(s)-1] + ".html") Abort(FILE_READ, e) MESSAGE = string(html) http.HandleFunc("/", billboard) Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil)) } func billboard(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/html") fmt.Fprint(w, MESSAGE) } func Abort(n int, e error) { if e != nil { fmt.Println(e) os.Exit(n) } } <!DOCTYPE html> <html> <head> <meta charset='UTF-8' /> <title>TIMER EXAMPLE</title> <script> function print(e, m) { document.getElementById(e).innerHTML += `<div>${m}</div>`; } window.onload = () => { let i = window.setInterval(() => { print("event_log", "setInterval triggered"); }, 500); window.setTimeout(() => { print("event_log", "setTimeout triggered"); window.setTimeout(() => { window.clearInterval(i); print("event_log", "setInterval cancelled"); }, 2000); }, 3000); } </script> </head> <body> <h1>TIMER EXAMPLE</h1> <h2>Timer Events</h2> <div id='event_log'></div> </body> </html>
  • 45. window.onload = () => { let i = window.setInterval(() => { print("event_log", "setInterval triggered"); }, 500); window.setTimeout(() => { print("event_log", "setTimeout triggered"); window.setTimeout(() => { window.clearInterval(i); print("event_log", "setInterval cancelled"); }, 2000); }, 3000); }
  • 46. window.onload = () => { let i = window.setInterval(() => { print("event_log", "setInterval triggered"); }, 500); window.setTimeout(() => { print("event_log", "setTimeout triggered"); window.setTimeout(() => { window.clearInterval(i); print("event_log", "setInterval cancelled"); }, 2000); }, 3000); }
  • 47. package main import "fmt" import "io/ioutil" import "net/http" import "os" import "strings" const LAUNCH_FAILED = 1 const FILE_READ = 2 const ADDRESS = ":3000" var MESSAGE string func main() { s := strings.Split(os.Args[0], "/") html, e := ioutil.ReadFile(s[len(s)-1] + ".html") Abort(FILE_READ, e) MESSAGE = string(html) http.HandleFunc("/", billboard) Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil)) } func billboard(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/html") fmt.Fprint(w, MESSAGE) } func Abort(n int, e error) { if e != nil { fmt.Println(e) os.Exit(n) } } <!DOCTYPE html> <html> <head> <meta charset='UTF-8' /> <title>TIMER EXAMPLE</title> <script> function print(e, m) { document.getElementById(e).innerHTML += `<div>${m}</div>`; } const doAfter = (i, f) => { return window.setTimeout(f, i) }; const doEvery = (i, f) => { return window.setInterval(f, i) }; window.onload = () => { let i = doEvery(500, () => { print("event_log", "doEvery triggered"); ); doAfter(3000, () => { print("event_log", "doAfter triggered"); doAfter(2000, () => { window.clearInterval(i); print("event_log", "doEvery cancelled"); }); }); } </script> </head> <body> <h1>TIMER EXAMPLE</h1> <h2>Timer Events</h2> <div id='event_log'></div> </body> </html>
  • 48. const doAfter = (i, f) => { return window.setTimeout(f, i) }; const doEvery = (i, f) => { return window.setInterval(f, i) }; window.onload = () => { let i = doEvery(500, () => { print("event_log", "doEvery triggered"); }); doAfter(3000, () => { print("event_log", "doAfter triggered"); doAfter(2000, () => { window.clearInterval(i); print("event_log", "doEvery cancelled"); }); }); }
  • 49. window.onload = () => { let i = window.setInterval(() => { print("event_log", "setInterval triggered"); }, 500); window.setTimeout(() => { print("event_log", "setTimeout triggered"); window.setTimeout(() => { window.clearInterval(i); print("event_log", "setInterval cancelled"); }, 2000); }, 3000); } window.onload = () => { let i = doEvery(500, () => { print("event_log", "doEvery triggered"); }); doAfter(3000, () => { print("event_log", "doAfter triggered"); doAfter(2000, () => { window.clearInterval(i); print("event_log", "doEvery cancelled"); }); }); }
  • 50. package main import "fmt" import "net/http" import "os" import "strings" import "text/template" const LAUNCH_FAILED = 1 const FILE_READ = 2 const BAD_TEMPLATE = 3 const ADDRESS = ":3000" type Commands map[string]func(http.ResponseWriter, *http.Request) type PageCon fi guration struct{ Commands } func main() { p := PageCon fi guration{ Commands{ "A": AJAX_handler("A"), "B": AJAX_handler("B"), "C": AJAX_handler("C") }} html, e := template.ParseFiles(BaseName() + ".html") Abort(FILE_READ, e) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/html") Abort(BAD_TEMPLATE, html.Execute(w, p)) }) for c, f := range p.Commands { http.HandleFunc("/"+c, f) } Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil)) } func Abort(n int, e error) { if e != nil { fmt.Println(e) os.Exit(n) } } func BaseName() string { s := strings.Split(os.Args[0], "/") return s[len(s)-1] } func AJAX_handler(c string) func(http.ResponseWriter, *http.Request) { return func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/plain") fmt.Fprint(w, c) } } <!DOCTYPE html> <html> <head> <meta charset='UTF-8' /> <title>TIMER FETCH EXAMPLE</title> <script> const print = (e, m) => document.getElementById(e).innerHTML += `<div>${m}</div>`; const doEvery = (i, f) => { return window.setInterval(f, i) }; var timers = {} function doCommand(c) { if (timers[c]) { print("event_log", `no longer polling ${c}`); window.clearInterval(timers[c]); timers[c] = null; } else { print("event_log", `polling ${c}`); timers[c] = doEvery(500, () => { fetch(c) .then(response => response.text()) .then(text => print("event_log", text)) .catch(e => print("event_log", `Request Failed: ${e}`)); }); } } function newButton(n, c) { let b = document.createElement("BUTTON"); b.onclick = c; b.appendChild(document.createTextNode(n)); return b; } window.onload = () => { let button_bar = document.getElementById("action_buttons"); {{range $c, $v := .Commands}} button_bar.appendChild( newButton('{{$c}}', () => doCommand('{{$c}}'))); {{end}} } </script> </head> <body> <h1>TIMER FETCH EXAMPLE</h1> <h2>Known Asynchronous Actions</h2> <div id="action_buttons"></div> <h2>Server Output</h2> <div id='event_log'></div> </body> </html>
  • 51. var timers = {} function doCommand(c) { if (timers[c]) { print("event_log", `no longer polling ${c}`); window.clearInterval(timers[c]); timers[c] = null; } else { print("event_log", `polling ${c}`); timers[c] = doEvery(500, () => { fetch(c) .then(response => response.text()) .then(text => print("event_log", text)) .catch(e => print("event_log", `Request Failed: ${e}`)); }); } }
  • 52. var timers = {} function doCommand(c) { if (timers[c]) { print("event_log", `no longer polling ${c}`); window.clearInterval(timers[c]); timers[c] = null; } else { print("event_log", `polling ${c}`); timers[c] = doEvery(500, () => { fetch(c) .then(response => response.text()) .then(text => print("event_log", text)) .catch(e => print("event_log", `Request Failed: ${e}`)); }); } }
  • 54. package main import "fmt" import "log" import "net/http" import "os" import "strings" import "text/template" import "golang.org/x/net/websocket" const LAUNCH_FAILED = 1 const FILE_READ = 2 const BAD_TEMPLATE = 3 const ADDRESS = ":3000" type PageCon fi guration struct { URL string Commands []string } func main() { p := PageCon fi guration{"/socket", []string{"A", "B", "C"}} html, e := template.ParseFiles(BaseName() + ".html") Abort(FILE_READ, e) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/html") Abort(BAD_TEMPLATE, html.Execute(w, p)) }) http.Handle(p.URL, websocket.Handler(func(ws *websocket.Conn) { defer func() { if e := ws.Close(); e != nil { log.Println(e.Error()) } }() var b struct{ Message string } for { if e := websocket.JSON.Receive(ws, &b); e == nil { log.Printf("received: %vn", b.Message) websocket.JSON.Send(ws, []interface{}{b.Message}) } else { log.Printf("socket receive error: %vn", e) break } } })) Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil)) } func Abort(n int, e error) { if e != nil { fmt.Println(e) os.Exit(n) } } func BaseName() string { s := strings.Split(os.Args[0], "/") return s[len(s)-1] } <!DOCTYPE html> <html> <head> <meta charset='UTF-8' /> <title>WebSocket EXAMPLE</title> <script> function print(m) { document.getElementById("event_log").innerHTML += `<div>${m}</div>`; } function newButton(n, c) { let b = document.createElement("BUTTON"); b.onclick = c; b.appendChild(document.createTextNode(n)); return b; } window.onload = () => { var socket = new WebSocket(`ws://${location.host}{{.URL}}`); socket.onopen = (e) => print("opening socket: {{.URL}}"); socket.onclose = (e) => print("closing socket: {{.URL}}"); socket.onerror = (e) => print(e.message); socket.onmessage = (m) => print(JSON.parse(m.data)); let button_bar = document.getElementById("action_buttons"); {{range $c, $v := .Commands}} button_bar.appendChild( newButton('{{$v}}', () => socket.send( JSON.stringify({ Message: '{{$v}}' })))); {{end}} } </script> </head> <body> <h1>WebSocket EXAMPLE</h1> <h2>Known Asynchronous Actions</h2> <div id="action_buttons"></div> <h2>Server Output</h2> <div id='event_log'></div> </body> </html>
  • 55. import "golang.org/x/net/websocket" type PageCon fi guration struct { URL string Commands []string } func main() { p := PageCon fi guration{"/socket", []string{"A", "B", "C"}} html, e := template.ParseFiles(BaseName() + ".html") Abort(FILE_READ, e) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/html") Abort(BAD_TEMPLATE, html.Execute(w, p)) }) http.Handle(p.URL, websocket.Handler(func(ws *websocket.Conn) { defer func() { if e := ws.Close(); e != nil { log.Println(e.Error()) } }() var b struct{ Message string } for { if e := websocket.JSON.Receive(ws, &b); e == nil { log.Printf("received: %vn", b.Message) websocket.JSON.Send(ws, []interface{}{b.Message}) } else { log.Printf("socket receive error: %vn", e) break } } })) Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil)) }
  • 56. import "golang.org/x/net/websocket" type PageCon fi guration struct { URL string Commands []string } func main() { p := PageCon fi guration{"/socket", []string{"A", "B", "C"}} html, e := template.ParseFiles(BaseName() + ".html") Abort(FILE_READ, e) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/html") Abort(BAD_TEMPLATE, html.Execute(w, p)) }) http.Handle(p.URL, websocket.Handler(func(ws *websocket.Conn) { defer func() { if e := ws.Close(); e != nil { log.Println(e.Error()) } }() var b struct{ Message string } for { if e := websocket.JSON.Receive(ws, &b); e == nil { log.Printf("received: %vn", b.Message) websocket.JSON.Send(ws, []interface{}{b.Message}) } else { log.Printf("socket receive error: %vn", e) break } } })) Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil)) }
  • 57. window.onload = () => { var socket = new WebSocket(`ws://${location.host}{{.URL}}`); socket.onopen = (e) => print("opening socket: {{.URL}}"); socket.onclose = (e) => print("closing socket: {{.URL}}"); socket.onerror = (e) => print(e.message); socket.onmessage = (m) => print(JSON.parse(m.data)); let button_bar = document.getElementById("action_buttons"); {{range $c, $v := .Commands}} button_bar.appendChild( newButton('{{$v}}', () => socket.send( JSON.stringify({ Message: '{{$v}}' })))); {{end}} }
  • 58. window.onload = () => { var socket = new WebSocket(`ws://${location.host}{{.URL}}`); socket.onopen = (e) => print("opening socket: {{.URL}}"); socket.onclose = (e) => print("closing socket: {{.URL}}"); socket.onerror = (e) => print(e.message); socket.onmessage = (m) => print(JSON.parse(m.data)); let button_bar = document.getElementById("action_buttons"); {{range $c, $v := .Commands}} button_bar.appendChild( newButton('{{$v}}', () => socket.send( JSON.stringify({ Message: '{{$v}}' })))); {{end}} }
  • 59. package main import "fmt" import "log" import "net/http" import "os" import "strings" import "text/template" import "golang.org/x/net/websocket" const LAUNCH_FAILED = 1 const FILE_READ = 2 const BAD_TEMPLATE = 3 const ADDRESS = ":3000" type PageCon fi guration struct { URL string Commands []string } func main() { p := PageCon fi guration{"/socket", []string{"A", "B", "C"}} html, e := template.ParseFiles(BaseName() + ".html") Abort(FILE_READ, e) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/html") Abort(BAD_TEMPLATE, html.Execute(w, p)) }) events := make(chan string, 4096) var monitors []*websocket.Conn http.Handle(p.URL, websocket.Handler(func(ws *websocket.Conn) { i := len(monitors) monitors = append(monitors, ws) defer func() { if e := ws.Close(); e != nil { log.Println(e.Error()) } monitors[i] = nil }() var b struct{ Message string } for { if e := websocket.JSON.Receive(ws, &b); e == nil { events <- b.Message } else { log.Printf("socket receive error: %vn", e) break } } })) go func() { for { e := <-events for _, ws := range monitors { if ws != nil { go func(ws *websocket.Conn, e string) { websocket.JSON.Send(ws, []interface{}{e}) }(ws, e) } } } }() Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil)) } func Abort(n int, e error) { if e != nil { fmt.Println(e) os.Exit(n) } } func BaseName() string { s := strings.Split(os.Args[0], "/") return s[len(s)-1] } <!DOCTYPE html> <html> <head> <meta charset='UTF-8' /> <title>WebSocket EXAMPLE</title> <script> function print(m) { document.getElementById("event_log").innerHTML += `<div>${m}</div>`; } function newButton(n, c) { let b = document.createElement("BUTTON"); b.onclick = c; b.appendChild(document.createTextNode(n)); return b; } window.onload = () => { var socket = new WebSocket(`ws://${location.host}{{.URL}}`); socket.onopen = (e) => print("opening socket: {{.URL}}"); socket.onclose = (e) => print("closing socket: {{.URL}}"); socket.onerror = (e) => print(e.message); socket.onmessage = (m) => print(JSON.parse(m.data)); let button_bar = document.getElementById("action_buttons"); {{range $c, $v := .Commands}} button_bar.appendChild( newButton('{{$v}}', () => socket.send( JSON.stringify({ Message: '{{$v}}' })))); {{end}} } </script> </head> <body> <h1>WebSocket EXAMPLE</h1> <h2>Known Asynchronous Actions</h2> <div id="action_buttons"></div> <h2>Server Output</h2> <div id='event_log'></div> </body> </html>
  • 60. func main() { p := PageCon fi guration{"/socket", []string{"A", "B", "C"}} html, e := template.ParseFiles(BaseName() + ".html") Abort(FILE_READ, e) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/html") Abort(BAD_TEMPLATE, html.Execute(w, p)) }) events := make(chan string, 4096) var monitors []*websocket.Conn http.Handle(p.URL, websocket.Handler(func(ws *websocket.Conn) { i := len(monitors) monitors = append(monitors, ws) defer func() { if e := ws.Close(); e != nil { log.Println(e.Error()) } monitors[i] = nil }() var b struct{ Message string } for { if e := websocket.JSON.Receive(ws, &b); e == nil { events <- b.Message } else { log.Printf("socket receive error: %vn", e) break } } })) go func() { for { e := <-events for _, ws := range monitors { if ws != nil { go func(ws *websocket.Conn, e string) { websocket.JSON.Send(ws, []interface{}{e}) }(ws, e) } } } }() Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil)) } events := make(chan string, 4096) var monitors []*websocket.Conn http.Handle(p.URL, websocket.Handler(func(ws *websocket.Conn) { i := len(monitors) monitors = append(monitors, ws) defer func() { if e := ws.Close(); e != nil { log.Println(e.Error()) } monitors[i] = nil }() var b struct{ Message string } for { if e := websocket.JSON.Receive(ws, &b); e == nil { events <- b.Message } else { log.Printf("socket receive error: %vn", e) break } } }))
  • 61. func main() { p := PageCon fi guration{"/socket", []string{"A", "B", "C"}} html, e := template.ParseFiles(BaseName() + ".html") Abort(FILE_READ, e) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/html") Abort(BAD_TEMPLATE, html.Execute(w, p)) }) events := make(chan string, 4096) var monitors []*websocket.Conn http.Handle(p.URL, websocket.Handler(func(ws *websocket.Conn) { i := len(monitors) monitors = append(monitors, ws) defer func() { if e := ws.Close(); e != nil { log.Println(e.Error()) } monitors[i] = nil }() var b struct{ Message string } for { if e := websocket.JSON.Receive(ws, &b); e == nil { events <- b.Message } else { log.Printf("socket receive error: %vn", e) break } } })) go func() { for { e := <-events for _, ws := range monitors { if ws != nil { go func(ws *websocket.Conn, e string) { websocket.JSON.Send(ws, []interface{}{e}) }(ws, e) } } } }() Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil)) } events := make(chan string, 4096) var monitors []*websocket.Conn go func() { for { e := <-events for _, ws := range monitors { if ws != nil { go func(ws *websocket.Conn, e string) { websocket.JSON.Send(ws, []interface{}{e}) }(ws, e) } } } }()
  • 62. func main() { p := PageCon fi guration{"/socket", []string{"A", "B", "C"}} html, e := template.ParseFiles(BaseName() + ".html") Abort(FILE_READ, e) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/html") Abort(BAD_TEMPLATE, html.Execute(w, p)) }) events := make(chan string, 4096) var monitors []*websocket.Conn http.Handle(p.URL, websocket.Handler(func(ws *websocket.Conn) { i := len(monitors) monitors = append(monitors, ws) defer func() { if e := ws.Close(); e != nil { log.Println(e.Error()) } monitors[i] = nil }() var b struct{ Message string } for { if e := websocket.JSON.Receive(ws, &b); e == nil { events <- b.Message } else { log.Printf("socket receive error: %vn", e) break } } })) go func() { for { e := <-events for _, ws := range monitors { if ws != nil { go func(ws *websocket.Conn, e string) { websocket.JSON.Send(ws, []interface{}{e}) }(ws, e) } } } }() Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil)) } events := make(chan string, 4096) var monitors []*websocket.Conn http.Handle(p.URL, websocket.Handler(func(ws *websocket.Conn) { i := len(monitors) monitors = append(monitors, ws) defer func() { if e := ws.Close(); e != nil { log.Println(e.Error()) } monitors[i] = nil }() var b struct{ Message string } for { if e := websocket.JSON.Receive(ws, &b); e == nil { events <- b.Message } else { log.Printf("socket receive error: %vn", e) break } } }))
  • 63. func main() { p := PageCon fi guration{"/socket", []string{"A", "B", "C"}} html, e := template.ParseFiles(BaseName() + ".html") Abort(FILE_READ, e) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/html") Abort(BAD_TEMPLATE, html.Execute(w, p)) }) events := make(chan string, 4096) var monitors []*websocket.Conn http.Handle(p.URL, websocket.Handler(func(ws *websocket.Conn) { i := len(monitors) monitors = append(monitors, ws) defer func() { if e := ws.Close(); e != nil { log.Println(e.Error()) } monitors[i] = nil }() var b struct{ Message string } for { if e := websocket.JSON.Receive(ws, &b); e == nil { events <- b.Message } else { log.Printf("socket receive error: %vn", e) break } } })) go func() { for { e := <-events for _, ws := range monitors { if ws != nil { go func(ws *websocket.Conn, e string) { websocket.JSON.Send(ws, []interface{}{e}) }(ws, e) } } } }() Abort(LAUNCH_FAILED, http.ListenAndServe(ADDRESS, nil)) } events := make(chan string, 4096) var monitors []*websocket.Conn go func() { for { e := <-events for _, ws := range monitors { if ws != nil { go func(ws *websocket.Conn, e string) { websocket.JSON.Send(ws, []interface{}{e}) }(ws, e) } } } }()
  • 64. package main import "log" import "golang.org/x/net/websocket" const SERVER = "ws://localhost:3000/socket" const ADDRESS = "http://localhost/" func main() { if ws, e := websocket.Dial(SERVER, "", ADDRESS); e == nil { var m []interface{} for { if e := websocket.JSON.Receive(ws, &m); e == nil { log.Printf("message: %vn", m) } else { log.Fatal(e) } } } else { log.Fatal(e) } }
  • 65. package main import "log" import "golang.org/x/net/websocket" const SERVER = "ws://localhost:3000/socket" const ADDRESS = "http://localhost/" func main() { if ws, e := websocket.Dial(SERVER, "", ADDRESS); e == nil { var m []interface{} for { if e := websocket.JSON.Receive(ws, &m); e == nil { log.Printf("message: %vn", m) } else { log.Fatal(e) } } } else { log.Fatal(e) } }
  • 66. package main import "log" import "golang.org/x/net/websocket" const SERVER = "ws://localhost:3000/socket" const ADDRESS = "http://localhost/" func main() { if ws, e := websocket.Dial(SERVER, "", ADDRESS); e == nil { var m []interface{} for { if e := websocket.JSON.Receive(ws, &m); e == nil { log.Printf("message: %vn", m) } else { log.Fatal(e) } } } else { log.Fatal(e) } }
  • 67. package main import "log" import "os" import "time" import "golang.org/x/net/websocket" const SERVER = "ws://localhost:3000/socket" const ADDRESS = "http://localhost/" func main() { if ws, e := websocket.Dial(SERVER, "", ADDRESS); e == nil { var b struct{ Message string } for _, v := range os.Args[1:] { b.Message = v websocket.JSON.Send(ws, &b) time.Sleep(1 * time.Second) } } else { log.Fatal(e) } }
  • 68. package main import "log" import "os" import "time" import "golang.org/x/net/websocket" const SERVER = "ws://localhost:3000/socket" const ADDRESS = "http://localhost/" func main() { if ws, e := websocket.Dial(SERVER, "", ADDRESS); e == nil { var b struct{ Message string } for _, v := range os.Args[1:] { b.Message = v websocket.JSON.Send(ws, &b) time.Sleep(1 * time.Second) } } else { log.Fatal(e) } }
  • 69. package main import "log" import "os" import "time" import "golang.org/x/net/websocket" const SERVER = "ws://localhost:3000/socket" const ADDRESS = "http://localhost/" func main() { if ws, e := websocket.Dial(SERVER, "", ADDRESS); e == nil { var b struct{ Message string } for _, v := range os.Args[1:] { b.Message = v websocket.JSON.Send(ws, &b) time.Sleep(1 * time.Second) } } else { log.Fatal(e) } }