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



我使用的是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的流量不会流向该方法。我做错了什么?

这是一个非常常见的问题,并对葡萄藤路线图进行了一些更改。

葡萄藤3.1.0+

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

此外,路由在版本4中进行了更新,以匹配Node/Express路由机制,因此如果愿意,您可以选择完全不使用正则表达式。然而,该版本仍处于规划阶段。

葡萄藤3.0.x

虽然GET请求包含查询字符串参数并不罕见,但让我们首先确保使用了正确的URI设计。引用O'Reilly的RESTful Web Services,第233页,标题下的URI设计(强调我的):

在设计URI时,使用路径变量来分隔层次结构的元素,或通过有向图的路径。示例:/weblogs/myweblog/entries/100从一般到具体。从日志列表,到特定日志,到该日志中的条目,再到特定条目。每个路径变量在某种意义上都是"零";内部";上一个。

使用标点符号可以在同一层次结构级别上分隔多条数据。当项目的顺序很重要时使用逗号,就像在纬度和经度中一样:/Earth/37.0,-95.2。如果顺序无关紧要,请使用分号:/color-blends/red;blue

只使用查询变量来建议将参数插入算法,或者在其他两种技术失败时使用。如果两个URI的查询变量不同,则意味着它们是同一底层算法的不同输入集。

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

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

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

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

更正确的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

可能更正确的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正则表达式省略了后面的$,它通常表示字符串的末尾,并且我们让route方法来处理传递的参数。如果我们真的想成为一个坚持者,我们也可以这样写:

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

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

相关内容

最新更新