[Scarpet Suggestion] Add web requests to scarpet
Ghoulboy78 opened this issue ยท 5 comments
Title kinda says it all.
This would entail adding a function like: web_request(url, method, options?)
where url
is (rather obviously) the url, method
is one of: get
, put
, delete
, or head
. The optional options
parameter is a map of all the parameters, like auth tokens, or a form perhaps.
About the responses... A string response is probably good enough. There's no need for anything else, there are built-in methods to parse things like JSON, and the programmer will have to implement their methods for other encodings anyway.
there is not a datatype for bytes. maybe return base64-ed string. if it was a string, It only takes one line to change it back. if it not a text or (is text, but without using the carpet's preferred encoding), the user can do the thing they want as well.
But I still don't understand why an app needs network permissions. It's not a good choice any way you look at it.
Technically each app from the appstore is capable of fetching any arbitrary web resource, but its all limited to downloading.
Consideration about 'preventing downloading dangerous files' vs 'just fetching string responses' is that they are equivalent (pretty much). The only way to combat it is the fact that apps are scripts, so open source, and at least submitting them to the default appstore is warranted with some community supervision. As an admin, what you do with your scripts is up to you.
In terms of considerations for blocking aspects of requests - seeing no problem with that. The simplest the API the better, otherwise one would unnecessarily complicate this stuff. If you need to lazy fetch those making a task is the proper way to do it. I guess if you know how to handle parallel tasks you would understand scarpet tasks enough to do that.
In terms of a good model, pythons 'requests' library is a good example of not overcomplicating things. You would have as input (uri, method, timeout?, params?, headers?, body?) or (uri, method, options?) where options is a map with all optional requests keys, like params, headers, body, timeout etc) and with a response {content -> ..., status -> code/timout,etc , headers -> ...} and that's it? I woudn't bother with encoding / streaming at this point. @Ghoulboy78 before you comment further on that topic I recommend you take a look at that classic library.
Another thing that would be complex to provide is cookies and sessions, Don't think that's needed
Comment by @altrisi :
This addition could be debatable because it can easily break sandboxing of apps. You are basically handing them all the internet. If implemented poorly (by Carpet or by an app), a player could from making the server call a "bad" url (may leak things like IPs under a proxy) to tricking the app into downloading potentially unwanted files that could get flagged as provided by Carpet. Is this really an issue? Well, probably not. It should be the programmer's responsibility to use it with caution.
Now, complexity. You'd have to think what you want to support. The most common request type is GET, which is, in simple terms, just having an url and making a request to it. However, you also have POST (like GET but with more params), PUT, DELETE, PATCH. Would those be supported? Including sending whole files to an URL?
Not only that, given that you are handing this powers to an app that is most likely going to use this to access APIs, so you'll most likely need to provide methods to attach headers into requests in order to be able to attach things like authentication/API tokens, special request parameters, etc.
Let's get into performance and blocking the game thread... What to do with that? I can think of multiple ways to deal with that, since it'll be necessary since you don't really want a long web request (for example, 30s) to stall your game's thread (potentially triggering watchdog if you are not careful). One possibility would be limiting requests to not run on the server thread (throw IEE if that's the case) but be on a task (value), however this makes it more difficult to implement from Scarpet code since tasks is not really a heavily used feature. Another way would be the request actually returning a task, making it more flexible to work with, since if it's a critical request you can immediately join it, but we still hit a bit of complexity given we are still using tasks (plus maybe you could even cancel it). Last but not least, you could add a callback parameter to the request function that would be called when the request finishes (probably docking it to the main thread/caller's thread), however that would remove the flexibility of it given you can't really control what happens with it, plus there's no way at all to force a critical request to block the execution of the game.
About the responses... A string response is probably good enough. There's no need for anything else, there are built-in methods to parse things like JSON, and the programmer will have to implement their methods for other encodings anyway.
I feel it worth mentioning that the comment by altrisi came before, not after the earlier comment by gnembon (which is why he mentions in the comment about downloading, a concern raised in altrisi's comment).
With regards to it, it would be safer to only allow to string responses to avoid downloading potentially dangerous files. On the other hand, it is true that that would lend a lot more functionality to scarpet potentially and hey, maybe even simplify the se_installer
app that altrisi was working on by not requiring the file to be downloaded using /script download, but by just having it in the __on_start
method, or static, or with a command. Thus I would agree with gnembon, to allow downloading of files to the app's private area.
As to the actual implementation, I believe it ought to be in separate functions for web_get
, web_post
, web_put
, web_delete
and web_patch
, (or some other prefix, like web_request_get
or smth). This would make it so you don't just have 1 function with all the possibilities squashed into it. On the other hand, squishing all the functionality into one function appears to be the standard in scarpet, as with draw_shape
function, so idk.