mirror of
https://github.com/oven-sh/bun
synced 2026-02-02 15:08:46 +00:00
Introduce experimental support for on-demand bundling via HTML imports and Bun.serve() (#16395)
This commit is contained in:
@@ -466,12 +466,12 @@ public:
|
||||
|
||||
/* Register an HTTP route handler acording to URL pattern */
|
||||
void onHttp(std::string method, std::string pattern, MoveOnlyFunction<void(HttpResponse<SSL> *, HttpRequest *)> &&handler, bool upgrade = false) {
|
||||
HttpContextData<SSL> *httpContextData = getSocketContextData();
|
||||
HttpContextData<SSL> *httpContextData = getSocketContextData();
|
||||
|
||||
/* Todo: This is ugly, fix */
|
||||
std::vector<std::string> methods;
|
||||
if (method == "*") {
|
||||
methods = httpContextData->currentRouter->upperCasedMethods;
|
||||
methods = {"*"};
|
||||
} else {
|
||||
methods = {method};
|
||||
}
|
||||
|
||||
@@ -35,43 +35,7 @@ namespace uWS {
|
||||
|
||||
template <class USERDATA>
|
||||
struct HttpRouter {
|
||||
/* These are public for now */
|
||||
std::vector<std::string> upperCasedMethods = {
|
||||
"ACL",
|
||||
"BIND",
|
||||
"CHECKOUT",
|
||||
"CONNECT",
|
||||
"COPY",
|
||||
"DELETE",
|
||||
"GET",
|
||||
"HEAD",
|
||||
"LINK",
|
||||
"LOCK",
|
||||
"M-SEARCH" ,
|
||||
"MERGE",
|
||||
"MKACTIVITY",
|
||||
"MKCALENDAR",
|
||||
"MKCOL",
|
||||
"MOVE",
|
||||
"NOTIFY",
|
||||
"OPTIONS",
|
||||
"PATCH",
|
||||
"POST",
|
||||
"PROPFIND",
|
||||
"PROPPATCH",
|
||||
"PURGE",
|
||||
"PUT",
|
||||
"REBIND",
|
||||
"REPORT",
|
||||
"SEARCH",
|
||||
"SOURCE",
|
||||
"SUBSCRIBE",
|
||||
"TRACE",
|
||||
"UNBIND",
|
||||
"UNLINK",
|
||||
"UNLOCK",
|
||||
"UNSUBSCRIBE",
|
||||
};
|
||||
static constexpr std::string_view ANY_METHOD_TOKEN = "*";
|
||||
static const uint32_t HIGH_PRIORITY = 0xd0000000, MEDIUM_PRIORITY = 0xe0000000, LOW_PRIORITY = 0xf0000000;
|
||||
|
||||
private:
|
||||
@@ -81,23 +45,20 @@ private:
|
||||
/* Handler ids are 32-bit */
|
||||
static const uint32_t HANDLER_MASK = 0x0fffffff;
|
||||
|
||||
/* Methods and their respective priority */
|
||||
std::map<std::string, int> priority;
|
||||
|
||||
/* List of handlers */
|
||||
std::vector<MoveOnlyFunction<bool(HttpRouter *)>> handlers;
|
||||
|
||||
/* Current URL cache */
|
||||
std::string_view currentUrl;
|
||||
std::string_view urlSegmentVector[MAX_URL_SEGMENTS];
|
||||
int urlSegmentTop;
|
||||
std::string_view currentUrl = {};
|
||||
std::string_view urlSegmentVector[MAX_URL_SEGMENTS] = {};
|
||||
int urlSegmentTop = -1;
|
||||
|
||||
/* The matching tree */
|
||||
struct Node {
|
||||
std::string name;
|
||||
std::vector<std::unique_ptr<Node>> children;
|
||||
std::vector<uint32_t> handlers;
|
||||
bool isHighPriority;
|
||||
std::string name = {};
|
||||
std::vector<std::unique_ptr<Node>> children = {};
|
||||
std::vector<uint32_t> handlers = {};
|
||||
bool isHighPriority = false;
|
||||
|
||||
Node(std::string name) : name(name) {}
|
||||
} root = {"rootNode"};
|
||||
@@ -141,8 +102,8 @@ private:
|
||||
struct RouteParameters {
|
||||
friend struct HttpRouter;
|
||||
private:
|
||||
std::string_view params[MAX_URL_SEGMENTS];
|
||||
int paramsTop;
|
||||
std::string_view params[MAX_URL_SEGMENTS] = {};
|
||||
int paramsTop = -1;
|
||||
|
||||
void reset() {
|
||||
paramsTop = -1;
|
||||
@@ -173,7 +134,7 @@ private:
|
||||
inline std::pair<std::string_view, bool> getUrlSegment(int urlSegment) {
|
||||
if (urlSegment > urlSegmentTop) {
|
||||
/* Signal as STOP when we have no more URL or stack space */
|
||||
if (!currentUrl.length() || urlSegment > 99) {
|
||||
if (!currentUrl.length() || urlSegment > int(MAX_URL_SEGMENTS - 1)) {
|
||||
return {{}, true};
|
||||
}
|
||||
|
||||
@@ -280,10 +241,8 @@ private:
|
||||
|
||||
public:
|
||||
HttpRouter() {
|
||||
int p = 0;
|
||||
for (std::string &method : upperCasedMethods) {
|
||||
priority[method] = p++;
|
||||
}
|
||||
/* Always have ANY route */
|
||||
getNode(&root, std::string(ANY_METHOD_TOKEN.data(), ANY_METHOD_TOKEN.length()), false);
|
||||
}
|
||||
|
||||
std::pair<int, std::string_view *> getParameters() {
|
||||
@@ -323,14 +282,19 @@ public:
|
||||
void add(std::vector<std::string> methods, std::string pattern, MoveOnlyFunction<bool(HttpRouter *)> &&handler, uint32_t priority = MEDIUM_PRIORITY) {
|
||||
/* First remove existing handler */
|
||||
remove(methods[0], pattern, priority);
|
||||
|
||||
|
||||
for (std::string method : methods) {
|
||||
/* Lookup method */
|
||||
Node *node = getNode(&root, method, false);
|
||||
/* Iterate over all segments */
|
||||
setUrl(pattern);
|
||||
for (int i = 0; !getUrlSegment(i).second; i++) {
|
||||
node = getNode(node, std::string(getUrlSegment(i).first), priority == HIGH_PRIORITY);
|
||||
std::string strippedSegment(getUrlSegment(i).first);
|
||||
if (strippedSegment.length() && strippedSegment[0] == ':') {
|
||||
/* Parameter routes must be named only : */
|
||||
strippedSegment = ":";
|
||||
}
|
||||
node = getNode(node, strippedSegment, priority == HIGH_PRIORITY);
|
||||
}
|
||||
/* Insert handler in order sorted by priority (most significant 1 byte) */
|
||||
node->handlers.insert(std::upper_bound(node->handlers.begin(), node->handlers.end(), (uint32_t) (priority | handlers.size())), (uint32_t) (priority | handlers.size()));
|
||||
@@ -339,11 +303,20 @@ public:
|
||||
/* Alloate this handler */
|
||||
handlers.emplace_back(std::move(handler));
|
||||
|
||||
/* Assume can find this handler again */
|
||||
if (((handlers.size() - 1) | priority) != findHandler(methods[0], pattern, priority)) {
|
||||
std::cerr << "Error: Internal routing error" << std::endl;
|
||||
std::abort();
|
||||
}
|
||||
/* ANY method must be last, GET must be first */
|
||||
std::sort(root.children.begin(), root.children.end(), [](const auto &a, const auto &b) {
|
||||
if (a->name == "GET" && b->name != "GET") {
|
||||
return true;
|
||||
} else if (b->name == "GET" && a->name != "GET") {
|
||||
return false;
|
||||
} else if (a->name == ANY_METHOD_TOKEN && b->name != ANY_METHOD_TOKEN) {
|
||||
return false;
|
||||
} else if (b->name == ANY_METHOD_TOKEN && a->name != ANY_METHOD_TOKEN) {
|
||||
return true;
|
||||
} else {
|
||||
return a->name < b->name;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
bool cullNode(Node *parent, Node *node, uint32_t handler) {
|
||||
@@ -408,4 +381,4 @@ public:
|
||||
|
||||
}
|
||||
|
||||
#endif // UWS_HTTPROUTER_HPP
|
||||
#endif // UWS_HTTPROUTER_HPP
|
||||
Reference in New Issue
Block a user