Skip to content

Commit

Permalink
add web2 docs
Browse files Browse the repository at this point in the history
  • Loading branch information
Fleeym committed Jun 8, 2024
1 parent 7260552 commit 2349d5f
Show file tree
Hide file tree
Showing 2 changed files with 105 additions and 2 deletions.
103 changes: 101 additions & 2 deletions tutorials/fetch.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,107 @@
# Making Web Requests
# The new web request API (web.hpp)

> :warning: This is the documentation for the new web API. We have left the old documentation at the bottom of the page, for the time being
Making web requests in C++ sucks, and GD doesn't really help with it. Cocos2d has the `CCHTTPRequest` class, which GD uses to make its web requests, but it's a complicated mess to try to get working and it's not really ergonomical.

Luckily, Geode come to the rescue with the `geode::utils::web` namespace, which contains functions resembling a familiar web API: **fetch**. Geode has two types of web requests: **synchronous** and **asynchronous**.
To fix this, Geode has the `WebRequest` API, which is much more versatile. All web requests are **asynchronous**, so they run on a separate thread.

Under the hood, the `WebRequests` API uses [Tasks](/tutorials/tasks), so make sure you have read that guide before going into this one.

## Creating a web request

Creating a web request is as simple as creating a new `WebRequest` object, and setting some params on it.

```cpp
#include <Geode/utils/web.hpp>

web::WebRequest req = web::WebRequest();

// Let's add some query params
req.param("one", "two");
req.param("three", "four");

// Maybe set our UserAgent?
req.userAgent("Geode Web Request!");

// For POST / PUT requests, we should probably send a body. Choose whichever suits your needs

// Byte vector (std::vector<uint8_t>)
req.body({ 0x23, 0x24, 0x25 });
// Strings
req.bodyString("Hello, server!");
// JSON (uses any matjson::Value)
// Note that you should probably have some actual data in your json
auto myjson = matjson::Value();
req.json(myjson);

// Let's set some headers, shall we?
req.header("Content-Type", "application/json");

// Set a timeout for the request, in seconds
req.timeout(30);
```
There are more functions, regarding certificate verification, proxy settings. You can find more info about them by looking through the headers!
Now, let's send out request. The API has specific methods for POST, GET, PUT, PATCH. If you want to send a different method, you can use `.send()`. Calling these functions will return a **WebTask**, which is just an alias for `Task<WebResponse, WebProgress>`.
```cpp
// We're still using the same 'req' object from the codeblock above...
std::string url = "https://example.org";
// Let's do a POST request
auto task = req.post(url);
```

## Getting the response from our request

If you remember the [Tasks](/tutorials/tasks) tutorial, you probably also remember that Tasks have to listened to using the [Events](/tutorials/events) system. We can create an `EventListener` for our request and use it to get our response.

```cpp
class MyCoolClass {
EventListener<WebTask> m_listener;
};

// Continuing our code from above...

m_listener.bind([] (web::WebTask::Event* e) {
if (web::WebResponse* value = e->getValue()) {
// The request finished!
} else if (web::WebProgress* progress = e->getProgress()) {
// The request is still in progress...
} else if (e->isCancelled()) {
// Our request was cancelled
}
});
m_listener.setFilter(task);
```
> :warning: Note that if the task itself goes out of scope, then the request will cancel. If the listener goes out of scope, then the callback will never be called, hence if you want to replace your request, you should cancel the current one, and call setFilter() on the listener instead of creating a new one.
Once we receive our response, we can check multiple things on it! You can see the list of everything you can do with intellisense, or by checking the headers.
```cpp
// Check if the response status code is 2xx
res->ok();
// Get the actual status code
res->code();
// Get a specific header
res->header("Content-Type");
// Get all headers
res->headers();
// Get the response body as bytes
res->data();
// Get the response body as a string
res->string();
// Get the response body as matjson::Value (json)
res->json();
```

## The old web APIs

The old web APIs were deprecated as of **v3.0.0-alpha.1**, you can still find them on older versions of Geode. They contains functions resembling a familiar web API: **fetch**. Geode has two types of web requests: **synchronous** and **asynchronous**.

## Synchronous requests

Expand Down
4 changes: 4 additions & 0 deletions tutorials/tasks.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,10 @@ m_taskListener.setFilter(calculation());

> :warning: `setFilter` should always be called after `bind`
## Lifetime of a Task

> :warning: The Task lives as long as the handle (the Task object) is not destroyed. If the handle is destroyed, then the task will be marked as **cancelled**. At the same time, you should also not destroy **the listener** while the request is running. Since all callbacks run on the next frame (on the main thread), then if the listener is destroyed before that, **the callback will never be called**.
## Other ways of creating Tasks

There are other ways to create Tasks. We will go summarily through them, you can find out more info about them by **reading the header file**.
Expand Down

0 comments on commit 2349d5f

Please sign in to comment.