jetc: add #api directive + jetc_api_<name> route metadata export
Stage 1 of the APIServer plan: a compiled --shared .so currently exports
only a bare jetc_render_<name>(Global&, MString&) with no way for a host
to discover what HTTP method+path it wants to serve. Adds a leading
"#api METHOD /path" directive (one or more, parsed the same way jetc
already strips a leading "#!" shebang line - not modeled as a new
AST/tag-attribute concept, since jetc's parser has no existing notion of
the enclosing <jet> tag's attributes to hang this off of).
In --shared mode, JetCodegen now also emits a second exported function
alongside the render entry point:
struct JetApiRoute { const char *method; const char *path; };
extern "C" const JetApiRoute *jetc_api_<name>(int *count) { ... }
<name> is derived the same way for both symbols (sanitizeIdent(
baseNameNoExt(inputPath))), so a future host loader can find both by
convention from just the .so's filename - no name needs to be embedded
in the metadata itself, and the routes a module declares can never drift
out of sync with the render function that implements them (the failure
mode a sidecar manifest file would have).
Malformed directives (missing method/path, path without a leading '/')
are a hard compile error; #api directives present without --shared print
a non-fatal warning (the metadata has nowhere to go without a host to
load a .so, but the render-only executable/CGI path still works fine).
Verified live, not just compiled: rebuilt jetc, compiled demo3.jet (a new
worked example with two #api lines sharing one handler) via
build-shared.sh into a real demo3.so, and added api_test.cpp (mirrors
host_test.cpp's dlopen()/dlsym() pattern) confirming jetc_api_demo3
returns the expected two routes at runtime. Re-ran host_test against the
same .so to confirm the render path is unaffected. Confirmed demo.jet/
demo2.jet (no #api lines) emit no JetApiRoute code at all - no regression
for templates that don't declare routes.
Also fixed a gitignore gap surfaced while committing this: an earlier
"jetc/*.cpp" ignore rule (meant for generated *.compiled.cpp output) was
a blanket pattern that silently hid this commit's own api_test.cpp from
git status. Narrowed to "jetc/*.compiled.cpp" (the actual generated-file
naming, per build-compiled.sh/build-shared.sh) and added explicit ignores
for the host_test/api_test/demo3 binaries plus two known stale generated
leftovers (demo.cpp/demo2.cpp) that predate this session.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
a32444acc2
commit
634eb7a9a9
6 files changed
+135
-15
No files matched your search
@@ -0,0 +1,39 @@
|
||||
// Minimal dlsym() check for the jetc_api_<name> route-metadata export added
|
||||
// alongside jetc_render_<name> in --shared mode (see JetCodegen.cpp). Proves
|
||||
// a host can discover a compiled module's declared routes purely from the
|
||||
// .so itself, with no separate manifest file - the actual point of putting
|
||||
// routing metadata in an exported symbol instead of a sidecar file.
|
||||
#include <dlfcn.h>
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
|
||||
struct JetApiRoute { const char *method; const char *path; };
|
||||
typedef const JetApiRoute *(*ApiFn)(int *count);
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
if (argc < 3) {
|
||||
std::cerr << "usage: api_test <module.so> <api-symbol>" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
void *handle = dlopen(argv[1], RTLD_NOW);
|
||||
if (!handle) {
|
||||
std::cerr << "dlopen failed: " << dlerror() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
dlerror();
|
||||
ApiFn api = (ApiFn)dlsym(handle, argv[2]);
|
||||
const char *err = dlerror();
|
||||
if (err) {
|
||||
std::cerr << "dlsym failed: " << err << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int count = -1;
|
||||
const JetApiRoute *routes = api(&count);
|
||||
std::cout << count << " route(s):" << std::endl;
|
||||
for (int i = 0; i < count; ++i)
|
||||
std::cout << " " << routes[i].method << " " << routes[i].path << std::endl;
|
||||
|
||||
dlclose(handle);
|
||||
return 0;
|
||||
}
|
||||
Reference in new issue
Block a user