1
0
Fork 0
mirror of https://github.com/ossrs/srs.git synced 2025-03-09 15:49:59 +00:00

URL: Use SrsHttpUri to parse URL and query.

This commit is contained in:
winlin 2022-08-28 19:24:44 +08:00
parent 9bd3c51818
commit 28154e820c
4 changed files with 234 additions and 86 deletions

View file

@ -7,6 +7,7 @@ The changelog for SRS.
## SRS 5.0 Changelog ## SRS 5.0 Changelog
* v5.0, 2022-08-28, URL: Use SrsHttpUri to parse URL and query. v5.0.48
* v5.0, 2022-08-28, Fix [#2881](https://github.com/ossrs/srs/issues/2881): HTTP: Support merging api to server. v5.0.47 * v5.0, 2022-08-28, Fix [#2881](https://github.com/ossrs/srs/issues/2881): HTTP: Support merging api to server. v5.0.47
* v5.0, 2022-08-27, Fix [#3108](https://github.com/ossrs/srs/issues/3108): STAT: Update stat for SRT. v5.0.46 * v5.0, 2022-08-27, Fix [#3108](https://github.com/ossrs/srs/issues/3108): STAT: Update stat for SRT. v5.0.46
* v5.0, 2022-08-26, Log: Stat the number of logs. v5.0.45 * v5.0, 2022-08-26, Log: Stat the number of logs. v5.0.45

View file

@ -9,6 +9,6 @@
#define VERSION_MAJOR 5 #define VERSION_MAJOR 5
#define VERSION_MINOR 0 #define VERSION_MINOR 0
#define VERSION_REVISION 47 #define VERSION_REVISION 48
#endif #endif

View file

@ -42,97 +42,58 @@ using namespace std;
#include <srs_kernel_utility.hpp> #include <srs_kernel_utility.hpp>
#include <srs_protocol_http_stack.hpp> #include <srs_protocol_http_stack.hpp>
/**
* resolve the vhost in query string
* @pram vhost, update the vhost if query contains the vhost.
* @param app, may contains the vhost in query string format:
* app?vhost=request_vhost
* app...vhost...request_vhost
* @param param, the query, for example, ?vhost=xxx
*/
void srs_vhost_resolve(string& vhost, string& app, string& param)
{
// get original param
size_t pos = 0;
if ((pos = app.find("?")) != std::string::npos) {
param = app.substr(pos);
}
// filter tcUrl
app = srs_string_replace(app, ",", "?");
app = srs_string_replace(app, "...", "?");
app = srs_string_replace(app, "&&", "?");
app = srs_string_replace(app, "&", "?");
app = srs_string_replace(app, "=", "?");
if (srs_string_ends_with(app, "/_definst_")) {
app = srs_erase_last_substr(app, "/_definst_");
}
if ((pos = app.find("?")) != std::string::npos) {
std::string query = app.substr(pos + 1);
app = app.substr(0, pos);
if ((pos = query.find("vhost?")) != std::string::npos) {
query = query.substr(pos + 6);
if (!query.empty()) {
vhost = query;
}
} else if ((pos = query.find("domain?")) != std::string::npos) {
query = query.substr(pos + 7);
if (!query.empty()) {
vhost = query;
}
}
}
// vhost with params.
if ((pos = vhost.find("?")) != std::string::npos) {
vhost = vhost.substr(0, pos);
}
/* others */
}
void srs_discovery_tc_url(string tcUrl, string& schema, string& host, string& vhost, string& app, string& stream, int& port, string& param) void srs_discovery_tc_url(string tcUrl, string& schema, string& host, string& vhost, string& app, string& stream, int& port, string& param)
{ {
size_t pos = std::string::npos; // Standard URL is:
std::string url = tcUrl; // rtmp://ip/app/app2/stream?k=v
// Where after last slash is stream.
if ((pos = url.find("://")) != std::string::npos) { string fullUrl = tcUrl;
schema = url.substr(0, pos); fullUrl += stream.empty() ? "/" : (stream.at(0) == '/' ? stream : "/" + stream);
url = url.substr(schema.length() + 3); fullUrl += param.empty() ? "" : (param.at(0) == '?' ? param : "?" + param);
srs_info("discovery schema=%s", schema.c_str());
} // First, we covert the FMLE URL to standard URL:
// rtmp://ip/app/app2?k=v/stream
if ((pos = url.find("/")) != std::string::npos) { size_t pos_query = fullUrl.find("?");
host = url.substr(0, pos); size_t pos_rslash = fullUrl.rfind("/");
url = url.substr(host.length() + 1); if (pos_rslash != string::npos && pos_query != string::npos && pos_query < pos_rslash) {
srs_info("discovery host=%s", host.c_str()); fullUrl = fullUrl.substr(0, pos_query) // rtmp://ip/app/app2
} + fullUrl.substr(pos_rslash) // /stream
+ fullUrl.substr(pos_query, pos_rslash - pos_query); // ?k=v
port = SRS_CONSTS_RTMP_DEFAULT_PORT;
if (schema == "https") {
port = SRS_DEFAULT_HTTPS_PORT;
} }
if ((pos = host.find(":")) != std::string::npos) { // Remove the _definst_ of FMLE URL.
srs_parse_hostport(host, host, port); if (fullUrl.find("/_definst_") != string::npos) {
srs_info("discovery host=%s, port=%d", host.c_str(), port); fullUrl = srs_string_replace(fullUrl, "/_definst_", "");
} }
if (url.empty()) { // Parse the standard URL.
app = SRS_CONSTS_RTMP_DEFAULT_APP; SrsHttpUri uri;
} else { srs_error_t err = srs_success;
app = url; if ((err = uri.initialize(fullUrl)) != srs_success) {
srs_warn("Ignore parse url=%s err %s", fullUrl.c_str(), srs_error_desc(err).c_str());
srs_freep(err);
return;
} }
vhost = host; schema = uri.get_schema();
srs_vhost_resolve(vhost, app, param); host = uri.get_host();
srs_vhost_resolve(vhost, stream, param); port = uri.get_port();
stream = srs_path_basename(uri.get_path());
// Ignore when the param only contains the default vhost. param = uri.get_query().empty() ? "" : "?" + uri.get_query();
if (param == "?vhost=" SRS_CONSTS_RTMP_DEFAULT_VHOST) {
// Parse app without the prefix slash.
app = srs_path_dirname(uri.get_path());
if (!app.empty() && app.at(0) == '/') app = app.substr(1);
if (app.empty()) app = SRS_CONSTS_RTMP_DEFAULT_APP;
// Try to parse vhost from query, or use host if not specified.
string vhost_in_query = uri.get_query_by_key("vhost");
if (vhost_in_query.empty()) vhost_in_query = uri.get_query_by_key("domain");
if (!vhost_in_query.empty() && vhost_in_query != SRS_CONSTS_RTMP_DEFAULT_VHOST) vhost = vhost_in_query;
if (vhost.empty()) vhost = host;
// Only one param, the default vhost, clear it.
if (param.find("&") == string::npos && vhost_in_query == SRS_CONSTS_RTMP_DEFAULT_VHOST) {
param = ""; param = "";
} }
} }

View file

@ -17,6 +17,7 @@
#include <srs_protocol_http_conn.hpp> #include <srs_protocol_http_conn.hpp>
#include <srs_kernel_buffer.hpp> #include <srs_kernel_buffer.hpp>
#include <srs_kernel_codec.hpp> #include <srs_kernel_codec.hpp>
#include <srs_protocol_utility.hpp>
#define SRS_DEFAULT_RECV_BUFFER_SIZE 131072 #define SRS_DEFAULT_RECV_BUFFER_SIZE 131072
@ -3621,3 +3622,188 @@ VOID TEST(ProtocolRTMPTest, GuessingStream)
} }
} }
VOID TEST(ProtocolRTMPTest, DiscoveryUrl)
{
if (true) {
string tcUrl = "invalid://ip:8888/app", stream = "stream?k=v&domain=ossrs.io&k2=v2";
string schema, host, vhost, app, param; int port;
srs_discovery_tc_url(tcUrl, schema, host, vhost, app, stream, port, param);
EXPECT_STREQ("invalid", schema.c_str());
EXPECT_STREQ("ip", host.c_str());
EXPECT_EQ(8888, port);
EXPECT_STREQ("app", app.c_str());
EXPECT_STREQ("stream", stream.c_str());
EXPECT_STREQ("ossrs.io", vhost.c_str());
EXPECT_STREQ("?k=v&domain=ossrs.io&k2=v2", param.c_str());
}
if (true) {
string tcUrl = "invalid://ip/app", stream = "stream?k=v&domain=ossrs.io&k2=v2";
string schema, host, vhost, app, param; int port;
srs_discovery_tc_url(tcUrl, schema, host, vhost, app, stream, port, param);
EXPECT_STREQ("invalid", schema.c_str());
EXPECT_STREQ("ip", host.c_str());
EXPECT_EQ(80, port);
EXPECT_STREQ("app", app.c_str());
EXPECT_STREQ("stream", stream.c_str());
EXPECT_STREQ("ossrs.io", vhost.c_str());
EXPECT_STREQ("?k=v&domain=ossrs.io&k2=v2", param.c_str());
}
if (true) {
string tcUrl = "rtmp://ip/app", stream = "stream?k=v&domain=ossrs.io&k2=v2";
string schema, host, vhost, app, param; int port;
srs_discovery_tc_url(tcUrl, schema, host, vhost, app, stream, port, param);
EXPECT_STREQ("rtmp", schema.c_str());
EXPECT_STREQ("ip", host.c_str());
EXPECT_EQ(1935, port);
EXPECT_STREQ("app", app.c_str());
EXPECT_STREQ("stream", stream.c_str());
EXPECT_STREQ("ossrs.io", vhost.c_str());
EXPECT_STREQ("?k=v&domain=ossrs.io&k2=v2", param.c_str());
}
if (true) {
string tcUrl = "https://ip/app", stream = "stream?k=v&domain=ossrs.io&k2=v2";
string schema, host, vhost, app, param; int port;
srs_discovery_tc_url(tcUrl, schema, host, vhost, app, stream, port, param);
EXPECT_STREQ("https", schema.c_str());
EXPECT_STREQ("ip", host.c_str());
EXPECT_EQ(443, port);
EXPECT_STREQ("app", app.c_str());
EXPECT_STREQ("stream", stream.c_str());
EXPECT_STREQ("ossrs.io", vhost.c_str());
EXPECT_STREQ("?k=v&domain=ossrs.io&k2=v2", param.c_str());
}
if (true) {
string tcUrl = "http://ip/app", stream = "stream?k=v&domain=ossrs.io&k2=v2";
string schema, host, vhost, app, param; int port;
srs_discovery_tc_url(tcUrl, schema, host, vhost, app, stream, port, param);
EXPECT_STREQ("http", schema.c_str());
EXPECT_STREQ("ip", host.c_str());
EXPECT_EQ(80, port);
EXPECT_STREQ("app", app.c_str());
EXPECT_STREQ("stream", stream.c_str());
EXPECT_STREQ("ossrs.io", vhost.c_str());
EXPECT_STREQ("?k=v&domain=ossrs.io&k2=v2", param.c_str());
}
if (true) {
string tcUrl = "rtmp://ip/app", stream = "stream?domain=__defaultVhost__";
string schema, host, vhost, app, param; int port;
srs_discovery_tc_url(tcUrl, schema, host, vhost, app, stream, port, param);
EXPECT_STREQ("rtmp", schema.c_str());
EXPECT_STREQ("ip", host.c_str());
EXPECT_EQ(1935, port);
EXPECT_STREQ("app", app.c_str());
EXPECT_STREQ("stream", stream.c_str());
EXPECT_STREQ("ip", vhost.c_str());
EXPECT_TRUE(param.empty());
}
if (true) {
string tcUrl = "rtmp://ip/app/_definst_", stream = "stream?k=v&domain=ossrs.io&k2=v2";
string schema, host, vhost, app, param; int port;
srs_discovery_tc_url(tcUrl, schema, host, vhost, app, stream, port, param);
EXPECT_STREQ("rtmp", schema.c_str());
EXPECT_STREQ("ip", host.c_str());
EXPECT_EQ(1935, port);
EXPECT_STREQ("app", app.c_str());
EXPECT_STREQ("stream", stream.c_str());
EXPECT_STREQ("ossrs.io", vhost.c_str());
EXPECT_STREQ("?k=v&domain=ossrs.io&k2=v2", param.c_str());
}
if (true) {
string tcUrl = "rtmp://ip", stream = "stream?k=v&domain=ossrs.io&k2=v2";
string schema, host, vhost, app, param; int port;
srs_discovery_tc_url(tcUrl, schema, host, vhost, app, stream, port, param);
EXPECT_STREQ("rtmp", schema.c_str());
EXPECT_STREQ("ip", host.c_str());
EXPECT_EQ(1935, port);
EXPECT_STREQ("__defaultApp__", app.c_str());
EXPECT_STREQ("stream", stream.c_str());
EXPECT_STREQ("ossrs.io", vhost.c_str());
EXPECT_STREQ("?k=v&domain=ossrs.io&k2=v2", param.c_str());
}
if (true) {
string tcUrl = "rtmp://ossrs.io/app/app2", stream = "stream?k=v&k2=v2";
string schema, host, vhost, app, param; int port;
srs_discovery_tc_url(tcUrl, schema, host, vhost, app, stream, port, param);
EXPECT_STREQ("rtmp", schema.c_str());
EXPECT_STREQ("ossrs.io", host.c_str());
EXPECT_EQ(1935, port);
EXPECT_STREQ("app/app2", app.c_str());
EXPECT_STREQ("stream", stream.c_str());
EXPECT_STREQ("ossrs.io", vhost.c_str());
EXPECT_STREQ("?k=v&k2=v2", param.c_str());
}
if (true) {
string tcUrl = "rtmp://ip/app/app2", stream = "stream?k=v&domain=ossrs.io&k2=v2";
string schema, host, vhost, app, param; int port;
srs_discovery_tc_url(tcUrl, schema, host, vhost, app, stream, port, param);
EXPECT_STREQ("rtmp", schema.c_str());
EXPECT_STREQ("ip", host.c_str());
EXPECT_EQ(1935, port);
EXPECT_STREQ("app/app2", app.c_str());
EXPECT_STREQ("stream", stream.c_str());
EXPECT_STREQ("ossrs.io", vhost.c_str());
EXPECT_STREQ("?k=v&domain=ossrs.io&k2=v2", param.c_str());
}
if (true) {
string tcUrl = "rtmp://ip/app/app2", stream = "stream?k=v&vhost=ossrs.io&k2=v2";
string schema, host, vhost, app, param; int port;
srs_discovery_tc_url(tcUrl, schema, host, vhost, app, stream, port, param);
EXPECT_STREQ("rtmp", schema.c_str());
EXPECT_STREQ("ip", host.c_str());
EXPECT_EQ(1935, port);
EXPECT_STREQ("app/app2", app.c_str());
EXPECT_STREQ("stream", stream.c_str());
EXPECT_STREQ("ossrs.io", vhost.c_str());
EXPECT_STREQ("?k=v&vhost=ossrs.io&k2=v2", param.c_str());
}
if (true) {
string tcUrl = "rtmp://ip/app/app2", stream = "stream?k=v&k2=v2";
string schema, host, vhost, app, param; int port;
srs_discovery_tc_url(tcUrl, schema, host, vhost, app, stream, port, param);
EXPECT_STREQ("rtmp", schema.c_str());
EXPECT_STREQ("ip", host.c_str());
EXPECT_EQ(1935, port);
EXPECT_STREQ("app/app2", app.c_str());
EXPECT_STREQ("stream", stream.c_str());
EXPECT_STREQ("ip", vhost.c_str());
EXPECT_STREQ("?k=v&k2=v2", param.c_str());
}
if (true) {
string tcUrl = "rtmp://ip/app/app2?k=v", stream = "stream";
string schema, host, vhost, app, param; int port;
srs_discovery_tc_url(tcUrl, schema, host, vhost, app, stream, port, param);
EXPECT_STREQ("rtmp", schema.c_str());
EXPECT_STREQ("ip", host.c_str());
EXPECT_EQ(1935, port);
EXPECT_STREQ("app/app2", app.c_str());
EXPECT_STREQ("stream", stream.c_str());
EXPECT_STREQ("ip", vhost.c_str());
EXPECT_STREQ("?k=v", param.c_str());
}
if (true) {
string tcUrl = "rtmp://ip/app?k=v", stream = "stream";
string schema, host, vhost, app, param; int port;
srs_discovery_tc_url(tcUrl, schema, host, vhost, app, stream, port, param);
EXPECT_STREQ("rtmp", schema.c_str());
EXPECT_STREQ("ip", host.c_str());
EXPECT_EQ(1935, port);
EXPECT_STREQ("app", app.c_str());
EXPECT_STREQ("stream", stream.c_str());
EXPECT_STREQ("ip", vhost.c_str());
EXPECT_STREQ("?k=v", param.c_str());
}
}