host = NULL;
method = NULL;
length = NULL;
- content_type = NULL;
copy_source = NULL;
http_auth = NULL;
}
#define RGW_ATTR_BUCKETS RGW_ATTR_PREFIX "buckets"
#define RGW_ATTR_META_PREFIX RGW_ATTR_PREFIX "x-amz-meta-"
#define RGW_ATTR_CONTENT_TYPE RGW_ATTR_PREFIX "content_type"
+#define RGW_ATTR_CACHE_CONTROL RGW_ATTR_PREFIX "cache_control"
+#define RGW_ATTR_CONTENT_DISP RGW_ATTR_PREFIX "content_disposition"
+#define RGW_ATTR_CONTENT_ENC RGW_ATTR_PREFIX "content_encoding"
+#define RGW_ATTR_CONTENT_LANG RGW_ATTR_PREFIX "content_language"
+#define RGW_ATTR_EXPIRES RGW_ATTR_PREFIX "expires"
#define RGW_ATTR_ID_TAG RGW_ATTR_PREFIX "idtag"
#define RGW_ATTR_SHADOW_OBJ RGW_ATTR_PREFIX "shadow_name"
#define RGW_ATTR_MANIFEST RGW_ATTR_PREFIX "manifest"
const char *method;
const char *length;
uint64_t content_length;
- const char *content_type;
+ map<string, string> generic_attrs;
struct rgw_err err;
bool expect_cont;
bool header_ended;
common_init_finish(g_ceph_context);
rgw_tools_init(g_ceph_context);
+
+ rgw_rest_init();
curl_global_init(CURL_GLOBAL_ALL);
bufferlist bl, aclbl;
map<string, bufferlist> attrs;
int len;
+ map<string, string>::iterator iter;
perfcounter->inc(l_rgw_put);
attrs[RGW_ATTR_USER_MANIFEST] = manifest_bl;
}
- if (s->content_type) {
- bl.clear();
- bl.append(s->content_type, strlen(s->content_type) + 1);
- attrs[RGW_ATTR_CONTENT_TYPE] = bl;
+ for (iter = s->generic_attrs.begin(); iter != s->generic_attrs.end(); ++iter) {
+ bufferlist& attrbl = attrs[iter->first];
+ const string& val = iter->second;
+ attrbl.append(val.c_str(), val.size() + 1);
}
rgw_get_request_metadata(s, attrs);
attrs[RGW_ATTR_ACL] = aclbl;
rgw_get_request_metadata(s, attrs);
- if (s->content_type) {
- bufferlist bl;
- bl.append(s->content_type, strlen(s->content_type) + 1);
- attrs[RGW_ATTR_CONTENT_TYPE] = bl;
+ map<string, string>::iterator iter;
+ for (iter = s->generic_attrs.begin(); iter != s->generic_attrs.end(); ++iter) {
+ bufferlist& attrbl = attrs[iter->first];
+ const string& val = iter->second;
+ attrbl.append(val.c_str(), val.size() + 1);
}
-
return 0;
}
bufferlist aclbl;
map<string, bufferlist> attrs;
rgw_obj obj;
+ map<string, string>::iterator iter;
if (get_params() < 0)
return;
attrs[RGW_ATTR_ACL] = aclbl;
- if (s->content_type) {
- bufferlist bl;
- bl.append(s->content_type, strlen(s->content_type) + 1);
- attrs[RGW_ATTR_CONTENT_TYPE] = bl;
+ for (iter = s->generic_attrs.begin(); iter != s->generic_attrs.end(); ++iter) {
+ bufferlist& attrbl = attrs[iter->first];
+ const string& val = iter->second;
+ attrbl.append(val.c_str(), val.size() + 1);
}
rgw_get_request_metadata(s, attrs);
#define dout_subsys ceph_subsys_rgw
+
+struct rgw_http_attr {
+ const char *rgw_attr;
+ const char *http_attr;
+};
+
+/*
+ * mapping between rgw object attrs and output http fields
+ */
+static struct rgw_http_attr rgw_to_http_attr_list[] = {
+ { RGW_ATTR_CONTENT_TYPE, "Content-Type"},
+ { RGW_ATTR_CONTENT_LANG, "Content-Language"},
+ { RGW_ATTR_EXPIRES, "Expires"},
+ { RGW_ATTR_CACHE_CONTROL, "Cache-Control"},
+ { RGW_ATTR_CONTENT_DISP, "Content-Disposition"},
+ { RGW_ATTR_CONTENT_ENC, "Content-Encoding"},
+ { NULL, NULL},
+};
+
+
+map<string, string> rgw_to_http_attrs;
+
+void rgw_rest_init()
+{
+ for (struct rgw_http_attr *attr = rgw_to_http_attr_list; attr->rgw_attr; attr++) {
+ rgw_to_http_attrs[attr->rgw_attr] = attr->http_attr;
+ }
+}
+
+struct generic_attr {
+ const char *http_header;
+ const char *rgw_attr;
+};
+
+/*
+ * mapping between http env fields and rgw object attrs
+ */
+struct generic_attr generic_attrs[] = {
+ { "CONTENT_TYPE", RGW_ATTR_CONTENT_TYPE },
+ { "HTTP_CONTENT_LANGUAGE", RGW_ATTR_CONTENT_LANG },
+ { "HTTP_EXPIRES", RGW_ATTR_EXPIRES },
+ { "HTTP_CACHE_CONTROL", RGW_ATTR_CACHE_CONTROL },
+ { "HTTP_CONTENT_DISPOSITION", RGW_ATTR_CONTENT_DISP },
+ { "HTTP_CONTENT_ENCODING", RGW_ATTR_CONTENT_ENC },
+ { NULL, NULL },
+};
+
static void dump_status(struct req_state *s, const char *status)
{
int r = s->cio->print("Status: %s\n", status);
s->content_length = atoll(s->length);
}
- s->content_type = s->env->get("CONTENT_TYPE");
+ for (int i = 0; generic_attrs[i].http_header; i++) {
+ const char *env = s->env->get(generic_attrs[i].http_header);
+ if (env) {
+ s->generic_attrs[generic_attrs[i].rgw_attr] = env;
+ }
+ }
+
s->http_auth = s->env->get("HTTP_AUTHORIZATION");
if (g_conf->rgw_print_continue) {
#include "rgw_op.h"
#include "rgw_formats.h"
+
+extern std::map<std::string, std::string> rgw_to_http_attrs;
+
+extern void rgw_rest_init();
+
extern void rgw_flush_formatter_and_reset(struct req_state *s,
ceph::Formatter *formatter);
}
}
+struct response_attr_param {
+ const char *param;
+ const char *http_attr;
+};
+
+static struct response_attr_param resp_attr_params[] = {
+ {"response-content-type", "Content-Type"},
+ {"response-content-language", "Content-Language"},
+ {"response-expires", "Expires"},
+ {"response-cache-control", "Cache-Control"},
+ {"response-content-disposition", "Content-Disposition"},
+ {"response-content-encoding", "Content-Encoding"},
+ {NULL, NULL},
+};
+
int RGWGetObj_ObjStore_S3::send_response(bufferlist& bl)
{
- string content_type_str;
const char *content_type = NULL;
+ string content_type_str;
int orig_ret = ret;
+ map<string, string> response_attrs;
+ map<string, string>::iterator riter;
if (ret)
goto done;
}
}
- if (s->args.has_response_modifier()) {
+ for (struct response_attr_param *p = resp_attr_params; p->param; p++) {
bool exists;
- content_type_str = s->args.get("response-content-type", &exists);
- if (exists)
- content_type = content_type_str.c_str();
- string val = s->args.get("response-content-language", &exists);
- if (exists)
- s->cio->print("Content-Language: %s\n", val.c_str());
- val = s->args.get("response-expires", &exists);
- if (exists)
- s->cio->print("Expires: %s\n", val.c_str());
- val = s->args.get("response-cache-control", &exists);
- if (exists)
- s->cio->print("Cache-Control: %s\n", val.c_str());
- val = s->args.get("response-content-disposition", &exists);
- if (exists)
- s->cio->print("Content-Disposition: %s\n", val.c_str());
- val = s->args.get("response-content-encoding", &exists);
- if (exists)
- s->cio->print("Content-Encoding: %s\n", val.c_str());
+ string val = s->args.get(p->param, &exists);
+ if (exists) {
+ if (strcmp(p->param, "response-content-type") != 0) {
+ response_attrs[p->http_attr] = val;
+ } else {
+ content_type_str = val;
+ content_type = content_type_str.c_str();
+ }
+ }
}
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) {
- name += sizeof(RGW_ATTR_PREFIX) - 1;
- s->cio->print("%s: %s\r\n", name, iter->second.c_str());
- } else if (!content_type && strcmp(name, RGW_ATTR_CONTENT_TYPE) == 0) {
- content_type = iter->second.c_str();
- }
+ const char *name = iter->first.c_str();
+ map<string, string>::iterator aiter = rgw_to_http_attrs.find(name);
+ if (aiter != rgw_to_http_attrs.end()) {
+ if (response_attrs.count(aiter->second) > 0) // was already overridden by a response param
+ continue;
+
+ if ((!content_type) && aiter->first.compare(RGW_ATTR_CONTENT_TYPE) == 0) { // special handling for content_type
+ content_type = iter->second.c_str();
+ continue;
+ }
+ response_attrs[aiter->second] = iter->second.c_str();
+ } else {
+ if (strncmp(name, RGW_ATTR_META_PREFIX, sizeof(RGW_ATTR_META_PREFIX)-1) == 0) {
+ name += sizeof(RGW_ATTR_PREFIX) - 1;
+ s->cio->print("%s: %s\r\n", name, iter->second.c_str());
+ }
+ }
}
}
set_req_state_err(s, ret);
dump_errno(s);
+
+ for (riter = response_attrs.begin(); riter != response_attrs.end(); ++riter) {
+ s->cio->print("%s: %s\n", riter->first.c_str(), riter->second.c_str());
+ }
+
if (!content_type)
content_type = "binary/octet-stream";
end_header(s, content_type);
supplied_etag = s->env->get("HTTP_ETAG");
- if (!s->content_type) {
+ if (!s->generic_attrs.count(RGW_ATTR_CONTENT_TYPE)) {
dout(5) << "content type wasn't provided, trying to guess" << dendl;
const char *suffix = strrchr(s->object, '.');
if (suffix) {
suffix++;
if (*suffix) {
string suffix_str(suffix);
- s->content_type = rgw_find_mime_by_ext(suffix_str);
+ s->generic_attrs[RGW_ATTR_CONTENT_TYPE] = rgw_find_mime_by_ext(suffix_str);
}
}
}
{
const char *content_type = NULL;
int orig_ret = ret;
+ map<string, string> response_attrs;
+ map<string, string>::iterator riter;
if (sent_header)
goto send_data;
}
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) {
- name += sizeof(RGW_ATTR_META_PREFIX) - 1;
- s->cio->print("X-%s-Meta-%s: %s\r\n", (s->object ? "Object" : "Container"), name, iter->second.c_str());
- } else if (!content_type && strcmp(name, RGW_ATTR_CONTENT_TYPE) == 0) {
- content_type = iter->second.c_str();
- }
+ const char *name = iter->first.c_str();
+ map<string, string>::iterator aiter = rgw_to_http_attrs.find(name);
+ if (aiter != rgw_to_http_attrs.end()) {
+ if (aiter->first.compare(RGW_ATTR_CONTENT_TYPE) == 0) { // special handling for content_type
+ content_type = iter->second.c_str();
+ continue;
+ }
+ response_attrs[aiter->second] = iter->second.c_str();
+ } else {
+ if (strncmp(name, RGW_ATTR_META_PREFIX, sizeof(RGW_ATTR_META_PREFIX)-1) == 0) {
+ name += sizeof(RGW_ATTR_META_PREFIX) - 1;
+ s->cio->print("X-%s-Meta-%s: %s\r\n", (s->object ? "Object" : "Container"), name, iter->second.c_str());
+ }
+ }
}
}
if (ret)
set_req_state_err(s, ret);
dump_errno(s);
+
+ for (riter = response_attrs.begin(); riter != response_attrs.end(); ++riter) {
+ s->cio->print("%s: %s\n", riter->first.c_str(), riter->second.c_str());
+ }
+
if (!content_type)
content_type = "binary/octet-stream";
end_header(s, content_type);