#2404 How to config Wisp / afBedSheet for HTTP method HEAD?

shturman Fri 13 Mar 2015

Now i get response with status "501 Not Implemented" instead status 200 with headers only.

SlimerDude Fri 13 Mar 2015

Yarr, BedSheet does not automatically handle HEAD requests - the clue is in the response code - 501 Not Implemented! It is something you'll need to do yourself.

That said, if you are serving static files from the file system then HEAD requests are handled.

For other kinds of HEAD requests I don't think it's feasible for BedSheet to simply strip content from the response. For instance, what if you had a PUT handler that creates content? It'd be wrong to assume that a HEAD request to the same URL should call the same handler, create content, but then just return the headers!

Also, one of the reasons for implementing / responding to HEAD requests is to optimise / reduce the server load - i.e. give the request handler an opportunity NOT to contact that database. And to exercise that right requires custom handler code.

SlimerDude Fri 13 Mar 2015

Hi, if you let us know what kind of requests you need to respond to HEAD requests I may be able to suggest some quick wins. (Though support may be limited I'm about to go away on holidays for 3 weeks!)

For instance, if it's just Text responses then you could replace the default TextProcessor with your own that does not print the text for HEAD requests:

using afIoc::Inject
using afBedSheet

internal const class MyTextProcessor : ResponseProcessor {
    @Inject private const HttpRequest  req
    @Inject private const HttpResponse res
    
    new make(|This|in) { in(this) }
    
    override Obj process(Obj response) {
        text := (Text) response
        
        res.headers.contentType = text.contentType

        if (req.httpMethod != "HEAD")
            res.out.print(text.text)
        else
            res.headers.contentLength = text.text.toBuf.size

        return true
    }   
}

Add it to your AppModule overriding the default:

@Contribute { serviceType=ResponseProcessors# }
static Void contributeResponseProcessors(Configuration config) {
    myTextProcessor := config.autobuild(MyTextProcessor#)
    config.overrideValue(Text#, myTextProcessor, "myTextProcessor")
}

Then just make sure the required Routes respond to HEAD as well as GET.

shturman Fri 13 Mar 2015

Thanks a lot! Now i need to respond to HEAD request for root url "/" that configured to routing of static welcome page:

@Contribute { serviceType=Routes# }
static Void contributeRoutes(Configuration config){
  config.add(Route(`/`, `public/index.html`.toFile))
}

Now HEAD requests are handled for "/index.html" but no for "/"

And that if index.html in future will be efan page?

SlimerDude Fri 13 Mar 2015

Try this:

@Contribute { serviceType=Routes# }
static Void contributeRoutes(Configuration config){
  config.add(Route(`/`, `public/index.html`.toFile, "GET HEAD"))
}

Files are handled by the FileAssetProcessor which will also deal with HEAD requests.

If it becomes an efan page then the handler should return a Text object which you can handle as per the earlier post.

shturman Fri 13 Mar 2015

Thanks, it work! )

SlimerDude Mon 30 Mar 2015

As FileAssetProcessor handles HEAD requests, it seems only reasonable that TextProcessor should too, so I added it. It's essentially the code I pasted earlier.

HEAD requests still have to be explicitly handled by routes, but should a Text object be returned during a HEAD request, the text content is not printed.

This commit also fixes a bug where the Content-Length header for HEAD requests was usually overwritten and set to zero.

Login or Signup to reply.