Improve Rhizome HTTP status codes

Also improve some reason phrases and test them
This commit is contained in:
Andrew Bettison 2015-09-21 18:42:13 +09:30
parent 96055e6b6c
commit 6123503c15
7 changed files with 127 additions and 81 deletions

View File

@ -1118,7 +1118,7 @@ static int http_request_start_body(struct http_request *r)
else if (r->verb == HTTP_VERB_POST) { else if (r->verb == HTTP_VERB_POST) {
if (r->request_header.content_length == CONTENT_LENGTH_UNKNOWN) { if (r->request_header.content_length == CONTENT_LENGTH_UNKNOWN) {
IDEBUGF(r->debug, "Malformed HTTP %s request: missing Content-Length header", r->verb); IDEBUGF(r->debug, "Malformed HTTP %s request: missing Content-Length header", r->verb);
return 411; return 411; // Length Required
} }
if (r->request_header.content_length == 0) { if (r->request_header.content_length == 0) {
r->parser = http_request_reject_content; r->parser = http_request_reject_content;
@ -1142,7 +1142,7 @@ static int http_request_start_body(struct http_request *r)
} else { } else {
IDEBUGF(r->debug, "Unsupported HTTP %s request: Content-Type %s not supported", IDEBUGF(r->debug, "Unsupported HTTP %s request: Content-Type %s not supported",
r->verb, alloca_mime_content_type(&r->request_header.content_type)); r->verb, alloca_mime_content_type(&r->request_header.content_type));
return 415; return 415; // Unsupported Media Type
} }
} }
} }
@ -1917,6 +1917,9 @@ static const char *httpResultString(int response_code)
case 414: return "Request-URI Too Long"; case 414: return "Request-URI Too Long";
case 415: return "Unsupported Media Type"; case 415: return "Unsupported Media Type";
case 416: return "Requested Range Not Satisfiable"; case 416: return "Requested Range Not Satisfiable";
case 422: return "Unprocessable Entity";
case 423: return "Locked";
case 429: return "Too Many Requests";
case 431: return "Request Header Fields Too Large"; case 431: return "Request Header Fields Too Large";
case 500: return "Internal Server Error"; case 500: return "Internal Server Error";
case 501: return "Not Implemented"; case 501: return "Not Implemented";

View File

@ -93,10 +93,16 @@ public class RhizomeCommon
JSONTokeniser json = new JSONTokeniser(new InputStreamReader(conn.getErrorStream(), "UTF-8")); JSONTokeniser json = new JSONTokeniser(new InputStreamReader(conn.getErrorStream(), "UTF-8"));
decodeRestfulStatus(status, json); decodeRestfulStatus(status, json);
} }
if (status.http_status_code == HttpURLConnection.HTTP_FORBIDDEN) switch (status.http_status_code) {
case HttpURLConnection.HTTP_FORBIDDEN: // for crypto failure (missing secret)
case HttpURLConnection.HTTP_NOT_FOUND: // for unknown BID
case 422: // Unprocessable Entity, for invalid/malformed manifest
case 423: // Locked, for database busy
case 429: // Too Many Requests, for out of manifests
return status; return status;
if (status.http_status_code == HttpURLConnection.HTTP_NOT_IMPLEMENTED) case HttpURLConnection.HTTP_NOT_IMPLEMENTED:
throw new ServalDNotImplementedException(status.http_status_message); throw new ServalDNotImplementedException(status.http_status_message);
}
throw new ServalDInterfaceException("unexpected HTTP response: " + status.http_status_code + " " + status.http_status_message); throw new ServalDInterfaceException("unexpected HTTP response: " + status.http_status_code + " " + status.http_status_message);
} }

View File

@ -1658,6 +1658,14 @@ next:
return ret; return ret;
} }
/* Unpacks a database MANIFESTS table row into a manifest structure.
*
* Returns RHIZOME_BUNDLE_STATUS_SAME if unpack succeeds
* Returns RHIZOME_BUNDLE_STATUS_NEW if manifest is not found
* Returns RHIZOME_BUNDLE_STATUS_ERROR on error
* Returns RHIZOME_BUNDLE_STATUS_BUSY if the database is locked
* Caller is responsible for allocating and freeing rhizome_manifest
*/
static enum rhizome_bundle_status unpack_manifest_row(sqlite_retry_state *retry, rhizome_manifest *m, sqlite3_stmt *statement) static enum rhizome_bundle_status unpack_manifest_row(sqlite_retry_state *retry, rhizome_manifest *m, sqlite3_stmt *statement)
{ {
int r=sqlite_step_retry(retry, statement); int r=sqlite_step_retry(retry, statement);

View File

@ -107,22 +107,22 @@ static int rhizome_direct_import_end(struct http_request *hr)
http_request_simple_response(&r->http, 201, "Bundle succesfully imported"); http_request_simple_response(&r->http, 201, "Bundle succesfully imported");
return 0; return 0;
case RHIZOME_BUNDLE_STATUS_SAME: case RHIZOME_BUNDLE_STATUS_SAME:
http_request_simple_response(&r->http, 200, "Bundle already imported"); http_request_simple_response(&r->http, 200, "Bundle already imported"); // OK
return 0; return 0;
case RHIZOME_BUNDLE_STATUS_OLD: case RHIZOME_BUNDLE_STATUS_OLD:
http_request_simple_response(&r->http, 403, "Newer bundle already stored"); http_request_simple_response(&r->http, 202, "Newer bundle already stored"); // Accepted
return 0; return 0;
case RHIZOME_BUNDLE_STATUS_INVALID: case RHIZOME_BUNDLE_STATUS_INVALID:
http_request_simple_response(&r->http, 403, "Manifest is invalid"); http_request_simple_response(&r->http, 422, "Manifest is invalid"); // Unprocessable Entity
return 0; return 0;
case RHIZOME_BUNDLE_STATUS_INCONSISTENT: case RHIZOME_BUNDLE_STATUS_INCONSISTENT:
http_request_simple_response(&r->http, 403, "Manifest is inconsistent with file"); http_request_simple_response(&r->http, 422, "Manifest is inconsistent with file"); // Unprocessable Entity
return 0; return 0;
case RHIZOME_BUNDLE_STATUS_FAKE: case RHIZOME_BUNDLE_STATUS_FAKE:
http_request_simple_response(&r->http, 403, "Manifest not signed"); http_request_simple_response(&r->http, 403, "Manifest not signed"); // Forbidden
return 0; return 0;
case RHIZOME_BUNDLE_STATUS_NO_ROOM: case RHIZOME_BUNDLE_STATUS_NO_ROOM:
http_request_simple_response(&r->http, 403, "Not enough space"); http_request_simple_response(&r->http, 202, "Not enough space"); // Accepted
return 0; return 0;
case RHIZOME_BUNDLE_STATUS_READONLY: case RHIZOME_BUNDLE_STATUS_READONLY:
case RHIZOME_BUNDLE_STATUS_DUPLICATE: case RHIZOME_BUNDLE_STATUS_DUPLICATE:

View File

@ -75,22 +75,28 @@ static int http_request_rhizome_response(struct httpd_request *r, uint16_t resul
uint16_t rhizome_result = 0; uint16_t rhizome_result = 0;
switch (r->bundle_status) { switch (r->bundle_status) {
case RHIZOME_BUNDLE_STATUS_NEW: case RHIZOME_BUNDLE_STATUS_NEW:
rhizome_result = 201; // Created
break;
case RHIZOME_BUNDLE_STATUS_SAME: case RHIZOME_BUNDLE_STATUS_SAME:
case RHIZOME_BUNDLE_STATUS_DUPLICATE: case RHIZOME_BUNDLE_STATUS_DUPLICATE:
rhizome_result = 201; rhizome_result = 200; // OK
break; break;
case RHIZOME_BUNDLE_STATUS_OLD:
case RHIZOME_BUNDLE_STATUS_NO_ROOM: case RHIZOME_BUNDLE_STATUS_NO_ROOM:
rhizome_result = 200; case RHIZOME_BUNDLE_STATUS_OLD:
rhizome_result = 202; // Accepted
break;
case RHIZOME_BUNDLE_STATUS_FAKE:
case RHIZOME_BUNDLE_STATUS_READONLY:
rhizome_result = 403; // Forbidden
break; break;
case RHIZOME_BUNDLE_STATUS_INVALID: case RHIZOME_BUNDLE_STATUS_INVALID:
case RHIZOME_BUNDLE_STATUS_FAKE:
case RHIZOME_BUNDLE_STATUS_INCONSISTENT: case RHIZOME_BUNDLE_STATUS_INCONSISTENT:
case RHIZOME_BUNDLE_STATUS_READONLY: rhizome_result = 422; // Unprocessable Entity
rhizome_result = 403; break;
case RHIZOME_BUNDLE_STATUS_BUSY:
rhizome_result = 423; // Locked
break; break;
case RHIZOME_BUNDLE_STATUS_ERROR: case RHIZOME_BUNDLE_STATUS_ERROR:
case RHIZOME_BUNDLE_STATUS_BUSY:
rhizome_result = 500; rhizome_result = 500;
break; break;
} }
@ -118,12 +124,14 @@ static int http_request_rhizome_response(struct httpd_request *r, uint16_t resul
break; break;
case RHIZOME_PAYLOAD_STATUS_TOO_BIG: case RHIZOME_PAYLOAD_STATUS_TOO_BIG:
case RHIZOME_PAYLOAD_STATUS_EVICTED: case RHIZOME_PAYLOAD_STATUS_EVICTED:
rhizome_result = 200; rhizome_result = 202; // Accepted
break;
case RHIZOME_PAYLOAD_STATUS_CRYPTO_FAIL:
rhizome_result = 403; // Forbidden
break; break;
case RHIZOME_PAYLOAD_STATUS_WRONG_SIZE: case RHIZOME_PAYLOAD_STATUS_WRONG_SIZE:
case RHIZOME_PAYLOAD_STATUS_WRONG_HASH: case RHIZOME_PAYLOAD_STATUS_WRONG_HASH:
case RHIZOME_PAYLOAD_STATUS_CRYPTO_FAIL: rhizome_result = 422; // Unprocessable Entity
rhizome_result = 403;
break; break;
case RHIZOME_PAYLOAD_STATUS_ERROR: case RHIZOME_PAYLOAD_STATUS_ERROR:
rhizome_result = 500; rhizome_result = 500;
@ -146,9 +154,9 @@ static int http_request_rhizome_response(struct httpd_request *r, uint16_t resul
} }
if (result == 0) { if (result == 0) {
result = 500; result = 500;
message = NULL; message = "Result logic error";
} }
http_request_simple_response(&r->http, result, message ? message : result == 403 ? "Rhizome operation failed" : NULL); http_request_simple_response(&r->http, result, message);
return result; return result;
} }
@ -159,7 +167,7 @@ static int restful_rhizome_bundlelist_json(httpd_request *r, const char *remaind
r->http.response.header.content_type = CONTENT_TYPE_JSON; r->http.response.header.content_type = CONTENT_TYPE_JSON;
r->http.render_extra_headers = render_manifest_headers; r->http.render_extra_headers = render_manifest_headers;
if (!is_rhizome_http_enabled()) if (!is_rhizome_http_enabled())
return 403; return 404;
int ret = authorize_restful(&r->http); int ret = authorize_restful(&r->http);
if (ret) if (ret)
return ret; return ret;
@ -191,7 +199,7 @@ static int restful_rhizome_newsince(httpd_request *r, const char *remainder)
{ {
r->http.response.header.content_type = CONTENT_TYPE_JSON; r->http.response.header.content_type = CONTENT_TYPE_JSON;
if (!is_rhizome_http_enabled()) if (!is_rhizome_http_enabled())
return 403; return 404;
int ret = authorize_restful(&r->http); int ret = authorize_restful(&r->http);
if (ret) if (ret)
return ret; return ret;
@ -338,7 +346,7 @@ static int restful_rhizome_insert(httpd_request *r, const char *remainder)
r->http.response.header.content_type = CONTENT_TYPE_JSON; r->http.response.header.content_type = CONTENT_TYPE_JSON;
r->http.render_extra_headers = render_manifest_headers; r->http.render_extra_headers = render_manifest_headers;
if (!is_rhizome_http_enabled()) if (!is_rhizome_http_enabled())
return 403; return 404;
int ret = authorize_restful(&r->http); int ret = authorize_restful(&r->http);
if (ret) if (ret)
return ret; return ret;
@ -389,7 +397,7 @@ static int insert_make_manifest(httpd_request *r)
if (!r->u.insert.received_manifest) if (!r->u.insert.received_manifest)
return http_response_form_part(r, "Missing", PART_MANIFEST, NULL, 0); return http_response_form_part(r, "Missing", PART_MANIFEST, NULL, 0);
if ((r->manifest = rhizome_new_manifest()) == NULL) if ((r->manifest = rhizome_new_manifest()) == NULL)
return http_request_rhizome_response(r, 500, "Internal Error: Out of manifests", NULL); return http_request_rhizome_response(r, 429, "Manifest table full", NULL); // Too Many Requests
assert(r->u.insert.manifest.length <= sizeof r->manifest->manifestdata); assert(r->u.insert.manifest.length <= sizeof r->manifest->manifestdata);
memcpy(r->manifest->manifestdata, r->u.insert.manifest.buffer, r->u.insert.manifest.length); memcpy(r->manifest->manifestdata, r->u.insert.manifest.buffer, r->u.insert.manifest.length);
r->manifest->manifest_all_bytes = r->u.insert.manifest.length; r->manifest->manifest_all_bytes = r->u.insert.manifest.length;
@ -403,7 +411,7 @@ static int insert_make_manifest(httpd_request *r)
rhizome_manifest_free(r->manifest); rhizome_manifest_free(r->manifest);
r->manifest = NULL; r->manifest = NULL;
r->bundle_status = RHIZOME_BUNDLE_STATUS_INVALID; r->bundle_status = RHIZOME_BUNDLE_STATUS_INVALID;
return http_request_rhizome_response(r, 403, "Malformed manifest", NULL); return http_request_rhizome_response(r, 422, "Malformed manifest", NULL); // Unprocessable Entity
default: default:
WHYF("rhizome_manifest_parse() returned %d", n); WHYF("rhizome_manifest_parse() returned %d", n);
// fall through // fall through
@ -427,19 +435,19 @@ static int insert_make_manifest(httpd_request *r)
break; break;
case RHIZOME_ADD_FILE_INVALID: case RHIZOME_ADD_FILE_INVALID:
r->bundle_status = RHIZOME_BUNDLE_STATUS_INVALID; // TODO separate enum for CLI return codes r->bundle_status = RHIZOME_BUNDLE_STATUS_INVALID; // TODO separate enum for CLI return codes
return http_request_rhizome_response(r, 403, message, NULL); return http_request_rhizome_response(r, 422, message, NULL); // Unprocessable Entity
case RHIZOME_ADD_FILE_BUSY: case RHIZOME_ADD_FILE_BUSY:
r->bundle_status = RHIZOME_BUNDLE_STATUS_BUSY; // TODO separate enum for CLI return codes r->bundle_status = RHIZOME_BUNDLE_STATUS_BUSY; // TODO separate enum for CLI return codes
return http_request_rhizome_response(r, 403, message, NULL); return http_request_rhizome_response(r, 423, message, NULL); // Locked
case RHIZOME_ADD_FILE_REQUIRES_JOURNAL: case RHIZOME_ADD_FILE_REQUIRES_JOURNAL:
r->bundle_status = RHIZOME_BUNDLE_STATUS_INVALID; // TODO separate enum for CLI return codes r->bundle_status = RHIZOME_BUNDLE_STATUS_INVALID; // TODO separate enum for CLI return codes
return http_request_rhizome_response(r, 403, message, NULL); return http_request_rhizome_response(r, 422, message, NULL); // Unprocessable Entity
case RHIZOME_ADD_FILE_INVALID_FOR_JOURNAL: case RHIZOME_ADD_FILE_INVALID_FOR_JOURNAL:
r->bundle_status = RHIZOME_BUNDLE_STATUS_INVALID; // TODO separate enum for CLI return codes r->bundle_status = RHIZOME_BUNDLE_STATUS_INVALID; // TODO separate enum for CLI return codes
return http_request_rhizome_response(r, 403, message, NULL); return http_request_rhizome_response(r, 422, message, NULL); // Unprocessable Entity
case RHIZOME_ADD_FILE_WRONG_SECRET: case RHIZOME_ADD_FILE_WRONG_SECRET:
r->bundle_status = RHIZOME_BUNDLE_STATUS_READONLY; // TODO separate enum for CLI return codes r->bundle_status = RHIZOME_BUNDLE_STATUS_READONLY; // TODO separate enum for CLI return codes
return http_request_rhizome_response(r, 403, message, NULL); return http_request_rhizome_response(r, 403, message, NULL); // Forbidden
} }
if (!result_valid) if (!result_valid)
FATALF("result = %d", result); FATALF("result = %d", result);
@ -518,7 +526,7 @@ static int insert_mime_part_header(struct http_request *hr, const struct mime_pa
r->payload_status = rhizome_write_open_journal(&r->u.insert.write, r->manifest, 0, RHIZOME_SIZE_UNSET); r->payload_status = rhizome_write_open_journal(&r->u.insert.write, r->manifest, 0, RHIZOME_SIZE_UNSET);
if (r->payload_status == RHIZOME_PAYLOAD_STATUS_ERROR) { if (r->payload_status == RHIZOME_PAYLOAD_STATUS_ERROR) {
WHYF("rhizome_write_open_journal() returned %d %s", r->payload_status, rhizome_payload_status_message(r->payload_status)); WHYF("rhizome_write_open_journal() returned %d %s", r->payload_status, rhizome_payload_status_message(r->payload_status));
return 500; return http_request_rhizome_response(r, 500, "Error in payload open for write (journal)", NULL);
} }
} else { } else {
// Note: r->manifest->filesize can be RHIZOME_SIZE_UNSET at this point, if the manifest did // Note: r->manifest->filesize can be RHIZOME_SIZE_UNSET at this point, if the manifest did
@ -526,7 +534,7 @@ static int insert_mime_part_header(struct http_request *hr, const struct mime_pa
r->payload_status = rhizome_write_open_manifest(&r->u.insert.write, r->manifest); r->payload_status = rhizome_write_open_manifest(&r->u.insert.write, r->manifest);
if (r->payload_status == RHIZOME_PAYLOAD_STATUS_ERROR) { if (r->payload_status == RHIZOME_PAYLOAD_STATUS_ERROR) {
WHYF("rhizome_write_open_manifest() returned %d %s", r->payload_status, rhizome_payload_status_message(r->payload_status)); WHYF("rhizome_write_open_manifest() returned %d %s", r->payload_status, rhizome_payload_status_message(r->payload_status));
return 500; return http_request_rhizome_response(r, 500, "Error in payload open for write", NULL);
} }
} }
switch (r->payload_status) { switch (r->payload_status) {
@ -575,7 +583,7 @@ static int insert_mime_part_body(struct http_request *hr, char *buf, size_t len)
switch (r->payload_status) { switch (r->payload_status) {
case RHIZOME_PAYLOAD_STATUS_NEW: case RHIZOME_PAYLOAD_STATUS_NEW:
if (rhizome_write_buffer(&r->u.insert.write, (unsigned char *)buf, len) == -1) if (rhizome_write_buffer(&r->u.insert.write, (unsigned char *)buf, len) == -1)
return 500; return http_request_rhizome_response(r, 500, "Error in payload write", NULL);
break; break;
case RHIZOME_PAYLOAD_STATUS_STORED: case RHIZOME_PAYLOAD_STATUS_STORED:
// TODO: calculate payload hash so it can be compared with stored payload // TODO: calculate payload hash so it can be compared with stored payload
@ -672,7 +680,7 @@ static int restful_rhizome_insert_end(struct http_request *hr)
{ {
strbuf msg = strbuf_alloca(200); strbuf msg = strbuf_alloca(200);
strbuf_sprintf(msg, "Payload size (%"PRIu64") contradicts manifest (filesize=%"PRIu64")", r->u.insert.payload_size, r->manifest->filesize); strbuf_sprintf(msg, "Payload size (%"PRIu64") contradicts manifest (filesize=%"PRIu64")", r->u.insert.payload_size, r->manifest->filesize);
return http_request_rhizome_response(r, 403, "Inconsistent filesize", strbuf_str(msg)); return http_request_rhizome_response(r, 422, "Inconsistent filesize", strbuf_str(msg)); // Unprocessable Entity
} }
case RHIZOME_PAYLOAD_STATUS_WRONG_HASH: case RHIZOME_PAYLOAD_STATUS_WRONG_HASH:
r->bundle_status = RHIZOME_BUNDLE_STATUS_INCONSISTENT; r->bundle_status = RHIZOME_BUNDLE_STATUS_INCONSISTENT;
@ -681,19 +689,19 @@ static int restful_rhizome_insert_end(struct http_request *hr)
strbuf_sprintf(msg, "Payload hash (%s) contradicts manifest (filehash=%s)", strbuf_sprintf(msg, "Payload hash (%s) contradicts manifest (filehash=%s)",
alloca_tohex_rhizome_filehash_t(r->u.insert.write.id), alloca_tohex_rhizome_filehash_t(r->u.insert.write.id),
alloca_tohex_rhizome_filehash_t(r->manifest->filehash)); alloca_tohex_rhizome_filehash_t(r->manifest->filehash));
return http_request_rhizome_response(r, 403, "Inconsistent filehash", strbuf_str(msg)); return http_request_rhizome_response(r, 422, "Inconsistent filehash", strbuf_str(msg)); // Unprocessable Entity
} }
case RHIZOME_PAYLOAD_STATUS_CRYPTO_FAIL: case RHIZOME_PAYLOAD_STATUS_CRYPTO_FAIL:
r->bundle_status = RHIZOME_BUNDLE_STATUS_READONLY; r->bundle_status = RHIZOME_BUNDLE_STATUS_READONLY;
return http_request_rhizome_response(r, 403, "Missing bundle secret", NULL); return http_request_rhizome_response(r, 403, "Missing bundle secret", NULL); // Forbidden
case RHIZOME_PAYLOAD_STATUS_TOO_BIG: case RHIZOME_PAYLOAD_STATUS_TOO_BIG:
r->bundle_status = RHIZOME_BUNDLE_STATUS_NO_ROOM; r->bundle_status = RHIZOME_BUNDLE_STATUS_NO_ROOM;
return http_request_rhizome_response(r, 403, "Bundle too big", NULL); return http_request_rhizome_response(r, 202, "Bundle too big", NULL); // Accepted
case RHIZOME_PAYLOAD_STATUS_EVICTED: case RHIZOME_PAYLOAD_STATUS_EVICTED:
r->bundle_status = RHIZOME_BUNDLE_STATUS_NO_ROOM; r->bundle_status = RHIZOME_BUNDLE_STATUS_NO_ROOM;
return http_request_rhizome_response(r, 403, "Bundle evicted", NULL); return http_request_rhizome_response(r, 202, "Bundle evicted", NULL); // Accepted
case RHIZOME_PAYLOAD_STATUS_ERROR: case RHIZOME_PAYLOAD_STATUS_ERROR:
return http_request_rhizome_response(r, 500, NULL, NULL); return http_request_rhizome_response(r, 500, "Payload store error", NULL);
} }
if (!status_valid) if (!status_valid)
FATALF("rhizome_finish_store() returned status = %d", r->payload_status); FATALF("rhizome_finish_store() returned status = %d", r->payload_status);
@ -701,19 +709,20 @@ static int restful_rhizome_insert_end(struct http_request *hr)
const char *invalid_reason = rhizome_manifest_validate_reason(r->manifest); const char *invalid_reason = rhizome_manifest_validate_reason(r->manifest);
if (invalid_reason) { if (invalid_reason) {
r->bundle_status = RHIZOME_BUNDLE_STATUS_INVALID; r->bundle_status = RHIZOME_BUNDLE_STATUS_INVALID;
return http_request_rhizome_response(r, 403, invalid_reason, NULL); return http_request_rhizome_response(r, 422, invalid_reason, NULL); // Unprocessable Entity
} }
if (r->manifest->malformed) { if (r->manifest->malformed) {
r->bundle_status = RHIZOME_BUNDLE_STATUS_INVALID; r->bundle_status = RHIZOME_BUNDLE_STATUS_INVALID;
return http_request_rhizome_response(r, 403, r->manifest->malformed, NULL); return http_request_rhizome_response(r, 422, r->manifest->malformed, NULL); // Unprocessable Entity
} }
if (!r->manifest->haveSecret) { if (!r->manifest->haveSecret) {
r->bundle_status = RHIZOME_BUNDLE_STATUS_READONLY; r->bundle_status = RHIZOME_BUNDLE_STATUS_READONLY;
return http_request_rhizome_response(r, 403, "Missing bundle secret", NULL); return http_request_rhizome_response(r, 403, "Missing bundle secret", NULL); // Forbidden
} }
rhizome_manifest *mout = NULL; rhizome_manifest *mout = NULL;
r->bundle_status = rhizome_manifest_finalise(r->manifest, &mout, !r->u.insert.force_new); r->bundle_status = rhizome_manifest_finalise(r->manifest, &mout, !r->u.insert.force_new);
int result = 500; int result = 500;
const char *message = NULL;
DEBUGF(rhizome, "r->bundle_status=%d", r->bundle_status); DEBUGF(rhizome, "r->bundle_status=%d", r->bundle_status);
switch (r->bundle_status) { switch (r->bundle_status) {
case RHIZOME_BUNDLE_STATUS_NEW: case RHIZOME_BUNDLE_STATUS_NEW:
@ -730,18 +739,20 @@ static int restful_rhizome_insert_end(struct http_request *hr)
} }
result = 201; result = 201;
break; break;
case RHIZOME_BUNDLE_STATUS_ERROR:
message = "Error in manifest finalise";
// fall through
case RHIZOME_BUNDLE_STATUS_INVALID: case RHIZOME_BUNDLE_STATUS_INVALID:
case RHIZOME_BUNDLE_STATUS_FAKE: case RHIZOME_BUNDLE_STATUS_FAKE:
case RHIZOME_BUNDLE_STATUS_INCONSISTENT: case RHIZOME_BUNDLE_STATUS_INCONSISTENT:
case RHIZOME_BUNDLE_STATUS_NO_ROOM: case RHIZOME_BUNDLE_STATUS_NO_ROOM:
case RHIZOME_BUNDLE_STATUS_READONLY: case RHIZOME_BUNDLE_STATUS_READONLY:
case RHIZOME_BUNDLE_STATUS_ERROR:
case RHIZOME_BUNDLE_STATUS_BUSY: case RHIZOME_BUNDLE_STATUS_BUSY:
if (mout && mout != r->manifest) if (mout && mout != r->manifest)
rhizome_manifest_free(mout); rhizome_manifest_free(mout);
rhizome_manifest_free(r->manifest); rhizome_manifest_free(r->manifest);
r->manifest = NULL; r->manifest = NULL;
return http_request_rhizome_response(r, 0, NULL, NULL); return http_request_rhizome_response(r, 0, message, NULL);
} }
if (result == 500) if (result == 500)
FATALF("rhizome_manifest_finalise() returned status = %d", r->bundle_status); FATALF("rhizome_manifest_finalise() returned status = %d", r->bundle_status);
@ -761,7 +772,7 @@ static int restful_rhizome_(httpd_request *r, const char *remainder)
r->http.response.header.content_type = CONTENT_TYPE_JSON; r->http.response.header.content_type = CONTENT_TYPE_JSON;
r->http.render_extra_headers = render_manifest_headers; r->http.render_extra_headers = render_manifest_headers;
if (!is_rhizome_http_enabled()) if (!is_rhizome_http_enabled())
return 403; return 404;
int ret = authorize_restful(&r->http); int ret = authorize_restful(&r->http);
if (ret) if (ret)
return ret; return ret;
@ -785,7 +796,7 @@ static int restful_rhizome_(httpd_request *r, const char *remainder)
if (r->http.verb != HTTP_VERB_GET) if (r->http.verb != HTTP_VERB_GET)
return 405; return 405;
if ((r->manifest = rhizome_new_manifest()) == NULL) if ((r->manifest = rhizome_new_manifest()) == NULL)
return 500; return http_request_rhizome_response(r, 429, "Manifest table full", NULL); // Too Many Requests
r->bundle_status = rhizome_retrieve_manifest(&bid, r->manifest); r->bundle_status = rhizome_retrieve_manifest(&bid, r->manifest);
switch(r->bundle_status){ switch(r->bundle_status){
case RHIZOME_BUNDLE_STATUS_SAME: case RHIZOME_BUNDLE_STATUS_SAME:
@ -795,10 +806,15 @@ static int restful_rhizome_(httpd_request *r, const char *remainder)
rhizome_manifest_free(r->manifest); rhizome_manifest_free(r->manifest);
r->manifest = NULL; r->manifest = NULL;
break; break;
default: case RHIZOME_BUNDLE_STATUS_BUSY:
rhizome_manifest_free(r->manifest);
return http_request_rhizome_response(r, 423, "Database busy", NULL); // Locked
case RHIZOME_BUNDLE_STATUS_ERROR:
rhizome_manifest_free(r->manifest); rhizome_manifest_free(r->manifest);
r->manifest = NULL; r->manifest = NULL;
return 500; return http_request_rhizome_response(r, 500, "Manifest retrieve error", NULL);
default: // should not return others
FATALF("rhizome_retrieve_manifest() returned status = %d", r->bundle_status);
} }
return handler(r, remainder); return handler(r, remainder);
} }
@ -808,7 +824,7 @@ static int restful_rhizome_bid_rhm(httpd_request *r, const char *remainder)
if (*remainder) if (*remainder)
return 404; return 404;
if (r->manifest == NULL) if (r->manifest == NULL)
return http_request_rhizome_response(r, 403, NULL, NULL); return http_request_rhizome_response(r, 404, "Bundle not found", NULL); // Not Found
http_request_response_static(&r->http, 200, "rhizome-manifest/text", http_request_response_static(&r->http, 200, "rhizome-manifest/text",
(const char *)r->manifest->manifestdata, r->manifest->manifest_all_bytes (const char *)r->manifest->manifestdata, r->manifest->manifest_all_bytes
); );
@ -820,14 +836,14 @@ static int restful_rhizome_bid_raw_bin(httpd_request *r, const char *remainder)
if (*remainder) if (*remainder)
return 404; return 404;
if (r->manifest == NULL) if (r->manifest == NULL)
return http_request_rhizome_response(r, 403, NULL, NULL); return http_request_rhizome_response(r, 404, "Bundle not found", NULL); // Not Found
if (r->manifest->filesize == 0) { if (r->manifest->filesize == 0) {
http_request_response_static(&r->http, 200, CONTENT_TYPE_BLOB, "", 0); http_request_response_static(&r->http, 200, CONTENT_TYPE_BLOB, "", 0);
return 1; return 1;
} }
int ret = rhizome_response_content_init_filehash(r, &r->manifest->filehash); int ret = rhizome_response_content_init_filehash(r, &r->manifest->filehash);
if (ret) if (ret)
return http_request_rhizome_response(r, ret, NULL, NULL); return ret;
http_request_response_generated(&r->http, 200, CONTENT_TYPE_BLOB, rhizome_payload_content); http_request_response_generated(&r->http, 200, CONTENT_TYPE_BLOB, rhizome_payload_content);
return 1; return 1;
} }
@ -837,7 +853,7 @@ static int restful_rhizome_bid_decrypted_bin(httpd_request *r, const char *remai
if (*remainder) if (*remainder)
return 404; return 404;
if (r->manifest == NULL) if (r->manifest == NULL)
return http_request_rhizome_response(r, 403, NULL, NULL); return http_request_rhizome_response(r, 404, "Bundle not found", NULL); // Not Found
if (r->manifest->filesize == 0) { if (r->manifest->filesize == 0) {
// TODO use Content Type from manifest (once it is implemented) // TODO use Content Type from manifest (once it is implemented)
http_request_response_static(&r->http, 200, CONTENT_TYPE_BLOB, "", 0); http_request_response_static(&r->http, 200, CONTENT_TYPE_BLOB, "", 0);
@ -845,7 +861,7 @@ static int restful_rhizome_bid_decrypted_bin(httpd_request *r, const char *remai
} }
int ret = rhizome_response_content_init_payload(r, r->manifest); int ret = rhizome_response_content_init_payload(r, r->manifest);
if (ret) if (ret)
return http_request_rhizome_response(r, ret, NULL, NULL); return ret;
// TODO use Content Type from manifest (once it is implemented) // TODO use Content Type from manifest (once it is implemented)
http_request_response_generated(&r->http, 200, CONTENT_TYPE_BLOB, rhizome_payload_content); http_request_response_generated(&r->http, 200, CONTENT_TYPE_BLOB, rhizome_payload_content);
return 1; return 1;
@ -855,7 +871,7 @@ static int rhizome_response_content_init_read_state(httpd_request *r)
{ {
if (r->u.read_state.length == RHIZOME_SIZE_UNSET && rhizome_read(&r->u.read_state, NULL, 0)) { if (r->u.read_state.length == RHIZOME_SIZE_UNSET && rhizome_read(&r->u.read_state, NULL, 0)) {
rhizome_read_close(&r->u.read_state); rhizome_read_close(&r->u.read_state);
return 404; return http_request_rhizome_response(r, 404, "Payload not found", NULL);
} }
assert(r->u.read_state.length != RHIZOME_SIZE_UNSET); assert(r->u.read_state.length != RHIZOME_SIZE_UNSET);
int ret = http_response_init_content_range(r, r->u.read_state.length); int ret = http_response_init_content_range(r, r->u.read_state.length);
@ -876,14 +892,14 @@ int rhizome_response_content_init_filehash(httpd_request *r, const rhizome_fileh
case RHIZOME_PAYLOAD_STATUS_STORED: case RHIZOME_PAYLOAD_STATUS_STORED:
return rhizome_response_content_init_read_state(r); return rhizome_response_content_init_read_state(r);
case RHIZOME_PAYLOAD_STATUS_NEW: case RHIZOME_PAYLOAD_STATUS_NEW:
return 403; return http_request_rhizome_response(r, 404, "Payload not found", NULL);
case RHIZOME_PAYLOAD_STATUS_ERROR: case RHIZOME_PAYLOAD_STATUS_ERROR:
case RHIZOME_PAYLOAD_STATUS_WRONG_SIZE: case RHIZOME_PAYLOAD_STATUS_WRONG_SIZE:
case RHIZOME_PAYLOAD_STATUS_WRONG_HASH: case RHIZOME_PAYLOAD_STATUS_WRONG_HASH:
case RHIZOME_PAYLOAD_STATUS_CRYPTO_FAIL: case RHIZOME_PAYLOAD_STATUS_CRYPTO_FAIL:
case RHIZOME_PAYLOAD_STATUS_TOO_BIG: case RHIZOME_PAYLOAD_STATUS_TOO_BIG:
case RHIZOME_PAYLOAD_STATUS_EVICTED: case RHIZOME_PAYLOAD_STATUS_EVICTED:
return -1; return http_request_rhizome_response(r, 500, "Payload read error", NULL);
} }
FATALF("rhizome_open_read() returned status = %d", r->payload_status); FATALF("rhizome_open_read() returned status = %d", r->payload_status);
} }
@ -900,14 +916,15 @@ int rhizome_response_content_init_payload(httpd_request *r, rhizome_manifest *m)
case RHIZOME_PAYLOAD_STATUS_STORED: case RHIZOME_PAYLOAD_STATUS_STORED:
return rhizome_response_content_init_read_state(r); return rhizome_response_content_init_read_state(r);
case RHIZOME_PAYLOAD_STATUS_NEW: case RHIZOME_PAYLOAD_STATUS_NEW:
return http_request_rhizome_response(r, 404, "Payload not found", NULL);
case RHIZOME_PAYLOAD_STATUS_CRYPTO_FAIL: case RHIZOME_PAYLOAD_STATUS_CRYPTO_FAIL:
return 403; return http_request_rhizome_response(r, 403, NULL, NULL); // Forbidden
case RHIZOME_PAYLOAD_STATUS_ERROR: case RHIZOME_PAYLOAD_STATUS_ERROR:
case RHIZOME_PAYLOAD_STATUS_WRONG_SIZE: case RHIZOME_PAYLOAD_STATUS_WRONG_SIZE:
case RHIZOME_PAYLOAD_STATUS_WRONG_HASH: case RHIZOME_PAYLOAD_STATUS_WRONG_HASH:
case RHIZOME_PAYLOAD_STATUS_TOO_BIG: case RHIZOME_PAYLOAD_STATUS_TOO_BIG:
case RHIZOME_PAYLOAD_STATUS_EVICTED: case RHIZOME_PAYLOAD_STATUS_EVICTED:
return -1; return http_request_rhizome_response(r, 500, "Payload read error", NULL);
} }
FATALF("rhizome_open_decrypt_read() returned status = %d", r->payload_status); FATALF("rhizome_open_decrypt_read() returned status = %d", r->payload_status);
} }

View File

@ -979,7 +979,9 @@ enum rhizome_payload_status rhizome_store_payload_file(rhizome_manifest *m, cons
return rhizome_finish_store(&write, m, status); return rhizome_finish_store(&write, m, status);
} }
/* Return RHIZOME_PAYLOAD_STATUS_STORED if file blob found, RHIZOME_PAYLOAD_STATUS_NEW if not found. /* Returns RHIZOME_PAYLOAD_STATUS_STORED if file blob found
* Returns RHIZOME_PAYLOAD_STATUS_NEW if not found
* Returns RHIZOME_PAYLOAD_STATUS_ERROR if unexpected error
*/ */
enum rhizome_payload_status rhizome_open_read(struct rhizome_read *read, const rhizome_filehash_t *hashp) enum rhizome_payload_status rhizome_open_read(struct rhizome_read *read, const rhizome_filehash_t *hashp)
{ {

View File

@ -344,12 +344,13 @@ test_RhizomeManifestNonexist() {
--basic --user harry:potter \ --basic --user harry:potter \
"http://$addr_localhost:$PORTA/restful/rhizome/$BID_NONEXISTENT.rhm" "http://$addr_localhost:$PORTA/restful/rhizome/$BID_NONEXISTENT.rhm"
tfw_cat http.headers http.content tfw_cat http.headers http.content
assertStdoutIs 403 assertStdoutIs 404
assertGrep --matches=1 --ignore-case http.headers$n "^Serval-Rhizome-Result-Bundle-Status-Code: 0$CR\$" assertGrep --matches=1 --ignore-case http.headers$n "^Serval-Rhizome-Result-Bundle-Status-Code: 0$CR\$"
assertGrep --matches=1 --ignore-case http.headers$n "^Serval-Rhizome-Result-Bundle-Status-Message: .*bundle new to store.*$CR\$" assertGrep --matches=1 --ignore-case http.headers$n "^Serval-Rhizome-Result-Bundle-Status-Message: .*bundle new to store.*$CR\$"
assertGrep --matches=0 --ignore-case http.headers$n "^Serval-Rhizome-Result-Payload-Status-Code:" assertGrep --matches=0 --ignore-case http.headers$n "^Serval-Rhizome-Result-Payload-Status-Code:"
assertGrep --matches=0 --ignore-case http.headers$n "^Serval-Rhizome-Result-Payload-Status-Message:" assertGrep --matches=0 --ignore-case http.headers$n "^Serval-Rhizome-Result-Payload-Status-Message:"
assertJq http.content 'contains({"http_status_code": 403})' assertJq http.content 'contains({"http_status_code": 404})'
assertJq http.content 'contains({"http_status_message": "Bundle not found"})'
assertJq http.content 'contains({"rhizome_bundle_status_code": 0})' assertJq http.content 'contains({"rhizome_bundle_status_code": 0})'
assertJqGrep --ignore-case http.content '.rhizome_bundle_status_message' "bundle new to store" assertJqGrep --ignore-case http.content '.rhizome_bundle_status_message' "bundle new to store"
} }
@ -392,12 +393,13 @@ test_RhizomePayloadRawNonexistManifest() {
--basic --user harry:potter \ --basic --user harry:potter \
"http://$addr_localhost:$PORTA/restful/rhizome/$BID_NONEXISTENT/raw.bin" "http://$addr_localhost:$PORTA/restful/rhizome/$BID_NONEXISTENT/raw.bin"
tfw_cat http.headers http.content tfw_cat http.headers http.content
assertStdoutIs 403 assertStdoutIs 404
assertGrep --matches=1 --ignore-case http.headers$n "^Serval-Rhizome-Result-Bundle-Status-Code: 0$CR\$" assertGrep --matches=1 --ignore-case http.headers$n "^Serval-Rhizome-Result-Bundle-Status-Code: 0$CR\$"
assertGrep --matches=1 --ignore-case http.headers$n "^Serval-Rhizome-Result-Bundle-Status-Message: .*bundle new to store.*$CR\$" assertGrep --matches=1 --ignore-case http.headers$n "^Serval-Rhizome-Result-Bundle-Status-Message: .*bundle new to store.*$CR\$"
assertGrep --matches=0 --ignore-case http.headers$n "^Serval-Rhizome-Result-Payload-Status-Code:" assertGrep --matches=0 --ignore-case http.headers$n "^Serval-Rhizome-Result-Payload-Status-Code:"
assertGrep --matches=0 --ignore-case http.headers$n "^Serval-Rhizome-Result-Payload-Status-Message:" assertGrep --matches=0 --ignore-case http.headers$n "^Serval-Rhizome-Result-Payload-Status-Message:"
assertJq http.content 'contains({"http_status_code": 403})' assertJq http.content 'contains({"http_status_code": 404})'
assertJq http.content 'contains({"http_status_message": "Bundle not found"})'
assertJq http.content 'contains({"rhizome_bundle_status_code": 0})' assertJq http.content 'contains({"rhizome_bundle_status_code": 0})'
assertJqGrep --ignore-case http.content '.rhizome_bundle_status_message' "bundle new to store" assertJqGrep --ignore-case http.content '.rhizome_bundle_status_message' "bundle new to store"
} }
@ -419,12 +421,13 @@ test_RhizomePayloadRawNonexistPayload() {
--basic --user harry:potter \ --basic --user harry:potter \
"http://$addr_localhost:$PORTA/restful/rhizome/${BID[0]}/raw.bin" "http://$addr_localhost:$PORTA/restful/rhizome/${BID[0]}/raw.bin"
tfw_cat http.headers http.content tfw_cat http.headers http.content
assertStdoutIs 403 assertStdoutIs 404
assertGrep --matches=1 --ignore-case http.headers$n "^Serval-Rhizome-Result-Bundle-Status-Code: 1$CR\$" assertGrep --matches=1 --ignore-case http.headers$n "^Serval-Rhizome-Result-Bundle-Status-Code: 1$CR\$"
assertGrep --matches=1 --ignore-case http.headers$n "^Serval-Rhizome-Result-Bundle-Status-Message: .*bundle already in store.*$CR\$" assertGrep --matches=1 --ignore-case http.headers$n "^Serval-Rhizome-Result-Bundle-Status-Message: .*bundle already in store.*$CR\$"
assertGrep --matches=1 --ignore-case http.headers$n "^Serval-Rhizome-Result-Payload-Status-Code: 1$CR\$" assertGrep --matches=1 --ignore-case http.headers$n "^Serval-Rhizome-Result-Payload-Status-Code: 1$CR\$"
assertGrep --matches=1 --ignore-case http.headers$n "^Serval-Rhizome-Result-Payload-Status-Message: .*payload new to store.*$CR\$" assertGrep --matches=1 --ignore-case http.headers$n "^Serval-Rhizome-Result-Payload-Status-Message: .*payload new to store.*$CR\$"
assertJq http.content 'contains({"http_status_code": 403})' assertJq http.content 'contains({"http_status_code": 404})'
assertJq http.content 'contains({"http_status_message": "Payload not found"})'
assertJq http.content 'contains({"rhizome_bundle_status_code": 1})' assertJq http.content 'contains({"rhizome_bundle_status_code": 1})'
assertJqGrep --ignore-case http.content '.rhizome_bundle_status_message' "bundle already in store" assertJqGrep --ignore-case http.content '.rhizome_bundle_status_message' "bundle already in store"
assertJq http.content 'contains({"rhizome_payload_status_code": 1})' assertJq http.content 'contains({"rhizome_payload_status_code": 1})'
@ -495,12 +498,13 @@ test_RhizomePayloadDecryptedNonexistManifest() {
--basic --user harry:potter \ --basic --user harry:potter \
"http://$addr_localhost:$PORTA/restful/rhizome/$BID_NONEXISTENT/decrypted.bin" "http://$addr_localhost:$PORTA/restful/rhizome/$BID_NONEXISTENT/decrypted.bin"
tfw_cat http.headers http.content tfw_cat http.headers http.content
assertStdoutIs 403 assertStdoutIs 404
assertGrep --matches=1 --ignore-case http.headers$n "^Serval-Rhizome-Result-Bundle-Status-Code: 0$CR\$" assertGrep --matches=1 --ignore-case http.headers$n "^Serval-Rhizome-Result-Bundle-Status-Code: 0$CR\$"
assertGrep --matches=1 --ignore-case http.headers$n "^Serval-Rhizome-Result-Bundle-Status-Message: .*bundle new to store.*$CR\$" assertGrep --matches=1 --ignore-case http.headers$n "^Serval-Rhizome-Result-Bundle-Status-Message: .*bundle new to store.*$CR\$"
assertGrep --matches=0 --ignore-case http.headers$n "^Serval-Rhizome-Result-Payload-Status-Code:" assertGrep --matches=0 --ignore-case http.headers$n "^Serval-Rhizome-Result-Payload-Status-Code:"
assertGrep --matches=0 --ignore-case http.headers$n "^Serval-Rhizome-Result-Payload-Status-Message:" assertGrep --matches=0 --ignore-case http.headers$n "^Serval-Rhizome-Result-Payload-Status-Message:"
assertJq http.content 'contains({"http_status_code": 403})' assertJq http.content 'contains({"http_status_code": 404})'
assertJq http.content 'contains({"http_status_message": "Bundle not found"})'
assertJq http.content 'contains({"rhizome_bundle_status_code": 0})' assertJq http.content 'contains({"rhizome_bundle_status_code": 0})'
assertJqGrep --ignore-case http.content '.rhizome_bundle_status_message' "bundle new to store" assertJqGrep --ignore-case http.content '.rhizome_bundle_status_message' "bundle new to store"
} }
@ -522,12 +526,13 @@ test_RhizomePayloadDecryptedNonexistPayload() {
--basic --user harry:potter \ --basic --user harry:potter \
"http://$addr_localhost:$PORTA/restful/rhizome/${BID[0]}/decrypted.bin" "http://$addr_localhost:$PORTA/restful/rhizome/${BID[0]}/decrypted.bin"
tfw_cat http.headers http.content tfw_cat http.headers http.content
assertStdoutIs 403 assertStdoutIs 404
assertGrep --matches=1 --ignore-case http.headers$n "^Serval-Rhizome-Result-Bundle-Status-Code: 1$CR\$" assertGrep --matches=1 --ignore-case http.headers$n "^Serval-Rhizome-Result-Bundle-Status-Code: 1$CR\$"
assertGrep --matches=1 --ignore-case http.headers$n "^Serval-Rhizome-Result-Bundle-Status-Message: .*bundle already in store.*$CR\$" assertGrep --matches=1 --ignore-case http.headers$n "^Serval-Rhizome-Result-Bundle-Status-Message: .*bundle already in store.*$CR\$"
assertGrep --matches=1 --ignore-case http.headers$n "^Serval-Rhizome-Result-Payload-Status-Code: 1$CR\$" assertGrep --matches=1 --ignore-case http.headers$n "^Serval-Rhizome-Result-Payload-Status-Code: 1$CR\$"
assertGrep --matches=1 --ignore-case http.headers$n "^Serval-Rhizome-Result-Payload-Status-Message: .*payload new to store.*$CR\$" assertGrep --matches=1 --ignore-case http.headers$n "^Serval-Rhizome-Result-Payload-Status-Message: .*payload new to store.*$CR\$"
assertJq http.content 'contains({"http_status_code": 403})' assertJq http.content 'contains({"http_status_code": 404})'
assertJq http.content 'contains({"http_status_message": "Payload not found"})'
assertJq http.content 'contains({"rhizome_bundle_status_code": 1})' assertJq http.content 'contains({"rhizome_bundle_status_code": 1})'
assertJqGrep --ignore-case http.content '.rhizome_bundle_status_message' "bundle already in store" assertJqGrep --ignore-case http.content '.rhizome_bundle_status_message' "bundle already in store"
assertJq http.content 'contains({"rhizome_payload_status_code": 1})' assertJq http.content 'contains({"rhizome_payload_status_code": 1})'
@ -972,8 +977,9 @@ test_RhizomeInsertJournalForbidden() {
"http://$addr_localhost:$PORTA/restful/rhizome/insert" "http://$addr_localhost:$PORTA/restful/rhizome/insert"
tfw_cat http.header http.body tfw_cat http.header http.body
assertExitStatus == 0 assertExitStatus == 0
assertStdoutIs 403 assertStdoutIs 422
assertJq http.body 'contains({"http_status_code": 403})' assertJq http.body 'contains({"http_status_code": 422})'
assertJq http.body 'contains({"http_status_message": "Cannot add a journal bundle (use append instead)"})'
assertJqGrep --ignore-case http.body '.http_status_message' 'cannot add.*journal' assertJqGrep --ignore-case http.body '.http_status_message' 'cannot add.*journal'
executeOk_servald rhizome list executeOk_servald rhizome list
assert_rhizome_list assert_rhizome_list
@ -1097,8 +1103,9 @@ test_RhizomeInsertIncorrectFilesize() {
"http://$addr_localhost:$PORTA/restful/rhizome/insert" "http://$addr_localhost:$PORTA/restful/rhizome/insert"
tfw_cat http.header http.body tfw_cat http.header http.body
assertExitStatus == 0 assertExitStatus == 0
assertStdoutIs 403 assertStdoutIs 422
assertJq http.body 'contains({"http_status_code": 403})' assertJq http.body 'contains({"http_status_code": 422})'
assertJq http.body 'contains({"http_status_message": "Inconsistent filesize"})'
assertJq http.body 'contains({"rhizome_payload_status_code": 3})' assertJq http.body 'contains({"rhizome_payload_status_code": 3})'
assertJqGrep --ignore-case http.body '.rhizome_payload_status_message' 'payload size.*contradicts manifest' assertJqGrep --ignore-case http.body '.rhizome_payload_status_message' 'payload size.*contradicts manifest'
execute curl \ execute curl \
@ -1111,8 +1118,9 @@ test_RhizomeInsertIncorrectFilesize() {
"http://$addr_localhost:$PORTA/restful/rhizome/insert" "http://$addr_localhost:$PORTA/restful/rhizome/insert"
tfw_cat http.header http.body tfw_cat http.header http.body
assertExitStatus == 0 assertExitStatus == 0
assertStdoutIs 403 assertStdoutIs 422
assertJq http.body 'contains({"http_status_code": 403})' assertJq http.body 'contains({"http_status_code": 422})'
assertJq http.body 'contains({"http_status_message": "Inconsistent filesize"})'
assertJq http.body 'contains({"rhizome_payload_status_code": 3})' assertJq http.body 'contains({"rhizome_payload_status_code": 3})'
assertJqGrep --ignore-case http.body '.rhizome_payload_status_message' 'payload size.*contradicts manifest' assertJqGrep --ignore-case http.body '.rhizome_payload_status_message' 'payload size.*contradicts manifest'
executeOk_servald rhizome list executeOk_servald rhizome list
@ -1136,8 +1144,9 @@ test_RhizomeInsertIncorrectFilehash() {
"http://$addr_localhost:$PORTA/restful/rhizome/insert" "http://$addr_localhost:$PORTA/restful/rhizome/insert"
tfw_cat http.header http.body tfw_cat http.header http.body
assertExitStatus == 0 assertExitStatus == 0
assertStdoutIs 403 assertStdoutIs 422
assertJq http.body 'contains({"http_status_code": 403})' assertJq http.body 'contains({"http_status_code": 422})'
assertJq http.body 'contains({"http_status_message": "Inconsistent filehash"})'
assertJq http.body 'contains({"rhizome_payload_status_code": 4})' assertJq http.body 'contains({"rhizome_payload_status_code": 4})'
assertJqGrep --ignore-case http.body '.rhizome_payload_status_message' 'payload hash.*contradicts manifest' assertJqGrep --ignore-case http.body '.rhizome_payload_status_message' 'payload hash.*contradicts manifest'
executeOk_servald rhizome list executeOk_servald rhizome list
@ -1316,8 +1325,9 @@ test_RhizomeAppendNonJournalForbidden() {
"http://$addr_localhost:$PORTA/restful/rhizome/append" "http://$addr_localhost:$PORTA/restful/rhizome/append"
tfw_cat http.header http.body tfw_cat http.header http.body
assertExitStatus == 0 assertExitStatus == 0
assertStdoutIs 403 assertStdoutIs 422
assertJq http.body 'contains({"http_status_code": 403})' assertJq http.body 'contains({"http_status_code": 422})'
assertJq http.body 'contains({"http_status_message": "Cannot append to a non-journal"})'
assertJqGrep --ignore-case http.body '.http_status_message' 'cannot append.*non.*journal' assertJqGrep --ignore-case http.body '.http_status_message' 'cannot append.*non.*journal'
executeOk_servald rhizome list executeOk_servald rhizome list
assert_rhizome_list file1 assert_rhizome_list file1