Osy#betaa language · its runtime Osyrin · a hosted platform
Why Osy#Built for agentsAgents as declarationsWorkflows that waitRuns exactly onceSecure by defaultNothing to mockThe editor is the compilerUI in the languageDocuments are dataOne program

Reference / HTTP

HttpResponse

class HttpResponse { int StatusCode; string Body; byte[] Bytes; List<HttpHeader> Headers; bool IsSuccess; }

The result of an `Http.*` call. Carries the HTTP status code, the body as text AND as bytes, every response header, and a convenience `IsSuccess` flag for 2xx. A non-2xx status is a normal value here, not an exception — you branch on it.

stable1 example compiled by CIhttpnetworktype

Summary#

HttpResponse is what every Http.* verb (Http.*) returns. It has three fields:

FieldTypeMeaning
StatusCodeintThe HTTP status code — 200, 404, 500, …
BodystringThe response body decoded as UTF-8 text
Bytesbyte[]The body as it arrived — the honest answer for anything that is not text
HeadersList<HttpHeader>Every response header, each with a Name and a Value
IsSuccessbooltrue when the status is in the 2xx range

A non-2xx response is a normal return, so you inspect it rather than catch an error:

use Osysharp.Http;

var r = Http.Get(url);
if (r.IsSuccess) {
  Process(r.Body);
} else {
  Log("fetch failed with " + r.StatusCode);
}

Signature#

class HttpResponse {
  int StatusCode;
  string Body;                   // decoded as UTF-8
  byte[] Bytes;                  // as it arrived
  List<HttpHeader> Headers;      // each has .Name and .Value
  bool IsSuccess;
}

The type enters scope with the same dependency that enables the facade — use Osysharp.Http;. You rarely name it explicitly: var r = Http.Get(url); infers it.

Description#

Body is the response decoded as UTF-8. That is right for JSON and wrong for everything else: an image, a PDF, an object out of a blob store is not text, and decoding it produces mojibake rather than an error. Read Bytes for anything that is not text — it is the body exactly as it arrived, and .Length tells you how much of it there is.

Reading a header#

Headers is a list, not a map, because HTTP headers repeat — Set-Cookie is the everyday case, and a map would silently keep one of them. Each entry has a Name and a Value:

var etag = "";
foreach (var h in r.Headers) {
  if (h.Name == "ETag") { etag = h.Value; }
}

ETag is what verifies a store's own write; Content-Type and Content-Length are the other two anything binary usually wants.

IsSuccess is exactly 200 ≤ StatusCode < 300. It's a convenience for the common "did it work?" branch; when you care about a specific code (a 429 to back off, a 404 to treat as absent), read StatusCode directly.

Examples#

Distinguish "not found" from a real failure:

app Shop {
  model "model/**/*.osy";
  use Osysharp.Http;       // the manifest dependency that makes `Http.*` available
}

string FetchOrEmpty(string url) {
  var r = Http.Get(url);
  if (r.StatusCode == 404) return "";        // absent — expected
  if (!r.IsSuccess) return "";                // some other failure
  return r.Body;
}

See also#

  • Http.* — the Http.Get/Post/Put/Delete verbs that return this type

Related

Http.*

Make an outbound HTTP call to a URL you build at runtime — a webhook, a third-party API, a discovered endpoint…