Hi everyone, I'm building a kmp project with the t...
# ktor
r
Hi everyone, I'm building a kmp project with the targets android, ios, desktop and wasmjs where I want to use the Ktor HttpClient to request data from the openlibrary api. It works as expected from all targets, but starting the app with the wasmJsBrowserDeveloperRun task (or wasmJsBrowserProductionRun) the request fails with an error in the CORS preflight step (on the server that I obviously do not control). I'm using Ktor 3.1.2 and the ktor.client.js.wasm.js package and for the wasmJs target the io.ktor.client.engine.js.Js.create() method to create a HttpClientEngine. Is this 'just' a setting (i.e. header) on my side I miss (client!) or is it to early to have a preflight CORS request from the Ktor wasm client?
c
I don't know the specifics of this situation, but usually: CORS is configuration from the server to the browser, telling the browser what the site is allowed or not to access. This protects end-users from client-side script injections (even if a client-side injection is successful, the browser will refuse the request). This is something that is configured by the server, and that the browser itself enforces, the client has no control over it. Non-browser platforms ignore the CORS configuration, but presumably you would see the same issue in KJS since it runs in the browser too.
t
Yes, this is specific to browsers and happens when you try to call a resource that’s not under the same host (e.g., example.com accessing someOtherWebsite.com) or under the same host but a different port as well. The server has to return
Access-Control-Allow-Origin
with your domain name. One method to bypass this is to run a reverse proxy in your server to collect data from
openlibrary api
r
Thx @theapache64 all good, I know how CORS works, but my issue is with the client, not the server! Especially the new wasmJs client. The Openlibrary API works via all other channels, the other targets, and also directly from the browser. Here is the link that fails when sent from the Js HttpClient that comes from the io.ktorktor client js wasm js3.1.2 package: https://openlibrary.org/search.json?q=Kotlin&language=eng&fields=key%2Ctitle%2Cautho[…]lish_year%2Clanguage%2Cnumber_of_pages_median%2Cedition_count Just klick on it and you will see that it works perfectly from whatever browser or app. No need for a proxy. Therefore my question, is it a bug in the wasmJs implementation in the case the server uses a CORS preflight (the pre-test, which is almost always the case, however, if I'm right you can switch this behavior even off in some browsers) or do I have to setup Ktor Client differently?
c
Just klick on it and you will see that it works perfectly from whatever browser or app. No need for a proxy.
That's because it's a direct request from the same-origin. You (the user) wants to access that page. CORS (cross-origin resource sharing) doesn't come into play. Now if you host a website under your own domain name, and that website tries to access that page, then it's a cross-origin request and CORS gets triggered.
The client JS/Ktor code can in no way control whether a request is successful or not after CORS. This is done by the browser, Ktor has absolutely no say in this.
r
Yep, understood what you mean @CLOVIS and I'll try from a server with a proper domain as well as soon as I find some time to. However, I found this about the security model of wasm (https://webassembly.org/docs/security/), the devil could indeed be in the details. No clue how the openlibrary api has CORS implemented. Could be likely that they have the "*" setting. Didn't found any doc about it yet. But it definitively makes sense to understand the wasm security model better. I'll write it here as soon as I find a solution. Thx!
@theapache64 @CLOVIS found it! It was indeed a setting in my Ktor Client Factory. I had a default setting for each request.
Copy code
defaultRequest {
    contentType(ContentType.Application.Json)
}
The CORS preflight error was telling already what the problem was: '... has been blocked by CORS policy: Request header field content-type is not allowed by Access-Control-Allow-Headers in preflight response.' By setting the the content type for each request the CORS preflight request failed. Cool, thx for your help!
c
Uh, wow, I never realized this could be an issue. TIL, that definitely sounds like something that could trip people up.