Skip to main content

InvokeResponse

InvokeResponse is the fluent response builder passed as the second parameter to every entry point handler. Methods can be chained.

[EntryPoint]
public static Task EntryPoint(InvokeRequest req, InvokeResponse res)
{
res.Status(200).Json(new JsonObject { ["message"] = "Hello" });
return Task.CompletedTask;
}

Status Methods

Status(code)

Set the HTTP status code. Returns this for chaining.

public InvokeResponse Status(int statusCode)
res.Status(201).Json(new JsonObject { ["created"] = true });
res.Status(404).Json(new JsonObject { ["error"] = "Not Found" });

SendStatus(code)

Set the status code and end the response immediately with the status text as the body.

public void SendStatus(int statusCode)
res.SendStatus(204); // 204 No Content
res.SendStatus(404); // 404 Not Found

Response Body Methods

Json(object)

Serialize an object to JSON and send it with Content-Type: application/json.

public void Json(object value)
res.Status(200).Json(new JsonObject
{
["name"] = "Alice",
["age"] = 30
});

Json<T>(T value, JsonTypeInfo<T> typeInfo)

AOT-safe JSON serialization using a JsonTypeInfo<T> from a source-generated JsonSerializerContext.

public void Json<T>(T value, JsonTypeInfo<T> typeInfo)
[JsonSerializable(typeof(MyResponse))]
internal partial class MyContext : JsonSerializerContext { }

record MyResponse(string Name, int Age);

res.Status(200).Json(new MyResponse("Alice", 30), MyContext.Default.MyResponse);

Json(JsonNode value)

Send a JsonNode (e.g., JsonObject or JsonArray) as JSON.

public void Json(JsonNode value)
var items = new JsonArray();
items.Add(new JsonObject { ["id"] = 1, ["name"] = "Item 1" });
items.Add(new JsonObject { ["id"] = 2, ["name"] = "Item 2" });

res.Status(200).Json(items);

Send(string text)

Send a plain text response with Content-Type: text/plain.

public void Send(string text)
res.Status(200).Send("Hello, World!");

Send(byte[] data)

Send raw bytes. Use Type() first to set the correct content type.

public void Send(byte[] data)
var pdfBytes = File.ReadAllBytes("report.pdf");
res.Status(200).Type("application/pdf").Send(pdfBytes);

Redirect(string url, int statusCode = 302)

Redirect the client to another URL.

public void Redirect(string url, int statusCode = 302)
res.Redirect("/new-path"); // 302 Found
res.Redirect("/new-path", 301); // 301 Moved Permanently

End()

End the response with no body.

public void End()
res.Status(204).End();

Header Methods

SetHeader(name, value)

Set a response header. Returns this for chaining.

public InvokeResponse SetHeader(string name, string value)
res.SetHeader("x-request-id", Guid.NewGuid().ToString())
.Status(200)
.Json(new JsonObject { ["ok"] = true });

AppendHeader(name, value)

Append a value to a response header (useful for multi-value headers). Returns this for chaining.

public InvokeResponse AppendHeader(string name, string value)
res.AppendHeader("cache-control", "no-cache")
.AppendHeader("cache-control", "no-store");

Type(contentType)

Set the Content-Type header. Returns this for chaining.

public InvokeResponse Type(string contentType)
res.Type("text/html").Send("<h1>Hello</h1>");
res.Type("application/xml").Send("<result>ok</result>");

File Response Methods

SendFile(filePath, options?)

Send a file as the response body, detecting its MIME type automatically. Returns this for chaining.

public InvokeResponse SendFile(string filePath, SendFileOptions? options = null)
// Absolute path
res.SendFile("/var/task/public/index.html");

// Relative path resolved from a root directory
res.SendFile("images/logo.png", new SendFileOptions { Root = "/var/task/public" });

Responds with 404 if the file is not found, 403 if access is denied, 500 on any other I/O error.


Download(filePath, filename?, options?)

Prompt the browser to download a file as an attachment. Sets Content-Disposition: attachment and delegates to SendFile.

public InvokeResponse Download(string filePath, string? filename = null, SendFileOptions? options = null)
res.Download("/var/task/reports/report.pdf", "monthly-report.pdf");

Attachment(filename?)

Set the Content-Disposition header to attachment, optionally with a filename. Non-ASCII filenames are RFC 5987–encoded. Returns this for chaining.

public InvokeResponse Attachment(string? filename = null)
res.Attachment("résumé.pdf").SendFile("/var/task/files/cv.pdf");

SendFileOptions

Options accepted by SendFile and Download:

PropertyTypeDefaultDescription
Rootstring?"/"Root directory to resolve the file path against
MaxAgeint?nullCache max-age in milliseconds for Cache-Control: public, max-age=N
CacheControlbooltrueWhether to emit a Cache-Control header when MaxAge is set
LastModifiedbooltrueWhether to set the Last-Modified header from the file's mtime
HeadersDictionary<string, string>?nullAdditional response headers to merge into the response
res.SendFile("/var/task/public/style.css", new SendFileOptions
{
MaxAge = 31_536_000_000, // 1 year in ms
Headers = new Dictionary<string, string>
{
["x-served-by"] = "invoke"
}
});

Common Patterns

Success with data

res.Status(200).Json(new JsonObject
{
["success"] = true,
["data"] = new JsonObject { ["id"] = 42, ["name"] = "Alice" }
});

Created resource

res.Status(201)
.SetHeader("location", $"/users/{newId}")
.Json(new JsonObject { ["id"] = newId });

Error response

res.Status(400).Json(new JsonObject
{
["error"] = "Validation failed",
["details"] = "name is required"
});

No content

res.Status(204).End();