Prevent unwanted headers when returning 304 Not Modified with ServiceStack
Asked Answered
W

2

6

Using ServiceStack, I just want to return 304 Not Modified as such:

HTTP/1.1 304 Not Modified

But ServiceStack adds many other unwanted (returning HttpResult with 304 code) headers as such:

HTTP/1.1 304 Not Modified
Content-Length: 0
Content-Type: application/json
Server: Microsoft-HTTPAPI/2.0
X-Powered-By: ServiceStack/3.94 Win32NT/.NET
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Headers: Content-Type
Date: Tue, 07 Aug 2012 13:39:19 GMT

How can I prevent the other headers from being outputted? I've tried various approaches with HttpResult, registering a dummy content type filter, but as its name implies only controls content, not the headers, or others listed here. I've also tried implementing my own IHttpResult derivative with IStreamWriter and IHasOptions with the same results: ServiceStack adds unwanted headers.

Thanks

Update

Was able to remove content-type by using the following, but some headers are still present i.e. content-length, server, and date.

    public override object OnGet(FaultTypes request)
    {
      var result = new HttpResult
      {
       StatusCode = HttpStatusCode.NotModified,
       StatusDescription = "Not Modified", // Otherwise NotModified written!
      };

      // The following are hacks to remove as much HTTP headers as possible
      result.ResponseFilter = new NotModifiedContentTypeWriter();
      // Removes the content-type header
      base.Request.ResponseContentType = string.Empty;

      return result;
    }

class NotModifiedContentTypeWriter : ServiceStack.ServiceHost.IContentTypeWriter
{
  ServiceStack.ServiceHost.ResponseSerializerDelegate ServiceStack.ServiceHost.IContentTypeWriter.GetResponseSerializer(string contentType)
  {
    return ResponseSerializerDelegate;
  }

  void ServiceStack.ServiceHost.IContentTypeWriter.SerializeToResponse(ServiceStack.ServiceHost.IRequestContext requestContext, object response, ServiceStack.ServiceHost.IHttpResponse httpRes)
  {
  }

  void ServiceStack.ServiceHost.IContentTypeWriter.SerializeToStream(ServiceStack.ServiceHost.IRequestContext requestContext, object response, System.IO.Stream toStream)
  {
  }

  string ServiceStack.ServiceHost.IContentTypeWriter.SerializeToString(ServiceStack.ServiceHost.IRequestContext requestContext, object response)
  {
    return string.Empty;
  }

  public void ResponseSerializerDelegate(ServiceStack.ServiceHost.IRequestContext requestContext, object dto, ServiceStack.ServiceHost.IHttpResponse httpRes)
  {
  }
}
Worsham answered 7/8, 2012 at 13:50 Comment(0)
K
8

The only headers emitted by ServiceStack are the ones registered in the EndpointHostConfig.GlobalResponseHeaders.

Remove them if you don't want them emitted, e.g:

SetConfig(new EndpointHostConfig { 
    GlobalResponseHeaders = new Dictionary<string,string>()
});

You can add them on an adhoc-basis using a HttpResult, e.g:

return new HttpResult(dto) {
    Headers = {
       { "Access-Control-Allow-Origin", "*" },
       { "Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS" } 
       { "Access-Control-Allow-Headers", "Content-Type" }, }
};

Both options explained in more detail at: servicestack REST API and CORS

Karakalpak answered 7/8, 2012 at 14:53 Comment(9)
Thanks for the answer, but this only removes the CORS, not the others. I still have HTTP/1.1 304 Not Modified Content-Length: 0 Content-Type: application/json Expires: Thu, 16 Aug 2012 16:20:25 GMT Server: Microsoft-HTTPAPI/2.0 Date: Thu, 16 Aug 2012 16:20:24 GMTWorsham
The emitted headers that aren't in GlobalResponseHeaders or added yourself on a per-service basis with HttpResult are not from ServiceStack. IIS / ASP.NET may choose to add their own headers.Karakalpak
Not using IIS/ASP.Net, just console app test. Seems added from JSON serializer and others. How can I control these?Worsham
Nothing is added from any serializers. Are you sure you're setting GlobalResponseHeaders = new Dictionary<string,string>()? This will remove the ServiceStack headers. I don't know how to remove the Server HTTP header that is added by HttpListener.Karakalpak
Yes, GlobalResponseHeaders is empty dictionary. Seems content-type and length are automatically added by JSON serializer, but no control over them...Worsham
Right ContentLength are added by ASP.NET/IIS when you write to the response stream. ServiceStack adds Content-Type as mandated by the HTTP Spec, there's an option to append ;charset=utf-8 with Config.AppendUtf8CharsetOnContentTypes but the header itself is controlled by the ContentType used, you can create your own at: servicestack.net/ServiceStack.Northwind/vcard-format.htmKarakalpak
HTTP spec says content-type is required by some status codes, not all. Tried using my own content type without success (differs from requested content and only controls response content i.e. not headers). What could I intercept in ServiceStack or ASP.NET/IIS to control http messages (header+content)?Worsham
If there's a response body, there should be a Content-Type. You can control it by returning HttpResult in service or you can also set it with httpReq.ResponseContentType - but the Content-Type is bound to the ContentType formatter.Karakalpak
No more content-type, but content-length is still written!Worsham
E
0

Actually you can just do something like this in your API

base.Response.StatusCode = (int) HttpStatusCode.NotModified;
base.Response.EndHttpRequestWithNoContent();
return new HttpResult();

Which would not return ContentType, ContentLength, etc

Epi answered 28/5, 2014 at 19:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.