@@ -2334,14 +2334,15 @@ kj::Array<kj::byte> measureConfig(config::Worker::Reader& config) {
2334
2334
return digest;
2335
2335
}
2336
2336
2337
- class Server ::WorkerdApiService final : public Service, private WorkerInterface {
2337
+ class Server ::WorkerdApiService final : public Service {
2338
2338
// Service used when the service is configured as network service.
2339
2339
2340
2340
public:
2341
2341
WorkerdApiService (Server& server): server(server) {}
2342
2342
2343
2343
kj::Own<WorkerInterface> startRequest (IoChannelFactory::SubrequestMetadata metadata) override {
2344
- return { this , kj::NullDisposer::instance };
2344
+ auto & context = IoContext::current ();
2345
+ return kj::heap<WorkerdApiRequestHandler>(*this , context.getWorker ());
2345
2346
}
2346
2347
2347
2348
bool hasHandler (kj::StringPtr handlerName) override {
@@ -2351,102 +2352,102 @@ public:
2351
2352
private:
2352
2353
Server& server;
2353
2354
2354
- kj::Promise<void > request (
2355
- kj::HttpMethod method, kj::StringPtr url, const kj::HttpHeaders& headers,
2356
- kj::AsyncInputStream& requestBody, kj::HttpService::Response& response) override {
2357
- if (url == " http://workerd.local/workers" ) {
2358
- return requestBody.readAllText ().then ([this , &headers, &response](auto confJson) {
2359
- capnp::MallocMessageBuilder confArena;
2360
- capnp::JsonCodec json;
2361
- json.handleByAnnotation <config::NewWorker>();
2362
- auto conf = confArena.initRoot <config::NewWorker>();
2363
- json.decode (confJson, conf);
2355
+ class WorkerdApiRequestHandler final : public WorkerInterface {
2356
+ public:
2357
+ WorkerdApiRequestHandler (WorkerdApiService& parent, const Worker& requester)
2358
+ : parent(parent), requester(requester) {}
2364
2359
2365
- kj::String id = workerd::randomUUID (kj::none);
2360
+ kj::Promise<void > request (
2361
+ kj::HttpMethod method, kj::StringPtr url, const kj::HttpHeaders& headers,
2362
+ kj::AsyncInputStream& requestBody, kj::HttpService::Response& response) override {
2363
+ if (url != " http://workerd.local/workers" ) {
2364
+ auto out = response.send (404 , " Not Found" , headers, kj::none);
2365
+ auto errMsg = " Unknown workerd API endpoint" _kjc.asBytes ();
2366
+ co_await out->write (errMsg.begin (), errMsg.size ());
2367
+ co_return ;
2368
+ }
2366
2369
2367
- server. actorConfigs . insert ( kj::str (id), {} );
2370
+ auto confJson = co_await requestBody. readAllText ( );
2368
2371
2369
- kj::Maybe<kj::Array<kj::byte>> expectedMeasurement = kj::none;
2370
- if (conf.hasExpectedMeasurement ()) {
2371
- auto res = kj::decodeHex (conf.getExpectedMeasurement ());
2372
- if (res.hadErrors ) {
2373
- auto out = response.send (400 , " Bad Request" , headers, kj::none);
2374
- auto errMsg = " invalid expected measurement" _kjc.asBytes ();
2375
- return out->write (errMsg.begin (), errMsg.size ());
2376
- }
2377
- expectedMeasurement = kj::mv (res);
2378
- }
2372
+ capnp::MallocMessageBuilder confArena;
2373
+ capnp::JsonCodec json;
2374
+ json.handleByAnnotation <config::NewWorker>();
2375
+ auto conf = confArena.initRoot <config::NewWorker>();
2376
+ json.decode (confJson, conf);
2379
2377
2380
- kj::Maybe<kj::String> configError = kj::none;
2381
- auto workerService = server.makeWorker (
2382
- id, conf.getWorker ().asReader (), {},
2383
- [&configError](auto err) { configError = kj::mv (err); },
2384
- kj::mv (expectedMeasurement)
2385
- );
2386
- KJ_IF_SOME (err, configError) {
2387
- throw KJ_EXCEPTION (FAILED, err);
2388
- }
2389
- auto & worker = server.services .insert (kj::str (id), kj::mv (workerService)).value ;
2390
- worker->link ();
2378
+ WorkerService* requesterService;
2379
+ KJ_IF_SOME (svc, parent.server .services .find (requester.getName ())) {
2380
+ requesterService = &kj::downcast<WorkerService>(*svc);
2381
+ } else {
2382
+ auto out = response.send (500 , " Internal Server Error" , headers, kj::none);
2383
+ auto errMsg = " unable to locate requester service" _kjc.asBytes ();
2384
+ co_await out->write (errMsg.begin (), errMsg.size ());
2385
+ co_return ;
2386
+ }
2391
2387
2392
- auto resMessage = kj::heap<capnp::MallocMessageBuilder>(); // TODO: not alloc
2393
- auto res = resMessage->initRoot <config::ServiceDesignator>();
2394
- res.setName (id);
2395
- auto resJson = json.encode (res);
2388
+ kj::String id = workerd::randomUUID (kj::none);
2396
2389
2397
- auto out = response.send (201 , " Created" , headers, kj::none);
2398
- return out->write (resJson.begin (), resJson.size ()).attach (kj::mv (out), kj::mv (resJson));
2399
- });
2400
- } else if (url.startsWith (" http://workerd.local/workers/" _kjc) &&
2401
- url.endsWith (" /events/scheduled" )) {
2402
- auto workerId = url.slice (29 , 29 + 36 );
2403
- return requestBody.readAllText ().then ([this , workerId = kj::mv (workerId),
2404
- &headers, &response](auto confJson) {
2405
- capnp::MallocMessageBuilder confArena;
2406
- capnp::JsonCodec json;
2407
- json.handleByAnnotation <rpc::Trace::ScheduledEventInfo>();
2408
- auto event = confArena.initRoot <rpc::Trace::ScheduledEventInfo>();
2409
- json.decode (confJson, event);
2410
-
2411
- KJ_IF_SOME (svc, server.services .find (workerId)) {
2412
- IoChannelFactory::SubrequestMetadata metadata;
2413
- auto worker = svc->startRequest (kj::mv (metadata));
2414
- kj::Date scheduledTime = kj::UNIX_EPOCH +
2415
- static_cast <long long >(event.getScheduledTime ()) * kj::MILLISECONDS;
2416
- auto cron = event.getCron ();
2417
- return worker->runScheduled (scheduledTime, cron)
2418
- .then ([&response, &headers](auto scheduledResult) {
2419
- return response.send (204 , " No Content" , headers, kj::none)->write (nullptr , 0 );
2420
- }).attach (kj::mv (cron));
2421
- } else {
2422
- return response.send (404 , " Not Found" , headers, kj::none)->write (nullptr , 0 );
2423
- }
2424
- });
2425
- } else {
2426
- return response.send (404 , " Not Found" , headers, kj::none)->write (nullptr , 0 );
2390
+ parent.server .actorConfigs .insert (kj::str (id), {});
2391
+
2392
+ kj::Maybe<kj::Array<kj::byte>> expectedMeasurement = kj::none;
2393
+ if (conf.hasExpectedMeasurement ()) {
2394
+ auto res = kj::decodeHex (conf.getExpectedMeasurement ());
2395
+ if (res.hadErrors ) {
2396
+ auto out = response.send (400 , " Bad Request" , headers, kj::none);
2397
+ auto errMsg = " invalid expected measurement" _kjc.asBytes ();
2398
+ co_await out->write (errMsg.begin (), errMsg.size ());
2399
+ co_return ;
2400
+ }
2401
+ expectedMeasurement = kj::mv (res);
2402
+ }
2403
+
2404
+ kj::Maybe<kj::String> configError = kj::none;
2405
+ auto workerService = parent.server .makeWorker (
2406
+ id, conf.getWorker ().asReader (), {},
2407
+ [&configError](auto err) { configError = kj::mv (err); },
2408
+ kj::mv (expectedMeasurement)
2409
+ );
2410
+ KJ_IF_SOME (err, configError) {
2411
+ auto out = response.send (400 , " Bad Request" , headers, kj::none);
2412
+ auto errMsg = kj::str (err);
2413
+ co_await out->write (errMsg.begin (), errMsg.size ());
2414
+ co_return ;
2415
+ }
2416
+ auto & worker = parent.server .services .insert (kj::str (id), kj::mv (workerService)).value ;
2417
+ worker->link ();
2418
+
2419
+ uint newWorkerChannel = requesterService->addChannel (worker);
2420
+
2421
+ auto resMsg = kj::str (newWorkerChannel);
2422
+ auto out = response.send (201 , " Created" , headers, kj::none);
2423
+ co_await out->write (resMsg.begin (), resMsg.size ()).attach (kj::mv (out), kj::mv (resMsg));
2424
+ co_return ;
2427
2425
}
2428
- }
2429
2426
2430
- kj::Promise<void > connect (
2431
- kj::StringPtr host, const kj::HttpHeaders& headers, kj::AsyncIoStream& connection,
2432
- ConnectResponse& tunnel, kj::HttpConnectSettings settings) override {
2433
- throwUnsupported ();
2434
- }
2427
+ kj::Promise<void > connect (
2428
+ kj::StringPtr host, const kj::HttpHeaders& headers, kj::AsyncIoStream& connection,
2429
+ ConnectResponse& tunnel, kj::HttpConnectSettings settings) override {
2430
+ throwUnsupported ();
2431
+ }
2432
+ void prewarm (kj::StringPtr url) override {}
2433
+ kj::Promise<ScheduledResult> runScheduled (kj::Date scheduledTime, kj::StringPtr cron) override {
2434
+ throwUnsupported ();
2435
+ }
2436
+ kj::Promise<AlarmResult> runAlarm (kj::Date scheduledTime, uint32_t retryCount) override {
2437
+ throwUnsupported ();
2438
+ }
2439
+ kj::Promise<CustomEvent::Result> customEvent (kj::Own<CustomEvent> event) override {
2440
+ throwUnsupported ();
2441
+ }
2435
2442
2436
- void prewarm (kj::StringPtr url) override {}
2437
- kj::Promise<ScheduledResult> runScheduled (kj::Date scheduledTime, kj::StringPtr cron) override {
2438
- throwUnsupported ();
2439
- }
2440
- kj::Promise<AlarmResult> runAlarm (kj::Date scheduledTime, uint32_t retryCount) override {
2441
- throwUnsupported ();
2442
- }
2443
- kj::Promise<CustomEvent::Result> customEvent (kj::Own<CustomEvent> event) override {
2444
- throwUnsupported ();
2445
- }
2443
+ [[noreturn]] void throwUnsupported () {
2444
+ JSG_FAIL_REQUIRE (Error, " WorkerdApiService does not support this event type." );
2445
+ }
2446
2446
2447
- [[noreturn]] void throwUnsupported () {
2448
- JSG_FAIL_REQUIRE (Error, " WorkerdApiService does not support this event type." );
2449
- }
2447
+ private:
2448
+ WorkerdApiService& parent;
2449
+ const Worker& requester;
2450
+ };
2450
2451
};
2451
2452
2452
2453
// =======================================================================================
@@ -2609,6 +2610,9 @@ static kj::Maybe<WorkerdApi::Global> createBinding(
2609
2610
binding.getService (),
2610
2611
kj::mv (errorContext)
2611
2612
});
2613
+ if (binding.getService ().getName () == " @workerd" ) {
2614
+ return makeGlobal (Global::WorkerdApi { .subrequestChannel = channel });
2615
+ }
2612
2616
return makeGlobal (Global::Fetcher {
2613
2617
.channel = channel,
2614
2618
.requiresHost = true ,
0 commit comments