Don't like this style? Click here to change it! blue.css
Task: let users navigate to an infinite number of URLs in your app.
There are MANY ways to do this, but my flag for the day is one of them:
Let's group the various ways of doing this into several groups:
#
part of a URL to synthesize the targetI'll start here because it's the simplest and most "conceptual".
Instead of a separate file per page we use a function to draw our new page.
All animation engines will wipe the screen and redraw it at least 20 times per second. We can use the same notion, clear the body or hide a div, now draw an appropriate page.
Here are some tricks for having unrendered HTML that you can keep up your sleeve for later.
Trick 1: multiple pages, all but one hidden.
See the Pen dGKyjZ by Andy Novocin (@AndyNovo) on CodePen.
Simple Pages: Add a fourth page template. Add a button on your page that when clicked alerts "hi".
Trick 2: multiple pages, all hidden, one display area.
See the Pen xZzxyq by Andy Novocin (@AndyNovo) on CodePen.
Simple Pages: Add a fourth to this example. What are the differences with the first trick. Any pros and cons that you can see?
Trick 3: script tags with bad types don't render.
See the Pen MKXWLa by Andy Novocin (@AndyNovo) on CodePen.
Simple Pages: Add a fourth. What are the differences? What are the pros and cons?
Trick 4: inline-template literals.
See the Pen version3 by Andy Novocin (@AndyNovo) on CodePen.
Simple Pages: Add a fourth to this example. What are the differences with the first trick. Any pros and cons that you can see?
For what it's worth, the 3rd trick is the one I see most often in simple page examples. Another trick is to keep separate HTML template files and use a library to help you load them.
So this is the same as above but you can pack your data into URL parameters.
You see this a ton in marketing analytics links, there are many ways to call google.com with various params that don't change your results at all (but do tell them a lot about you).
I won't spend a ton of time on this, but here's how you can read URL params:
(Be careful with XSS)
And the source code:
So the cool thing here is that the DOM has two events you can listen for that help us use an old thing in a new way:
window.addEventListener("hashchange", handleHash)
window.addEventListener("load", handleHash)
So far our URLs have been a tad ugly. ?blah=page2
or #page2
or no deep linking at all
But there's something beautiful about websec.prof.ninja/some/totally/unexpected/url
To pull that off we need a little help from the server. Here are three ways to get all requests to a certain URL to be handled by the same file:
.htaccess
file for an Apache server (or the try_files directive for NGINX)This is important enough that I made a separate page for it:
When you do firebase init for hosting you'll select single Page App mode which sends all 404 errors to index.html
Here's a demo for the second option (using NODE to augment your routing). The second is the one I use most often (a sample .htaccess
follows). The third one is what I used for Minceraft
Head to Glitch.com and make a new
"hello-node" app. Change the one line in server.js
which said fastify.get("/", function(request, response) {
and add the wildcard character: fastify.get("/*", function(request, response) {
AND
add the line wildcard: false
to the "fastify-public" configuration. (If you're feeling lazy I've got an entire server.js below.)
Visit your URL, then your URL/farts, then your URL/hello/world.
For posterity here's an .htaccess for sending all URLs to the same spot (a PHP file in this case):
So all of these methods we've learned so far are under the hood of how the web app frameworks do it.
Thus, this section is almost to show you concepts of how you might consider engineering wrappers for your routing one day.
The earlier glitch example is essentially the hello world you need, but we'll do a whole bit on building REST APIs soon. So we can handle this case later. (In essence have the server handle /:param1/:param2 with some templating.)
This is the same tech of a typical REST API, so here's a dumb example:
Find my favorite mountain: ./flag