ServiceStack - 使用gzip /紧缩与JSONP请求压缩 [英] ServiceStack - Using gzip/deflate compression with JSONP requests

查看:221
本文介绍了ServiceStack - 使用gzip /紧缩与JSONP请求压缩的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有使用 RequestContext.ToOptimizedResult(),例如压缩响应ServiceStack服务:

I have a ServiceStack service that compresses the response using RequestContext.ToOptimizedResult(), e.g.:

[Route("/numbers/search")]
public class FindNumbers
{
}

public object Get(FindNumbers query)
{
    var data = new List<string> { "One", "Two", "Three" };
    return RequestContext.ToOptimizedResult(data);
}



发出类似的请求时,这完美的作品:

This works perfectly when issuing a request like:

GET http://myhost:13487/numbers/search.json

和作为与的Accept-Encoding 请求头有望被压缩:

And is compressed as expected with the Accept-Encoding request header:

Accept-Encoding: gzip,deflate,sdch

我可以还发出JSONP请求:

I can also issue a JSONP request:

GET http://myhost:13487/numbers/search?callback=func

这正确返回应用程序/ JavaScript的回调(未压缩)。

which correctly returns an application/javascript callback (uncompressed).

当我添加了的Accept-Encoding 请求头与JSONP请求,响应压缩JSON数据按原来的JSON请求,而不是压缩应用程序/ JavaScript的回调。

When I add the Accept-Encoding request header to the JSONP request, the response is the compressed JSON data as per the original JSON request, and not a compressed application/javascript callback.

有没有我缺少这种行为的任何明显的原因,还是它只是在ServiceStack的错误吗?我的期望是获得一个压缩JSONP回调的反应,但我相当绿色JSONP并有可能回退一个很好的理由。

Are there any obvious reasons that I'm missing for this behaviour, or is it simply a bug in ServiceStack? My expectation would be to receive a compressed JSONP callback in the response, but I'm fairly green with JSONP and there may be a good reason for the fallback.

请注意,我在通过ServiceStack源工作的进展,但我想我会得到这个赫然出现更多的大脑比一个人好......

Note, I'm in progress of working through the ServiceStack source, but I figured I'd get this out there as more brains are better than one...

在此先感谢

修改

所以,我跟踪这个问题了下列源

So, I've traced the issue down the following source

https://github.com/ServiceStack/ServiceStack/blob/5d09d439cd1a13712411552e2b3ede5a71af2ee5/src/ServiceStack/Host/Handlers/GenericHandler.cs#L79

https://github.com/ServiceStack/ServiceStack/blob/5d09d439cd1a13712411552e2b3ede5a71af2ee5/src/ServiceStack/Host/RestHandler.cs#L107

if (doJsonp && !(response is CompressedResult))
    return httpRes.WriteToResponse(httpReq, response, (callback + "(").ToUtf8Bytes(),")".ToUtf8Bytes());

return httpRes.WriteToResponse(httpReq, response);



因此,如果该响应是一个压缩的结果,则不管为JSONP要求经由?回调= FUNC 响应将简单地包含该压缩的JSON(在上述例的情况下),该环与上述我的发现真。所以它看起来像JSONP回调包装必须早些时候在调用堆栈的应用。

So if the response is a compressed result, then regardless of the requirement for JSONP via ?callback=func the response will simply contain the compressed json (in the case of the example above), which rings true with my findings above. So it looks like the jsonp callback wrapper needs to be applied earlier in the callstack.

推荐答案

对于那些有兴趣,我解决了这通过编写拦截响应和处理压缩的之外的服务方法,这是我认为它应该做的压缩插件。它还涉及上述JSONP问题。

For those that are interested, I solved this by writing a compression plugin that intercepts the response and handles the compression outside of the service method, which is where I believe it should be done. It also addresses the JSONP issue described above.

在我看来,压缩是一个正交关注的服务方法的逻辑,和移动这种业务方法之外作为响应滤波器使服务服务调用固有强类型,而不是丑陋的公共对象MyServiceMethod(DtoType要求),允许任意的压缩/非压缩的响应{} 签名存在。我已经采取了这里假定,如果客户端状态的有效的Accept-Encoding 头则响应会被压缩无关,我认为这是一个公平的征召令。

In my opinion, compression is an orthogonal concern to the service method logic, and moving this outside of the service method as a response filter enables service to service calls to exist with inherent strong typing instead of the ugly public object MyServiceMethod(DtoType request) { } signatures for allowing arbitrary compressed/uncompressed responses. I've taken the assumption here that if the client states a valid Accept-Encoding header then the response will be compressed regardless, which I think is a fair call to make.

现在,我已经选择对拉请求ServiceStack我看到它作为方法的框架,如何处理压缩的重大变革,将需要大量的前期讨论与业主。这段代码纯粹是为了示范的目的,但我使用它,它工作得很好。

For now, I've opted against a pull request to ServiceStack as I see it as a major change in the approach to how the framework handles compression and would require considerable upfront discussion with the owners. This code is purely for demonstrative purposes, but I'm using it and it works very well.

代码:

public class CompressionFeature : IPlugin
{
    public void Register(IAppHost appHost)
    {
        appHost.ResponseFilters.Add((request, response, dto) =>
        {
            if (dto == null || dto is AuthResponse || dto is CompressedResult || dto is Exception) return;

            using (var serializationContext = new HttpRequestContext(request, response, dto))
            {
                if (!serializationContext.RequestAttributes.AcceptsDeflate && !serializationContext.RequestAttributes.AcceptsGzip) return;

                var serializedDto = EndpointHost.ContentTypeFilter.SerializeToString(serializationContext, dto);

                var callback = request.GetJsonpCallback();
                var isJsonpRequest = EndpointHost.Config.AllowJsonpRequests && !string.IsNullOrEmpty(callback);

                if (isJsonpRequest)
                {
                    serializedDto = (callback + "(") + serializedDto + ")";
                    serializationContext.ResponseContentType = ContentType.JavaScript;
                }

                var compressedBytes = serializedDto.Compress(serializationContext.CompressionType);
                var compressedResult = new CompressedResult(compressedBytes, serializationContext.CompressionType, serializationContext.ResponseContentType);
                response.WriteToResponse(compressedResult, serializationContext.ResponseContentType);
            }
        });
    }
}



注册插件,在APPHOST:

Register the plugin in your AppHost:

appHost.Plugins.Add(new CompressionFeature());

这篇关于ServiceStack - 使用gzip /紧缩与JSONP请求压缩的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆