int SrsHttpRoot::best_match(const char* path, int length, SrsHttpHandlerMatch** ppmatch) { int ret = ERROR_SUCCESS; // find the best matched child handler. std::vector<SrsHttpHandler*>::iterator it; for (it = handlers.begin(); it != handlers.end(); ++it) { SrsHttpHandler* h = *it; // search all child handlers. h->best_match(path, length, ppmatch); } // if already matched by child, return. if (*ppmatch) { return ret; } // not matched, error. return ERROR_HTTP_HANDLER_MATCH_URL; }
int SrsHttpHandler::best_match(const char* path, int length, SrsHttpHandlerMatch** ppmatch) { int ret = ERROR_SUCCESS; SrsHttpHandler* handler = NULL; const char* match_start = NULL; int match_length = 0; for (;;) { // ensure cur is not NULL. // ensure p not NULL and has bytes to parse. if (!path || length <= 0) { break; } const char* p = NULL; for (p = path + 1; p - path < length && *p != SRS_CONSTS_HTTP_PATH_SEP; p++) { } // whether the handler can handler the node. const char* pchild = p; if (!can_handle(path, p - path, &pchild)) { break; } // save current handler, it's ok for current handler atleast. handler = this; match_start = path; match_length = p - path; // find the best matched child handler. std::vector<SrsHttpHandler*>::iterator it; for (it = handlers.begin(); it != handlers.end(); ++it) { SrsHttpHandler* h = *it; // matched, donot search more. if (h->best_match(pchild, length - (pchild - path), ppmatch) == ERROR_SUCCESS) { break; } } // whatever, donot loop. break; } // if already matched by child, return. if (*ppmatch) { return ret; } // not matched, error. if (handler == NULL) { ret = ERROR_HTTP_HANDLER_MATCH_URL; return ret; } // matched by this handler. *ppmatch = new SrsHttpHandlerMatch(); (*ppmatch)->handler = handler; (*ppmatch)->matched_url.append(match_start, match_length); int unmatch_length = length - match_length; if (unmatch_length > 0) { (*ppmatch)->unmatched_url.append(match_start + match_length, unmatch_length); } return ret; }