[HN Gopher] How to win at CORS
___________________________________________________________________
How to win at CORS
Author : jaffathecake
Score : 343 points
Date : 2021-10-14 08:59 UTC (1 days ago)
(HTM) web link (jakearchibald.com)
(TXT) w3m dump (jakearchibald.com)
| thepasswordis wrote:
| CORS has been no shortage of greys in my beard!
|
| When I'm writing some frontend that is hosted on localhost, with
| an API that is hosted on its domain somewhere, it _always_ is
| some sort of PITA to get the dev environ started.
|
| There's a plugin for firefox that ignores CORS which is helpful
| for this. It's becoming less useful for me as my APIs now usually
| have a toggle to add a cross origin header which allows
| localhost. Still useful.
| eurasiantiger wrote:
| Just use http-proxy to set up a local domain so you can access
| your dev environment at frontend.yoursite.local (proxied to
| localhost:3000) and the api at api.yoursite.local (proxied to
| whatever 3rd party api). Boom, problem solved. You can even
| rewrite headers and content of the requests in and out.
| jnovacho wrote:
| Do you have any recomendations, which proxy to use?
| Specifically on Win.
| eurasiantiger wrote:
| https://www.npmjs.com/package/http-proxy
|
| Integrates nicely with existing JS frontend tooling.
| dspillett wrote:
| _> writing some frontend that is hosted on localhost_
|
| I assume this would also work for CORS purposes: for some time
| I've not used localhost where possible, for SSL reasons. Giving
| the local machine a perfectly valid name that I can get a cert
| for via LE (or already have a cert for, I actually use a non-
| production name for which I maintain a wildcard cert) is
| slightly less faf than having my own signing cert installed as
| trusted everywhere I might need it. Anything I might do
| publicly is HTTPS-only so my dev/test environments are too.
| roca wrote:
| I tried really hard to get <video> and <audio> to default to
| requiring same-origin but people were still skeptical about CORS
| deployment, and there were also arguments for consistency with
| <img>. Oh well, I think we eventually got to a consensus that
| that "consistency" is not worth having.
| jaffathecake wrote:
| I think you folks were in a really tricky spot. Making
| <audio>/<video> require CORS would have been the right decision
| for security reasons, particularly since <audio>/<video>
| introduces range requests. It would have prevented these
| security bugs https://jakearchibald.com/2018/i-discovered-a-
| browser-bug/.
|
| However, the competition at the time was Flash, and making
| <audio>/<video> so much harder than it was with Flash would
| have put developers off.
|
| Fwiw, I regret that opaque responses can go into the service
| worker cache, since it caused quota-sniffing issues that we had
| to work around. But, if we didn't allow it, it would have been
| a feature regression vs appcache. sigh
| lloydatkinson wrote:
| I am really glad they overruled you.
| EE84M3i wrote:
| webfonts require it though! I was really surprised!
| roca wrote:
| Yeah, when Web fonts rolled around we fought that battle
| again and won. Some important people saw the light :-). (And
| to be fair, CORS was more widely available on servers.)
| jaffathecake wrote:
| I think font foundries were particularly keen on that juicy
| Origin header so they could tell who was using their font,
| and block sites that hadn't paid.
| roca wrote:
| That is also true.
| AllThatJazz wrote:
| Earlier this year, the feds signed an agreement that let Boeing
| executives off the hook for the 737 MAX catastrophes, which
| killed 346 people.
|
| The lead prosecutor, Erin Nealy Cox, then took a job with the
| firm that leads Boeing's criminal defense.
| jakear wrote:
| For some real fun try accessing a redirect's resource when the
| redirector requires an Authorization header. You'll need 4
| separate round trips, and the final endpoint will need to
| restrict requests based on Referer in addition to Origin, meaning
| you need to write all your own preflighting logic.
| lloydatkinson wrote:
| CORS is a stupid idea that serves no purpose. If someone is
| really determined they will either 1) turn off CORS with a
| browser extension 2) simply call your precious API from something
| other than an a browser
|
| It is essentially security by obscurity and protects nothing.
| Don't get me started how some technologies like AWS Lambda with a
| Gateway, when a function has an error, responds by default in
| such a way it makes the browser log a CORS error instead of, you
| know, a 500 or the actual error message.
|
| I always do the "allow anything" setting for CORS when I make an
| API.
| fraktl wrote:
| Out of curiosity, how come you dared to make this comment
| without ensuring you've got all your facts straight?
|
| No, it isn't security through obscurity. Yes, it protects and
| it protects _a lot_.
|
| Thank you for contributing to lack of knowledge, do keep up.
| lloydatkinson wrote:
| You're welcome
| jaffathecake wrote:
| Author here! I don't know if you read the article, but it
| includes the history and reason behind CORS.
|
| It definitely protects more than nothing :)
| lloydatkinson wrote:
| I had a quick scan yeah. I'm sure historically it does but
| I've yet to ever need or encounter anyone that makes use of
| these features. I've never been in a team that particularly
| cares about any of it's supposed value either, it's merely a
| frustration to remove...
| jaffathecake wrote:
| You should try out some connected home devices, including
| things like routers. Like I said in the article, many of
| them assume they're safe because they're on a local
| network, so their security is lax.
|
| Also, I know quite a few public sites that serve debugging
| data if the request comes from the company's IP range. They
| shouldn't be doing this, but they do.
|
| Maybe one day we can remove CORS for no-credential requests
| if we can detect that the destination isn't "internal", and
| we just decide that folks who serve debugging data by IP
| deserve to have their data leak. I've heard ideas around
| this for 10 years now, but maybe it'll happen eventually.
| johncolanduoni wrote:
| Did any of your teams put private data into HTML or JSON
| responses authenticated with a cookie, but which didn't
| require anything like a CSRF header? If so they should have
| cared about it because without CORS policies any user
| logged into your site could have their data read by any
| other site they visited.
| lloydatkinson wrote:
| Oh it's turned on, but it always only boils down to "turn
| it totally off" or "here is the whitelist". Such a
| lacking tool.
| lol768 wrote:
| > CORS is a stupid idea that serves no purpose. If someone is
| really determined they will either 1) turn off CORS with a
| browser extension 2) simply call your precious API from
| something other than an a browser
|
| > It is essentially security by obscurity and protects nothing.
|
| What.
|
| I think there's been a fundamental misunderstanding of who is
| being protected here on your part, and what CORS is actually
| for.
|
| It's your run-of-the-mill user that CORS protects, and CORS
| being enforced protects them when they visit e.g. an attacker-
| controlled site with, for example, a valid cookie-based session
| on your service. It prevents the attacker's site from making
| dangerous authenticated requests to your API service and
| reading the result.
|
| > If someone is really determined they will either 1) turn off
| CORS with a browser extension 2) simply call your precious API
| from something other than an a browser
|
| That's not what CORS is designed to protect against at all, _of
| course_ you can hit an API separately and your HTTP client will
| ignore the CORS headers. Your HTTP client isn 't a browser! It
| doesn't _need_ to worry about CORS.
|
| Similarly, users shooting themselves in the foot by disabling
| CORS are only hurting themselves. They are not the attacker
| here.
| Randosaurus wrote:
| Nowadays you can set cookie flags to ensure those sorts of
| attacks don't happen.
| [deleted]
| lucideer wrote:
| Being an engineer who doesn't understand CORS is ok; I've
| worked with a few good ones who struggled with it, so clearly
| CORS is not a very intuitive tech.
|
| Not understanding CORS and making a comment like this is taking
| that ignorance to a new level though. Please read up on what
| you're talking about.
| lloydatkinson wrote:
| Please tell me more about how publically accessible by anyone
| REST API's need CORS. Are you actually suggesting people have
| to tell companies what domains they will be calling an API
| from, in order to add it to the list of allowed domains, in
| the code base?
| hbn wrote:
| > Please tell me more about how publically accessible by
| anyone REST API's need CORS
|
| It's not security for the provider of the API, it's
| security for the user of a web browser
| lucideer wrote:
| Does your publicly accessible API provide contextual
| information based on client-state? It probably doesn't, in
| which case you're right, CORS isn't needed, and lo and
| behold, this is exactly what the Origin wildcard is for.
| Adding it isn't a big deal.
|
| But no, it's not really a great idea to make every single
| privileged API in the world completely insecure just so the
| admins of public APIs can avoid adding a wildcard header to
| their servers.
| 88913527 wrote:
| I can tell you how to lose at CORS in Chrome. If your browser
| caches a response, and sometime later you mutate the request by
| adding the "Origin" header it (e.g, add attribute
| crossorigin="anonymous" to a <script> tag), Chrome won't make a
| new request. What it will do is use the cached response, which is
| missing the ACAO response header, and thus the browser rejects a
| file from its own cache via draconian security policy.
|
| There are many ways to lose at CORS and this one is my story.
| jaffathecake wrote:
| Author here! The post covers this detail. This happens because
| your response is missing a Vary header.
|
| Getting Vary right isn't just important for Chrome, it's
| important for CDNs too.
| 88913527 wrote:
| You're right, the real issue is CloudFront won't include
| Origin in the Vary response header if it wasn't included in
| the initial request. And if you change your HTML attributes,
| you're changing your request, but you essentially end up with
| a poisoned local cache. Rolling out crossorigin="anonymous"
| on previously cached assets is a subtlety you won't know
| about (even if you think you know CORS) until your site
| breaks as critical assets are missing.
| speleding wrote:
| Ha, I feel your pain, I ran into something similar with
| Chrome and Cloudfront.
|
| For us it got triggered because an image on the site
| appeared both as a video "poster" attribute (which loads
| with CORS) and as a regular image. So depending on which
| image the user encountered first you would see a CORS
| error. But it would be gone after a reload, so devilishly
| hard to reproduce until you realise what's happening.
|
| Also took me ages to figure out that Cloudfront didn't
| include the Origin in the Vary header if it wasn't in the
| original request.
|
| (@jaffathecake perhaps that Cloudfront behaviour warrants a
| special mention. Great article by the way, I learned a lot)
| Benjamin_Dobell wrote:
| If your data is coming from an S3 origin and the original
| (cached request) was _not_ CORS (but you also want to
| support CORS), then you can inject the necessary headers
| with Lambda@Edge or CloudFront Functions.
|
| S3 is used as an example, as it does _not_ include a Vary
| header for non-CORS requests. However, the same would be
| true of some other origin which isn 't correctly inserting
| a Vary header.
| speleding wrote:
| That works, but I found a simpler / cheaper alternative
| to fix this particular Cloudfront problem: Create a
| custom "Cache policy" that only includes the header
| "origin" and then the answer from Cloudfront will always
| include "Vary: origin", even if it wasn't in the request
| (That behaviour is not documented anywhere I could find,
| stumbled upon it by accident)
| jaffathecake wrote:
| Yeah, it's generally understood that you need to change the
| URL to cache-bust when the content changes, but it's easy
| to forget that you need to do the same thing if important
| headers change.
|
| Hmm, I think I'll add a section to the article on this when
| I'm back at my laptop.
| jaffathecake wrote:
| Aaaand it's done
| https://jakearchibald.com/2021/cors/#cors-and-caching
|
| Thanks for prompting this!
| ourcat wrote:
| ServiceWorkers also don't play nice with CORS in my experience.
| We often need to bypass them in Angular when making certain
| requests.
| jaffathecake wrote:
| Author here! I'm also an editor on the service worker spec,
| so I'm interested to know where the pain points are.
| ourcat wrote:
| Hi Jake! (I watch your videos ;)) Many times, the (Angular)
| ServiceWorker has given us CORS headaches on various
| requests to our APIs and AWS storage files. The only method
| we've found, after various AWS configs and ngsw-config.json
| attempts, was to add `ngsw-bypass=true` to all requests.
| I'll see if I can find the Github issue, where this has
| come up before.
|
| Incidentally, while you're here, I'm planning on building
| something which will require use of SharedArrayBuffer. Will
| adding the (now) required Cross-Origin isolation COOP/COEP
| headers cause any issues to existing CORS setups?
|
| :)
| jaffathecake wrote:
| COOP+COEP won't change how CORS works, but it means you
| can't have no-cors resources on your page unless they
| have CORP headers
| ourcat wrote:
| Very useful info. Thanks!
| nerdkid93 wrote:
| > remember, the 's' in 'IoT' stands for security
|
| I don't know why, but this cracked me up. :D
| hbn wrote:
| Worth noting that it's a fairly common saying, not something he
| came up with for the article
| pkpioneer wrote:
| How to Win Every Game in Netflix's 'Squid Game':
| https://pkpioneer.blogspot.com/2021/10/how-to-beat-every-gam...
| jaffathecake wrote:
| Bonus fact: I wanted the 'app'
| (https://jakearchibald.com/2021/cors/playground/) to allow the
| HTTP method to be set to anything, which meant I needed a server
| that could accept anything.
|
| I usually use NodeJS, but it turns out the HTTP library they use
| turns the HTTP method into an enum, so only a subset is supported
| (https://github.com/nodejs/node/blob/d798de1c653efa5ec0015d44...)
| . This restriction only exists in their HTTP/1 library, their
| HTTP/2 library supports any method.
|
| Anyway, I couldn't use that, so I used Deno via Deno Deploy.
| Their HTTP library supports any method, and the APIs they use are
| very similar to web APIs, so it was really easy to get started.
| Here's the server code: https://github.com/jakearchibald/cors-
| playground/blob/main/i....
| chrismorgan wrote:
| My recollection from _circa_ 2013 is that Node.js at least used
| to use the nginx HTTP parser, which was a _horror_ of manually-
| implemented state machine written so in the name of
| performance, but consequently basically unmaintainable and
| fairly bug-riddled. And not as fast as it should have been,
| anyway. (The state machine approach is fine, but it should have
| used a lot more code generation.) It read the method byte by
| byte into the state machine, and baulked at unknown methods.
| Evidently they've kept that limitation, whatever they may have
| changed since in the parser they use (and I think nginx did
| eventually abandon and replace that parser entirely).
|
| (These are my recollections from investigation I did back in
| 2013 when I was writing the first serious Rust HTTP library.)
| TechBro8615 wrote:
| Sounds like a security researcher could have some fun
| comparing old nginx patches to whatever got pulled into the
| node codebase.
| jaffathecake wrote:
| Whoa, I didn't know that! But yeah, it seems like
| https://github.com/nodejs/http-parser is based on nginx. It
| now uses https://github.com/nodejs/llhttp but has some of the
| same legacy.
|
| On the other hand, deno's HTTP stuff is built on top of
| Hyper, a Rust library https://github.com/hyperium/hyper
| fadikhadra wrote:
| Hey Jake, would love to see this topic discussed in HTTP 203!
| jaffathecake wrote:
| We've got an episode on Deno https://www.youtube.com/watch?v=
| SYkzk_j3yb0&list=PLNYkxOF6rc..., and another which covers
| cross-origin fetches https://www.youtube.com/watch?v=vfAHa5GB
| Lio&list=PLNYkxOF6rc... (although it isn't CORS specific), or
| did you mean something more specific?
| fadikhadra wrote:
| I guess I missed that one https://www.youtube.com/watch?v=v
| fAHa5GBLio&list=PLNYkxOF6rc.... Will have a look thanks for
| sharing.
| pachico wrote:
| Rather than adding my own personal experience in the matter, I
| want to do gratulate the author for the article.
|
| It's engaging and even entertaining. Very well done!
| ufmace wrote:
| I've banged my head against some CORS puzzles recently. That's a
| pretty good guide, but I actually know an extra quirk that was
| missed:
|
| You know that nice "Access-Control-Allow-Credentials: true"
| header? In theory, it means that you can make authorized requests
| with cookies included to the cross-origin API. It actually has
| some extra rules that aren't obvious though. The cookies won't
| actually send unless they explicitly have "SameSite=None" set.
| Which itself isn't valid unless you are both making the request
| over HTTPS, and the cookie also has the flag "Secure". See here:
| https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Se...
|
| The cookie logic is kind of mysterious. When everything is set up
| correctly and it works, it's pretty invisible to the code making
| the cross-origin requests. But if it isn't set up quite right, it
| will just not work, and it can be pretty tricky to figure out
| what's wrong. The whole SameSite logic is a pretty interesting
| kludge too. Ideally, most things would be SameSite=Strict, but
| that also means that links the user follows from third-parties to
| your site won't include cookies, since in theory those requests
| could include GET params doing who knows what.
|
| Digging into all of the CORS rules and how they interact is
| almost an archaeology project into how the web was built and all
| of the weird things that both legit sites and malicious attackers
| have tried to do over the years.
| jaffathecake wrote:
| The article mentions the SameSite stuff early on, then kinda
| mentions it in passing when it comes to CORS + credentials "The
| same-site rules around cookies still apply, as do the kinds of
| isolation we see in Firefox and Safari. But these only come
| into effect cross-site, not cross-origin".
|
| Seems like I need to word it better though.
| Steltek wrote:
| Is it fair to say that the strongest CORS request allows the
| weakest? That is, if your server supports a preflighted,
| credentialed, cached CORS request with weird headers and
| methods, then it would support just about anything?
|
| Perhaps a detailed walkthrough of that one specific scenario,
| which would enable almost all others, would be helpful.
| jaffathecake wrote:
| Yeah, the most permissive CORS allows everything, although
| it's kinda risky to do if you don't understand the
| consequences.
| ncc-erik wrote:
| Very comprehensive blog, nice work.
|
| As a pentester, I always get excited when I see ACAO or an
| OPTIONS request in my proxy logs. It's still really hard to
| wrangle and get right.
| Animats wrote:
| You can't always access an image across origin boundaries.
|
| If you load an IMG into WebGL as a texture, that's not allowed
| cross-domain. It's considered "processing" the image, rather than
| just displaying it. I ran into this when displaying slippy maps
| from map tiles. You can display the map tiles with JavaScript
| regardless of origin, but use WebGL, and you have to deal with
| the origin problem.
| jaffathecake wrote:
| The article covers this. It's because WebGL has texture
| readback, giving you access to the pixel data.
|
| Reading image pixels isn't allowed unless the resource passes a
| CORS check.
| billfruit wrote:
| How they jump into the article without explaining or even
| expanding what the CORS acronym stands for.
| codetrotter wrote:
| It means Cross-Origin Resource Sharing. You can read about it
| at https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
|
| I agree though that it is good practice to say what acronyms
| mean when using them.
| kindall wrote:
| If you don't already know what CORS is, you're probably not a
| Web developer and don't need to know.
| nuerow wrote:
| > If you don't already know what CORS is, you're probably not
| a Web developer and don't need to know.
|
| This is an appallingly poor and misguided take, and goes
| against the most basic rules of writing technical documents.
| Docs need to be clear, unambiguous, and self-contained. The
| very first time a acronym is presented, it must be after the
| full name is presented.
|
| It takes less than a sentence to do the right thing. There is
| no excuse.
| Waterluvian wrote:
| I think this is misguided reasoning. Everyone starts
| somewhere, and the hallmark of reasonably competent writing
| is a ramp-up. Whether it's one sentence or one chapter.
|
| I think failing to define acronyms is a violation of just
| about any style guide out there.
|
| Communication is a majority of engineering so I think these
| things are very important.
| mrweasel wrote:
| Sometimes OPS people get the job of fixing CORS for
| developers who don't understand how it works exactly.
|
| I work with a client who built a web app in... Vue, I think.
| For unknown reasons they decided that it would be better that
| the APIs they need to call to live on the same domain. At the
| same time, the developers decided that the API microservices
| should not return CORS headers. Instead it was left to
| operations to hack in CORS headers in the
| webserver/loadbalancer.
| hsbauauvhabzb wrote:
| To be fair, there are many web devs who have never needed to
| worry about cross origin resource sharing
| soniczentropy wrote:
| How do you become one of those kind instead of smashing
| your face against CORS constantly
| hsbauauvhabzb wrote:
| Legacy developers would be the biggest group.
| adminscoffee wrote:
| i think the purpose of cors is to slowly make web devs go
| insane. but yeah, more coors less cors
| 5e92cb50239222b wrote:
| Usually the same ones who then download plugins like
|
| https://addons.mozilla.org/en-US/firefox/addon/access-
| contro...
|
| because properly configuring the backend is "too
| complicated".
|
| Been there, done that.
| hsbauauvhabzb wrote:
| You can use the origin announce headers from Firefox to
| block cors also, unsure if that works with chrome.
|
| But I was referring to legacy code (or those whose SPA is
| stored on the same domain as API endpoints).
| jaffathecake wrote:
| Author here! I added a small reference to the acronym in the
| article, but I don't think it really matters.
|
| I actually forgot what it stands for the other week, but it
| didn't prevent me understanding it. And relearning the acronym
| didn't help me understand it more.
| billfruit wrote:
| Thank you. I was just nitpicking, there.
| jaffathecake wrote:
| At least the expansion of the acronym isn't actively
| harmful to understanding what it is, unlike AJAX, JAMStack
| etc etc
| humbleMouse wrote:
| I'm pretty sure "Cross Origin Request" is extremely helpful
| for people learning this concept. It literally describes
| exactly what is happening.
| nhumrich wrote:
| How to win at CORS: Don't use it. Just put the apis you need on
| the same domain, use a reverse proxy. Same-site just works,
| always.
| fraktl wrote:
| This.
|
| But hey, with so many impostors around - they're not capable of
| fathoming how golden this advice is.
|
| Sad truth is, since "developers" don't use this, they genuinely
| don't understand browsers and HTTP and that's what 's
| dangerous.
| blacktriangle wrote:
| This is just not an option for so many very legitimate use
| cases. Building client-side apps that aggregate and display
| information from multiple web services hosting on domains
| totally outside of my control is valuable.
| humbleMouse wrote:
| Exactly, the whole concept of CORS is just a security issue
| waiting to happen. Especially these days with all these cloud
| systems having 14 network layers that all ignore certain
| headers and add other ones.
| locallost wrote:
| My colleagues and I came to the same conclusion some time ago.
| I think CORS is not that complicated in essence, but I don't
| need to deal with it often enough to really memorize all the
| details. And there are many, as the article shows. Somehow we
| were always able to in the end deal with it, but at one point
| we didn't want to anymore. You make all these plans on how this
| service should be service.example.com and that one
| service2.example.com and this kind of feels like building
| something, but in reality it's just a headache unless you
| really need to do this for some reason.
| jaffathecake wrote:
| Don't do this with third party APIs though! It's even riskier
| than adding a third party script.
| qubyte wrote:
| This is the resource I _wish_ I 'd had some years ago when I was
| starting out as a server dev. I remember the (lack of a) Vary
| header in particular causing me hours of frustration.
| Aulig wrote:
| I wish there was a way to let me make POST requests on behalf of
| the user without dealing with CORS. Of course the request
| wouldn't include any user cookies etc to avoid the security
| issues.
|
| I just want to easily let my users make API requests to an API
| whose CORS settings don't allow it. Instead I have to tell my
| users to give me their API key so I can make the request from my
| server. Or I'd have to tell them to run a program that makes the
| requests.
|
| Both options suck for non-technical users.
| jaffathecake wrote:
| > I wish there was a way to let me make POST requests on behalf
| of the user without dealing with CORS. Of course the request
| wouldn't include any user cookies etc to avoid the security
| issues.
|
| You can! And it can include credentials!
|
| You can do this with a basic <form> element, so fetch() lets
| you do the same. What you can't do is read the response.
|
| Demo:
| https://jakearchibald.com/2021/cors/playground/?prefillForm=...
| Aulig wrote:
| Thank you! Unfortunately I need to read the response (so
| extra thank you for pointing that out before), but maybe just
| posting will be enough for a future application :)
| rogual wrote:
| If CORS is supposed to solve the problem of credentials being
| sent to third-party sites without the user's knowledge, I don't
| understand why the solution wasn't just to not send the
| credentials.
| jaffathecake wrote:
| That isn't all it's supposed to solve. Give the article a read,
| these points are specifically addressed :)
| rogual wrote:
| Enlightening, thanks! I had thought maybe a site could in
| theory use your IP or even just your ability to connect to
| figure out who it thinks you are, but didn't know this was so
| common.
| lwouis wrote:
| When developing a webapp these days, I use a local proxy.
|
| This allows me to type a staging/production URL into Chrome, and
| get the frontend and the backend from either my local machine or
| staging/prod. I can mix and match any combination by
| checking/unchecking a box in Proxyman.
|
| This means there is no need to whitelist localhost for CORS, and
| other hoops. Another advantage is that you're experiencing the
| app with SSL, so you may notice bugs that you would miss if
| you're used to work with HTTP locally. I've had these bugs which
| "only happen on production" in the past, and it's a nasty thing
| to deal with because it will be in a rush, since it happens as a
| surprise, and impacts users immediately. It can also bypass QA if
| the QA environment is also using workarounds and not a prod-like
| setup with SSL and the likes.
|
| I recommend giving it a try. It's a workflow I haven't seen
| promoted anywhere before.
| raihansaputra wrote:
| Thanks for the tip for Proxyman!
| Jenk wrote:
| Alternatively there are dynamic DNS services like
| https://sslip.io/, https://nip.io, or if it ever comes back:
| https://xip.io.
|
| They let you use hostnames that redirect, so for example:
| https://foo.127.0.0.1.sslip.io will redirect to your localhost.
| tomashubelbauer wrote:
| I tried to achieve the same thing in the past and have run
| across issues with HSTS. The details are escaping me but I
| think it might have been that when using the production app
| without a proxy, the SSL certificate was associated with the
| HSTS records in the browser and when I switched to a proxy, the
| HSTS started failing because the certificate has changed. Have
| you run into this at all? How have you solved it?
| llimllib wrote:
| I don't develop at the same URL as I publish at - I'll
| generate keys with mkcert and host my site locally via a
| proxy at local.realdomainhere.com for a site that has
| dev.realdomainhere.com and the prod domain
| www.realdomainhere.com.
| tomashubelbauer wrote:
| I see, I misunderstood. My dream setup is one where I have
| the same URL for TEST/STAG/PROD and just switch which BE
| the URL resolves to based on some configuration/tool.
| Jiocus wrote:
| I have a certain workflow similar to this.
|
| 1. Let testing/staging environments present the same,
| valid certificates and keys as your production domain.
| Simply keep a copy for your internal use.
|
| 2.1 modify /etc/hosts so that production aliases
| localhost
|
| or
|
| 2.2 let an internal DNS service do the spoofing work.
|
| You'll still need some action to switch between
| environments. Full ownership of certificates is a
| recommendation. At your own risk.
| kijin wrote:
| HSTS doesn't complain as long as there's a valid certificate.
| If you ran into problems because of different certificates,
| you probably had HPKP.
| Steltek wrote:
| I run into occasional HSTS issues on my home network
| sometimes because I've wildcarded HSTS and not everything
| internal has a cert. It's usually recently arrived IoT
| stuff that hasn't been cordoned off behind a stronger
| proxy.
|
| Additionally, I run my own internal CA for various reasons
| and Firefox/Android seems to have stopped recognizing it.
| Irritating but it's a good razor for whether to upgrade
| internal or experimental apps to a Let's Encrypt cert.
| chrismorgan wrote:
| Point of fairly idle curiosity about the presentation of the
| article: why do you put a trailing slash on your empty elements
| (img, link) in your code samples?
|
| Some aren't aware that the trailing slash is useless in the HTML
| syntax, simply being ignored by the parser and not doing
| anything. (Except for in inline SVG and MathML content, which
| switch the parser into a more XML-like mode where the trailing
| slash behaves as in XML.) I know you're not in that category.
|
| Some hold that the trailing slash should be encouraged because it
| reminds the reader it's a void element.
|
| I can _imagine_ some recommending it for XML compatibility (which
| is related to the original purpose of the ignore-the-trailing-
| slash behaviour, though slightly inverted in direction), but I
| don't think I've ever encountered anyone saying so.
|
| I hold that in HTML syntax the trailing slash is mildly harmful,
| because I almost never see it applied consistently so that the
| document wasn't valid XML syntax anyway (for example, your site's
| source has a <link rel="preload" as="font" crossorigin
| href="/c/logo-font-5449c974.woff2">) and because it misleads
| people into thinking that it's a way of closing elements.
|
| So yeah, I'm curious, because it looks deliberate. Habit? Reason?
| :-)
|
| (For those that don't know about the two syntaxes for HTML: XML
| syntax for HTML is still a thing and probably always will be;
| load data:application/xhtml+xml,<html%20xmlns="http://www.w3.org/
| 1999/xhtml"/> in your browser as a starting point for a
| demonstration.)
| EE84M3i wrote:
| For me, I write the trailing slash because it's easier for me
| to reason about mentally. It also means I don't have to context
| switch if I'm writing JSX or XML instead of HTML.
| srgpqt wrote:
| For me, adding the ending slash is just like adding semicolons
| at the end of javascript statements. They may be optional
| sometimes, but there is something to be said about consistency
| and clarity that comes with using them always. Less cognitive
| overload to boot.
| kadoban wrote:
| Aren't they optional 100% of the time though?
| Waterluvian wrote:
| Not 100%. There are a small handful of really wicked
| gotchas. I think there's a lot of articles on them. I can't
| find the one I like and don't want to share one I haven't
| read yet.
| [deleted]
| chrismorgan wrote:
| Here's an example in each direction.
|
| In this first example, ASI inserts an undesired
| semicolon: return {a: 0}
|
| This returns undefined, and doesn't continue on to
| execute the block containing a statement 0 with label a.
| (Change it to {a: 0, b: 0} and you get a syntax error
| because of this reinterpretation of what was intended as
| an object literal.)
|
| In this second example, ASI _doesn't_ insert a desired
| semicolon: f() [].forEach.call(...)
|
| This becomes a syntax error, because the [] has become
| subscripting rather than an array literal. (Incidentally,
| [].forEach is smelly anyway; prefer
| Array.prototype.forEach, maybe assign that to a constant
| if you're doing it much.)
| runarberg wrote:
| The second example could be replaced with something more
| common like: f() ['foo',
| 'bar'].forEach(...)
|
| Which is probably a type error, except if `f()` returns
| something like: function f() {
| return { bar: ['Not the array', 'you were
| expecting'], } }
|
| Then you would actually iterate over the returned `bar`
| array, not the expected `['foo', 'bar']` array.
|
| Another fairly likely example of a desired semicolon not
| inserted is when the following line starts with a
| template string literal: f()
| `This is tagged with whatever f() returns`
|
| This will most likely be a type error, except if `f()`
| returns a function, that function will then be called on
| the template string to do whatever. However I have a hard
| time imagining when you would want to start a statement
| with a template string literal without doing something
| smelly like: `some ${interpolated}
| string`.includes(someVar) ? sideEffectA()
| : sideEffectB()
| chrismorgan wrote:
| Although there are certainly some similarities, trailing
| slash on empty tags is a different case to automatic
| semicolon insertion. Semicolons are mostly optional, but the
| trailing slash is never required, and does absolutely nothing
| --most specifically, it _doesn't_ close tags, and that's what
| I'm getting at with my position of the trailing slash being
| mildly harmful: it's teaching a mental model that's simply
| wrong.
| doliveira wrote:
| The name is literally a "self-closing tag", isn't it? And
| it's better for someone else reading: you may not recall
| what the tag is, but you know you don't have to look for a
| closing tag below.
| chrismorgan wrote:
| But that's the thing-- _it doesn't do that_. If you want
| an empty div, you _can't_ write <div/>, because that's
| equivalent to just <div>; you'll have to write
| <div></div> instead.
| srgpqt wrote:
| It's just that some tags (like IMG) are always self-
| closing, some are never self closing (DIV) and some can
| optionally be closed (P). The trailing / just signals the
| reader that the tag is meant to end then and there.
| 5e92cb50239222b wrote:
| Code (and layout) is written for the human reader first.
| The machine does not care about most whitespace, should we
| write everything into a single line? (Some of my colleagues
| seem to think so.)
| _ZeD_ wrote:
| FWIW I personally find more readable a /> as "end of empty tag"
| jaffathecake wrote:
| Author here! I used to have strong feelings about formatting
| stuff like this, but I since realised there are better things
| to spend effort on.
|
| For formatting, I just let https://prettier.io/ do it's thing,
| and it added the />. Although I do configure it to use single
| quotes in JS, so I guess I still have some opinion there.
|
| In terms of HTML, how far does your "but it isn't necessary"
| opinion go? Lots of closing elements are unnecessary in HTML,
| for instance, check out the source of
| https://fetch.spec.whatwg.org/
| chrismorgan wrote:
| Well, for my own _personal_ stuff I omit just about all that
| I can--head /body start and end tags, html end tag (not start
| tag because it has at least a lang attribute), tbody start
| tag where possible, thead/tbody/tfoot/tr/th/td/li/dt/dd/p end
| tags almost all of the time, attribute value quotes where
| valid... mostly just because it's fun doing so, and in some
| cases because it makes things decidedly cleaner (especially
| tables). I also don't use autoformatters because I will often
| disagree with their opinions in specific cases.
|
| For stuff I'm working on with others, I'll act more like a
| normal person, though I will still _prefer_ to drop at least
| <head></head><body></body></html>, and I've never worked with
| anyone that wanted to put trailing slashes on void elements
| (and haven't ever used Prettier on HTML, evidently).
|
| As for Prettier putting the trailing slash in: huh, that's a
| _really_ weird decision (and no flag for it!), given that
| they're not emitting valid XML (not escaping >, at the
| least), so it's just the personal preference thing, for
| something that was just added as an XHTML compatibility
| mechanism.
| jaffathecake wrote:
| Seems like your HTML formatting opinions are very similar
| to the owner of the fetch spec!
|
| Yeah, I don't always agree with Prettier, but ugh, I wasted
| hours in my early career arguing about formatting with
| teammates, but now I just let Prettier do it's thing, get
| over it, and spend the time on something else.
| chrismorgan wrote:
| Hence me only living life on the edge like that in
| personal projects! Most of what I write with others these
| days is in Rust, and I definitely go along with using
| rustfmt on such projects, even if I regularly dislike its
| opinions (sometimes even strongly).
| jaffathecake wrote:
| If you're interested, the discussion rages on in
| https://github.com/prettier/prettier/issues/5246
| adminscoffee wrote:
| very cool, wish dart/flutter made the list.
| johnmaguire wrote:
| I know it's not necessary, but I do it to distinguish to the
| reader whether they should expect a closing tag or not.
| AlbertoGP wrote:
| > I can imagine some recommending it for XML compatibility
| (which is related to the original purpose of the ignore-the-
| trailing-slash behaviour, though slightly inverted in
| direction), but I don't think I've ever encountered anyone
| saying so.
|
| Well, pleased to meet you!
|
| I do use it for XML compatibility: it allows me to use XML
| editor modes (usually _nxml_ in Emacs) which, being simpler to
| implement as they don't have to encode the rules of which tags
| close where, are more likely to be available and to work well.
|
| I've also done little customizations to _nxml_ over the years,
| and this way I have them always there no matter whether I'm
| working with XML or HTML.
|
| And then occasionally I use other XML tools on it, such as
| _xsltproc_. You can still pipe the HTML through _tidy_ to
| translate it (although xsltproc has --html, tidy has been more
| reliable), but having it compatible with XML does spare me
| small chores again and again.
| chrismorgan wrote:
| Yeah, that's fair enough. In the past I was more likely to
| close tags like p/tr/td than I am now because the Vim indent
| file I was using for html didn't handle some of those
| properly back then.
___________________________________________________________________
(page generated 2021-10-15 23:03 UTC)