in src/brpc/uri.cpp [158:245]
int URI::SetHttpURL(const char* url) {
Clear();
const char* p = url;
// skip heading blanks
if (*p == ' ') {
for (++p; *p == ' '; ++p) {}
}
const char* start = p;
// Find end of host, locate scheme and user_info during the searching
bool need_scheme = true;
bool need_user_info = true;
for (; true; ++p) {
const char action = g_url_parsing_fast_action_map[(int)*p];
if (action == URI_PARSE_CONTINUE) {
continue;
}
if (action == URI_PARSE_BREAK) {
break;
}
if (!is_valid_char(*p)) {
_st.set_error(EINVAL, "invalid character in url");
return -1;
} else if (*p == ':') {
if (p[1] == '/' && p[2] == '/' && need_scheme) {
need_scheme = false;
_scheme.assign(start, p - start);
p += 2;
start = p + 1;
}
} else if (*p == '@') {
if (need_user_info) {
need_user_info = false;
_user_info.assign(start, p - start);
start = p + 1;
}
} else if (*p == ' ') {
if (!is_all_spaces(p + 1)) {
_st.set_error(EINVAL, "Invalid space in url");
return -1;
}
break;
}
}
const char* host_end = SplitHostAndPort(start, p, &_port);
_host.assign(start, host_end - start);
if (*p == '/') {
start = p; //slash pointed by p is counted into _path
++p;
for (; *p && *p != '?' && *p != '#'; ++p) {
if (*p == ' ') {
if (!is_all_spaces(p + 1)) {
_st.set_error(EINVAL, "Invalid space in path");
return -1;
}
break;
}
}
_path.assign(start, p - start);
}
if (*p == '?') {
start = ++p;
for (; *p && *p != '#'; ++p) {
if (*p == ' ') {
if (!is_all_spaces(p + 1)) {
_st.set_error(EINVAL, "Invalid space in query");
return -1;
}
break;
}
}
_query.assign(start, p - start);
}
if (*p == '#') {
start = ++p;
for (; *p; ++p) {
if (*p == ' ') {
if (!is_all_spaces(p + 1)) {
_st.set_error(EINVAL, "Invalid space in fragment");
return -1;
}
break;
}
}
_fragment.assign(start, p - start);
}
return 0;
}