Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

content_type_provided called twice, or where to set headers #56

Closed
zoggy opened this issue Apr 7, 2016 · 2 comments
Closed

content_type_provided called twice, or where to set headers #56

zoggy opened this issue Apr 7, 2016 · 2 comments

Comments

@zoggy
Copy link

zoggy commented Apr 7, 2016

Hello,

I want to set some headers (cache-control) but there is no method to do so in the resource class. So I set it in the content_type_provided method:

class wm_file content_type blob =
  let md5 = Digest.to_hex (Digest.string blob) in
  fun () ->
  object(self)
    inherit [Cohttp_lwt_body.t] Wm.resource
    method allowed_methods rd = Wm.continue [`GET ] rd
    method content_types_provided rd =
      let resp_headers =
          Cohttp.Header.add_multi rd.Wm.Rd.resp_headers
          "cache-control" ["public"; "must-revalidate"]
      in
      let rd = { rd with Wm.Rd.resp_headers } in
      Wm.continue [ content_type, Wm.continue (`String blob) ] rd
    method content_types_accepted rd = Wm.continue [] rd
    method generate_etag rd = Wm.continue (Some md5) rd
  end

But it seems that this method is called twice (I can see it by adding print instructions). Is this a bug ?
And is there another way to specify headers ? Currently, I end up with duplicated values in the header I specify.

@seliopou
Copy link
Member

seliopou commented Apr 7, 2016

content_types_provided is indeed called in a few different places. In general none of the resource methods are guaranteed to be called once in the course of processing a request. For example, allowed_methods is called at the b10 state of the diagram, but is also used in the default implementation of the options method. There may be a few more examples like this in the code, but those are the ones that I can point out off the top of my head.

Having said that there is a way to accomplish what you want. The handlers associated with content types are indeed only called once. (If they were called multiple times per request, that would definitely be a bug.) If you set the cache control headers in the content type handler, you will get your desired behavior.

To make it concrete, take a look at this resource from issue #41. If you change the to_content method from that resource to instead read:

method to_content rd =
  let add_cache_control =
    Rd.with_resp_headers (fun headers ->
      Cohtt.Header.add_multi headers "cache-control" ["public"; "must-revalidate"])
  in
  serve_file filename (add_cache_control rd)

You will get your desired behavior (modulo the file reading, etc.).

@seliopou seliopou closed this as completed Apr 7, 2016
@zoggy
Copy link
Author

zoggy commented Apr 7, 2016

Thanks !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants