[HN Gopher] How to store your app's entire state in the url
___________________________________________________________________
How to store your app's entire state in the url
Author : escot
Score : 606 points
Date : 2023-01-09 16:57 UTC (1 days ago)
(HTM) web link (www.scottantipa.com)
(TXT) w3m dump (www.scottantipa.com)
| instagary wrote:
| This reminded me of Xstate (https://xstate.js.org/docs/). Their
| visual editor in VSCode does this.
| jdlyga wrote:
| You've just invented video game passwords! This reminds me of
| transferring over my save data from Golden Sun to Golden Sun: The
| Lost Age by typing in a 260 character password.
| pdntspa wrote:
| The early 2000's called, they want their ASP pages and IIS
| license back
| [deleted]
| arnorhs wrote:
| This is an interesting approach. Should help mitigate the URL max
| length for larger states.
|
| However as some people have pointed out it comes with a few
| caveats
|
| - The URL is unreadable for humans
|
| - You possibly end up storing things in the URL you did not
| intend
|
| - For smaller data sets the URL actually becomes larger than the
| URL params equivalent
|
| - You end up having to deal with version issues, possibly even
| URL string migrations as the code evolves
|
| I'm sure there still are use cases where this makes sense, but
| for most applications this ends up being overly complex
| gernb wrote:
| Lots of sites do this. Lately for me there's
|
| https://www.typescriptlang.org/play
|
| I'm mixed on it. It means it's mostly useless for having your own
| list of creations because you have to manually store the URLs
| (PITA) and you need to store them somewhere accessible if you
| want to repo the UX of the site actually storing them where you
| can more easily access them from anywhere.
| noduerme wrote:
| I'm sorta debating the merits of various methods like this
| because there's something I want to "Show HN" which involves
| browser-based analysis of CSV files... but the way I built it for
| myself, I just run it on a Node server that parses the file once
| and stores it as json and serves it when you reopen a project. So
| now I want to bundle the CSV/json with then project file. But
| putting it all in a base64 url seems a little crazy when
| saving/retrieving gzip files from the local filesystem is just as
| good an option. I think this is interesting as something to
| consider for shared projects, but probably not ideal if the main
| goal is to have everything run locally anyway.
| ananthakumaran wrote:
| About 6 years ago I had to do this on a project. We had charts
| with a lot of options and we wanted them to be bookmarkable and
| shared between colleagues. We started with base64, soon moved to
| a custom encoding with version support
| https://github.com/ananthakumaran/u
| jonny_eh wrote:
| Note that this could easily break or get messy as you make
| changes to your app. Consider either some kind of versioning
| indicator, or be very careful to only add fields, never changing
| them.
| benatkin wrote:
| This has taken off in the Vue community w/ https://sfc.vuejs.org/
| and https://uno.antfu.me/play/ and they use the fragment so it
| doesn't get sent to the HTTP server
| tonto wrote:
| I always like this when the url is always copyable, but in our
| app, the state can get quite large. We started with base64
| encoded gzip of json.stringified app state but just gets quite
| long. Arguably it could be reduced a little bit, but would still
| be hundreds-thousands of chars routinely, so we switched to using
| a little URL shortening service that we wrote on aws
| lambda+dynamodb
| binarymax wrote:
| Shameless plug for bashfill - a fun little drawing program for
| making art for bash stdout:
| https://max.io/bash.html?zip=eDE1eTF4MjRlMXgzeTF4MzB5MXg1ZTF...
|
| ...made in 2013 :) Here's the js that runs it:
| https://max.io/bash.js
| quickthrower2 wrote:
| Since it is ephemeral, local storage is probably fine? Feels like
| a better solution.
| cwt137 wrote:
| A few years ago, I worked on an app where some of the state was
| kept in the session and some was on the url as GET params. We ran
| into an issue where some browsers would only accept urls that
| were less than 1024 chars long. Is that still an issue today?
| aplummer wrote:
| The limit disappeared after ie9, however can and should are
| different things here
| werdnapk wrote:
| Yes. I had a bug report last year to deal with this due to the
| url being cut off in the browser with Ajax GET requests. I
| converted to a POST request which has no length limitations.
| NoobNoob wrote:
| I too obsess over shorter URLs but I do love the idea that the
| whole state is just a URL. From the comments, use good enough
| defaults and URL shorteners where necessary, and it's a brilliant
| design for a free-tier application.
| EGreg wrote:
| It's actually difficult to do this in the UX.
|
| Suppose that you have a hierarchy that was opened. Do you want to
| store all the hierarchy breadcrumbs in case you hit refresh, and
| reload all of them?
|
| Furthermore, what about URLs to initiate an action from a
| particular context? If you refresh what should it show? It should
| show a dialog / lightbox above the page, showing the form /
| interface for filling out before taking this action.
| ddyevf635372 wrote:
| Routes are the fundamental building blocks of a webpage, so the
| hierarchy will be represented by the routes in the url. Proper
| frontend framework, like Ember.js, built on top of routes and
| building a UX focused web app is much easier with them.
|
| https://guides.emberjs.com/release/routing/
| EGreg wrote:
| Your link and the explanation there is not enough. It only
| shows the current resource you are looking at. As I said
| above - you should also consider representing the breadcrumbs
| of how you got there in the hierarchy (you could have taken
| multiple paths) and also on top of that use URLs to represent
| actions that can be taken in dialogs !
|
| Here is a question for you: what happens when you have a url
| for a New Issue in github? By itself. It renders a form for a
| new issue full-page. But now what if I want it as an overlay
| over a hierarchical state that U navigated to? I should have
| a longer URL and it wouldnt be full screen anymore.
| ddyevf635372 wrote:
| Overlay is useful sometimes, however not always the best
| UX.
|
| The main route of the url (example.com/page/subpage)
| represents the background page of the overlay.
|
| You have two options. 1. Using further subroutes to
| represent the stage of the overlay if your framework
| supports it (Ember does)
| (example.com/page/subpage/form/step1). 2. Using query
| parans to store the state of the overlay (without the
| actual data of course): ... subpage?overlay=form&step=1
|
| Also breadcrumbs should always mirror the routes.
| Frameworks, libraries can automatically do it for you.
| mperham wrote:
| I recall this technique being used in 1999. It doesn't work well
| with caching proxies which key off the URL, using a Cookie header
| is cleaner and simpler.
| easrng wrote:
| Caching proxies which key off the URL are pretty much useless
| now because they don't work with HTTPS.
| temporallobe wrote:
| Out of necessity for a very similar issue, I actually wrote a
| small Javascript utility for this that does all this
| automatically and uses optional symmetric encryption. Would it be
| against the rules to post it here?
| philwelch wrote:
| Another way to generate potentially shorter base64 strings is to
| use something like Python's `struct` to store packed binary data,
| and then base64 encode that. Better yet, if that data payload can
| be generated server-side, you can also sign that data payload,
| which allows you to statelessly verify the data payload itself.
|
| (cf. https://docs.python.org/3/library/struct.html)
| tlavoie wrote:
| As usual when I see this sort of thing, I have questions around
| the security needs of the application. Storing all of this
| information on the client means that the client has to be trusted
| to not mess with all of this state. If it's important, it needs
| to be stored and checked server-side.
| deckard1 wrote:
| yep. A coworker introduced a CSRF doing this. I had to point
| out that you can't just take raw input from a URL and throw it
| back on the page. Even after I pointed it out and gave a proof-
| of-concept they still didn't get it.
| tlavoie wrote:
| Right, that's usually when I go into story-telling mode, to
| paint a picture of exactly the sorts of things I'd be doing
| with the problem as an attacker. Technical vulnerability
| descriptions provide useful information, but people often
| need an idea of what it really means, to them.
| somehnguy wrote:
| Validating data from the client should always be done on the
| server in that context, regardless of if state is being saved
| client side or not. I think this is just an extension of what
| you said though.
|
| I can think of many apps that don't need server side data
| storage or security that would benefit from this type of state
| saving however. For example, this app that I was using today -
| https://wheelofnames.com/ . Right now to save I need to create
| an account, presumably to tie my account to the saved state on
| the server side. That's pretty heavy/intrusive when all I want
| to do is keep the names list and preferences populated for my
| next visit.
| tlavoie wrote:
| Sure, there are reasonable use cases. It's worth pointing out
| where those use cases are not reasonable though, because
| those devs that don't know better will be inclined to treat
| obfuscated inputs as if they're trustworthy.
| saghm wrote:
| I imagine I'm not the first one to think of this, but a little
| while back I wrote a toy pastebin-like webpage that stored the
| code being rendered directly in the URL (with base64 and gzip
| compression to make it a bit smaller, although it still was quite
| large by usual standards). My thinking was that rather than
| having a centralized app for this publicly available, making a
| small page that could be statically hosted would make it easy for
| people or organizations to host their own page with whatever
| security they need (e.g. behind a firewall or VPN) and then the
| links could be shared privately on Slack or whatever without a
| need to add functionality for determining who should have access
| or how long to keep the code snippet around and instead just
| piggyback off of the privacy of whatever channel/DM they sent it
| across and how long the Slack instance is configured to retain
| history.
|
| When I first came up with this idea, I was going to write some
| sort of server backend rather than just doing everything in the
| frontend, but once I started actually working on it, I realized
| that it wouldn't really add any value and it would make it a bit
| more annoying for people to self-host. Since then, I've wondered
| a bit how viable "static pages with state in the URL that can be
| easily self-hosted" would be as an alternative to a desktop GUI
| or Electron app for more technical users. One of the nicest parts
| of this approach to me is that I was able to make in only a few
| hours one evening despite knowing only the basics of webdev from
| maybe 8-10 years ago and next to nothing about programming GUIs
| in general. This makes me think that it wouldn't be too hard for
| people to fork and modify it to their own liking (e.g. changing
| the hard-coded style settings for rendering the code snippets),
| so there could be potential for an ecosystem to grow organically
| around something like this.
|
| In case anyone is curious to take a look:
| https://gitlab.com/saghm/pastml/
| Ndymium wrote:
| Great minds think alike? I just posted about my URL-using
| pastebin: https://news.ycombinator.com/item?id=34315577
| dzaima wrote:
| There are quite a few of these apparently.
| https://topaz.github.io/paste/ (lzma) from the creator of
| Advent Of Code, and mine: https://dzaima.github.io/paste/
| (pako)
| saghm wrote:
| Oh wow! If you mean November 2022, pretty close to when I was
| doing mine! If you mean 2021, you definitely had the idea way
| before me
| Ndymium wrote:
| Nov 2022 it was. Seemed like everyone was having covid, and
| so was I. The idea came up in a Discord discussion, so I
| decided to go for it. Later I added the syntax highlighting
| and file naming. I also added a little extensible header
| system so that I could add more features in the future
| without breaking old URLs. Now I'm thinking maybe I should
| allow extra long URLs (>2048) if the user requests so, they
| seem to be supported in Chrome/Firefox/Safari...
| lol768 wrote:
| Am I alone in thinking it's ridiculous for an editor action to
| push/pop state in browser history to allow undo/redo? Surely this
| leads to substantial browser history pollution?
| vasco wrote:
| You are not wrong. I cannot think of many interactions with an
| editor where if the user presses the back button they want to
| undo the last micro action they did, instead of going to the
| previous page / major UI interaction. Even just trying the demo
| after adding 3 blocks I had to press back like 5 times to exit
| the page back to where I was before.
| kccqzy wrote:
| Absolutely agreed. Given how HN can be when complaining about
| back button breakage (so common that it had to be explicitly
| banned), I'm surprised so few people are talking about the
| implications here.
| getToTheChopin wrote:
| It's pretty common to do this using the URI fragment in a link.
|
| For example: https://themeasureofaplan.com/market-
| timing/#initialContribu...
|
| This shows the performance of a market timing strategy on the
| S&P500, where you invest $20,000 upfront and $1,000 per month
| thereafter, while only buying when the market is 25%+ away from
| the all-time high price (analysis from 1993 to 2023).
|
| These user input variables are all directly encoded in the URL,
| after the # symbol.
| iLoveOncall wrote:
| This is a terrible example though, there is no reason why those
| shouldn't be normal query parameters.
| getToTheChopin wrote:
| I don't see why normal query parameters (using ? symbol)
| would be better than putting the key/value pairs after a #
| symbol.
|
| They both achieve the purposes of allowing custom URLs that
| bring the user to a specific state of the app.
| wildrhythms wrote:
| An often unintended side effect of using the URL hash to
| contain state is that it breaks potentially linking to an
| anchor element ID somewhere in the page. Obviously this
| doesn't matter much if the page doesn't use anchor IDs or
| you don't intend on users doing that.
| nimzoLarsen wrote:
| Interesting. Just to make sure I understand -- that url
| contains all of the IDs and user inputs, and then you parse out
| of the key/value pairs and feed those inputs into the app?
| getToTheChopin wrote:
| Yep. See here for an explanation:
| https://stackoverflow.com/questions/12520124/parse-url-
| fragm...
|
| Edit: better link to explain the concept
| dndn1 wrote:
| I built a quick/wip payroll validator [0] that can read state
| (i.e. payroll details) from the URL.
|
| The purpose in this case was to generate a QR code, the idea is
| this can be included in physical payslips. Then the numbers
| behind the calculations (tax deductions) can be validated, broken
| down, and understood. I'm developing more tools to these ends,
| via my overarching project calculang, a language for calculations
| [1].
|
| I also have a loan/repayment validator [2] but haven't added this
| QR code feature yet.
|
| Bank letters e.g. "Interest rates are rising and now we want 100e
| more per month, every month" could use a QR code to an
| independent validator or to see the workings behind the 100
| calculation.
|
| Not using this in the real world now and there are security
| considerations to keep in mind, but reading state from a URL
| facilitates the usecase: QR codes that link physical numbers to
| their calculation and model.
|
| Implementation of payroll calculator is an Observable notebook
| and thankfully it neatly supports all my strict requirements as
| demo of this.
|
| [0] https://observablehq.com/@declann/payroll-playground-
| ireland...
|
| +Feature tweet:
| https://twitter.com/calculang/status/1608183731533107206
|
| [1] https://github.com/calculang/calculang
|
| [2] https://observablehq.com/@declann/loan-validator-dev
| cpa wrote:
| This is a handy trick that I've used on multiple occasions.
| However, it may not work on some corporate networks that filter
| URLs with more than a certain number of characters (I've
| encountered limits of 2048 and 4096 characters).
|
| The rationale being that long URLs are often suspicious and could
| potentially be used for SQL injection or path traversal attacks.
| Whether or not this is a good heuristic is left as an exercise to
| the reader.
| Ndymium wrote:
| Last November I had covid and during that time I wrote a little
| pastebin that runs in the browser, compresses the paste data with
| Brotli, and puts it in the URL. It has line numbers, file naming,
| and syntax highlighting so it's feature complete for my own use.
| Here's a demo, but beware, the URLs are loooong:
| https://nicd.gitlab.io/t/#NhfW?Qm3F?6-&22c&CQZXuP+Aej5OXzXk7...
|
| I find it interesting to sometimes play around with the pasted
| data just to see how it compresses. Sometimes adding a character
| or two may cut several characters from the URL length!
| calebegg wrote:
| > The maximum URL size is 2048
|
| FYI, this is almost entirely untrue. Maybe for some old
| versions of IE, but modern browsers can handle extremely long
| URIs
| jansan wrote:
| Is the Brotli compression done in the browser? If so, can you
| give some insight how this is done?
| Ndymium wrote:
| Yep, it is! You can find the sources on GitLab[0]. The
| compression is done using brotli-wasm[1].
|
| The entry point to the compression is the syncCompress[2]
| function, which converts the data to UTF-8, adds the needed
| header bytes, and then compresses using brotli-wasm.
| Decompression is done in a streaming way in
| streamDecompress[3]. This is to avoid zip bomb attacks, where
| even a short URL could decompress to gigabytes of data,
| locking the browser. Thankfully brotli-wasm had streaming
| decompression builtin, I just had to write the wrapper code
| to update the text content and the status bar in the UI.
|
| You can find the brotli-wasm code I'm using in the vendor
| folder[4], there is a JS wrapper and then the WASM code (both
| are straight from brotli-wasm).
|
| [0] https://gitlab.com/Nicd/t
|
| [1] https://github.com/httptoolkit/brotli-wasm
|
| [2] https://gitlab.com/Nicd/t/-/blob/05e587b0183ff80b1c6e050b
| 5d3...
|
| [3] https://gitlab.com/Nicd/t/-/blob/05e587b0183ff80b1c6e050b
| 5d3...
|
| [4] https://gitlab.com/Nicd/t/-/tree/05e587b0183ff80b1c6e050b
| 5d3...
| didericis wrote:
| Compression is one of the closest things to real life magic I'm
| aware of. Especially now that people have basically compressed
| the entire internet into a couple gig AI models.
|
| And then when I think about biology/genetics and what kind of
| unfathomably weird and convoluted compression is going on
| there, and then think about whatever it is our brain is
| doing... and then when I think about how like all of our
| _perception_ is probably some kind of weird inescapable
| compressed representation of true reality...
|
| It's all magic. Real life magic.
| holdenk wrote:
| I did something similar using Racket's (nee PLT scheme) web
| programming module (
| https://www2.ccs.neu.edu/racket/pubs/hosc07-sk-mf.pdf ) back with
| an app that got on slashdot --
| https://github.com/holdenk/web2.0collage
|
| The theory was wonderful (yay! stateless load balancer etc.) but
| in practice browsers at the time were less than happy with trying
| to store that much state in the URL.
| jwoglom wrote:
| Like some other commenters mentioned, this is a cool idea,
| however by storing JSON data inside base64, the length of the URL
| blows up very quickly as you start storing more state.
|
| While technically URLs have no formal length limit, various
| sources suggest that URLs with more than around 2,048 characters
| start causing issues in browsers, and around 8,196 start causing
| issues in CDNs (https://stackoverflow.com/a/417184). You can work
| around this partially by not storing this state information in
| the query string (path/to?<state>) and instead using a hash
| string (path/to#<state>), and then extract that data in
| JavaScript such that it's not sent to the server at all.
|
| IMO, the canonical way to solve this problem is using protocol
| buffers, which you can then serialize into a much smaller number
| of bytes, which is then base64 encoded. For example, as mentioned
| in another comment in this thread
| (https://news.ycombinator.com/item?id=34314578), Yahoo Finance
| has a 1,616 character-long URL with 1,572 characters of
| base64-encoded JSON state:
|
| > {"interval":"week","periodicity":1,"timeUnit":null,"candleWidth
| ":4.3486590038314175,"flipped":false,"volumeUnderlay":true,"adj":
| true,"crosshair":true,"chartType":"line","extended":false,"market
| Sessions":{},"aggregationType":"ohlc","chartScale":"linear","stud
| ies":{" vol undr ":{"type":"vol undr","inputs":{"id":" vol undr
| ","display":" vol undr "},"outputs":{"Up Volume":"#00b061","Down
| Volume":"#ff333a"},"panel":"chart","parameters":{"widthFactor":0.
| 45,"chartName":"chart"}}},"panels":{"chart":{"percent":1,"display
| ":"F","chartName":"chart","index":0,"yAxis":{"name":"chart","posi
| tion":null},"yaxisLHS":[],"yaxisRHS":["chart"," vol undr "]}},"se
| tSpan":{"multiplier":5,"base":"year","periodicity":{"period":1,"i
| nterval":"week"}},"lineWidth":2,"stripedBackground":true,"events"
| :true,"color":"#0081f2","stripedBackgroud":true,"eventMap":{"corp
| orate":{"divs":true,"splits":true},"sigDev":{}},"customRange":nul
| l,"symbols":[{"symbol":"F","symbolObject":{"symbol":"F","quoteTyp
| e":"EQUITY","exchangeTimeZone":"America/New_York"},"periodicity":
| 1,"interval":"week","timeUnit":null,"setSpan":{"multiplier":5,"ba
| se":"year","periodicity":{"period":1,"interval":"week"}}}]}
|
| The un-base64'd JSON dictionary is 1,162 characters long, 569 of
| which is composed of just the key names (48 percent!), and most
| of the remaining fields likely contain their default value. If
| this was instead encoded in protobuf, the key names wouldn't need
| to be included, since fields are referenced by their field ID,
| and default field values would take up little-to-no space since
| when the default value is present it isn't encoded into the
| structure. I presume that, if done efficiently, you could likely
| make an equivalent representation in protobuf that is 1/4th or
| even 1/8th the size. You also get, for better or for worse, what
| is essentially obfuscation for free (yes, you can read out the
| packed format, but without an equivalent protobuf struct
| definition it's still hard to tell what field is which, and the
| entire operation becomes much more labor-intensive).
| secondcoming wrote:
| Excellent, I was waiting for the protobuf suggestion.
| ladberg wrote:
| I tried to do that at first with https://textshader.com because
| the whole site is client-side and I didn't want to bother with a
| backend. It didn't really work because the state is unbounded in
| size, so instead I just chuck it on GitHub gists and then point
| to the gists. It means I don't have to store any data myself and
| there's zero recurring costs outside of the domain name... but if
| the site ever got popular I'd probably have to figure something
| else out.
| didericis wrote:
| I dream of a world where there's some kind of ipfs like thing
| for storing state in some sort of distributed commons, all
| while maintaining user privacy/allowing for state to expire if
| untouched, and monetized in a balanced way to incentivize
| hosting without discouraging consumer adoption too
| much/trending towards gouging.
|
| We're so close/all the pieces needed seem to exist, but getting
| something like that off the ground is super difficult.
| IYasha wrote:
| I'm not into web "programming", but do people really have to
| abndon binary data storage these days? I think compressing more
| informaiton produces still more information. While JSON is by no
| means as heavy as, for example, XML, it's far heavier than just
| array of int graph[x][y];
| Zamicol wrote:
| At work we have two api endpoints. One for JSON and the other
| for binary.
| recursive wrote:
| To put it into a url, you'll still need to serialize to text,
| even if the underlying data is binary.
| IYasha wrote:
| yup. data > gzip > UU/B64/URL-encode > text.
| misnome wrote:
| A colleague has been tasked with writing a remote image viewer.
| It's slower than before (running on the same machine) "because
| it's client-server".
|
| Naturally, the 16 Megapixel images are sent as an array of json
| floats...
| secondcoming wrote:
| Unless it's still at a proof-of-concept stage, that person is
| out of their depth.
| misnome wrote:
| Yes, yes they are. Unfortunately this is dysfunctional
| academia, so as long as the people paying the bills (who
| know nothing about building software) like them, they
| remain at this depth.
|
| Extra fun fact: Two years into the project, they hadn't
| heard of REST. Then rejected it, because, I quote, "The S
| means stateless and [they] need the server to store state"
| IYasha wrote:
| This is on another level! (0_0) Thank you for this
| example. Makes one rethink things )
| nonethewiser wrote:
| > I'm not into web "programming"
|
| Elaborate
| IYasha wrote:
| I write performance-critical code where it is normal to count
| bits, not just bytes, and keep track of number of
| instructions generated by your code. The whole web thing
| where people shove everything into a browser is just weird to
| me.
| wildrhythms wrote:
| What's weird about passing an application state back and
| forth in a serialized format? Surely your counting bits
| example can be extrapolated to make sense of that.
| metahost wrote:
| There is a max length to URLs after which it is all wild west
| based on the browser implementation.
|
| See: https://stackoverflow.com/a/417184
| threeseed wrote:
| This technique goes back to the late 90s where Apple WebObjects
| (owned by NeXT at the time) pioneered this approach in their web
| framework.
|
| https://en.wikipedia.org/wiki/WebObjects
|
| Was quite revolutionary at the time and it also included the
| first (or one of the very earliest at least) SQL ORMs.
| numair wrote:
| You're the first and only person to point out this fact, which
| shows how depressingly little history is studied by people who
| work in this field. It's a shame it's become about getting to
| The Money as quickly as possible...
| firstbabylonian wrote:
| How do we go about passing this kind of historic knowledge
| between generations of engineers? In my observation, most
| newcomers to the industry are trained either academically or
| through self-guided practical learning, i.e. by hacking and
| reading tutorials. Neither method exposes them to such
| 'contemporary history' of innovation within the field.
| wildrhythms wrote:
| I got a Compsci degree and we did in fact learn some
| history, figures like Grace Hopper and Alan Turing, how
| punched card computers worked (we even got to make our own
| punched cards!) Obviously people who are passionate about
| computers will find such history very interesting; the
| newcomers with dollar signs in their eyes won't care, they
| just want to 'make an app'.
| zengid wrote:
| relevant to mention the new tan-stack router that does this:
| https://tanstack.com/router/v1
| hardwaregeek wrote:
| I love doing this for playgrounds! It's so nice to be able to
| share a link with the code embedded. Especially if you're giving
| someone a bug report and they need a minimal reproduction.
| nerdponx wrote:
| I appreciate this feature a lot on sites like https://tio.run
| and https://mermaid.live/. However the URLs also get very long
| and I often want to run them through a shortener for e.g.
| posting to IRC. But there are worse problems to have!
| rickreynoldssf wrote:
| Your SEO guy is going to throttle you if you even consider
| thinking about doing this.
| jwilliams wrote:
| Not necessarily mandatory - but I'd also recommend a stable sort
| on the keys prior to `stringify`.
| eatonphil wrote:
| While this is great for being able to send anyone a URL to a
| stateful page without needing a backend database, keep in mind
| browsers have URL length limits and they vary by browser.
| Compressing as mentioned in the article can help but still you
| want to know when you're going to go over and figure out a plan
| for dealing with that.
| vbezhenar wrote:
| Chrome limits URLs to a maximum length of 2MB
|
| It's more likely that messaging app will have stricter limit
| than Chrome (and other browsers at this point do not matter).
|
| Though I'd suggest to use some kind of server storage if you
| need to transfer more than few kilobytes of data.
| eatonphil wrote:
| Great point too. At least you can count on being able to send
| over email.
|
| But yeah, the length will get long and even if the browser
| can handle it do you really want to be passing around that
| much text at once?
|
| I'm also curious what various OS clipboard size limits are.
| swyx wrote:
| This is quickly becoming a standard in apps and it really
| shouldnt be handrolled since its such a common requirement and
| easy to get wrong (between serializing/deserializing/unsetting
| states). In Svelte it is now as easy as using a store:
| https://github.com/paoloricciuti/sveltekit-search-params
|
| in general i've been forming a thesis [0] that there is a webapp
| hierarchy of state that goes something like:
|
| 1. component state (ephemeral, lasts component lifecycle)
|
| 2. temp app state (in-memory, lasts the session)
|
| 3. durable app state (persistent, whether localstorage or
| indexeddb or whatever)
|
| 4. sharable app state (url)
|
| 5. individual user data (private)
|
| 6. team user data (shared)
|
| 7. global data (public)
|
| and CRUD for all these states should be as easy to step down/up
| as much as possible with minimal api changes as possible
| (probably a hard boundary between 4/5 for authz). this makes
| feature development go a lot faster as you lower the cost of
| figuring out the right level of abstraction for a feature
|
| 0: relatedly, see The 5 Types of React Application State, another
| post that did well on HN
| https://twitter.com/swyx/status/1351028248759726088
|
| btw my personal site makes fun use of it -> any 404 page takes
| the 404'ed slug and offers it as a URL param that fills out the
| search bar for you to find the link that was broken, see
| https://www.swyx.io/learn%20in%20public
| WaffleIronMaker wrote:
| Does anyone know of solutions for this in React?
| austinpena wrote:
| Tanstack is working on a router that purports to solve a lot
| of this.
|
| https://tanstack.com/router/v1
| enos_feedler wrote:
| So you think of a new feature "X". That feature has a bunch of
| state it needs to manage. Each piece of state has
| _requirements_ over where it fits within this hierarchy based
| on how this state relates to the feature being developed. I
| don't understand where the cost lowering is? I know instantly
| where the state should live when I design the feature.
| swyx wrote:
| requirements evolve over time. and they tend to go up in
| terms of persistence/auth/sharability needs. it would be nice
| to make that easy; and conversely when they arent needed
| anymore it'd be nice to take the state persistence level down
| with just a few character changes rather than switching state
| systems entirely
| enos_feedler wrote:
| Agreed. Thats a nice conceptual layering as well. Thanks
| for sharing.
| marmada wrote:
| This makes sense but also seems very annoying to do? E.g let's
| say you are storing state in the URL, and now the user wants to
| save it to their profile. You need to upgrade the state from
| "encoded into the URL" to "stored in my database", which seems
| annoying.
| mhink wrote:
| Note on 2: I haven't seen this get a lot of use (or maybe I
| just haven't noticed it), but the Storage API also provides a
| `sessionStorage` object [1] with some interesting properties.
| Not only are values persisted across same-tab refreshes, but if
| you duplicate the tab, the session values are copied over as
| well (but they don't remain linked like `localStorage`). An
| interesting use case for this, IMO, is for tracking dynamic
| layout values (like if you have resizable panels, scroll areas,
| etc). If you keep this kind of thing in sessionStorage, you can
| refresh or duplicate the working tab and that ephemeral state
| will carry over, but since it's copied (not shared) the tabs
| won't step on each other.
|
| 1: https://developer.mozilla.org/en-
| US/docs/Web/API/Window/sess...
| skrebbel wrote:
| Unfortunately sessionStorage is not copied over when you
| ctrl+click a link, and that's arguably the most common way to
| "duplicate" a tab. Something about security iirc but i dont
| grok it.
|
| Still an underappreciated browser feature though, esp for
| class server-side rendered apps.
| mhink wrote:
| I'm actually kinda surprised that's the case for links to
| the same origin. I suppose you could probably still get
| this working by using `window.opener` along with
| `postMessage` to request data from the opener, although
| you'd have to be very conscientious about checking the
| origin and verifying that the requested data is actually ok
| to share.
| swyx wrote:
| i was thinking 2 is more like Redux, btw :)
|
| ive never honestly used sessionStorage as it's not intuitive
| to me (if i want it clientside i should probably track it
| serverside, and at that point server is my source of truth)
| s4i wrote:
| Yup. Session storage is particularly useful for remembering
| the initial URL of the user when they leave your app for SSO.
| porsager wrote:
| Could we please stop this "shouldn't be handrolled" or "don't
| write your own X". It only results in pushing some false idea
| that you have to be special to do these things, or that
| innovation is impossible. I can't believe we went from "don't
| roll your own crypto" to a plain thing like "don't roll your
| own url state management". What? That is obviously exactly what
| you should do to get a deeper understanding of the technologies
| you're working with. I think the only people I hear say this is
| because they have some agenda in pushing developers to be "tool
| users" instead of "problem solvers".
|
| It's not that you shouldn't say "there be dragons" or suggest
| existing solutions, but that's doable without saying you
| shouldn't do X at all...
| dietmtnview wrote:
| please don't do this, especially if you work with map
| coordinates.
| ngc6677 wrote:
| Also this:
|
| https://goog.space/?data=eyJ0eXBlIjoidGV4dCIsInZhbHVlIjoiIyB...
| phkahler wrote:
| I did this for an Othello game back in the 90's. The state was
| encoded in the URL along with the players move. It seemed weird
| to encode a slightly different URL for every move the player
| might click, but that also meant squares that were not legal
| moves didn't get a URL. And that meant the mouse pointer would
| change when you hovered over a valid square! Another trick was to
| return the updated board state, but also include an automatic
| reload after a few seconds with the computers next move already
| determined. This made it look like "thinking" was going on when
| in fact it was already decided when the board updated on players
| move ;-) This was all in a CGI script. As others have pointed
| out, it also supported "undo" via the back button. Fun.
| divbzero wrote:
| App state in URL can be a good idea, but if possible I prefer
| readable path/query parameters instead of unreadable base64
| encoding.
|
| As one comparison, this is Google Finance encoding stock chart
| parameters:
| https://www.google.com/finance/quote/F:NYSE?window=5Y
|
| Versus Yahoo! Finance doing the same: https://fin
| ance.yahoo.com/quote/F/chart?p=F#eyJpbnRlcnZhbCI6IndlZWsiLCJwZXJp
| b2RpY2l0eSI6MSwidGltZVVuaXQiOm51bGwsImNhbmRsZVdpZHRoIjo0LjM0ODY1O
| TAwMzgzMTQxNzUsImZsaXBwZWQiOmZhbHNlLCJ2b2x1bWVVbmRlcmxheSI6dHJ1ZS
| wiYWRqIjp0cnVlLCJjcm9zc2hhaXIiOnRydWUsImNoYXJ0VHlwZSI6ImxpbmUiLCJ
| leHRlbmRlZCI6ZmFsc2UsIm1hcmtldFNlc3Npb25zIjp7fSwiYWdncmVnYXRpb25U
| eXBlIjoib2hsYyIsImNoYXJ0U2NhbGUiOiJsaW5lYXIiLCJzdHVkaWVzIjp7IuKAj
| HZvbCB1bmRy4oCMIjp7InR5cGUiOiJ2b2wgdW5kciIsImlucHV0cyI6eyJpZCI6Iu
| KAjHZvbCB1bmRy4oCMIiwiZGlzcGxheSI6IuKAjHZvbCB1bmRy4oCMIn0sIm91dHB
| 1dHMiOnsiVXAgVm9sdW1lIjoiIzAwYjA2MSIsIkRvd24gVm9sdW1lIjoiI2ZmMzMz
| YSJ9LCJwYW5lbCI6ImNoYXJ0IiwicGFyYW1ldGVycyI6eyJ3aWR0aEZhY3RvciI6M
| C40NSwiY2hhcnROYW1lIjoiY2hhcnQifX19LCJwYW5lbHMiOnsiY2hhcnQiOnsicG
| VyY2VudCI6MSwiZGlzcGxheSI6IkYiLCJjaGFydE5hbWUiOiJjaGFydCIsImluZGV
| 4IjowLCJ5QXhpcyI6eyJuYW1lIjoiY2hhcnQiLCJwb3NpdGlvbiI6bnVsbH0sInlh
| eGlzTEhTIjpbXSwieWF4aXNSSFMiOlsiY2hhcnQiLCLigIx2b2wgdW5kcuKAjCJdf
| X0sInNldFNwYW4iOnsibXVsdGlwbGllciI6NSwiYmFzZSI6InllYXIiLCJwZXJpb2
| RpY2l0eSI6eyJwZXJpb2QiOjEsImludGVydmFsIjoid2VlayJ9fSwibGluZVdpZHR
| oIjoyLCJzdHJpcGVkQmFja2dyb3VuZCI6dHJ1ZSwiZXZlbnRzIjp0cnVlLCJjb2xv
| ciI6IiMwMDgxZjIiLCJzdHJpcGVkQmFja2dyb3VkIjp0cnVlLCJldmVudE1hcCI6e
| yJjb3Jwb3JhdGUiOnsiZGl2cyI6dHJ1ZSwic3BsaXRzIjp0cnVlfSwic2lnRGV2Ij
| p7fX0sImN1c3RvbVJhbmdlIjpudWxsLCJzeW1ib2xzIjpbeyJzeW1ib2wiOiJGIiw
| ic3ltYm9sT2JqZWN0Ijp7InN5bWJvbCI6IkYiLCJxdW90ZVR5cGUiOiJFUVVJVFki
| LCJleGNoYW5nZVRpbWVab25lIjoiQW1lcmljYS9OZXdfWW9yayJ9LCJwZXJpb2RpY
| 2l0eSI6MSwiaW50ZXJ2YWwiOiJ3ZWVrIiwidGltZVVuaXQiOm51bGwsInNldFNwYW
| 4iOnsibXVsdGlwbGllciI6NSwiYmFzZSI6InllYXIiLCJwZXJpb2RpY2l0eSI6eyJ
| wZXJpb2QiOjEsImludGVydmFsIjoid2VlayJ9fX1dfQ--
|
| In both examples, the only custom parameter is setting the time
| window to 5 years.
| BurningFrog wrote:
| The possible advantage of the encoding is that it that it can
| be encrypted and make parameter hacking impossible.
| PetahNZ wrote:
| You don't need to encode it to do that though. You can just
| sign the URL
| A4ET8a8uTh0 wrote:
| Harder. Not impossible. Harder. I don't want to make it sound
| like I am being disagreeable just for the sake of being
| disagreeable. If there is one thing the past decade has
| shown, it is that hacking is just a matter of time and
| whether a determined person is willing to direct resources at
| it.
| rsync wrote:
| I see you, and raise you:
|
| What if they encrypted the parameters _with a one-time pad_
| ?
| naasking wrote:
| One-time pads have to be stored server-side. If you're
| going to do that, you might as well just store the data
| itself under a GUID server-side so you avoid network
| transfers and then put the GUID in the URL.
| A4ET8a8uTh0 wrote:
| Hmm. Most likely ( if not only ) way to counter that
| would be social hacking ( because I assume the pad is
| generated automatically from some source ), which seems
| like the best way to obtain it. Then again.. I am not an
| expert in this field ( but we do sometimes use parameters
| from link for some projects ). Is it refreshed after some
| time passes ( if so, maybe there is an easier way to just
| observe what changes )?
| hot_gril wrote:
| Would have to do the signing server-side, predicated on the
| server checking the entire state to ensure validity. Such
| effort being put into preventing parameter-hacking would
| suggest there are serious vulnerabilities in that website.
| The URL is meant to be modified by the client.
| hot_gril wrote:
| > The URL is meant to be modified by the client.
|
| Clarification, the _human user_ probably won 't want to
| modify the URL, but the client will.
| thomasahle wrote:
| With something nice like the Google url, I would happily
| modify it myself.
| rattlesnakedave wrote:
| Yeah, why not just base64 encode, shove that into a db with a
| shorter key? I'm pretty positive this is how tiktok works for
| sharing videos.
| StevenNunez wrote:
| Probably don't want to pay for space for unauthed users.
| [deleted]
| [deleted]
| spullara wrote:
| Here is it decoded:
|
| {"interval":"week","periodicity":1,"timeUnit":null,"candleWidth
| ":4.3486590038314175,"flipped":false,"volumeUnderlay":true,"adj
| ":true,"crosshair":true,"chartType":"line","extended":false,"ma
| rketSessions":{},"aggregationType":"ohlc","chartScale":"linear"
| ,"studies":{" vol undr ":{"type":"vol undr","inputs":{"id":"
| vol undr ","display":" vol undr "},"outputs":{"Up
| Volume":"#00b061","Down Volume":"#ff333a"},"panel":"chart","par
| ameters":{"widthFactor":0.45,"chartName":"chart"}}},"panels":{"
| chart":{"percent":1,"display":"F","chartName":"chart","index":0
| ,"yAxis":{"name":"chart","position":null},"yaxisLHS":[],"yaxisR
| HS":["chart"," vol undr "]}},"setSpan":{"multiplier":5,"base":"
| year","periodicity":{"period":1,"interval":"week"}},"lineWidth"
| :2,"stripedBackground":true,"events":true,"color":"#0081f2","st
| ripedBackgroud":true,"eventMap":{"corporate":{"divs":true,"spli
| ts":true},"sigDev":{}},"customRange":null,"symbols":[{"symbol":
| "F","symbolObject":{"symbol":"F","quoteType":"EQUITY","exchange
| TimeZone":"America/New_York"},"periodicity":1,"interval":"week"
| ,"timeUnit":null,"setSpan":{"multiplier":5,"base":"year","perio
| dicity":{"period":1,"interval":"week"}}}]}
|
| I bet if they were more aggressive in using defaults it would
| be a lot smaller.
| a_c wrote:
| OT, we used to joke about LISP source code contains mostly
| brackets. Nowadays we literally store, transform and pass
| around willy nillily
| reaperducer wrote:
| _we used to joke about LISP source code contains mostly
| brackets._
|
| There was a programming language in the 1970's called SAM76
| that didn't care how many closing parentheses you had, as
| long as it was more than the number of opening parentheses.
|
| So, something like this was perfectly valid:
| a(1+r(em(2)))))))))))))))))))
| bboygravity wrote:
| That's genious IMO. Making sure the amount of opening and
| closing parantheses is equal is annoying and unnecesary.
|
| It screams "trust me all good with the closing
| parantheses".
| ajuc wrote:
| if ((v1.x()-v2.x())*(v1.x()-v2.x())+(v1.y()-v2.y())*(v1.y
| ())-v2.y())+(v1.z()-v2.z())*(v1.z()-v2.z()) >
| distance*distance) { // collision }
|
| Would you like this to fail to compile? Or would you
| prefer it to silently return the wrong value?
| matthewmacleod wrote:
| I'd prefer the compiler file an HR complaint against the
| author.
| tonmoy wrote:
| What if I wanted to copy that expression and use is as
| part of a different expression?
| andreareina wrote:
| paredit and rainbow parens makes it a non-issue for me.
| paledot wrote:
| I disagree. I would say when I get an unbalanced paren
| compiler error, it's more common for the omission to
| _not_ be at the end of the line. Having the compiler
| silently swallow the error would lead to serious bugs
| very quickly.
| NavinF wrote:
| Interactive prompts already do that. Eg if you google
| "2+2)*3" it will correctly print "12". This effectively
| lets you append operations to an expression without
| editing both sides.
|
| On the other hand, auto closing parentheses in code is a
| terrible idea for obvious reasons. There are only like 7
| languages used in industry and they all have excellent
| tooling that integrates with your editor to eliminate
| issues like this.
| lIl-IIIl wrote:
| Relevant xkcd: https://xkcd.com/859
| TeMPOraL wrote:
| I found that joke funny until I realized that, if you sum
| the count of round, square, angle and curly braces
| together, your typical piece of C++ or Java code has _more_
| brackets than equivalent piece of Lisp code...
| spullara wrote:
| Right, but having them all be the same is what people are
| joking about :) Although I might check the lisp/clojure
| vs java code on techempower or another rosetta stone like
| example.
| moring wrote:
| That, and the usual style of stacking all closing
| parentheses together at the end of the last line of a
| sub-expression / statement / whatever. People sometimes
| do this in Java and it's just as unreadable.
| User23 wrote:
| You read it by indentation not by counting parentheses.
| WorldMaker wrote:
| It's still very easy to make mistakes reading it that
| way. If you are reading it by indentation anyway you may
| as well use a parser that closes parentheses for you at
| indentation changes. (Like the ML family and Haskell and
| Python all decided to do.)
| User23 wrote:
| I don't find reading properly indented Lisp any harder
| than reading properly indented Python. I agree however
| with respect to having the tooling help with balancing
| delimiters, although I let the editor do that job instead
| of the parser. And that's one of the major advantages of
| Lisp. Structural editing is considerably easier to
| implement. Parinfer[1] for example is really cool. I have
| to say I'm really excited about tree-sitter allowing
| similar structural editing for harder to parse languages.
|
| [1] https://shaunlebron.github.io/parinfer/
| NavinF wrote:
| Well yeah that's a major reason why most programmers hate
| LISP syntax. It uses a parentheses for everything even
| though every keyboard has round, square, angle and curly
| braces.
| TeMPOraL wrote:
| I somehow doubt it. I tutored quite a few people of all
| ages who started to learn programming, mostly C, C++ and
| Java - they all initially have been mostly _confused_ by
| the different kinds of brackets. They quickly understood
| where the brackets go (scopes /blocks, function calls,
| array declarations and access, etc.), but took some time
| to internalize which bracket type is used in which
| context.
|
| I suspect the main reason programmers dislike Lisp syntax
| is that they try or see an example of some basic
| arithmetics, get surprised by the prefix notation that's
| so "unnatural" compared to the "obvious" infix notation
| they learned in primary school, and write off the entire
| language as weird, not noticing the fact that infix math
| is an exception in programming languages, as otherwise
| almost all code they write in any other language is in
| prefix notation too, just with a parenthesis shifted to
| the left.
|
| A somewhat mind-blowing observation to some people:
| (foo (bar baz quux)) foo(bar(baz, quux));
|
| The two lines above are _both_ in prefix notation. You
| can go from the first to the second one by a) shifting
| each left paren by one token to the right, and b) adding
| commas between whitespace-separated tokens.
| [deleted]
| xmprt wrote:
| I suppose beginner programmers might find all the
| different kinds of brackets in C++ confusing but after
| some experience, it helps a lot with readability. If I
| see `a[1]` then I know that `a` is probably an array. If
| I see `a(1)` then I know that `a` is probably a function.
| You could make the argument that those are terrible names
| for variables and methods and you'd be correct, but every
| small bit of context helps.
| moonchrome wrote:
| Clojure uses [] and {}, eg. : (defn fib
| [x, n] (if (< (count x) n) (fib (conj
| x (+ (last x) (nth x (- (count x) 2)))) n) x))
| hk__2 wrote:
| Speaking about LISP and state in the URL, this is how OVH
| stores the state when you buy a domain from them:
| https://www.ovh.com/fr/order/webcloud/?#/webCloud/domain/op
| tions?selection=~(domains~(list~(~(name~'somethinghn.com))~
| options~(~'dnssec)))
| TeMPOraL wrote:
| That's Clojure's EDN encoded for ClojureScript isn't it?
| I recognize this syntax from briefly working on a
| CLJ/CLJS app.
| bsima wrote:
| Nope, edn uses square brackets and doesn't have a `list`
| keyword. This is some custom representation.
|
| Probably written in Common Lisp? Based on some quick
| searching I found this reference
| https://docs.ovh.com/us/en/web-paas/languages-lisp/
| mattpallissard wrote:
| Or it could just be that s expressions are easy to parse.
| _fat_santa wrote:
| I suspect it's probably a global library that handles this.
| So refactoring it in one place would be difficult. If I had
| to guess their implementation looks something like this.
|
| SomeUrlService.pushState(JSON.stringify({ foo: 'bar' }));
|
| SomeUrlService.navigate('/some/url/here')
|
| Likely, that "SomeUrlService" is also tacking on plenty of
| other shit to the URL that is passed along. I don't work for
| Yahoo and never have, so this is all pure speculation.
| spullara wrote:
| Having worked there years and years ago, I doubt it. All
| those parameters look like chart parameters to me, probably
| local to Y! Finance.
| Altho00 wrote:
| What is the point of the encoding ? Is it obfuscation for the
| common user ? What's wrong with http://
| url.com/api/?interval=week&periodicity=1... since the encoded
| version is not shorter.
| rocho wrote:
| They have a nested structure, it's a pain to encode that in
| query parameters.
| deelly wrote:
| > What is the point of the encoding ?
|
| Absence of special characters. No need to escape symbols
| like {}:/\?& etc, etc.
| ninjanomnom wrote:
| Encoding isn't usually to obscure but to allow using
| characters not allowed in a URL or wherever text is being
| stored. This makes it a bit easier to directly take that
| encoded text later and decode it into something like json.
| [deleted]
| [deleted]
| galaxyLogic wrote:
| Right no need to put it all in the URL, it could be just a
| random key pointing to local storage for instance, if not some
| cloud database.
| thunky wrote:
| If it points to local storage then it's not shareable.
|
| If it points to a cloud database then you need a cloud
| database to do what a url could do.
| galaxyLogic wrote:
| Good point
| [deleted]
| hot_gril wrote:
| I decoded that, gzipped --best, then re-encoded and got
| something that's shorter at least
|
| H4sIAAAAAAACA7VU3W7TMBS+5ykmcxuNdOlGyd3QmECCIdYWNKYKnSanqVfHNrb
| TNqoq7QF4Sp6EYyfpaMYtdz7H5/vOz3fsHePSoVmDYCnbIK5YxDQarnKecVezdB
| Axx0ucSu5YKishIpaBzAV+47lbsnR4mgxHF+dv4jgZJYPh4PV5xBaCa405SxcgL
| EZsrUTlKXI0AojTmYq8kD90x8woa5fAzcGxBOMmtUaqSnCJVBVuHRLDE2sJZoVu
| jNZyJS1Ld3viLAqDBTjytGi1FBlrCccZiI4RDHmtq3KOHst+P/6iMk8qmRs6eo9
| rCDovhXOpKxeiOZXRh0Qs51aHBvtXVJmqXAee6pOvYSIU+DKO5/HFgMBXaiP/8i
| 8WSZKAR2qQ6NUJLXh5wECJJFog23gZriFzioYXnw7P215vIPA0oP2+4wmYxkkHU
| jpD6YLKT8Vfs39x+PZz3FKSiNWXWx6Y5HGEVpb72TebQjlroMCP78csvZ+11m2w
| DpDepGa+UkuyUrU+QVkJx7XgSN1Ra3OwPl/dyHe0qLvWDM30l9qzetXbpT3z0ht
| OO/oWslVhFKXvVg/XNBF7WEQl/GC9TqPB4ow9Ax7jPoEOA1ZGKwMOvZHz9YGORs
| w7ct8oL65w7VeXjKyyTpW3IAvsXpqty7nymt3v2nMrT2N8nj9gFoQ8uvxZKYft+
| r/7Mv0wuQvPhyZO1BN6zN+V9HeXJQ0sg1c3uPlxp8wqLFvv7T//Hfq/wf8Qaz/b
| v/gDbvc6N5oEAAA=
| [deleted]
| dyno12345 wrote:
| you could come up with a better compression scheme given that
| the dict keys and many of the values are probably common
| across everyone even if they don't repeat multiple times for
| a given user. a lot of flexibility would be lost though, and
| you would need to always update the scheme in a backwards-
| compatible way.
| mikepurvis wrote:
| Once you've already given up on human-readability, it
| probably doesn't much matter how long/gross the result is.
| Rather than spending effort and adding complexity, just
| provide a built in URL shortener.
| hot_gril wrote:
| I agree, same reason people use json in the first place
| despite the inefficiency, it's easier.
| wtetzner wrote:
| Well, there are limits to the lengths of URLs in much of
| the internet's infrastructure, so better compression
| could still be useful.
| jsvaughan wrote:
| This is the critical point to make. Paste a few long
| texts into the boxes and the url goes into the hundreds
| of thousands of characters long, whereas this says that
| anything more than about 2000 chars puts you into
| uncertain territory:
|
| https://stackoverflow.com/questions/417142/what-is-the-
| maxim...
| p1necone wrote:
| Isn't storing state in urls and then using a url
| shortener just a key/value store with extra steps?
| taneq wrote:
| But with added session id energy too!
| mikepurvis wrote:
| True, though I think the differences around shareability
| matter-- a mapping-table entry is immutable, whereas even
| a non-logged-in session token is probably not.
| hot_gril wrote:
| Could start with a smaller encoding. Use single-length
| keys, or better yet use protocol buffers or even ASN1.
| That's similar to taking advantage of common key names.
| waynesonfire wrote:
| would it be feasible to include the compression dictionary
| along w/ the data? And, maybe just send it once on the
| initial request and store it on the client?
| gnramires wrote:
| > would it be feasible to include the compression
| dictionary along w/ the data
|
| In theoretical terms (in particular Kolmogorov-complexity
| perspective), I believe the inclusion of a dictionary
| wouldn't help, it would strictly increase size. It can
| help (specially from a Shannon information perspective)
| if the compression is too computationally demanding to
| build the data model (which is kind of what all
| compressors do); but it almost certainly doesn't help in
| the case of something as small as an URL. But then it's
| possible to just pack a common compressor with the
| website (and just refer to it with a version code).
|
| I think the web in general would benefit greatly from
| some kind of standard compression libraries. Compression
| tends to have a significant cold start cost to work well,
| if that were mitigated certainly something like an url
| could be far shorter.
|
| I believe HTTP2 has header compression (RFC 7541)[1] with
| 'static tables', which seems to be a form of dictionary,
| but surprisingly to me no html compression with such
| shared dictionaries. There is caching libraries
| (unfortunately cross-domain caching seems to be
| deprecated[2] due to security concerns) I believe which
| helps in other ways, but I think a true dictionary-style
| compressor would bring huge bandwidth savings.
|
| Major web entities should get together to develop those
| standard dictionaries (and which algorithms to use them
| with), so they are reasonably fair for everyone (maybe
| even language specific dictionaries should be used).
|
| Security seems indeed a concern, but I think the key
| would be carefully preventing that a content were decoded
| with the incorrect dictionary (meaning the server could
| serve a different web page than the standard
| decompression) -- but overall it doesn't seem like a big
| issue (similar to cache, less problematic than cross-
| domain caching).
|
| In the future maybe even one of those fancy neural
| network (or otherwise machine learning inspired) methods
| could be an option, specially useful for highly bandwidth
| constrained like rural or satellite internet (although of
| course performance is always a priority with mobile
| devices being major users).
|
| [1] https://httpwg.org/specs/rfc7541.html#static.table.de
| finitio...
|
| [2] https://www.stefanjudis.com/notes/say-goodbye-to-
| resource-ca... Is this still accurate?
| WorldMaker wrote:
| > I believe HTTP2 has header compression (RFC 7541)[1]
| with 'static tables', which seems to be a form of
| dictionary, but surprisingly to me no html compression
| with such shared dictionaries.
|
| To my understanding, that static table in HTTP2 is
| directly in context of recommending and discussing Brotli
| compression, which does use a table like that as a
| standard static dictionary in HTTP2+ scenarios including
| other static dictionary inclusions derived from a corpus
| of HTML documents.
|
| https://en.wikipedia.org/wiki/Brotli
| gnramires wrote:
| > would benefit greatly from some kind of standard
| compression libraries
|
| Correction: standard compression dictionaries
| itssumitrai wrote:
| In this case, its actually required. The state is actually for
| the entire chart. It has lots of settings not just the time
| duration but type of chart, crosshair should be set or not,
| then there are several types of chart studies which could be
| applied on chart along with their own settings. And also the
| chart drawings with their own settings. This feature is there
| so that people can share their own customized chart in full
| with others, and not a generalized chart.
| thunderbong wrote:
| I used to obsess over URLs as well, until the day I realised
| that there's no web page with the URL gmail.com!
| michaelmior wrote:
| In your example, absolutely the first URL is better. But if as
| in the case of the OP, you're trying to encode an entire
| flowchart, I would argue it's a bit of a pointless exercise.
| Maybe you could come up with something reasonably readable, but
| I don't think anyone would care. It really depends on what kind
| of state you need to store.
| pifm_guy wrote:
| A flowchart can be encoded as simply the name of the state
| you're currently in.
| wildrhythms wrote:
| How would you predefine a state to include the flowchart
| nodes that the user creates?
| michaelmior wrote:
| How do you know what all the other states in the chart are
| and how they are connected?
| moffkalast wrote:
| Whoever needs to copy that long intestine of a url definitely
| cares.
| michaelmior wrote:
| If you can shorten the URL, sure. But if data stored in the
| URL means it needs to be incredibly long, I don't think
| most users care whether it's readable or not. Of course, at
| a certain length, it's worth reconsidering whether storing
| all the data in the URL is a good idea.
| __derek__ wrote:
| In a similar vein, I've long been a fan of Kayak's URL
| structure.[1]
|
| [1]: https://www.kayak.com/flights/SEA-
| IND/2023-01-10/2023-01-14?...
| thewisenerd wrote:
| ah, azure does the same for generating the "share" URL for
| their cost dashboards.
|
| it additionally gzip's the data to compress it futher, with..
| some savings..
|
| in the above example you've shared, gzip would've,
| orig=1177 base64=1572 gzip(orig)|base64=768
| OOPMan wrote:
| I feel like you're ignoring the context of the linked post
| while also trotting out the most obvious comparison of all
| times.
| orasis wrote:
| Another reason to not base64 encode is that many URLs with
| base64 strings will break in iMessage do to strings randomly
| matching various keywords that iMessage looks for. I think
| 'usd' is one such substring to look out for.
| secondcoming wrote:
| Surely that's something that Apple should fix, rather than
| everyone else working around it?
| hk__2 wrote:
| Yes, but even if Apple fixes it, you still have to deal
| with old devices. Better have something that works
| everywhere rather than "this website is optimized for
| IE/Chrome".
| depressedpanda wrote:
| This isn't at all comparable. It's purely an Apple
| problem.
| slivanes wrote:
| base64 does not have the problem here, iMessage has.
| Frustrating.
| jimbokun wrote:
| Agreed, iMessage should have URL detection that supersedes
| any other string parsing.
| 71bw wrote:
| The fault doesn't lie in iMessage, it lies in Apple in
| general. Google's AOSP keyboard will IMMEDIATELY detect
| that you are writing a link when you'll put http(s):// in
| front of whatever else you're currently writing and will
| just shut up and let you finish without interrupting
| every 2 seconds with autocorrection suggestions. This
| does not happen on Apple's i(Pad/O)S keyboard, where
| typing a link will usually leave the user with an
| excercise in frustration, trying to fight over the
| autocorrection, which, for the 17th time, has decided to
| convert your URL into "normal words". Not even changing
| the keyboard seems to fix it, as, from what I remember,
| Gboard still uses Apple's prediction engine...
| nanidin wrote:
| Curious if English is your mother tongue, and if so, which
| locale?
|
| As a native speaker of en-US, I would write this as "base64
| does not have the problem here, iMessage does."
| elteto wrote:
| Right before I was forked my parent did "export LC_ALL=C"
| and here I am.
| slivanes wrote:
| Originally en-AU. I was trying to match the "have" with a
| "has". My sentence has a truncated " the problem" in my
| head.
|
| Your version reads more correct, thanks for pointing it
| out.
| hot_gril wrote:
| I think the other params are custom too. There's probably other
| state not being stored in that URL. If users want to send
| charts to each other and have them show up the same, this
| actually seems like a reasonable way to do it.
| voidmain0001 wrote:
| Pass that super duper long Yahoo URL to Tinyurl and shrink it
| down to https://tinyurl.com/bdfepwar
|
| It seems like storing state in the URL could benefit from URL
| shortening techniques so long as the secret sauce logic is both
| client and server side.
| stnmtn wrote:
| This loses all the benefits of storing all state in the url,
| which is that it's inspectable by the client. Using a URL
| shortener still makes all the data stored somewhere in the
| server
| voidmain0001 wrote:
| Okay that's not exactly what I had in mind. My suggestion
| was to implement the same hash both server and client side
| so that the query string is small and manageable. Don't
| worry about the state not being fully legible because you
| will implement the hash decode on the client too. The code
| will be there for you to peruse.
| voidmain0001 wrote:
| I've lost my mind. I literally just implemented a
| dictionary web API the other week and have completely
| forgotten how I did it. Just forget what I wrote.
| vikramkr wrote:
| How would you decode the hash? Amy of infinite states
| could map to the hash
| lsaferite wrote:
| The primary benefit of storing all the state in the URL is
| that the server can be stateless. Using a shortener just
| moves the state to a different server. A user being able to
| inspect the state is just a side benefit.
| anshumankmr wrote:
| >
| https://finance.yahoo.com/quote/F/chart?p=F#eyJpbnRlcnZhbCI6...
|
| Dear god... this link was real. I thought it was like a joke or
| something
| PUSH_AX wrote:
| Genuinely curious to hear why you are so shocked. Long, ugly,
| user unfriendly urls are really prevalent. Arguments can be
| made even query params are pretty ugly.. Are urls expected to
| be a good UX these days? What's the big deal?
| pacifika wrote:
| Pipe that into bash (ie: the user doesn't know if they're
| loading malicious state)
| hunter2_ wrote:
| I don't think people care so much about a messy address bar
| as a messy chat/email message after pasting a URL.
| Shorteners and vanity URLs exist, but that's more friction
| than just copying from the address bar as-is.
|
| This can be overcome with html, markdown, and other rich
| text formats that let you specify the visible link text
| (missing from many chat apps*), but that's also friction to
| compose compared to automatically linking from just a URL.
|
| *Slack's implementation is awesome: type the link text,
| highlight it, and paste a URL.
| owl57 wrote:
| It's not even only about messiness.
| "https://news.ycombinator.com/item?id=34315441" isn't
| some horrible long base64, but it's not a good UX either:
| when you paste it in a messenger, or in your notes, by
| default the reader can't tell what's it about without
| clicking.
|
| _> *Slack 's implementation is awesome: type the link
| text, highlight it, and paste a URL._
|
| Yes! Matches my vision of hypertext perfectly: I usually
| type a message in normal human language and then paste
| links all over it for the reader who needs to dig deeper.
| TheBrokenRail wrote:
| > by default the reader can't tell what's it about
| without clicking.
|
| Most chat apps like Discord will automatically include an
| embed generated from a URL's metadata when present in a
| message.
| owl57 wrote:
| At least in Telegram, this works for at most one link per
| message, and quickly fills the screen if you send
| multiple such messages.
|
| And I believe that there is no standard API to get
| previews of non-public websites in a work chat, you need
| to develop site-specific bots or something like that?
| WorldMaker wrote:
| There is a standard for this. It's called oEmbed:
| https://oembed.com/
|
| The chat host still likely needs access to the "non-
| public website" to discover and call its oEmbed API, so
| that's something you'd have to figure out, but any
| website anywhere can offer oEmbed metadata if it wishes.
| hunter2_ wrote:
| > previews of non-public websites
|
| It would be interesting if browsers / OSes / apps offered
| a way to use the browser's cookie jar / basic auth
| headers / whatever sessioning scheme in whatever apps the
| user decides should display authenticated previews. Ask
| the user to allow the release of browser data scoped to
| the domains that the app suggests. Similar to how some
| Android apps can put up a prompt to release a Chrome-
| saved password to an app (which I _really_ wish more apps
| would include).
| gdprrrr wrote:
| Plesse no
| withinboredom wrote:
| I just include a screenshot. It's not that hard.
| OJFord wrote:
| > I don't think people care so much about a messy address
| bar as a messy chat/email message after pasting a URL.
|
| But it's painful how few care about that!
|
| I always clean them up before I send them (just manually
| - typically meaning all query parameters, e.g. with
| Amazon the text description after the actual ID) rarely
| even feel the need to check they still work, it's pretty
| easy, but maybe I shouldn't bother because it's only me
| that cares; they don't seem to notice that their links
| occupy half the screen and my don't!
| munk-a wrote:
| Just because a thing is prevalent doesn't mean it's good. I
| have a hard time believing all those parameters are
| completely necessary for the amount of data being
| displayed. Often times it feels like people just
| base64encode(page.state) and call it a day.
|
| I think it's advantageous to keep the complexity and
| specificity of information in URLs to a minimum outside of
| what's needed to retrieve the data set as it can make
| backwards compatibility easier - it is valuable (for long
| lasting tools) to have URLs that users can favorite and
| share for their common searches.
| PUSH_AX wrote:
| > Just because a thing is prevalent doesn't mean it's
| good.
|
| I agree with this sentiment. I'm not sure I've ever seen
| a url referred to as "good", I was just a bit confused as
| to why someone would baulk at a URL. In my opinion
| everything after the host portion of the url is to serve
| the apps needs, so it knows where to go or what to do,
| it's not _really_ an interface for the user as obviously
| there are better ways to present that.
| ben0x539 wrote:
| The point of a URL is that I can copy+paste it into IRC
| so my friends can look at the thing I want to share with
| them.
|
| If the URL has a bunch of goop in it, people are going to
| make fun of me for it, especially if it's super long and
| doesn't fit in a single line. Or if there's stuff in
| there that's specific to me and not the thing I want to
| show them.
| depressedpanda wrote:
| Where I work, we consider URLs part of the UI. Users
| should be able to share links with each other without
| pasting a wall of text. We also try to make all URLs
| human parsable so that they know what they are sharing.
| MereInterest wrote:
| I'd say everything after the host is part of the UX, and
| should serve the user needs. For example:
|
| * Should be book-markable.
|
| * If searching with a query, should have a clear query
| parameter for ease of browser integration.
|
| * If the URL contains slash dividers that can be read as
| categories (e.g.
| storefront.com/department/category/product), then
| deleting everything after a given slash should go to that
| category's page.
|
| * The link should be short enough to be sent over a
| plain-text conversation without becoming a wall of text.
|
| * The link should be short enough that it cannot hide a
| malicious subdomain (e.g.
| Google.com.flights.malicio.us/more/elements).
| hinkley wrote:
| * I should be able to guess if you're sending me a link
| about composting or a Rick Astley video
|
| Opaque slugs are problematic in a low-trust world.
| Phishing attempts are easier when the parameters are
| indecipherable. I'm not clicking on that shit in a text
| message or an email. I've seen what happens to people
| when they do.
| pixl97 wrote:
| Eh, I mean URL shorteners are a thing and all kind of
| things redirect on the web. The length of the URL doesn't
| really tell you much.
| TeMPOraL wrote:
| URL shorteners are a menace. I'm not clicking on the link
| if you send me a shortened one, especially not when on
| mobile. These days, shortened links have two primary
| applications: forcing you to go through a
| tracking/analytics gate, and serving single-click
| exploits. Neither of those is serving the user (unless
| you read it in "To Serve Man" sense).
| whatusername wrote:
| No - but they have been referred to as "cool" before.
| Gotta love the early 90's.
|
| https://www.w3.org/Provider/Style/URI
| bbarnett wrote:
| I can say that many, many times, I have zoomed in, picked
| date ranges, added options, then pasted the yahoo finance
| url to others... and they have all those same configs
| passed.
|
| It's _awesome_ and incredibly handy.
|
| Yahoo is on the ball here.
| tempestn wrote:
| Agreed. However they could still simplify the urls a ton
| by including only non-default parameters, and still
| achieve the same thing.
| itssumitrai wrote:
| Everything in chart is customizable, so no, its not
| possible to achieve the same thing in the way you are
| saying
| dncornholio wrote:
| And what problem does this solve? Hint, it doesn't. Long
| URL is ugly but who cares. Life is too short. Nice or
| ugly is relative. It stops nobody from using the tool or
| sharing links. It's a non-problem really.
| anshumankmr wrote:
| I Just like to keep query params simple and readable. I
| understand the possible use case for this obfuscated url
| which would make it difficult to scrape the site
| xwdv wrote:
| [flagged]
| anotheraccount9 wrote:
| A horse walks into a bar.
|
| Several of the patrons quickly get up and leave, realizing
| the potential danger in the situation.
| TeMPOraL wrote:
| Since I wasn't sure whether it's meant literally or if
| I'm missing some context, I decided to do a web search
| with this joke as a query, and was rewarded with a
| recording of it (apparently) playing out in real life:
|
| https://old.reddit.com/r/gamegrumps/comments/9kgeqg/a_hor
| se_...
| dhosek wrote:
| A priest, a rabbi and a minister walk into a bar.
|
| The bartender say, "What is this, a joke or something?"
| dspillett wrote:
| A priest, a rabbit, and a minister, walk into a blood
| donation clinic. The rabbit says "I think I might be a
| type-o".
| TedDoesntTalk wrote:
| Thank you for posting a joke to HN. Thank you for making
| me laugh today.
| nullsense wrote:
| This has to be my favorite version I've ever heard.
| BlueNorth wrote:
| There are different languages. The jokes are symptomatic of
| the differences. I'm not Indian but English is laughable
| for many good reasons. Without damage...
| scott_s wrote:
| There are. We just have a high bar. I wrote this, but
| others have also pointed to it:
| https://news.ycombinator.com/item?id=7609289
| 2ICofafireteam wrote:
| I did once and was told off for adding noise to the
| discussion by someone who didn't see the irony of their
| complaint also adding to the noise.
| xwdv wrote:
| For many HN, telling someone off for making a joke isn't
| noise but rather music to their ears.
| macintux wrote:
| If a one-time correction has its desired impact, the
| small addition to the noise reduces future noise.
| ant6n wrote:
| This is some sort of meta joke, right?
| throw10920 wrote:
| It's not, and it's pretty clearly true.
|
| The idea that "complaints about people violating the HN
| norms is somehow comparable to violating the norms" is
| trivially wrong if one thinks about it for more than a
| few seconds.
| munk-a wrote:
| Why are you assuming they work in FAANG?
| gerdesj wrote:
| There's no M in FAANG ...
| 2ICofafireteam wrote:
| Presumably.
| anotheraccount9 wrote:
| Two chemists walk into a bar. The first says "I'll take a
| glass of H2O." The second says "I'll take a glass of H2O
| too."
| valvar wrote:
| Oh no...
| sva_ wrote:
| [dead]
| [deleted]
| anon223345 wrote:
| I saw a $12 million app have to be essentially rewritten (at a
| bank)
|
| The "genius dev lead who went to Princeton" kept pushing that
| they went to Princeton so people stopped arguing against it
|
| Tried to do this securely and got pwned in the very first demo
| winrid wrote:
| I mean, they got pwned because they didn't validate the state
| against the current user's session. Not because storing state
| in the URL is insecure.
| forgotusername6 wrote:
| How can you secure state stored in the URL?
| winrid wrote:
| You don't. You secure the resources the state accesses.
| didericis wrote:
| If you're validating client url state against server session
| state that kind of defeats the purpose of trying to put _all_
| the state in the url.
|
| You're technically correct/sounds like you agree it's still a
| bad idea, even if there's a way to duplicate certain state
| for validation and make it work. Staying shackled to the
| earth via stupid rules of thumb like minimizing client state
| in banking apps does keep you from flying straight into the
| sun, though, which is nice.
| a-dub wrote:
| doing something like this means you have to pay attention to a
| few things:
|
| * back/forward button behavior
|
| * cache behavior
|
| * bookmarks over time
|
| surprising there's no discussion of it.
| barbazoo wrote:
| > Another great benefit is that these urls can be embedded. That
| means the user can put their graph on any ewb page that supports
| embedding. I see people typically do this with wikis like Notion,
| which means you can share with a team
|
| This is so valuable that it can't be overstated. Being able to
| store the raw data in a link WITH the visual representation,
| you'll never struggle trying to find out who has the latest
| version.
| wildrhythms wrote:
| Bingo. I use this all the time to let users pass
| preconfigurations of internal tools back and forth. These are
| tools that live on the client and don't have a backend. The
| downside is my users complain about 'long/ugly links' which is
| another problem...
| ecshafer wrote:
| What is old is new again.
|
| Back before websites were "Apps", you could often do exactly this
| (Including Authentication!) right from the url.
| Zamicol wrote:
| Before cookies, I remember in middle school (ebay?) using the
| URLs for sessions.
|
| If they forgot to include the session token on any link on the
| page, you'd be logged out and have to authenticate again, or
| you could navigate backwards back to a sessioned address in
| your history. Once I figured that out, I copy and pasted my
| session id so if they omitted the session on a link I wouldn't
| have to log in again.
| ceritium wrote:
| I did the same for https://markdowntable.jose.gr
|
| As some comments suggest, I will move the data from the query
| string to the URI fragment to avoid the length limitation.
| zX41ZdbW wrote:
| I'm successfully* using it in a few personal projects:
|
| ClickHouse Playground:
| https://play.clickhouse.com/play?user=play#U0VMRUNUIDE=
| ClickHouse Dashboards:
| https://sql.clickhouse.com/dashboard#eyJob3N0IjoiaHR0cHM6Ly9...
|
| The second example shows you why it is not an entirely good idea.
| The second link cannot be posted in Slack and Google Meet, so I
| have to use an URL shortener...
|
| Luckily I have it in my disposal: https://pastila.nl/ Example:
| https://pastila.nl/?02a0d469/8f49f7e4406bd4fbc0e7b142c470dfb...
| devmunchies wrote:
| Seems like it could be better to store the state in a database
| and create a unique, short ID that goes in the URL, especially if
| your doing server rendering (like SSR react or HTMX, or
| rails/Django)
|
| > I also didn't want to store anything on the backend (at least
| for the free tier).
|
| You can make the state unique in the DB by a user cookie ID and
| then upsert the state which will overwrite older state with the
| latest state. Then you only have 1 record per free user. Remove
| record that haven't been modified in 30 days and you don't have
| much overhead. Just off the cuff thinking.
| jonny_eh wrote:
| > You can make the state unique in the DB by a user cookie ID
|
| https://gdpr-info.eu/
| ErrantX wrote:
| I am genuinely intrigued as to why that's better?
|
| Especially as in the second part of your comment you restrict
| shareability/usability significantly from what the author wants
| to achieve (IE I can't as a free user bash out a diagram and
| share it, then later do another and share with a different
| person).
|
| In fact the solution is so elegant when you think on it; free
| account volume is incredibly scalable, zero storage cost, offer
| immediate value but also a really simple upsell to pro accounts
| (save to the DB so you don't have to save the URls).
| devmunchies wrote:
| > Especially as in the second part of your comment you
| restrict shareability/usability significantly
|
| no it doesn't. If my URL is `/thing#a1234` and I share it
| with you it will load my state for you. If you make a change,
| it's easy to push a new hash to the url that belongs to you.
|
| > I am genuinely intrigued as to why that's better?
|
| I didn't say it was better. We engineers are supposed to
| discuss solutions. I ended my last comment with "Just off the
| cuff thinking".
| kamikaz1k wrote:
| not my fight, but you literally wrote:
|
| > Seems like it could be better
|
| Maybe you didn't mean it that way, but it does come across
| that way. Just a data point for you; I got no beef...
| devmunchies wrote:
| oh I guess I did. thanks. should have said "I wonder if
| its better".
| tresilience wrote:
| This brings to mind the concept of continuation found in Seaside
| Smalltalk.
|
| https://www.seaside.st
| surume wrote:
| Just thinking - are there any security implications to this?
| Could sensitive data accidentally get added to the URL and then
| get intercepted?
| yurishimo wrote:
| Sure, but then I think most people would argue that you
| shouldn't store any of that state in the URL. It definitely is
| not a panacea.
| MutableLambda wrote:
| But it was done already in widely known in narrow circles
| PlantUML years ago?
| nojvek wrote:
| Shameless plug: I made a library to encode any json as query/hash
| params in a human readable manner adhering to url friendly
| characters.
|
| https://github.com/recurrency/urltron
|
| Perfect use case for storing page state in url.
| mguerville wrote:
| Isn't this also how old school games (I've seen it as late as the
| NES I think) did allow you to save progress, you'd get a short
| string as your "save" and could just enter it to restart the game
| in the same state later. I love that it offers essentially
| unlimited "saves"
| jonny_eh wrote:
| Great YouTube channel about reverse engineering old game
| password systems:
| https://www.youtube.com/playlist?list=PLzLzYGEbdY5nEFQsxzFan...
| colejohnson66 wrote:
| The downside of a lot of those "password" save systems was that
| you lost your lives, and sometimes more. The password sometimes
| just wasn't long enough to store enough information. For
| example, Driver[0] (at least on the Game Boy) is an icon-based
| one with eight(?) symbols per field and four fields. That's
| only 12 bits.
|
| [0]: https://en.wikipedia.org/wiki/Driver_(video_game)
| hot_gril wrote:
| And you can use your save on another system.
| [deleted]
| amadeuspagel wrote:
| How much of a concern is the length of the URL? It doesn't matter
| for bookmarks, but what about sharing? Character limits, or even
| just the unwieldiness of long URLs in a textarea?
| redbar0n wrote:
| > Since I update it on every graph edit, I get something major
| for free -- undo/redo. The browser's history stack becomes my
| undo/redo functionality.
|
| A pet peeve of mine is that webapps shouldn't hijack the browsers
| default functionality, here being back/forward that should refer
| to pages, not mutations of the same page.
|
| Ideally, one would have a separate undo/redo button on the page
| for page or url mutations (which should always be in sync). But
| mutating the URL shouldn't be done by pushing to the browser
| history stack, or if pushing one ought to remember to pop the
| current entry first so the result is a single mutated page on the
| history stack.
| [deleted]
| bmalicoat wrote:
| I love stuff like this. Around 2008 or so I was working on a Java
| game for the T-Mobile Sidekick (aka hiptop). The platform let you
| register url scheme handlers so I registered "drod" (the game was
| a from-scratch port of Deadly Rooms of Death, a classic shareware
| game). Since the game was a 16x16 grid-based game with 3 layers,
| it was super efficient at expressing levels, including monsters
| and locks and keys, with just a limited number of bits. On my
| website I had "DLC" in the form of drod://[base64 encoded level
| here]. It always filled me with joy that users already downloaded
| the levels when they navigated to the website. Clicking the link
| just opened the game with the data they already had on their
| device.
| EGreg wrote:
| On a related note ...
|
| If you don't want to store anything on the server, why serve the
| static JS and HTML? You can embed them in the URL also.
|
| In that cass the URL just becomes a local file.
|
| You should store the file locally, along with all the data it
| embeds.
|
| Or you can store the files on a CDN at the edge. The problem with
| the latter is that people can abuse the storage.
|
| Really, the Web needs to be overhauled to have a topology more
| like a DHT, where you only have peering agreements with a few
| peers, and they cache the content temporarily when it is
| requested a lot. So no centralized servers at all.
| redleader55 wrote:
| A better idea is to use the URI fragment (the string after the #
| sign). It has the advantage of not having a size limit, and not
| needing to be sent all to the backend during the request.
| `window.location.hash` is your friend.
| escot wrote:
| This is a great point, but also depends on what browsers you
| want to support. In my experience some browsers a) will
| truncate the url when you try to copy it from the browser bar
| (safari), and b) will not support any url including the hash
| past a certain cut off (like the SO comment states).
| escot wrote:
| I just updated knotend to use the hashmark, see my comment
| above!
| rcme wrote:
| Sometimes you might want the state on the backend, e.g. to
| generate open-graph metadata tags.
| culi wrote:
| well you don't have to store _ALL_ of your data this way.
| Also you can always just choose to send it to the backend
| still with a POST
| escot wrote:
| I just updated knotend so that it now uses the hashmark. I
| think this is a great idea, and it just loses the ability to
| get the urls server side, which in my case is totally fine. I
| also updated the blog post and acknowledged your comment, so
| thank you!
| Zamicol wrote:
| I wrote a library based on that very idea. It supports fragment
| query, just like normal queries.
|
| https://github.com/Cyphrme/URLFormJS
|
| I use it in a lot of places, like:
| https://convert.zamicol.com/#?inAlph=Text&in=Hello%20world!&...
|
| https://cyphr.me/ed25519_applet/ed.html#?msg=Hello%20World!&...
|
| https://cyphr.me/coze#?verify&input={%22pay%22:{%22root%22:%...
| TedDoesntTalk wrote:
| How to use this in React?
| no_wizard wrote:
| I don't think React has anything to do with it. Its just
| structuring URLs in the browser an appropriate way.
|
| You'd need to read state off the url fragment
| (location.hash). You can feed that into your appropriate
| state management system, I suppose. Some (like react
| router) I think support hash routing, but I don't know that
| they support both has routing and history routing at the
| same time, so that may not be quite up to task if thats the
| case.
| thedougd wrote:
| https://app.diagrams.net/ has an excellent example of this.
| File > Export As > URL...
| kishinmanglani wrote:
| That's really interesting. Do you have any idea how much data
| (i.e. max amount of json) you can store using something like
| that?
| bckygldstn wrote:
| It seems to vary greatly by browser. Based on this SO answer
| [1] MS edge only supported 2000 characters in 2017, while
| Chrome currently handles 40 million characters (of
| compressed, encoded json).
|
| [1] https://stackoverflow.com/a/44532746
| G3rn0ti wrote:
| Weirdly, with IEs it was exactly 2083 characters (1) not
| some base 2 number and MS never increased this number over
| all these years. This upper limit even included fragments.
| We tried to do something similar as described in the
| article and were surprised to learn about IEs limitation.
| In the end, we stored states on a JS object instead using
| their hash sum as keys and put that inside the fragment.
| Then fragment based navigation worked like charm across
| browsers.
|
| (1) https://support.microsoft.com/en-us/topic/maximum-url-
| length...
| refulgentis wrote:
| I don't quite understand and it's on me, trust me :)
|
| My reading is you were worried about length of encoding
| one state, so you moved to encapsulating states in a
| dictionary with keys of hash of State and objects of
| State
|
| And this led to a decrease in size of the URL?
|
| My guess at my misunderstanding: you kept the state
| dictionary server-side or at least some other storage
| method than the URL, and just used the URL to identify
| which state to use from the dictionary. I e. The bit you
| add to the URL is just the hash of the state, or
| dictionary key
| G3rn0ti wrote:
| Yes, in the final solution we just stored a hash sum
| inside the URL fragment (I think it was an MD5 sum) and
| the actual state inside a JS object in main memory. With
| a page reload you lost all states which was fine for us
| but you could use session storage to avoid that.
| TedDoesntTalk wrote:
| > were surprised to learn about IEs limitation
|
| IE was all about limitations Nothing surprised me about
| IE limitations.
| opportune wrote:
| Be careful with this. This is only supposed to be used on the
| client side. Many HTTP server implementations (and
| infrastructure you run on) will not let you use the URI
| fragment even if it does hit the wire, or things like caching
| will break - you almost certainly want use query parameters for
| anything backend related
| madeofpalk wrote:
| URI fragments being client side are entirely their point.
| _Clients_ should never send them to the server.
| TheRealPomax wrote:
| If you have so many parameters that you need a URL that's over
| 2048 characters, you should probably be reminded that
| localStorage exists.
| kelnos wrote:
| Using local storage means that you can't share a flowchart
| with someone else (or embed one in another page) at all, let
| alone easily.
| TheRealPomax wrote:
| If you need to show a flowchart that doesn't fit in a URL,
| the idea that you _should_ be able to do this with a URL is
| kinda bonkers. The solution there would be www.example.com
| /?data=url_for_the_flowchart_definition, because what
| you're talking about isn't page state, it's a secondary
| resource.
| dheera wrote:
| > It has the advantage of not having a size limit
|
| Still though I suppose you could probably gzip it before base64
| encoding it for some additional optimization.
|
| Extremely long URLs have other UX issues, e.g. sending them on
| chat apps and having them eat up multiple scroll pages in one
| URL, like:
|
| "Check out this event:
|
| http://..... ... ... (500 scroll-screen-lengths of just URL)
| ... ...
|
| Here's another event on the same day:
|
| http://..... ... ... (500 scroll-screen-lengths of just URL)
| ... ...
|
| Can you let me know what you think and which one you'd like to
| go to?"
| kelnos wrote:
| The article mentions that compression is already being used.
| jefftk wrote:
| I don't most chat apps truncate long URLs?
| imhoguy wrote:
| Mega.co.nz uses that to hide the decryption key for almost
| decade. You share links but Mega never knows your key because
| fragment hash is never sent to server or in referrer. Encrypted
| files are stored on Mega servers but the decryption occurs in
| JS on the client side, files are decrypted into temporary JS
| Blob objects in browser then you save them aka "download"
| locally... a lot of clever tech there.
| https://help.mega.io/security/data-protection/end-to-end-enc...
| mLuby wrote:
| Please don't. The web lives and dies by links, the more
| specific the better, so #to-an-id or #:~:text=to-search are so
| much more useful than bad state management that probably only
| works for that one logged-in user anyway. Put that state in the
| part of the URL you unambiguously control (query params).
|
| https://web.dev/text-fragments/#textstart
| Izkata wrote:
| Everything old is new again!
|
| A decade-plus ago, this was common in single-page apps. It was
| the only way to do it before the history API existed, and
| enough people were doing it that Google was pushing a fragment-
| url thing [0] that allowed server-side rendering. You'd make
| such links in a certain way, then the crawler would hope a
| simple modification of the URL could be rendered by the server
| and load that.
|
| (Per a comment on that source, it's not been a thing since
| 2015, since the google crawler can now handle javascript)
|
| [0] https://stackoverflow.com/questions/6001433/does-google-
| igno...
| dang wrote:
| Related ongoing thread:
|
| _Show HN: URL Snake_ -
| https://news.ycombinator.com/item?id=34288577 - Jan 2023 (30
| comments)
| anigbrowl wrote:
| It's clever, but I hate it: it makes computing weird and
| inaccessible to non-technical people, and makes citations etc.
| needlessly difficult to manage.
| vesinisa wrote:
| This is all fun and games until the junior dev edits the code to
| store the user's search history in that obfuscated appState
| object. The users end up sharing their URLs in public and
| unknowingly leaking some very private data.
| dools wrote:
| I've been using this hosted on my own server since it was first
| posted in 2013:
|
| https://news.ycombinator.com/item?id=5696127
| franciscop wrote:
| In React you normally create local ephemeral state like this:
| const [myState, setMyState] = useState(null);
|
| I've created at least 3 libraries that follow that same pattern,
| but instead of ephemeral the state is saved somewhere:
| // ?firstname= const [firstName, setFirstName] =
| useQuery('firstname'); // localStorage const
| [name, setName] = useStorage('name'); // global
| state (that can be connected to other places) const
| [user, setUser] = useStore('user');
| escot wrote:
| Hey all, I made this post to show a technique that I'm using in
| my keyboard-centric flowchart editor [0]. I really love urls, and
| the power that they hold, and would love to see more apps
| implement little hacks like this.
|
| Also, another shout out to mermaidjs and flowchart.fun for also
| implementing similar url-based sharing.
|
| [0] https://www.knotend.com
| bytesandbots wrote:
| If the schema is fixed, using proto buffers will greatly reduce
| the length required.
| tonerow wrote:
| Love the app!
| escot wrote:
| Thanks!
| tlarkworthy wrote:
| There is a size limit though that quickly gets exhausted if you
| are storing text (2000 chars)
| tonerow wrote:
| (maker of flowchart.fun here) This is technically true but
| it's a little more nuanced. The 2048 character limit comes
| from Internet Explorer. There's a great answer on SO
| https://stackoverflow.com/a/417184/903980
|
| Still on FF I opted to use LZ Compression (pretty sure many
| other sites do this as well) to get the number of characters
| down
| tlarkworthy wrote:
| I have done this myself and various tools e.g. slack,
| Twitter will truncate long urls. Eventually it will break
| somewhere, not just in the browser. If your tool has a hard
| limit on information content it's ok, but that does not
| seem to be the case here.
| escot wrote:
| You're right, its a limitation. Knotend also supports
| upload/download of a .knotend file to get around this.
| __MatrixMan__ wrote:
| Store the content in ipfs and just put the hash in the URL?
|
| I haven't used https://github.com/ipfs/js-ipfs in this
| capacity but I'm under the impression that that's moving bits
| around like that is more or less its purpose.
|
| Although I suppose this puts a burden on the URL-creator to
| pin the content until the URL-clicker doesn't need it
| anymore, which is not how URLs are supposed to work.
| rmetzler wrote:
| This is the right answer here. The solution works until it
| doesn't. Browser URLs are limited in real life. So when the
| state grows it will break sooner or later. Of course it
| depends on the usecase.
| michaelteter wrote:
| As long as your users are reasonably tech-saavy this is ok. But
| long URLs can be problematic when sent in email for many possible
| reasons, such as the email client wrapping the URL and then
| creating a link out of just part of the original URL. The user
| sometimes doesn't realize this and gets unpredictable results
| when trying to use the URL they "saved" in the email.
|
| Perhaps instead, assuming the user is online, hash the json state
| data, then send the json+hash to the server and update the URL to
| URL?hash. Then the user has a much shorter URL, and the server
| can lookup the json state from the provided hash to resume the
| app at that state. As a bonus you then have versions of the data
| over time (either posted automatically in the background or on-
| demand when the user clicks Save).
| [deleted]
| zelphirkalt wrote:
| Racket does this in its web framework and docs.
| actinium226 wrote:
| This is really cool, both the state-in-url and the app itself.
|
| Just wondering, how long did it take you to put the app together?
| escot wrote:
| I've been working on the app for over a year. The state-in-url
| thing was a pretty small portion of time, although I've
| fixed/updated it several times in that year to make it better.
| Thanks for the feedback. Did you make a flowchart?
| Maksadbek wrote:
| Worth to note that it actually should use the base62
| https://en.wikipedia.org/wiki/Base62
|
| It's the same as base64 but w/o "+" and "?" symbols.
| bytesandbots wrote:
| There is a URL safe version of base64 that uses - and _
| instead. Base64 tools can be more readily available.
| [deleted]
| AndrewStephens wrote:
| This is pretty common and has a bunch of advantages, like the
| fact you can link to and bookmark a particular state.
|
| Also, if you are careful you get undo and redo for free with the
| browser's back button doing all the work for you.
|
| The disadvantages are that your representation of internal state
| becomes part of the interface - if you ever change your app you
| need to deal with versioning the state so your new version can
| transparently handle the old state format.
|
| If your app has a server component that acts on this state, be
| super careful about acting on it and treat it as you would any
| other input under user control.
|
| If you app is completely client side, consider storing the state
| in the #fragment section of the URL. This never gets sent to the
| server. An example from my own site [0] - see how the fragment
| part of the URL changes as you select different topics.
|
| There are also limits on just how much you can cram into a URL
| but with care you can shove a lot of state.
|
| [0] https://sheep.horse/tagcloud.html#computing
| cryptonector wrote:
| If the state cookie is generated by the server, then the best
| thing to do is to encrypt all application state cookies, and
| include an expiration time in them.
|
| Also, consider whether you want to allow the user to share the
| URI or not. If not, then you need to always check that the user
| is authenticated as whatever you wrote in the state cookie.
| typingerror wrote:
| > _If your app has a server component that acts on this state,
| be super careful about acting on it and treat it as you would
| any other input under user control._
|
| I would recommend signing it if it's generated by the server
| component, and checking the signature when the server component
| is provided this signed state.
|
| For example to do this in Node is quite straightforward.
|
| Key generation: const crypto =
| require('crypto');
| crypto.generateKeyPair('ed25519', (e, pubkey, privkey) => {
| // save pubkey and privkey somewhere // ...
| }
|
| Signing: const data =
| Buffer.from(JSON.stringify(state)); const
| signature = crypto.sign(null, data, privkey);
| const signeddata = `${data.toString('base64')}.${signature.toSt
| ring('base64')}`.replace(/=/g,'');
|
| Verification: const parts =
| signeddata.split('.'); const data =
| Buffer.from(parts[0], 'base64'); const signature =
| Buffer.from(parts[1], 'base64'); if
| (crypto.verify(null, data, pubkey, signature)) { //
| signature not verified, throw or return // ...
| } const state = JSON.parse(data);
|
| As the above uses Ed25519 the signatures are quite small too.
| It needs a bit more error checking, and might need extras like
| expiry time and such, but should be roughly sufficient.
| AndrewStephens wrote:
| Good advice. For some apps you might also need to protect
| against replay attacks to prevent the user from reverting to
| a previous state in a way that you app should not allow
| (undo'ing a change of bank balance, etc).
|
| But if your state is so important it is probably better to
| not uses these techniques at all and just store the state on
| the server.
| awb wrote:
| This technique is client-side data only, so updating a
| client-side state would only _appear_ to revert your bank
| balance on the UI, but wouldn't trigger any server-side
| functions to do so.
|
| If you sent the client state to the server for some type of
| CRUD action or persistence, you'd need to sanitize and
| validate it first. And at that point like you said, why not
| just keep the state secure server-side and not trust the
| client.
| ivanhoe wrote:
| Excellent idea for those apps that need that type of
| protection. For many apps however ability to manually edit
| the link to get to the different state is actually a free
| bonus feature. I've built a CRM/Cases management app for the
| client that stores data filters in the url, and while there's
| a nice UI to control filters, we observed that lots of users
| simply go and edit the url directly to quickly get what they
| need.
| Brometheus wrote:
| I did this for passing parameter to a twitter card generator
| php script :joy:
| hot_gril wrote:
| > The disadvantages are that your representation of internal
| state becomes part of the interface
|
| This is the biggest reason to avoid this. URLs aren't meant to
| be used this way. I'd only do it if I wanted a quick and dirty
| solution.
| AndrewStephens wrote:
| > URLs aren't meant to be used this way
|
| I disagree, URLs are supposed to point to a resource - in
| this case the resource is the client state of the app (aka
| "deep linking"). It is a useful approach.
|
| Of course, it can easily be misused.
| hot_gril wrote:
| The suggestion was to put your entire client state into it,
| which is probably more than just the resource location (aka
| deep link).
| naasking wrote:
| There is no such thing as "client state" separate from
| the notion of resource under REST. The URL is meaningful
| only to a server. If a server can encode data in the URL
| so it doesn't need to persist it, that's perfectly fine,
| so long as the URL conforms to all expectations of
| resources, ie. caching directives, lifetime, etc.
| hot_gril wrote:
| Modern web apps often use the URL in ways that only
| matter to the client and can be edited client-side
| without issuing another request to the server, unless you
| reload manually, in which case everything is reset except
| the URL state. This doesn't violate REST principles. Some
| of that makes sense to put in the URL so users can return
| to past state, some is very temporary and wouldn't make
| sense at all to persist across a reload/back.
|
| For example, you may track the scroll position for the
| purpose of loading more content when the user reaches the
| bottom of a feed, but you don't want to persist that
| across reloads. And the user may click on some content
| and anchor the view to it, which you do persist in the
| URL for the purpose of history or sharing.
| naasking wrote:
| Sure, and all of that belongs in the fragment of the URL
| which is not sent to the server but is specifically
| reserved for client-side resources.
| dzhiurgis wrote:
| That's like one of the biggest webapp debate according to pg
| moralestapia wrote:
| >Also, if you are careful you get undo and redo for free with
| the browser's back button doing all the work for you.
|
| Ugh! Please don't do this!
| amadeuspagel wrote:
| > This is pretty common and has a bunch of advantages, like the
| fact you can link to and bookmark a particular state.
|
| Conversely, you can't link to the newest version.
| ivanhoe wrote:
| IMHO you should never store the data itself in the url, only
| the params that you use to fetch the data. So if the page is
| the list of the latest 10 posts in a category, you'll store
| the category in the url and the sorting criteria, not the IDs
| of the posts themselves. On the refresh you always get the
| fresh data.
| m00dy wrote:
| Another one would be passing ipfs hash in the url
| kevinfiol wrote:
| My favorite example of this is flems: https://flems.io/
| breck wrote:
| This is the way. Except I would never encode the data--just store
| state in plain text. That way you can edit urls by hand in a
| pinch (comes up a lot, actually). And more trustworthy and you
| can be sure you take your data with you.
|
| I do this in all my apps. https://ohayo.computer/,
| https://simoji.pub/, https://try.scroll.pub/,
| https://jtree.treenotation.org/designer/ etc.
|
| At one point I also made a tiny lib to make it easier:
|
| https://breckyunits.com/patch/
| shepherdjerred wrote:
| Shinylive, which lets you create and share data science apps,
| takes this approach:
| https://shiny.rstudio.com/py/docs/shinylive.html
| oaiey wrote:
| Just do not. That or alternatively a hidden field is how asp.net
| WebForms did it state management 20 years ago. Worst possible
| idea ever.
|
| Good for small scale unimportant external state management but
| not for your everyday web app.
| jonathanoliver wrote:
| When I saw this idea all I could think of was the ASP.NET
| "postback" form data and URL data! I'm glad to not have to deal
| with that anymore.
| tomwheeler wrote:
| It also degraded performance. I had to use a .NET-based issue
| tracking web app 20 years ago. The performance was horrible,
| with pages sometimes taking 20 seconds to load. I eventually
| viewed the source of the page and discovered a form field
| called "viewstate" that contained several megabytes of encoded
| data.
| sidharthv wrote:
| I had to add compression into Mermaid live editor's URL state as
| the length limit was exceeded with big diagrams.
|
| Wrote this SerDe which can be extended with better algorithms in
| the future. https://github.com/mermaid-js/mermaid-live-
| editor/blob/devel...
|
| Eg:
| https://mermaid.live/edit#pako:eNo9kUGTnCAQhf8K1adNlesoqKiHV...
| debacle wrote:
| Congratulations, you've implemented ViewState from aspx.
| tomtomistaken wrote:
| We are testing this on a map[0], it's fun. When tweeting the
| link, the tweet and its state is added to the map. Also, map
| stories are possible through Twitter threads. We just implemented
| a draw function and are working on an implementation for external
| geojsons.
|
| [0] https://map.decarbnow.space
| generalpf wrote:
| I remember when WebSphere Portal Server used to do this, and the
| URL would exceed 4096 characters, which was the limit that IE 6
| (?) would support, breaking the entire site.
| markandrewj wrote:
| There is still a browser URL limit, I have hit it recently
| while applying a large number of filters to a search in Kibana.
| jcuenod wrote:
| This is a useful idea when you've got complex nested state. The
| problem is changing any particular part of the state is non-
| trivial. I ended up making `friendly-serializer`[0] to "make
| objects more accessible in urls."
|
| The idea is that instead of a base64 string, you get something
| that is much easier to edit in the url bar:
|
| > name=John%20Doe&age=42&address.street=123%20Main%20Street&addre
| ss.city=Anytown&address.state=CA&address.phoneNumbers.0=123-456-7
| 890&address.phoneNumbers.1=234-567-8901
|
| There's a similar npm project to [0] that I discovered after I'd
| published this, but I don't recall the name. PRs welcome.
|
| [0] https://www.npmjs.com/package/friendly-serializer
| frosted-flakes wrote:
| You can have multiple values under the same search parameter.
| For example, ?a=b&a=c&a=d, which would be the array [b, c, d].
| Including the index key seems redundant.
|
| The native URLSearchParams browser interface even supports this
| with the getAll method.
|
| https://developer.mozilla.org/en-US/docs/Web/API/URLSearchPa...
| berelig wrote:
| This is exactly how Shel Kaphan (first eng @ Amazon) handled the
| state of a shopping cart in the mid 90s. Here is him discussing
| some of the pitfalls: https://lists.w3.org/Archives/Public/www-
| talk/1995NovDec/020...
| 12311231231 wrote:
| In other words, tracking
| withinrafael wrote:
| I don't have an opinion on this but do want to mention that
| LastPass does not (currently) encrypt the URL portion of its
| entries in the secure vault. Something to keep in mind!
| OOPMan wrote:
| Hmmmmmm....combine this with a link shortener and you have much
| the same effect except the actual state gets stored elsewhere.
|
| Which is totally missing the point and being intentionally daft
| but it is a little amusing XD
| aabbcc1241 wrote:
| Depending on how repeative the object keys are, you maybe able to
| save quite some spaces with compress-json [1].
|
| Since the OP is using lz-string to do compression, I suppose the
| data should be repetitive.
|
| [1] https://www.npmjs.com/package/compress-json
| locofocos wrote:
| Neat. I did this for a very basic react ratio calculator I built.
| My state was so basic and small, it felt fine for a toy project.
| Certainly a practice I would scrutinize in a production
| application, but it could be useful.
|
| https://locofocos.com/anything-ratio-calc
| paulirish wrote:
| Here's the non-psuedo code equivalent that can leverage the
| CompressionStream API rather than using a browserified-gzip-
| library (eg pako):
| https://github.com/GoogleChrome/lighthouse/blob/437eb4d757c5...
|
| We use it in Lighthouse for the exact same purpose, a URL #hash
| full of state. We found that modern browsers support 10mb of data
| in the hash.
| https://github.com/GoogleChrome/lighthouse/pull/12509#discus...
| brundolf wrote:
| Something to be careful about here is that browsers/proxies/etc
| have arbitrary length limits on URLs, and they can vary by quite
| a lot
|
| We did this once with a web-based REPL, where you could click a
| button to copy a link to something you'd previously eval'd and
| then send that to someone else and their buffer would be
| preloaded with it. It was super nifty, until someone tried it
| with a buffer that was a few hundred lines long and at least one
| browser just said "nope". It sounds like OP is doing some smart
| stuff to minimize URL length, which should help, but there's
| still a limit somewhere
| kissgyorgy wrote:
| I did something similar, but compressed with pako to make the URL
| as short as possible:
| https://www.pokerregion.com/?r=Y2RwYBBgYGFkcGAQYGBhZHBgEGBgY...
|
| Here is the compression code:
| https://gist.github.com/kissgyorgy/39623a7d0ba2f6faafb464b72...
|
| I used the properties of my data structure (multiple cards
| represented in a byte as bits) to represent the same data on less
| bytes (to avoid compressing JSON with unnecessary characters)
| vqt123 wrote:
| i do this on a site i threw together to annotate youtube videos
| with timestamps
|
| https://youtubenotes.com/
|
| i used sveltekit and vercel
| actually_a_dog wrote:
| Only about 20 years late:
| https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arc...
| chrismsimpson wrote:
| ASP.NET WebForms did this and it was horrible.
| 867-5309 wrote:
| I'm just getting a 414 Error
| escot wrote:
| Sorry about that, could you send the link that is giving you
| the 414?
| 867-5309 wrote:
| it would exceed the comment character limit ;)
| 2342346666 wrote:
| [dead]
| schwartzworld wrote:
| I built a tic tac toe game for my daughter a while a go that
| stores the game state in the URL as a proof of a similar concept.
| https://letter-press.netlify.app/ttt/
| Zamicol wrote:
| We wrote a library for storing application state in the URL. Its
| novel feature is using fragment query, which prevents the
| information from being sent to the server.
|
| https://github.com/Cyphrme/URLFormJS
|
| I would love to see it get more use.
|
| Here's a small demo:
| https://cyphrme.github.io/URLFormJS/#?first_name=Bob&last_na...
|
| See my other comment on this page for some other examples of its
| use.
| lelandfe wrote:
| Does this necessarily prevent the ability to provide in-page
| anchors?
| vbezhenar wrote:
| Since you're using JavaScript, you can implement anchors in
| the way you want.
| Zamicol wrote:
| The fragment query delimiter is `?` with `&` for between
| values, just like normal queries. It practice, browsers are
| not fragment delimiter aware so at the moment I would treat
| them as mutually exclusive.
|
| There's a larger issue of URL fragment delimiters. For a
| practical work around on Chrome only, fragment directive/text
| fragment can be used as a delimiter. (In my opinion, Chrome's
| delimiter should be re-worked with a new, more comprehensive
| delimiter.) Example of the workaround: https://en.wikipedia.o
| rg/wiki/URI_fragment#References:~:text...
| notRobot wrote:
| This looks very cool, and I'll definitely use it in a side
| project sometime soon!
| twhitmore wrote:
| Limited in size as URLs encounter size limits:
|
| https://stackoverflow.com/a/417184/768795
|
| I wouldn't consider state in the URL fully general, as data can
| easily exceed that for many apps; but it's a useable technique
| where it fits.
|
| Meaningful individual parameters are preferable, but similar size
| limits apply either way.
| aplummer wrote:
| I do like the approach and when it works great thats fantastic -
| please be careful of this as an attack vector.
|
| I know of at least one bank where this was exploited, because
| people see the base url, assume safe, and can't read the embedded
| escape / javascript in the longer part. Especially when the link
| is zipped into a little clickable thing and you can't see the URL
| at all.
| jsight wrote:
| This reminds me of ASP.Net's viewstate feature, tbh.
| mrdoob2 wrote:
| Made this thing in 2010. I can't remember if I saw the trick
| being used in another website before or not...
| https://mrdoob.com/projects/voxels/#A/bnciaTraheakhacTSiahfa...
| gautamdivgi wrote:
| Web servers and http enabled services can limit the length of
| headers and url. While this can be done it runs the risk of
| having surprises when unknown limits are encountered. Most of
| these limits are buried deep in docs, not easily visible.
| seri4l wrote:
| Not really because nothing after the # is sent to the web
| server.
| cdot2 wrote:
| I've run into some obscure email servers which reject any mail
| which includes URLs above a certain length limit and only throw
| vague "Mail rejected" errors.
| dzhiurgis wrote:
| IIRC some base64 characters need to go thru urlEncode
|
| https://stackoverflow.com/questions/1374753/passing-base64-e...
| stevebmark wrote:
| The Typescript Playground (https://www.typescriptlang.org/play)
| does something similar, it gzips the contents of your code and
| puts it in the URL. Pretty sweet!
| builwithlogic wrote:
| This is fine for f its public information and if thats fine then
| why not just add a param with a url encoded json string. Would
| this make the url shorter or longer? I think shorter. So why
| base64encode?
|
| Just wondering never created an entire app around this idea
| escot wrote:
| The encoding gives you cleaner urls that are restricted to the
| characters that base64 outputs, not necessarily shorter. The
| compression is to make it shorter.
| jncraton wrote:
| I did something similar in a simple whiteboarding app that I made
| a while back:
|
| https://github.com/jncraton/box-line-text
|
| The data representation could probably improve in terms of
| readability, but I'm happy with the way it provides a concise
| encoding while still including the text from the document
| directly:
|
| https://box-line-text.netlify.app/#;c2121Hello;5321;c1341Hac...!
| jerryzh wrote:
| one problem to me is that I run a script remove parameter in
| url(for tracker) ofc I can set a whitelist but it is a issue i
| consider
| jonnycomputer wrote:
| Why not use localStorage or sessionStorage instead of the URL?
| temporallobe wrote:
| I prefer this as well, but it's not as portable.
| escot wrote:
| URLs are great because you can share them. I may also add
| support for local storage, but it won't remove the ability to
| share via URL.
| martini333 wrote:
| Vuejs Playground does this. This is the url for the default
| tamplate:
|
| https://sfc.vuejs.org/#eNo9j71uwzAMhF+F5eIWqCV0NZQA3foGXbikj...
| ohyash wrote:
| I love this. My website tenor.cards has been backend-free for a
| while thanks to the URLs.
| https://tenor.cards/design_card/?p=Rm9yJTIwdGV4dCUyMHRoYXQlM...
|
| I didn't even know about window location hash, which I just
| learned from the other comments. Thank y'all.
| [deleted]
| [deleted]
| splistud wrote:
| [dead]
| strongpigeon wrote:
| Hah, I came up with the same thing for
| https://fivethreeone.app/calculator .
|
| The reason I did the compression (using pako as well) was that
| without it the URL was too long to show a preview on iMessage. I
| also compress the state manually myself which saved a bunch of
| bytes too.
| [deleted]
| pjpweaver wrote:
| I discovered when I hit a similar issue, that just putting a
| "-" character every 40 or so characters resolved the iMessage
| parsing issue. There may be a max URL length, but I hit it much
| sooner without the hyphens.
| paxys wrote:
| Base 64 is probably not the best encoding for this, since the URL
| allows for a wider range of characters. You can be more efficient
| by using them as well.
| macspoofing wrote:
| Base 64 is fine - he just needs to url-encode the parameter.
| moritzwarhier wrote:
| Great for complex apps in the browser and sharing complex save
| states!
|
| Bad for ordinary, mundane web applications and sharable URLs!
|
| Like, great for a musical step sequencer in the browser, bad for
| a website or HTTP service
|
| OTOH, app state on websites of commercial service prodivders
| might be best represented by a JSON blob anyway.
|
| In something like a checkout process or form submit, of course
| this doesn't matter much.
|
| But I prefer human-readable URLs wherever possible.
|
| And I implemented a similar pattern once, too.
|
| It's a very interesting approach in intself.
|
| Relevant POJO state tends to be small enough but long lists or
| resourcrs in a URL are not supported by most servers and not
| advisable.
| manchmalscott wrote:
| I am pretty certain BeepBox (An online sequencer/tracker) does
| this as well. It's pretty neat to send something in progress to a
| friend with just a URL, no accounts needed.
___________________________________________________________________
(page generated 2023-01-10 23:02 UTC)