ServiceStack URI encoding
本文关键字:encoding URI ServiceStack | 更新日期: 2023-09-27 18:31:52
我已经使用ServiceStack一段时间了,我对它提供的功能非常满意。已经用它实现了服务器服务,它就像一个魅力。
但是,最近我遇到了使用必须正确编码的复杂 URL 调用其他服务的问题。
代码如下:
请求:
[Route("/instruments/{Names}")]
internal class Request
{
public List<string> Names { get; set; }
}
方法调用:
var request = new Request { Names = list };
var c = new JsonServiceClient("http://host:12345/");
Response[] response;
try
{
response = c.Get<Response[]>(request);
}
catch (WebServiceException ex)
{
HandleWebException(ex, list);
yield break;
}
现在的问题是,有时名称可以包含特殊字符,例如空格或/。我想对这些属性进行编码。例如,我希望能够使用以下参数调用远程服务:"D''S N"应该编码为"D%5CS%20N"。因此,被调用的 URL 应如下所示:
http://host:12345/instruments/D%5CS%20N
现在的问题是JsonServiceClient在这里进行了错误的编码。我所说的实际上是:
http://host:12345/instruments/D/S%20N
用显然是错误的。任何如何解决这个问题的帮助都是合适的。
您不应该在 PathInformation 中注册像 List<T>
这样的复杂类型,请尝试使用单个字符串:
[Route("/instruments/{Name}")]
public class Request
{
public string Name { get; set; }
}
或者把它从/pathinfo 中取出,这样它就会在 QueryString 上被序列化为复杂类型:
[Route("/instruments")]
public class Request
{
public List<string> Names { get; set; }
}
我相信ServiceStack可以在这里得到改进。
如果我使用如下定义的请求 DTO:
[Route("/hello/{Name}/{Message}")]
public class Hello
{
public string Name { get; set; }
public string Message { get; set; }
}
然后客户端像这样调用:
var resp = cli.Get(new Hello { Message = "test", Name = "foo/bar" });
将失败。如果我用反斜杠替换斜杠,也会发生同样的情况。
我已经对 ServiceStack 做了一个补丁来修复这种行为(也适用于反斜杠),以便 Name 将被正确编码客户端和解码的服务器端。Demis,这是你可能有兴趣看看的东西吗?
顺便说一句,这与Java Jersey开箱即用.....
我遇到了同样的问题。 我的字符串不是一个复杂的对象。 只是一个带有斜杠的字符串。 看起来服务堆栈实际上正在正确接收 URL 编码的字符串。然后,Servicestack 似乎在将 URL 编码字符串传递给路由之前对其进行解码(这只是我的猜测),而不是使用请求 DTO 中的路由信息首先确定 URL 的哪一部分是路由,哪一部分是参数,然后路由,然后解码 URL 编码参数。我从服务堆栈收到如下错误:
Handler for Request not found (404):
Request.HttpMethod: GET
Request.PathInfo: /QuoteFeed/GetQuote/ACO/X CN
Request.QueryString:
Request.RawUrl: /QuoteFeed/GetQuote/ACO%2FX%20CN
请求定义如下:
[Route("/QuoteFeed/GetQuote/{Symbol}", Summary = "Retreive a price quote for the requested symbol.")]
public class GetQuote : IReturn<QuoteDataResponse>
{
[DataMember, ProtoMember(1)]
[ApiMember(Name = "Symbol",
Description = "The symbol, in the providers given format, for which a quote should be given.",
DataType = "string",
IsRequired = true)]
public string Symbol { get; set; }
}
要求客户端将斜杠替换为服务将交换回斜杠的其他特殊字符似乎很脆弱。 解决此问题的唯一方法是通过 POST 强制请求吗?
编辑 1
这是我让它工作的最佳尝试:
在客户端:
dim client = new JsonServiceClient (My.Settings.MarketDataServiceUri)
dim request = New GetQuote
request.Symbol = WebUtility.UrlEncode(txtBoxSymbol.Text.ToUpperInvariant)
在服务器端(在 AppHost.Init 中):
base.RequestBinders.Add(typeof(GetQuote), httpReq =>
{
var requestPath = string.Empty;
if (typeof(GetQuote).GetCustomAttributes(typeof(RouteAttribute), true
).FirstOrDefault() is RouteAttribute dnAttribute)
{
requestPath = dnAttribute.Path;
}
var routePath = requestPath;
var paramIndex = requestPath.IndexOf("{");
if (paramIndex > 0)
{
routePath = requestPath.Substring(0, paramIndex);
}
return new GetQuote
{
Symbol = WebUtility.UrlDecode(httpReq.PathInfo.Replace(routePath, string.Empty))
};
});
这真的很丑陋,但我找不到任何其他方法。 传入的符号必须具有斜杠,因为这是下游报价提供程序要求的格式,也是用户期望输入的格式。 这是最好的方法吗?