This is to let the client know we accept requests for partial content.
On HEAD requests we should also return the Content-Length header.
And we should also return the Last-Modified header with GET and HEAD requests, this way browsers and proxy's can cache content.
map<string, bufferlist> *attrs,
const time_t *mod_ptr,
const time_t *unmod_ptr,
+ time_t *lastmod,
const char *if_match,
const char *if_nomatch,
size_t *total_size,
void *handle;
off_t ofs = 0, end = -1;
size_t total_len;
+ time_t lastmod;
map<string, bufferlist> attrset;
- ret = prepare_get_obj(src_bucket, src_obj, 0, &end, &attrset, mod_ptr, unmod_ptr,
+ ret = prepare_get_obj(src_bucket, src_obj, 0, &end, &attrset, mod_ptr, unmod_ptr, &lastmod,
if_match, if_nomatch, &total_len, &handle, err);
if (ret < 0)
return ret;
map<string, bufferlist> *attrs,
const time_t *mod_ptr,
const time_t *unmod_ptr,
+ time_t *lastmod,
const char *if_match,
const char *if_nomatch,
size_t *total_size,
map<std::string, bufferlist> *attrs,
const time_t *mod_ptr,
const time_t *unmod_ptr,
+ time_t *lastmod,
const char *if_match,
const char *if_nomatch,
size_t *size,
init_common();
ret = rgwstore->prepare_get_obj(s->bucket_str, s->object_str, ofs, &end, &attrs, mod_ptr,
- unmod_ptr, if_match, if_nomatch, &total_len, &handle, &err);
+ unmod_ptr, &lastmod, if_match, if_nomatch, &total_len, &handle, &err);
if (ret < 0)
goto done;
size_t total_len;
off_t end;
time_t mod_time;
+ time_t lastmod;
time_t unmod_time;
time_t *mod_ptr;
time_t *unmod_ptr;
char *data;
off_t ofs = 0, end = -1;
size_t total_len;
+ time_t lastmod;
map<string, bufferlist>::iterator iter;
cerr << "copy " << src_bucket << ":" << src_obj << " => " << dest_bucket << ":" << dest_obj << std::endl;
map<string, bufferlist> attrset;
ret = prepare_get_obj(src_bucket, src_obj, ofs, &end, &attrset,
- mod_ptr, unmod_ptr, if_match, if_nomatch, &total_len, &handle, err);
+ mod_ptr, unmod_ptr, &lastmod, if_match, if_nomatch, &total_len, &handle, err);
if (ret < 0)
return ret;
map<string, bufferlist> *attrs,
const time_t *mod_ptr,
const time_t *unmod_ptr,
+ time_t *lastmod,
const char *if_match,
const char *if_nomatch,
size_t *total_size,
*end = size - 1;
*total_size = (ofs <= *end ? *end + 1 - ofs : 0);
+ *lastmod = mtime;
return 0;
map<string, bufferlist> *attrs,
const time_t *mod_ptr,
const time_t *unmod_ptr,
+ time_t *lastmod,
const char *if_match,
const char *if_nomatch,
size_t *total_size,
static void dump_content_length(struct req_state *s, int len)
{
CGI_PRINTF(s->fcgx->out, "Content-Length: %d\n", len);
+ CGI_PRINTF(s->fcgx->out, "Accept-Ranges: %s\n", "bytes");
}
static void dump_etag(struct req_state *s, const char *etag)
CGI_PRINTF(s->fcgx->out,"ETag: \"%s\"\n", etag);
}
+static void dump_last_modified(struct req_state *s, time_t t) {
+
+ char timestr[TIME_BUF_SIZE];
+ struct tm *tmp = localtime(&t);
+ if (tmp == NULL)
+ return;
+
+ if (strftime(timestr, sizeof(timestr), "%a, %d %b %Y %H:%M:%S %Z", tmp) == 0)
+ return;
+
+ CGI_PRINTF(s->fcgx->out, "Last-Modified: %s\n", timestr);
+}
+
void dump_value(struct req_state *s, const char *name, const char *fmt, ...)
{
#define LARGE_SIZE 8192
void dump_time(struct req_state *s, const char *name, time_t *t)
{
-#define TIME_BUF_SIZE 128
char buf[TIME_BUF_SIZE];
struct tm *tmp = localtime(t);
if (tmp == NULL)
void dump_range(struct req_state *s, off_t ofs, off_t end)
{
- CGI_PRINTF(s->fcgx->out,"Accept-Ranges: bytes\n", "");
CGI_PRINTF(s->fcgx->out,"Content-Range: bytes %d-%d/%d\n", (int)ofs, (int)end, (int)end + 1);
}
if (sent_header)
goto send_data;
- if (get_data && !ret) {
- if (range_str)
- dump_range(s, ofs, end);
- dump_content_length(s, total_len);
- }
+ if (range_str)
+ dump_range(s, ofs, end);
+
+ dump_content_length(s, total_len);
+ dump_last_modified(s, lastmod);
+
if (!ret) {
map<string, bufferlist>::iterator iter = attrs.find(RGW_ATTR_ETAG);
if (iter != attrs.end()) {
dump_etag(s, etag);
}
}
+
for (iter = attrs.begin(); iter != attrs.end(); ++iter) {
const char *name = iter->first.c_str();
if (strncmp(name, RGW_ATTR_META_PREFIX, sizeof(RGW_ATTR_META_PREFIX)-1) == 0) {
#ifndef CEPH_RGW_REST_H
#define CEPH_RGW_REST_H
+#define TIME_BUF_SIZE 128
#include "rgw_op.h"
void *handle = NULL;
off_t ofs = 0, end = -1;
size_t total_len;
+ time_t lastmod;
bufferlist::iterator iter;
- ret = rgwstore->prepare_get_obj(ui_bucket, user_id, ofs, &end, NULL, NULL, NULL, NULL, NULL, &total_len, &handle, &err);
+ ret = rgwstore->prepare_get_obj(ui_bucket, user_id, ofs, &end, NULL, NULL, NULL, &lastmod, NULL, NULL, &total_len, &handle, &err);
if (ret < 0)
return ret;
do {
size_t total_len;
ret = rgwstore->prepare_get_obj(ui_email_bucket, email, ofs, &end, NULL, NULL,
- NULL, NULL, NULL, &total_len, &handle, &err);
+ NULL, NULL, NULL, NULL, &total_len, &handle, &err);
if (ret < 0)
return ret;
do {