Summary#
Http.* is the outbound-HTTP facade for URLs you can't name at author time — a webhook target, a REST API, an
endpoint that comes from data. It mirrors the shape of a familiar HTTP client:
use Osyrin.Http;
var r = Http.Get("https://api.example.com/orders/" + order.Code);
if (r.IsSuccess) {
order.Tracking = r.Body;
}Every verb returns an HttpResponse (StatusCode, Body, IsSuccess). A non-2xx status is a normal return,
not an error — a 404 gives you r.StatusCode == 404 and r.IsSuccess == false, so you branch on the result instead
of catching an exception.
For a declared, fixed endpoint with typed request/response, use a client block instead — Http.* is the
escape hatch for the dynamic case beside it.
Signature#
use Osyrin.Http;
HttpResponse Http.Get(string url [, Map<string, string> headers])
HttpResponse Http.Delete(string url [, Map<string, string> headers])
HttpResponse Http.Post(string url, string body, string contentType [, Map<string, string> headers])
HttpResponse Http.Put(string url, string body, string contentType [, Map<string, string> headers])
HttpResponse Http.Patch(string url, string body, string contentType [, Map<string, string> headers])url— an absolutehttp/httpsURL.body/contentType(Post/Put/Patch) — the request body text and its media type (e.g."application/json").headers(optional, any verb) — extra request headers such asAuthorization. AMap<string, string>.
Description#
Http.* is enabled by declaring the dependency in your app manifest:
app Shop {
model "model/**/*.osy";
use Osyrin.Http;
}An Http.* call without use Osyrin.Http; is a compile error naming the fix — a network dependency is visible in the
manifest, not hidden in a function body.
Default open, host-protected. You can reach any public host — that's your call, the same as any dependency.
What the platform guarantees is that you cannot reach its own internals: a URL that resolves to a loopback,
private (10.x/192.168.x/…), or cloud-metadata address is refused — checked against the resolved address, so a
hostname that points at an internal IP is blocked too. Two more limits protect the host: an absolute timeout ceiling
and a maximum response size; a call that runs too long is cancelled and an over-size response is refused.
Headers and auth. Pass a headers map to authenticate an outbound call or set a custom content type:
var headers = new Dictionary<string, string>();
headers.Add("Authorization", "Bearer " + token);
var r = Http.Post("https://hooks.example.com/notify", payload, "application/json", headers);Bodies are text. The request body and the response Body are strings. Build or parse JSON with the JSON surface
(paired with this facade) — Http.* moves the bytes; it doesn't assume a format.
Long-running callbacks aren't held connections. If an external system calls you back minutes or hours later, model
that as a workflow event (a webhook that raises an event), not an Http.* call that blocks — the timeout ceiling
exists precisely so a call can't hold a connection open indefinitely.
Examples#
Post a JSON webhook and record whether it was accepted:
// `use` is a MANIFEST declaration — it belongs in your app.osy, not in a model file.
app Shop {
model "model/**/*.osy";
use Osyrin.Http;
}
entity Order {
[Required] string Code;
bool WebhookAccepted;
int WebhookStatus;
}
void NotifyShipped(Order order) {
var body = "{\"order\":\"" + order.Code + "\",\"status\":\"shipped\"}";
var r = Http.Post("https://hooks.partner.com/orders", body, "application/json");
order.WebhookAccepted = r.IsSuccess;
order.WebhookStatus = r.StatusCode;
}Call an authenticated API and use the response body:
string LookupTracking(string carrier, string code, string token) {
var headers = new Dictionary<string, string>();
headers.Add("Authorization", "Bearer " + token);
var r = Http.Get("https://api." + carrier + ".com/track/" + code, headers);
return r.IsSuccess ? r.Body : "";
}See also#
- HttpResponse — the
StatusCode/Body/IsSuccessresult every verb returns - File.Url — the other capability-gated I/O surface (
use Osyrin.Storage;)