当我的请求 URL 有查询字符串时,如何编写正则表达式来使用 Grapevine 路由流量?

How do I write a regular expression to route traffic with Grapevine when my request URL has a query string?

我正在使用 Grapevine,我想路由具有查询字符串的请求流量,但我不太了解正则表达式,无法弄清楚为什么它不起作用。

例如

http://localhost:1234/service/function?param1=1&param2=2

我这样定义 RESTRoute

[RESTRoute(Method = HttpMethod.GET, PathInfo = @"^/service/function\?\D+$")]
public void HandleFooRequestString(HttpListenerContext context)
{
    PrintRequest(context);
    this.SendTextResponse(context, "foo is a success!");
}

但是发送到 URL 的流量不会流向该方法。我做错了什么?

这是一个 pretty common question,并且对 Grapevine 路线图产生了一些变化。

小道消息 3.1.0 +

在最新版本的 Grapevine 中,查询字符串在正则表达式模式匹配之前从 URL 中剥离,因此这不再是问题。

此外,版本 4 中的路由正在更新以匹配 Node/Express routing mechanism,因此您可以根据需要选择完全不使用正则表达式。不过这个版本还在规划阶段。

小道消息 3.0.x

虽然 GET 请求在 header URI 设计 下包含 query string parameters, let's first make sure we are using proper URI design. To quote from O'Reilly's RESTful Web Services,第 233 页当然并不少见(强调我的):

When designing URIs, use path variables to separate elements of a hierarchy, or a path through a directed graph. Example: /weblogs/myweblog/entries/100 goes from the general to the specific. From a list of weblogs, to a particular weblog, to the entries in that weblog, to a particular entry. Each path variable is in some sense "inside" the previous one.

Use punctuation characters to separate multiple pieces of data at the same level of hierarchy. Use commas when the order of the items matters, as it does in latitude and longitude: /Earth/37.0,-95.2. Use semicolons when the order doesn't matter: /color-blends/red;blue.

Use query variables only to suggest arguments being plugged into an algorithm, or when the other two techniques fail. If two URIs differ only in their query variables, it implies that they're the different sets of inputs into the same underlying algorithm.

这里最重要的一点是,一般来说,我们的 URI 应该只使用查询字符串将参数传递给算法。如果,确实,我们希望在我们的方法中使用查询字符串参数,那么这些参数应该通过请求路由到的方法进行验证,并且我们的 PathInfo 正则表达式应该反映接收此类参数的可能性。

示例:何时不使用查询字符串

假设您想请求给定特定数字用户 ID 的用户数据,假设 632。在这种情况下,可能很想使用查询字符串,但最好不要使用。

  • 不太正确的 URI:/user?id=632
  • 更正确的 URI:/user/632

more-correct URI 的 RESTRoute 将如下所示:

[RESTRoute(Method = HttpMethod.GET, PathInfo = @"^/user/\d+$")]
public void GetUser(HttpListenerContext context)
{
    var userid = context.RawUrl.GrabFirst(@"^/user/(\d+)$");
    // you got your user id, do something
}

示例:正确使用查询字符串

如果您想创建一个将两个整数相乘的 REST 路由,那么 - 除了 URI 假设代表资源,而不是对资源的操作 - 使用查询字符串可能更合适。

  • 可能不太正确的 URI:/2/product/3
  • 可能更正确的 URI:/product?x=2&y=3

可能-more-correct URI 的 RESTRoute 将如下所示:

[RESTRoute(Method = HttpMethod.GET, PathInfo = @"^/product")]
public void MultiplyTwoIntegers(HttpListenerContext context)
{
    var x = context.Request.QueryString["x"];
    var y = context.Request.QueryString["y"];

    // Verify the inputs and do the math.
}

请注意,PathInfo 正则表达式省略了尾部 $,这通常表示字符串结束,我们让路由方法处理获取传递的参数。如果我们真的想成为一个坚持者,我们也可以这样写:

[RESTRoute(Method = HttpMethod.GET, PathInfo = @"^/product\?.+$")]

这将确保它至少看起来像查询字符串中可能有一些参数,但实际上并不是必需的,因为无论如何我们都要进行检查。