// PKL-129: HTTP fetch wrapper for URI imports on the native target.
// `main` is `async fn main`, so we can await `@http.get` directly.
///|
/// Fetch the body of `url` over HTTP / HTTPS. Returns the decoded body
/// on success, `None` on failure (with the message printed to stdout
/// so the caller's `fail` path surfaces an unambiguous diagnostic).
///
/// PKL-129b1: follow up to 5 redirects (301 / 302 / 303 / 307 / 308).
/// `pkg.pkl-lang.org` returns 301 redirects to a CDN host before
/// serving the metadata JSON, so without redirect-following the
/// registry probe always fails. The 5-hop cap matches `curl`'s
/// default and prevents loops.
pub async fn fetch_uri(url : String) -> String? {
let mut current = url
let mut remaining = 5
while remaining > 0 {
try {
let (resp, body) = @http.get(current)
if is_http_redirect(resp.code) {
match resp.headers.get("location") {
Some(next) => {
current = next
remaining = remaining - 1
continue
}
None =>
match resp.headers.get("Location") {
Some(next) => {
current = next
remaining = remaining - 1
continue
}
None => {
println(
"http \{resp.code} \{resp.reason} fetching \{current} (no Location header)",
)
return None
}
}
}
}
if resp.code < 200 || resp.code >= 300 {
println("http \{resp.code} \{resp.reason} fetching \{current}")
return None
}
return Some(body.text())
} catch {
e => {
println("http fetch failed: \{e}")
return None
}
}
}
println("http fetch failed: too many redirects (last url: \{current})")
None
}
///|
pub async fn fetch_uri_bytes(url : String) -> Bytes? {
let mut current = url
let mut remaining = 5
while remaining > 0 {
try {
let (resp, body) = @http.get(current)
if is_http_redirect(resp.code) {
match resp.headers.get("location") {
Some(next) => {
current = next
remaining = remaining - 1
continue
}
None =>
match resp.headers.get("Location") {
Some(next) => {
current = next
remaining = remaining - 1
continue
}
None => {
println(
"http \{resp.code} \{resp.reason} fetching \{current} (no Location header)",
)
return None
}
}
}
}
if resp.code < 200 || resp.code >= 300 {
println("http \{resp.code} \{resp.reason} fetching \{current}")
return None
}
return Some(body.binary())
} catch {
e => {
println("http fetch failed: \{e}")
return None
}
}
}
println("http fetch failed: too many redirects (last url: \{current})")
None
}