#include #include "cgiResult.h" class WritableToCgiResult : public TransformImpl { public: void transform(const WritableContent * wc, CgiResult * cr, ExecContext * ec) const { cr->header->addHeader("Content-Type", Glib::ustring::compose("%1; charset=%2", wc->getContentType(ec), cr->encoding)); cr->header->addHeader("Cache-control", "no-cache"); auto size = wc->getSizeInBytes(ec); if (size) { auto range = wc->getRange(ec); if (range) { cr->header->addHeader("Status", "206 Partial Content"); cr->header->addHeader("Content-Length", Glib::ustring::compose("%1", range->End - range->Start + 1)); cr->header->addHeader("Content-Range", Glib::ustring::compose("%1 %2-%3/%4", range->Unit, range->Start, range->End, *size)); } else { cr->header->addHeader("Content-Length", Glib::ustring::compose("%1", *size)); } } if (wc->isSeekable()) { cr->header->addHeader("Accept-Ranges", "bytes"); } auto modifiedTime = wc->getModifiedTime(ec); if (modifiedTime) { char buf[100]; struct tm stm; gmtime_r(&*modifiedTime, &stm); strftime(buf, sizeof(buf), "%a, %d %b %Y %T %z", &stm); cr->header->addHeader("Last-Modified", buf); } try { cr->header->render(cr->stream); wc->writeTo(cr->stream, cr->encoding, ec); } catch (const std::ios_base::failure &) { // ignore (client may have gone away) } } }; DECLARE_TRANSFORM(WritableToCgiResult);