Can ServiceStack Runner Get Request Body?

2019-01-18 12:23发布

问题:

Is it possible, without major hackery, to get the raw request body of a ServiceStack request within the Runner?

I am writing an oauth service provider to run on top of ServiceStack using the new API (Service and Runner). Due to how OAuth signing works I need to get the raw request body for each request. The OAuth protection layer is added to the Runner so that an invalid OAuth request can easily return an empty/error response without any boilerplate in the Service class or subclassing a special "OAuthService" class.

回答1:

The way to access the Raw Request Body is to use IHttpRequest.GetRawBody() or read from IHttpRequest.InputStream.

But as the HTTP Request body is a forward only stream, by default it can only be called once which is usually called by ServiceStack to deserialize the Request DTO. The Serialization and Deserialization docs show how to tell ServiceStack to skip deserializing the Request and inject the unread Request Stream into the Request DTO with:

public class Hello : IRequiresRequestStream
{
    /// <summary>
    /// The raw Http Request Input Stream
    /// </summary>
    Stream RequestStream { get; set; }
}

If you still want ServiceStack to deserialize the Request DTO but also access the raw request body you need to tell ServiceStack to buffer the request before its read, which you can do by adding the PreRequestFilter:

appHost.PreRequestFilters.Insert(0, (httpReq, httpRes) => {
    httpReq.UseBufferedStream = true;
});

Which now lets you call httpReq.GetRawBody() multiple times or read directly from the IHttpRequest.InputStream since it's now buffered.