i18next / i18next-http-backend

i18next-http-backend is a backend layer for i18next using in Node.js, in the browser and for Deno.
MIT License
447 stars 69 forks source link

browser refuses to load files with credentials in url #122

Closed jemand771 closed 1 year ago

jemand771 commented 1 year ago

🐛 Bug Report

When visiting my site example.com with credentials in the url, e.g. admin:admin@example.com, language files aren't loaded. Interestingly, they don't even show up as failed in devtools' network tab, they just don't happen.

Since "manually" requesting the file (from js code) works, I assume this is related to the way this library does its requests. It's very likely that the browser blocks this request because credentials in urls are somewhat deprecated, however (!) doing the same request from angular's http client (also inside the browser) works.

To Reproduce

I've created a repo with a small example, but you can also just take any existing example, add credentials to the url, and it should break.

To get started from my example repo:

To get started from the sandbox:

Expected behavior

Language files should load even with credentials in the url. I know that feature is deprecated, but i18n suddenly breaking because of it isn't great.

Also, just for the lolz I tried manually requesting the file, just in case this was a general browser issue:

export class AppComponent {
  constructor(http: HttpClient) {
    http.get("/assets/locales/en.json").pipe(first()).subscribe(content => console.log(content));
  }
}

this successfully requests the file and prints its contents

Your Environment

adrai commented 1 year ago

Yes, that's a limitation of the fetch api... Just passt the requested authorization header like this:

      useFactory: (i18next: ITranslationService) => () => i18next.use(HttpApi).init({
        lng: "en",
        backend: {
-          loadPath: "assets/locales/{{lng}}.json",
+          loadPath: "http://localhost:4200/assets/locales/{{lng}}.json",
+          customHeaders: {
+            authorization: 'Basic ' + btoa('admin:admin')
+          }
        }
      }),
jemand771 commented 1 year ago

mhmm, I've tried it manually using fetch and now I get a helpful error message (also listed in the fetch docs)

the problem here isn't that I'm trying to pass credentials, my problem is lazy users that bookmark urls with credentials (don't ask) and unknowingly break language file loading. when I use fetch to request a path, the browser conveniently includes the "current url" which happens to include deprecated-style credentials if the user put them there

but I guess this is more of a general issue I need to work around, not one with the http backend. it just happened to be the first place I noticed it. sorry!

adrai commented 1 year ago

Then define the loadPath to be absolute and not relative.

jemand771 commented 1 year ago

you're right, I can just use

{
  lng: "en",
  backend: {
    loadPath: `${window.location.href}assets/locales/{{lng}}.json`
  }
}

it feels dirty, but it works. thanks!