webdev

#define webdev: \ I---------------------------------------------------------------------------------------\ I---------------------------------------------------------------------------------------\ I \ I /$$ /$$ /$$ /$$ \ I | $$ /$ | $$ | $$ | $$ \ I | $$ /$$$| $$ /$$$$$$ | $$$$$$$ /$$$$$$$ /$$$$$$ /$$ /$$ \ I | $$/$$ $$ $$ /$$__ $$| $$__ $$ /$$__ $$ /$$__ $$| $$ /$$/ \ I | $$$$_ $$$$| $$$$$$$$| $$ \ $$| $$ | $$| $$$$$$$$ \ $$/$$/ \ I | $$$/ \ $$$| $$_____/| $$ | $$| $$ | $$| $$_____/ \ $$$/ \ I | $$/ \ $$| $$$$$$$| $$$$$$$/| $$$$$$$| $$$$$$$ \ $/ \ I |__/ \__/ \_______/|_______/ \_______/ \_______/ \_/ \ I \ I---------------------------------------------------------------------------------------\ I---------------------------------------------------------------------------------------I Classical_web_workstack: • server {Apache, Ngix, Lighttpd} • database {Mysql, Mongodb} • markup generator {php, Node.js} • markup {html, xml} • stylesheet {css, sass} • client side script {Javascript, Python} — stacks of well known combinations: • LAMP; "Linux Apache2 Mysql Php" • WAMP; "Windows Apache2 Mysql Php" • MERN; "Mongodb Express.js React.js Node.js" there are 6 gorillion others no one cares or knows about Captcha:"Completely Automated Public Turing test to distinguish between Computers and HumAns" such a lame and forced acronym • any gateway task to keep script kiddies away { copy the code from the image; click the fire hydrants; which way is the cat facing? } • flooding mitigation tactic • also filters the disabled and mentally challenged (based) An_insight_to_databases: • many, many websites are simply CRUD — what if we allowed direct database accesss?: "sqlgen" • the client first downloads a script which contains metadata on how to interact with the database server • implementing CRUD is virtually automated away • even less stress on the server • the workload on the client is still minimal, things will actually appear faster because display is cached away • security is improved because of the reduced complexity • the tooling is easy to generalize • implementing searches no longer require extra care and more importantly they dont break • power users can figure out the state of the database in case of a visual bug • think of a read only wiki of sorts, everything is still stored as simple files, however the server abides a database protocol; we actually gain the advantage of complete site-maps out of the box — why dont we allow direct access to databases?: //?! ### Site rendering in simple terms ### {// examples • the goal is the same with each methodology • we have data.txt • it contains key-value pairs ○ its generated with this script #!/bin/bash # generator.sh OUTPUT="data.txt" while true; do rm $OUTPUT for i in {0..7}; do (tr -dc A-Za-z0-9 </dev/urandom | head -c 8; echo ' : '$RANDOM ) >> $OUTPUT done sleep 5 done • each website will attempt to display the contents of data.txt } Static: • completely handwritten • old school • fast both server and client side • there are no rapidly changing elements as every modification is manual • works very well for small sites consistent in content { // static.html <div style="position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%);"> <h1>Example webpage</h1> <div> <table> <tr><td>dYcoNjAe</td><td>15810</td></tr> <tr><td>aey3hj9V</td><td>30474</td></tr> <tr><td>w50EXL8K</td><td>9688 </td></tr> <tr><td>gt3qgccG</td><td>21265</td></tr> <tr><td>z63cbqAt</td><td>29301</td></tr> <tr><td>uchA1fn8</td><td>1941 </td></tr> <tr><td>YRxi9MrI</td><td>31986</td></tr> <tr><td>AMqnWWNZ</td><td>16368</td></tr> </table> <div> </div> • since its all manual, the values are hardcoded • was a chore just to create the example } Dynamic: • created at request • a (markup) generator must be used {php} { // dynamic.php <div style="position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%);"> <h1>Example webpage</h1> <div> <table> <?php $file = fopen('data.txt', 'r'); while(($line = fgets($file)) !== false): list($key, $value) = explode(':', $line, 2); $key = trim($key); $value = trim($value); ?> <tr><td><?=$key?></td><td><?=$value?></td></tr> <?php endwhile; fclose($file); ?> </table> <div> </div> • the file is actually opened and read • the websites content is guaranteed to correspond to data.txt's contents } Prerendered: • a dynamic is eval-ed before being deployed • at runtime the pre-generated version is being shipped • hybrid of static and dynamic • often also called static for simplicity • less typing than with static • contents might get out of date • often used when the pages do not require updating, but all use the same template {every page needs the same header added} { // dynamic.php <div style="position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%);"> <h1>Example webpage</h1> <div> <table> <?php $file = fopen('data.txt', 'r'); while(($line = fgets($file)) !== false): list($key, $value) = explode(':', $line, 2); $key = trim($key); $value = trim($value); ?> <tr><td><?=$key?></td><td><?=$value?></td></tr> <?php endwhile; fclose($file); ?> </table> <div> </div> // its rendered to disk $ php dynamic.php > prerendered.html // prerendered.html is shipped } Live: • the website is blank by default, the content is appended by communicating with the server in the background • uses websockets • stateful connection • can update the contents without refreshing the page • most reliable regarding data-freshness • requires by far the most work relative to the other methods • requires writing js, for this reason alone, it's cancer { // Socks server using python #!/bin/python # sockets.py import asyncio import websockets import json async def send_data(ws): while True: j = {} with open('data.txt', 'r') as f: for line in f: key, value = map(str.strip, line.split(':', 1)) j[key] = value await ws.send(json.dumps(j, indent=4)) await asyncio.sleep(2) asyncio.get_event_loop().run_until_complete(websockets.serve(send_data, 'localhost', 8765)) asyncio.get_event_loop().run_forever() // Socks client using Javascript nested into the webpage <div style="position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%);"> <h1>Example webpage</h1> <div> <table> </table> <div> </div> <script> let socket = new WebSocket('ws://localhost:8765'); socket.onmessage = (event) => { let table = document.getElementsByTagName('table')[0]; table.innerHTML = ''; data = JSON.parse(event.data) for(d in data){ var row = table.appendChild(document.createElement('tr')); var key_cell = row.appendChild(document.createElement('td')); var value_cell = row.appendChild(document.createElement('td')); key_cell.innerText = d; value_cell.innerText = data[d]; } } </script> • looks cool, i know } # CORS:"Cross-origin resource sharing" • web browser ''feature'' • the policy that forbids clients side scripts to issue request to arbitrary hosts • if one makes a client side request the CORS header is checked, if it does not contain the issuing domain as authorized, it's hard denied • never relevant when requesting resources from the same domain • security concern • without CORS one could steal private data or outsource malicious work • it cripples user side scripts from doing legit work too Brython: • Javascript implementation of Python 3 • can completely replace user side Javascript <!-- Brython hello world; equivalent to a Javascript console.log() call --> <!-- Dependency for Brython; obviously could be served locally --> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/brython/3.10.0/brython.js"></script> <!-- Code section --> <script type="text/python"> print("Hello world!") </script> • capable of completely replacing javascript completely, finally giving an alternative to front-end developers • see AT "Python/Brython" CGI: rfc3875 • "Common Gateway Interface" • old fashion (based) way of doing dynamic content • the server executes and passes data to binaries +========+ ---> +========+ ---> +=========+ | client | | server | | process | +========+ <--- +========+ <--- +=========+ • program arguments can be specified, allowing for arbitrary interpreters {perl myscipt.pl} • all backend development should be done using CGI, because you get accurate diagnostics (unlike using daemons) and changes are guaranteed to apply on save, because there is no caching (unlike builtin webservers) { // CGI Hello World in C++ // @BAKE g++ $@ -o $*.cgi #include <stdio.h> signed main(int argc, char * * argv, char * * envp) { fputs("Content-Type: text/plain\r\n\r\n", stdout); fputs("hello world", stdout); return 0; } } • "The script MUST return a Content-Type header field." Meta_variables: • passed in an implementation defined way • usually implemented using environment variables AUTH_TYPE : implementation defined CONTENT_LENGTH : message body size CONTENT_TYPE : mimetype GATEWAY_INTERFACE : CGI version PATH_INFO : access path PATH_TRANSLATED : rendered ${PATH_INFO} { %20 translation } QUERY_STRING : ?! REMOTE_ADDR : clients address REMOTE_HOST : clients domain REMOTE_IDENT : ?! REMOTE_USER : ?! REQUEST_METHOD : http method {GET|POST|PUT|DELETE} SCRIPT_NAME : CGI script name SERVER_NAME : server address SERVER_PORT : server port SERVER_PROTOCOL : server protocol with version number SERVER_SOFTWARE : server name and version FastCGI: • alternative to CGI • addresses the performance concern of spawning a new process at every request • CGI vs fastCGI comes down to a complexity vs speed trade-off • a fastCGI script is a coroutine