Skip to content

Commit

Permalink
bug(forgejo): Improved auto-detection
Browse files Browse the repository at this point in the history
Previously, the Forgejo/Gitea auto-detection worked by hittin an
endpoint that only exists on these forges, out of the ones we support.
But it had no indication other than its existence that it is a Forgejo
instance.

While looking at other ways to identify these, I found the
`/swagger.v1.json` endpoint. It has the full API documentation in a
Swagger JSON format, and includes an `info.title` key, which *does*
mention "Gitea API" or "Forgejo API", depending on the forge. It's a
rather large document, however.

Luckily, we don't need the whole document! This file is part of the web
UI, not the API itself, and as such, includes cookies! One of those
cookies is `i_like_gitea` (for both Forgejo and Gitea). As such, we can
do a HEAD request, and check the cookie.

This is both more reliable than the old method, and involves less
network traffic too.

Signed-off-by: Gergely Nagy <me@gergo.csillger.hu>
  • Loading branch information
algernon authored and cafkafk committed Nov 3, 2023
1 parent 10a6066 commit 41c5ec9
Show file tree
Hide file tree
Showing 3 changed files with 132 additions and 9 deletions.
125 changes: 124 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ hyper = { version = "0.14.27", features = ["client"] }
log = "0.4.20"
pretty_env_logger = "0.5.0"
regex = "1.10.2"
reqwest = { version = "0.11.22", features = ["json"] }
reqwest = { version = "0.11.22", features = ["cookies", "json"] }
serde = { version = "1.0.190", features = ["derive"] }
serde_json = "1.0.107"
serde_yaml = "0.9.27"
Expand Down
14 changes: 7 additions & 7 deletions src/api/v1/forges/forgejo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,17 @@ impl Forgejo {
}

pub async fn is_host_forgejo(host: &str) -> Result<bool, ForgeError> {
// I couldn't find a more reasonable way to detect Forgejo, so we'll check
// an API endpoint that is specific to this forge, and if it exists, we
// assume it's a Forgejo instance.
let uri = format!("https://{}/api/v1/settings/api", &host);
let client = reqwest::Client::builder().user_agent(USER_AGENT).build()?;
let uri = format!("https://{}/swagger.v1.json", &host);
let client = reqwest::Client::builder()
.user_agent(USER_AGENT)
.cookie_store(true)
.build()?;
let res = client
.get(&uri)
.head(uri)
.header(ACCEPT, "application/json")
.send()
.await?;
Ok(res.status() == 200)
Ok(res.status() == 200 && res.cookies().any(|cookie| cookie.name() == "i_like_gitea"))
}
}

Expand Down

0 comments on commit 41c5ec9

Please sign in to comment.