GenHTTP Lambda

Cara kerjanya

Anda menulis snippet C#. Apa pun yang dikembalikannya di-host di alamat publik, lewat HTTPS, dalam hitungan detik. Inilah semuanya, sesuai urutan yang akan Anda temui.

Apa itu lambda

Lambda adalah snippet yang mengembalikan handler GenHTTP. Platform mengompilasinya, memuatnya, lalu memasang apa pun yang dikembalikannya di bawah alamat Anda sendiri. Tidak ada proyek, tidak ada file build, dan tidak ada statement using. Semua modul GenHTTP sudah di-import untuk Anda.

return Content.From(Resource.FromString("hello"));

Itu sudah lambda yang lengkap. Setelah di-deploy di /lambda/your-key/, lambda ini menjawab setiap request dengan kata hello.

Snippet ini berisi statement, bukan class. Hal terakhir yang dilakukannya adalah mengembalikan sesuatu yang bisa melayani request: handler, atau builder untuk handler.

Lambda pertama Anda

  1. 1
    Tekan Buat lambda. Anda mendapat alamat publik dan kunci editor. Kunci itu satu-satunya jalan untuk masuk lagi, jadi simpan baik-baik. Tidak ada yang bisa memulihkannya untuk Anda.
  2. 2
    Anda masuk ke pusat kontrolnya, dengan layanan REST kecil yang sudah tertulis sebagai versi pertama. Itu hanya titik awal.
  3. 3
    Berikan kunci editor ke agen dan jelaskan apa yang harus dibuat. Agen menulis versi-versi baru lewat MCP. Atau buka Kode dan tulis sendiri: Periksa mengompilasi tanpa menyimpan apa pun, lalu menunjukkan pesan compiler, lengkap dengan file dan barisnya.
  4. 4
    Tekan Deploy. Sekarang lambda Anda online. Sebelum itu, tidak ada yang bisa diakses. Deploy ulang memperpanjang masa online-nya.

Pusat kontrol

Link editor membuka pusat kontrol, bukan kotak teks. Sebagian besar kode di sini ditulis oleh agen, jadi yang pertama tampil di layar adalah kondisi lambda Anda. Sidebar berisi lambda-nya (apakah online, alamatnya, dan tombol kalau ada versi lebih baru yang menunggu untuk online) beserta bagian-bagiannya. Hal yang jarang dilakukan, seperti mengganti alamat atau menghapus lambda, ada di menu ⋯ di sana.

Ringkasan
Apakah lambda online, berapa request hari ini dan berapa yang gagal, perubahan terakhir, dan sisa ruang penyimpanan.
Ubah
Tulis apa yang perlu diubah, dan agen di server ini akan mengerjakannya sementara Anda melihat. Agen bekerja di sebuah draf, mencobanya di sana, lalu menggabungkannya menjadi versi berikutnya begitu berhasil. Matikan Langsung online setelah selesai kalau Anda ingin mencoba drafnya sendiri dulu.
Draf
Perubahan yang dikerjakan di samping lambda: masing-masing dicoba di alamatnya sendiri dan digabungkan menjadi versi berikutnya setelah hasilnya pas. Saat dibuka, draf punya kode, data, dan log-nya sendiri.
File
File dari sebuah versi: kode dan asetnya, yaitu programnya sendiri. Ikon gembok atau globe menunjukkan apakah publik bisa mengaksesnya.
Data
Apa yang disimpan lambda selama berjalan, dipakai bersama oleh semua versi: workspace. Lihat isinya, unggah dan hapus file, atau nonaktifkan.
Versi
Apa yang diubah setiap versi dan apa yang diminta, serta bedanya dengan versi sebelumnya. Deploy atau rollback dari sini, atau mulai draf dari versi mana pun.
Deployment
Apa yang online dan kapan, dan apa yang membuatnya berhenti.
Statistik
Request, kegagalan, waktu respons, dan path yang paling sering diminta, selama satu jam atau satu hari terakhir.
Log
Request yang masuk, apa yang dicetak lambda, dan stack trace dari setiap error, secara langsung.
Kode
Menulis kode secara manual. Periksa mengompilasi, Simpan membuat versi, Deploy membuatnya online. Di draf, Simpan menyimpannya di draf dan Deploy pratinjau membuatnya online di alamat draf itu. Ctrl-S menyimpan; F12 membuka deklarasi.

Setiap bagian bekerja dengan cara yang sama: judulnya, tombol ⓘ yang menjelaskannya, aksinya di kanan, dan (kalau punya lebih dari satu tampilan) deretan tab di bawahnya. Tab di bagian kode adalah file-filenya.

Trafik dan log hanya ada di memori, untuk dipantau, bukan untuk diarsipkan: restart server memulainya dari awal. Versi dan riwayat deployment disimpan permanen.

Mencatat alasan

Sebuah versi berisi kode, plus dua catatan opsional: spesifikasi, yaitu apa yang diinginkan pengguna dan alasannya, sebisa mungkin dengan kata-kata mereka sendiri, dan perubahan, satu baris tentang apa yang dilakukan versi itu. Keduanya ditampilkan di samping diff di riwayat versi, jadi alasannya tetap tercatat di samping isinya. Berguna untuk Anda, dan untuk agen berikutnya yang membaca riwayat sebelum mengubah apa pun.

POST /api/v1/lambdas/{editorKey}/versions
{
  "files": [ { "name": "lambda.cs", "code": "..." } ],
  "specification": "Buku tamu yang bisa diisi orang; entri harus tetap ada setelah restart",
  "change": "Menyimpan entri di workspace supaya tetap ada setelah restart"
}

Agen mengirim dua field yang sama ke write_code. Di Kode, saat menyimpan Anda diminta mengisi perubahannya. Keduanya opsional. Spesifikasi yang terlalu panjang dipotong di 4.000 karakter, dan perubahan di 500 karakter, bukan ditolak. Draf menyimpan dua catatannya sendiri, dan versi hasil penggabungannya mengambil alih catatan itu.

Mengubah dengan aman

Versi tidak pernah berubah setelah disimpan, dan justru itulah yang membuat setiap versi layak disimpan: versi mana pun bisa dibandingkan, dan dijadikan online lagi persis seperti semula. Untuk mengubah lambda yang sedang dipakai orang, mulai draf.

  1. 1
    Mulai di Draf, atau dari versi mana pun. Draf adalah salinan kode dan aset versi itu, dan salinan data lambda.
  2. 2
    Ubah sesering yang diperlukan, di Kode atau dengan meminta agen. Deploy pratinjau membuatnya online di alamatnya sendiri, /features/…/, dengan salinan datanya sendiri. Pengunjung lambda tidak melihat apa pun, dan tidak ada yang ditulisnya yang sampai ke data lambda.
  3. 3
    Gabungkan setelah hasilnya pas: draf menjadi versi berikutnya, lengkap dengan catatannya, dan bisa langsung online kalau Anda mau. Drafnya ikut hilang, termasuk pratinjau dan salinan datanya.
POST /api/v1/lambdas/{editorKey}/features
{ "name": "Papan peringkat" }

PUT  /api/v1/lambdas/{editorKey}/features/{feature}/files?deploy=true
POST /api/v1/lambdas/{editorKey}/features/{feature}/merge
{ "deploy": true }

Beberapa draf bisa dikerjakan sekaligus. Hanya draf yang berbasis versi terbaru yang bisa digabungkan, supaya penggabungan tidak pernah membatalkan versi yang disimpan setelah draf itu dimulai. Kalau ada draf lain yang digabungkan lebih dulu, masukkan perubahannya (atau minta agen melakukannya), lalu jadikan versi terbaru sebagai dasar draf. Tidak ada yang tergabung dengan sendirinya; itu disengaja.

Lebih dari satu file

Tipe tidak harus berada di bawah kode yang memakainya. Di Kode, tekan + di samping daftar file, dan file baru itu dikompilasi bersama snippet, di namespace yang sama, jadi tidak perlu import apa pun untuk mengaksesnya. Nama tanpa ekstensi dianggap C#.

lambda.cs
var shelf = new Shelf();

return Inline.Create()
             .Get(() => shelf.All())
             .Post((Book book) => shelf.Add(book));
Shelf.cs
public sealed class Shelf
{
    private readonly List<Book> _books = [];

    public IEnumerable<Book> All() => _books;

    public Book Add(Book book)
    {
        _books.Add(book);
        return book;
    }
}

public record Book(string Title, string Author);

Menyajikan halaman

Ada dua cara untuk menyajikan halaman, dan satu cara lagi untuk file yang diunggah orang di sampingnya.

Satu halaman, ditulis inline

Cocok untuk yang kecil. Halamannya jadi bagian dari snippet.

var page = Resource.FromString("""
                              <!doctype html>
                              <title>Mine</title>
                              <h1>It works</h1>
                              """)
                   .Type(new ContentType("text/html; charset=utf-8"));

return Content.From(page);

Folder berisi file sungguhan

Pilihan tepat untuk apa pun yang punya stylesheet dan script. File ditambahkan dengan cara yang sama seperti file C#, dan disajikan persis seperti yang ditulis. Tidak ada yang mengompilasinya.

return Layout.Create()
             .Add("api", api)
             .Add(Assets.App("site"));

File unggahan, dari data

Untuk apa yang diunggah orang atau dibuat lambda (gambar, dokumen), disajikan di samping aplikasinya. Bukan untuk halaman aplikasinya sendiri: halaman itu tempatnya di folder file, di mana halaman ikut masuk versi bersama kode yang membutuhkannya.

return Layout.Create()
             .Add("api", api)
             .Add("uploads", Workspace.Files("uploads"))
             .Add(Assets.App("site"));

Front end, langkah demi langkah

Cara kedua, secara lengkap. Setiap demo menyajikan halamannya dengan cara ini, dari folder bernama web. Buka demo-crud untuk melihat contohnya. Demo hanya bisa dibaca; kunci editornya adalah namanya sendiri.

  1. 1
    Di Kode, tekan + di samping daftar file, lalu ketik site/index.html. Nama dengan garis miring menaruh file di dalam folder. Nama dengan ekstensi dianggap sebagai jenis file sesuai ekstensinya.
  2. 2
    Tambahkan site/app.css dan site/app.js dengan cara yang sama. Halaman Anda merujuk keduanya dengan nama, seperti href="app.css", karena folder itu adalah root dari apa yang disajikan, bukan bagian dari alamat.
  3. 3
    Untuk apa pun yang bukan teks, seperti gambar atau font, buka sebuah file di site, lalu tekan tombol unggah di samping daftar file. File itu akan masuk ke folder yang sama. PNG tidak bisa diketik di editor teks, jadi pakai tombol itu.
  4. 4
    Di lambda.cs, sajikan foldernya:
    return Layout.Create().Add(Assets.App("site"));
  5. 5
    Tekan Deploy. site/index.html menjawab di /, site/app.css di /app.css, dan alamat apa pun yang tidak cocok dengan file mana pun dijawab dengan halaman itu. Jadi front end yang mengatur routing sendiri tetap jalan saat seseorang me-reload halaman di deep link.
  6. 6
    Tambahkan API di sampingnya, dan halaman itu punya lawan bicara:
    var api = Inline.Create().Get("notes", () => notes);
    
    return Layout.Create()
                 .Add("api", api)
                 .Add(Assets.App("site"));

Dua tempat file disimpan

Lambda menyimpan file di dua tempat, dan editor menampilkannya terpisah: File berisi file dari sebuah versi (programnya), dan Data berisi workspace (apa yang disimpan program itu). Bedanya ada di milik siapa. File dari sebuah versi milik versi itu; data milik lambda, dan dipakai bersama oleh semua versi.

Di sebuah versiDi data
isinyakode dan aset: programnya, termasuk front endapa pun yang ditulis lambda, atau diunggah seseorang
kapan berubahtidak pernah: perubahan menjadi versi barubegitu ada yang ditulis ke dalamnya
saat deployfile inilah yang persis dibuat onlinetidak pernah disentuh
rollbackfile lama kembalitidak berpengaruh: semua versi memakainya bersama
drafdimulai sebagai salinannyamemakai salinannya
kapan hilangbersama versi lama, setelah melewati batasbersama lambda, atau saat Anda menonaktifkannya
diakses dari kode sebagaiAssetsWorkspace

Keduanya tidak bisa jadi satu tempat. Kalau jadi satu, deploy akan menghapus semua yang sudah ditulis lambda sejak deploy sebelumnya, atau tidak ada yang bisa dihapus dari file yang dibawanya. Game yang menyimpan papan peringkat butuh yang kedua; halaman yang disajikannya butuh yang pertama. Jadi halamannya masuk ke versi, dan papan peringkatnya ke data.

Menyimpan data

Workspace adalah direktori privat yang boleh dibaca dan ditulis lambda Anda. Di situlah tempat untuk apa pun yang harus bertahan lebih lama dari satu request, atau satu deployment.

var notes = new List<string>();

if (Workspace.Exists("notes.json"))
{
    notes.AddRange(JsonSerializer.Deserialize<List<string>>(Workspace.ReadText("notes.json")) ?? []);
}

return Inline.Create()
             .Get("notes", () => notes)
             .Post("notes", (string text) =>
             {
                 notes.Add(text);
                 Workspace.WriteText("notes.json", JsonSerializer.Serialize(notes));
                 return notes.Count;
             });

Ada juga ReadBytes, WriteBytes, Delete, List, CreateFolder, dan Tree/Files/App untuk menyajikannya. Selain itu, tidak ada bagian file system yang bisa diakses.

Websocket

Didukung, dan bukan sekadar tambahan. Demo demo-game memasangkan pemain dan menjalankan setiap permainan di server. Bentuk paling sederhananya berupa tiga callback:

var room = new ConcurrentDictionary<IReactiveConnection, string>();

var socket = Websocket.Functional()
                      .OnOpen(c => { room[c] = "someone"; return ValueTask.CompletedTask; })
                      .OnMessage(async (c, text) =>
                      {
                          foreach (var other in room.Keys)
                          {
                              await other.WritePayloadAsync(text);
                          }
                      })
                      .OnClose((c, _) => { room.TryRemove(c, out _); return ValueTask.CompletedTask; });

return Layout.Create().Add("chat", socket);

Satu hal yang sering menjebak: browser tidak bisa menambahkan header pada handshake websocket. Kirim yang dibutuhkan handler lewat query, yang dibacanya dari connection.Request.Header.Query, atau kirim data rahasia sebagai pesan pertama.

Yang tidak diizinkan

Kode Anda berjalan di server bersama, jadi sebagian C# ditolak sebelum dikompilasi: menjalankan proses, membuka socket sendiri, memuat assembly, mengakses file system di luar workspace Anda, dan reflection yang dipakai untuk mengakali semua itu.

Semua yang lain tersedia, termasuk seluruh API modul GenHTTP. Kalau ada yang ditolak, Anda diberi tahu baris mana dan alasannya, bukan sekadar pesan gagal.

Membawa kode Anda keluar

Unduh sebagai proyek .NET di editor memberi Anda semuanya: solution yang bisa Anda buka, jalankan dengan dotnet run, dan simpan. Isinya satu package reference, tanpa jejak platform ini sama sekali.

Snippet Anda menjadi isi Program.cs, dibungkus host yang menyajikan apa yang dikembalikannya. File Anda yang lain ikut persis seperti yang Anda tulis. Workspace dan Assets menjadi dua folder di samping kode, dengan method yang sama, jadi tidak ada yang perlu diubah di kode Anda.

Penting diketahui sebelum Anda membangun apa pun di sini: yang Anda tulis adalah milik Anda, dan bisa dibawa keluar utuh. Menjalankannya di server ini tidak membuatnya terkunci di server ini.

Menyerahkannya ke agen

Ada endpoint MCP di /mcp. Arahkan agen ke sana, dan agen itu bisa melakukan semua yang bisa dilakukan editor: membaca panduan, membaca demo secara lengkap, menulis file, mengompilasinya, dan men-deploy. Di baliknya, API-nya sama.

Agen mencatat alasannya sambil bekerja (write_code menerima spesifikasi dan perubahan), dan bisa melihat apa yang sudah di-deploy-nya. read_logs menjawab dengan request terbaru lambda, apa yang dicetaknya, dan stack trace dari setiap exception. Dari situ agen tahu kodenya benar-benar jalan, bukan sekadar menebak. Anda memantau hal yang sama di pusat kontrol.

Selengkapnya →