ppy / osu-api

Public API for accessing osu! related data.
320 stars 16 forks source link

osu!api is not fetch-compatible #135

Open ghost opened 7 years ago

ghost commented 7 years ago

I couldn't find an issue on this one so I guess I'll open one.

The osu!api is not fetch-friendly.

Or at least it is if you provide a valid API key, but if you ever provide an invalid API key, the server responds with a 401 without setting the Access-Control-Allow-Origin header is not set on the response and therefore makes fetch completely fail. At least on some implementations.

Usage example:

fetch("https://osu.ppy.sh/api/get_users?key=invalid_key&u=1337")
.then(function(response)
{
    console.log("This never gets processed because the browser will fail before the response can even be handled");
})
.catch(error)
{
    console.log("This never gets processed either because the browser will not consider this error as a network error and will just directly throw outside of the promise");
});

And the browser will throw an error like this one:

No 'Access-Control-Allow-Origin' header is present on the requested resource.
Origin 'http://mysuperdomain.lol' is therefore not allowed access.
The response had HTTP status code 401.
If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

And as said above, the error is thrown completely outside of the promise so the error just can't be handled properly.

I know the fetch API is pretty new but it would be pretty great if the osu!api could support it completely.

Oh and before someone starts asking why would you provide an invalid API key: I'm currently making a web service where users can enter their API key and get some goodies. So in this case, if some user ever enters an invalid API key, I can't handle the error properly and this makes me sad, because I like handling errors.

omkelderman commented 7 years ago

Pro-tip: _do not_ ask users for their API key! From https://osu.ppy.sh/p/api:

DO NOT GIVE THIS OUT TO OTHERS. IT'S EQUIVALENT TO GIVING OUT YOUR PASSWORD. YOUR ACCOUNT MAY BE COMPROMISED.

ghost commented 7 years ago

Sorry, I understand how this could have caused confusion.

It's not actually to get their api key, since the data is never sent to the server.

It's just some application that, when provided an api key, does requests for the user - on his computer and not on a server - to retrieve data and display it in some way.

For example you give it an api key - not sent to the server, just kept in the browser memory - and the application will retrieve, like, an user and display some data on him.

It's actually more complicated but it won't help the discussion to speak about it here.

I'm not stealing api key if that's your concern.

omkelderman commented 7 years ago

Sure, I got that, and while I believe you, I don't have a guarantee that you'll not snipe my api-key. Thing is, things like this can potentially lead to malicious stuff, im not saying you're a bad guy, just that apps like that are (imo) inappropriate.

I've seen webprojects like this (where you had to input api key), I never used them. (again, this is mostly just my opinion)

kkartaltepe commented 7 years ago

If you want to present nice information about a user you should have them enter their username/id and do the calls from your app using your app's API key. I don't think you should be trying to subvert the API key system by having users create their own keys to feed into your system (in addition to this being a security concern as already mentioned).

As for making the API fetch compatible. I don't see any issue except that it makes this use of API keys on the client side more feasible when API keys shouldn't be exposed to the user and, a user of a service shouldn't need an API key.

ghost commented 7 years ago

Alright so.

The application is not about fetching the users and display informations about them, it's about fetching a room and calculating user scores, mainly for tournaments. I'm creating this app mainly just for a tournament, to simplify referee's work.

But really the issue is totally not about that. You can believe me or not, I just don't care. It still doesn't help this issue and is totally irrelevant in this case, so please stop talking about it, I'm mainly reporting an issue with the osu!api, not talking about why my application is bad.

The fetch problem is a CORS protocol issue, and since CORS seems to be a standard used in every fetch api that are implemented, that will also be a new standard replacing XMLHttpRequest, it probably means that web APIs such as the osu!api will need to switch to this new standard one day (I guess, I'm not sure about it).

It also means that the problem can reside in either client-side or server-side, because the fetch API can also be used on the server side (at least for Node.js applications).

If I were to change my application to fetch items on server-side and therefore use MY api key and not the user's one, it would still fail because the response when the api key is invalid doesn't return the Access-Control-Allow-Origin header, and because the fetch api doesn't support such responses.

If it's not important, not feasible, not useful or anything else, please just close it and be done.

Oh and just to be clear about something, the application I'm developing is and will remain on github, completely open source, and will probably be used only by a few people that trust me enough to use their api key, so really, please stop. I was just using it as an example because I discovered this "issue that could be just something unimportant" during the development of this app, but it could just be anything else.

omkelderman commented 7 years ago

But really the issue is totally not about that. You can believe me or not, I just don't care. It still doesn't help this issue and is totally irrelevant in this case, so please stop talking about it, I'm mainly reporting an issue with the osu!api, not talking about why my application is bad.

The thing is, it is relevant. This is a issue specific to client-side-javascript-requests. The problem is (as you indeed have pointed out) that the api does not return a Access-Control-Allow-Origin. Which in my opinion is indeed correct since it should not allow any origin to fetch data!

It also means that the problem can reside in either client-side or server-side, because the fetch API can also be used on the server side (at least for Node.js applications).

This is not the case! Afaik in the current latest nodejs build the fetch API is not there, but even if it was, it would not matter: requests coming a server do not suffer from having that header not set. It'll just work.

Oh and just to be clear about something, the application I'm developing is and will remain on github, completely open source, and will probably be used only by a few people that trust me enough to use their api key, so really, please stop. I was just using it as an example because I discovered this "issue that could be just something unimportant" during the development of this app, but it could just be anything else.

I get that, but my point is, that it should be actively discouraged to have such kind of apps.

_To summarize:_ I completely understand that you have no malicious intentions with your project. I also understand that only a few people will use it. But it is in general not recommended to do anything with the osu api in client-side-javascript. Therefore I recommend to keep the current behavior to discourage others from doing so, potentially allowing malicious things.

What I recommend to you is if you are creating a small tool to help out a few people to make their lives easier do one of the following:

ghost commented 7 years ago

I didn't come here to get tips on how to code, I just wanted to report an issue, so I'll just ignore your comment and pretend someone will someday speak about the issue at hand.

RomainGuarinoni commented 3 years ago

Hello, I am answering this question a little late but I have found a way to solve this problem! In fact, you won't be able to fetch data from a website because the osu api doesn't allow to fetch data from a website (because of the cors policy). Instead, you can create your own server by using express (for example) and then, from your server, fetch the api of osu (with axios for example) and return the osu data in your response . Then, you can call from your website your own server which will return you the data of the api of osu.

lnfel commented 2 months ago

What I hate most is when people ask genuine questions and people straight out being rude and not even trying to talk about the topic at hand. OP question is valid, I've set-up multiple back-end apps that dealt with public facing API, if you want users to consume API just freakin send the Access-Control-Allow-Origin response header and set it to *. I know this has been dealt with v2 but this behaviour is just unacceptable in my standards.

And yes, Romain's answer is right. Currently osu API (v2) does not allow client-side access to API due to security reasons, calls must be done server-side.