diff --git a/.gitignore b/.gitignore index 3ba83849c5..545285dce3 100644 --- a/.gitignore +++ b/.gitignore @@ -80,3 +80,7 @@ cppcheck.tmp Installation/arangod.conf Installation/epm/arangodb.sublist nbproject/ + +html/admin/api-docs/ +!html/admin/api-docs/api-docs.json +test.cpp.txt diff --git a/Documentation/Scripts/generateSwagger.py b/Documentation/Scripts/generateSwagger.py index 67e9846f48..aafe21ec2b 100644 --- a/Documentation/Scripts/generateSwagger.py +++ b/Documentation/Scripts/generateSwagger.py @@ -94,36 +94,37 @@ class InitializationError(Exception): pass # idea from http://gnosis.cx/TPiP/chap4.txt class StateMachine: - def __init__(self): - self.handlers = [] - self.startState = None - self.endStates = [] + def __init__(self): + self.handlers = [] + self.startState = None + self.endStates = [] - def add_state(self, handler, end_state=0): - self.handlers.append(handler) - if end_state: - self.endStates.append(handler) + def add_state(self, handler, end_state=0): + self.handlers.append(handler) + if end_state: + self.endStates.append(handler) - def set_start(self, handler): - self.startState = handler + def set_start(self, handler): + self.startState = handler + + def run(self, cargo=None): + if not self.startState: + raise InitializationError,\ + "must call .set_start() before .run()" + if not self.endStates: + raise InitializationError, \ + "at least one state must be an end_state" + handler = self.startState + while 1: + (newState, cargo) = handler(cargo) + if newState in self.endStates: + newState(cargo) + break + elif newState not in self.handlers: + raise RuntimeError, "Invalid target %s" % newState + else: + handler = newState - def run(self, cargo=None): - if not self.startState: - raise InitializationError,\ - "must call .set_start() before .run()" - if not self.endStates: - raise InitializationError, \ - "at least one state must be an end_state" - handler = self.startState - while 1: - (newState, cargo) = handler(cargo) - if newState in self.endStates: - newState(cargo) - break - elif newState not in self.handlers: - raise RuntimeError, "Invalid target %s" % newState - else: - handler = newState class Regexen: def __init__(self): self.brief = re.compile('.*@brief') @@ -398,22 +399,22 @@ def read_through(cargo): if __name__ == "__main__": - automat = StateMachine() - automat.add_state(read_through) - automat.add_state(eof, end_state=1) - automat.add_state(comment) - automat.add_state(resturlparameters) - automat.add_state(resturlparam) - automat.add_state(restqueryparameters) - automat.add_state(restqueryparam) - automat.add_state(restbodyparam) - automat.add_state(restheaderparameters) - automat.add_state(restheaderparam) - automat.add_state(restdescription) - automat.add_state(restreturncodes) - automat.add_state(restreturncode) - automat.add_state(examples) - automat.add_state(example_arangosh_run) - automat.add_state(error, end_state=1) - automat.set_start(read_through) - automat.run((sys.stdin, '')) + automat = StateMachine() + automat.add_state(read_through) + automat.add_state(eof, end_state=1) + automat.add_state(comment) + automat.add_state(resturlparameters) + automat.add_state(resturlparam) + automat.add_state(restqueryparameters) + automat.add_state(restqueryparam) + automat.add_state(restbodyparam) + automat.add_state(restheaderparameters) + automat.add_state(restheaderparam) + automat.add_state(restdescription) + automat.add_state(restreturncodes) + automat.add_state(restreturncode) + automat.add_state(examples) + automat.add_state(example_arangosh_run) + automat.add_state(error, end_state=1) + automat.set_start(read_through) + automat.run((sys.stdin, '')) diff --git a/arangod/Utils/Transaction.h b/arangod/Utils/Transaction.h index 6b27d84ece..91689736b7 100644 --- a/arangod/Utils/Transaction.h +++ b/arangod/Utils/Transaction.h @@ -414,6 +414,7 @@ namespace triagens { TRI_primary_collection_t* primary = primaryCollection(trxCollection); *barrier = TRI_CreateBarrierElement(&primary->_barrierList); + if (*barrier == 0) { return TRI_ERROR_OUT_OF_MEMORY; } @@ -422,6 +423,7 @@ namespace triagens { int res = this->lock(trxCollection, TRI_TRANSACTION_READ); if (res != TRI_ERROR_NO_ERROR) { + this->unlock(trxCollection, TRI_TRANSACTION_READ); TRI_FreeBarrier(*barrier); *barrier = 0; return res; @@ -484,6 +486,7 @@ namespace triagens { int res = this->lock(trxCollection, TRI_TRANSACTION_READ); if (res != TRI_ERROR_NO_ERROR) { + this->unlock(trxCollection, TRI_TRANSACTION_READ); return res; } @@ -530,6 +533,7 @@ namespace triagens { int res = this->lock(trxCollection, TRI_TRANSACTION_READ); if (res != TRI_ERROR_NO_ERROR) { + this->unlock(trxCollection, TRI_TRANSACTION_READ); return res; } @@ -542,7 +546,9 @@ namespace triagens { } *barrier = TRI_CreateBarrierElement(&primary->_barrierList); + if (*barrier == 0) { + this->unlock(trxCollection, TRI_TRANSACTION_READ); return TRI_ERROR_OUT_OF_MEMORY; } diff --git a/arangod/V8Server/v8-query.cpp b/arangod/V8Server/v8-query.cpp index b1473333e0..220c51ad5c 100644 --- a/arangod/V8Server/v8-query.cpp +++ b/arangod/V8Server/v8-query.cpp @@ -1746,10 +1746,17 @@ static v8::Handle JS_AnyQuery (v8::Arguments const& argv) { res = trx.finish(res); if (res != TRI_ERROR_NO_ERROR) { + if (barrier != 0) { + TRI_FreeBarrier(barrier); + } TRI_V8_EXCEPTION_MESSAGE(scope, res, "cannot fetch document"); } if (document._data == 0 || document._key == 0) { + if (barrier != 0) { + TRI_FreeBarrier(barrier); + } + return scope.Close(v8::Null()); } diff --git a/arangod/VocBase/transaction.c b/arangod/VocBase/transaction.c index 7aab7ab881..c22569117d 100644 --- a/arangod/VocBase/transaction.c +++ b/arangod/VocBase/transaction.c @@ -1177,6 +1177,11 @@ static int UnlockCollection (TRI_transaction_collection_t* trxCollection, assert(trxCollection->_locked == true); primary = trxCollection->_collection->_collection; + + if (trxCollection->_nestingLevel < nestingLevel) { + // only process our own collections + return TRI_ERROR_NO_ERROR; + } if (type == TRI_TRANSACTION_READ) { LOG_TRX(trxCollection->_transaction, diff --git a/html/admin/api-docs/document b/html/admin/api-docs/document index 7e22f64346..7238894582 100644 --- a/html/admin/api-docs/document +++ b/html/admin/api-docs/document @@ -57,7 +57,7 @@ "notes": "Creates a new document in the collection named `collection`. A JSON representation of the document must be passed as the body of the POST request.

If the document was created successfully, then the \"Location\" header contains the path to the newly created document. The \"ETag\" header field contains the revision of the document.

The body of the response contains a JSON object with the following attributes:

- `_id` contains the document handle of the newly created document
- `_key` contains the document key
- `_rev` contains the document revision

If the collection parameter `waitForSync` is `false`, then the call returns as soon as the document has been accepted. It will not wait, until the documents has been sync to disk.

Optionally, the URL parameter `waitForSync` can be used to force synchronisation of the document creation operation to disk even in case that the `waitForSync` flag had been disabled for the entire collection. Thus, the `waitForSync` URL parameter can be used to force synchronisation of just this specific operations. To use this, set the `waitForSync` parameter to `true`. If the `waitForSync` parameter is not specified or set to `false`, then the collection's default `waitForSync` behavior is applied. The `waitForSync` URL parameter cannot be used to disable synchronisation for collections that have a default `waitForSync` value of `true`.

", "summary": "creates a document", "httpMethod": "POST", - "examples": "Create a document given a collection named `products`. Note that the revision identifier might or might not by equal to the auto-generated key.

unix> curl -X POST --data @- --dump - http://localhost:8529/_api/document?collection=products\n{ \"Hello\": \"World\" }\n\nHTTP/1.1 201 Created\ncontent-type: application/json; charset=utf-8\netag: \"13251162\"\nlocation: /_api/document/products/13251162\n\n{ \n  \"error\" : false, \n  \"_id\" : \"products/13251162\", \n  \"_rev\" : \"13251162\", \n  \"_key\" : \"13251162\" \n}\n\n

Create a document in a collection named `products` with a collection-level `waitForSync` value of `false`.

unix> curl -X POST --data @- --dump - http://localhost:8529/_api/document?collection=productsNoWait\n{ \"Hello\": \"World\" }\n\nHTTP/1.1 202 Accepted\ncontent-type: application/json; charset=utf-8\netag: \"16069210\"\nlocation: /_api/document/productsNoWait/16069210\n\n{ \n  \"error\" : false, \n  \"_id\" : \"productsNoWait/16069210\", \n  \"_rev\" : \"16069210\", \n  \"_key\" : \"16069210\" \n}\n\n

Create a document in a collection with a collection-level `waitForSync` value of `false`, but using the `waitForSync` URL parameter.

unix> curl -X POST --data @- --dump - http://localhost:8529/_api/document?collection=productsNoWait&waitForSync=true\n{ \"Hello\": \"World\" }\n\nHTTP/1.1 201 Created\ncontent-type: application/json; charset=utf-8\netag: \"14627418\"\nlocation: /_api/document/productsNoWait/14627418\n\n{ \n  \"error\" : false, \n  \"_id\" : \"productsNoWait/14627418\", \n  \"_rev\" : \"14627418\", \n  \"_key\" : \"14627418\" \n}\n\n

Create a document in a new, named collection

unix> curl -X POST --data @- --dump - http://localhost:8529/_api/document?collection=products&createCollection=true\n{ \"Hello\": \"World\" }\n\nHTTP/1.1 202 Accepted\ncontent-type: application/json; charset=utf-8\netag: \"23999066\"\nlocation: /_api/document/products/23999066\n\n{ \n  \"error\" : false, \n  \"_id\" : \"products/23999066\", \n  \"_rev\" : \"23999066\", \n  \"_key\" : \"23999066\" \n}\n\n

Unknown collection name:

unix> curl -X POST --data @- --dump - http://localhost:8529/_api/document?collection=productsUnknown\n{ \"Hello\": \"World\" }\n\nHTTP/1.1 404 Not Found\ncontent-type: application/json; charset=utf-8\n\n{ \n  \"error\" : true, \n  \"errorMessage\" : \"collection /_api/collection/productsUnknown not found\", \n  \"code\" : 404, \n  \"errorNum\" : 1203 \n}\n\n

Illegal document:

unix> curl -X POST --data @- --dump - http://localhost:8529/_api/document?collection=products\n{ 1: \"World\" }\n\nHTTP/1.1 400 Bad Request\ncontent-type: application/json; charset=utf-8\n\n{ \n  \"error\" : true, \n  \"errorMessage\" : \"expecting attribute name\", \n  \"code\" : 400, \n  \"errorNum\" : 600 \n}\n\n

", + "examples": "Create a document given a collection named `products`. Note that the revision identifier might or might not by equal to the auto-generated key.

unix> curl -X POST --data @- --dump - http://localhost:8529/_api/document?collection=products\n{ \"Hello\": \"World\" }\n\nHTTP/1.1 201 Created\ncontent-type: application/json; charset=utf-8\netag: \"17973671\"\nlocation: /_api/document/products/17973671\n\n{ \n  \"error\" : false, \n  \"_id\" : \"products/17973671\", \n  \"_rev\" : \"17973671\", \n  \"_key\" : \"17973671\" \n}\n\n

Create a document in a collection named `products` with a collection-level `waitForSync` value of `false`.

unix> curl -X POST --data @- --dump - http://localhost:8529/_api/document?collection=products\n{ \"Hello\": \"World\" }\n\nHTTP/1.1 202 Accepted\ncontent-type: application/json; charset=utf-8\netag: \"21316007\"\nlocation: /_api/document/products/21316007\n\n{ \n  \"error\" : false, \n  \"_id\" : \"products/21316007\", \n  \"_rev\" : \"21316007\", \n  \"_key\" : \"21316007\" \n}\n\n

Create a document in a collection with a collection-level `waitForSync` value of `false`, but using the `waitForSync` URL parameter.

unix> curl -X POST --data @- --dump - http://localhost:8529/_api/document?collection=products&waitForSync=true\n{ \"Hello\": \"World\" }\n\nHTTP/1.1 201 Created\ncontent-type: application/json; charset=utf-8\netag: \"19743143\"\nlocation: /_api/document/products/19743143\n\n{ \n  \"error\" : false, \n  \"_id\" : \"products/19743143\", \n  \"_rev\" : \"19743143\", \n  \"_key\" : \"19743143\" \n}\n\n

Create a document in a new, named collection

unix> curl -X POST --data @- --dump - http://localhost:8529/_api/document?collection=products&createCollection=true\n{ \"Hello\": \"World\" }\n\nHTTP/1.1 202 Accepted\ncontent-type: application/json; charset=utf-8\netag: \"29049255\"\nlocation: /_api/document/products/29049255\n\n{ \n  \"error\" : false, \n  \"_id\" : \"products/29049255\", \n  \"_rev\" : \"29049255\", \n  \"_key\" : \"29049255\" \n}\n\n

Unknown collection name:

unix> curl -X POST --data @- --dump - http://localhost:8529/_api/document?collection=products\n{ \"Hello\": \"World\" }\n\nHTTP/1.1 404 Not Found\ncontent-type: application/json; charset=utf-8\n\n{ \n  \"error\" : true, \n  \"errorMessage\" : \"collection /_api/collection/products not found\", \n  \"code\" : 404, \n  \"errorNum\" : 1203 \n}\n\n

Illegal document:

unix> curl -X POST --data @- --dump - http://localhost:8529/_api/document?collection=products\n{ 1: \"World\" }\n\nHTTP/1.1 400 Bad Request\ncontent-type: application/json; charset=utf-8\n\n{ \n  \"error\" : true, \n  \"errorMessage\" : \"expecting attribute name\", \n  \"code\" : 400, \n  \"errorNum\" : 600 \n}\n\n

", "nickname": "createsADocument" } ], @@ -96,7 +96,7 @@ "notes": "Returns the document identified by document-handle. The returned document contains two special attributes: _id containing the document handle and _rev containing the revision.

", "summary": "reads a document", "httpMethod": "GET", - "examples": "Use a document handle:

unix> curl --dump - http://localhost:8529/_api/document/products1/19214938\n\nHTTP/1.1 200 OK\ncontent-type: application/json; charset=utf-8\netag: \"19214938\"\n\n{ \n  \"hallo\" : \"world\", \n  \"_id\" : \"products1/19214938\", \n  \"_rev\" : \"19214938\", \n  \"_key\" : \"19214938\" \n}\n\n

Use a document handle and an etag:

unix> curl --header 'if-none-match: \"29110874\"' --dump - http://localhost:8529/_api/document/products2/29110874\n\nHTTP/1.1 200 OK\ncontent-type: application/json; charset=utf-8\netag: \"29110874\"\n\n{ \n  \"hallo\" : \"world\", \n  \"_id\" : \"products2/29110874\", \n  \"_rev\" : \"29110874\", \n  \"_key\" : \"29110874\" \n}\n\n

Unknown document handle:

unix> curl --dump - http://localhost:8529/_api/document/products/unknownhandle\n\nHTTP/1.1 404 Not Found\ncontent-type: application/json; charset=utf-8\n\n{ \n  \"error\" : true, \n  \"errorMessage\" : \"document /_api/document/products/unknownhandle not found\", \n  \"code\" : 404, \n  \"errorNum\" : 1202 \n}\n\n

", + "examples": "Use a document handle:

unix> curl --dump - http://localhost:8529/_api/document/products/24265127\n\nHTTP/1.1 200 OK\ncontent-type: application/json; charset=utf-8\netag: \"24265127\"\n\n{ \n  \"hallo\" : \"world\", \n  \"_id\" : \"products/24265127\", \n  \"_rev\" : \"24265127\", \n  \"_key\" : \"24265127\" \n}\n\n

Use a document handle and an etag:

unix> curl --header 'if-none-match: \"34292135\"' --dump - http://localhost:8529/_api/document/products/34292135\n\n

Unknown document handle:

unix> curl --dump - http://localhost:8529/_api/document/products/unknownhandle\n\nHTTP/1.1 404 Not Found\ncontent-type: application/json; charset=utf-8\n\n{ \n  \"error\" : true, \n  \"errorMessage\" : \"document /_api/document/products/unknownhandle not found\", \n  \"code\" : 404, \n  \"errorNum\" : 1202 \n}\n\n

", "nickname": "readsADocument" } ], @@ -118,7 +118,7 @@ "notes": "Returns a list of all URI for all documents from the collection identified by collection.

", "summary": "reads all documents from collection", "httpMethod": "GET", - "examples": "

unix> curl --dump - http://localhost:8529/_api/document/?collection=24457818\n\nHTTP/1.1 200 OK\ncontent-type: application/json; charset=utf-8\n\n{ \n  \"documents\" : [ \n    \"/_api/document/products3/26358362\", \n    \"/_api/document/products3/25440858\", \n    \"/_api/document/products3/26096218\" \n  ] \n}\n\n

", + "examples": "

unix> curl --dump - http://localhost:8529/_api/document/?collection=products\n\nHTTP/1.1 200 OK\ncontent-type: application/json; charset=utf-8\n\n{ \n  \"documents\" : [ \n    \"/_api/document/products/31408551\", \n    \"/_api/document/products/31146407\", \n    \"/_api/document/products/30622119\" \n  ] \n}\n\n

", "nickname": "readsAllDocumentsFromCollection" } ], @@ -140,7 +140,7 @@ "notes": "Like GET, but only returns the header fields and not the body. You can use this call to get the current revision of a document or check if the document was deleted.

", "summary": "reads a document header", "httpMethod": "HEAD", - "examples": "

unix> curl --data @- --dump - http://localhost:8529/_api/document/productshead/32256602\n{}\n\n

", + "examples": "

unix> curl -X HEAD --dump - http://localhost:8529/_api/document/products/37306791\n\nHTTP/1.1 200 OK\ncontent-type: application/json; charset=utf-8\netag: \"37306791\"\n\n

", "nickname": "readsADocumentHeader" } ], @@ -183,7 +183,7 @@ "notes": "Completely updates (i.e. replaces) the document identified by document-handle. If the document exists and can be updated, then a HTTP 201 is returned and the \"ETag\" header field contains the new revision of the document.

If the new document passed in the body of the request contains the document-handle in the attribute _id and the revision in _rev, these attributes will be ignored. Only the URI and the \"ETag\" header are relevant in order to avoid confusion when using proxies.

Optionally, the URL parameter waitForSync can be used to force synchronisation of the document replacement operation to disk even in case that the waitForSync flag had been disabled for the entire collection. Thus, the waitForSync URL parameter can be used to force synchronisation of just specific operations. To use this, set the waitForSync parameter to true. If the waitForSync parameter is not specified or set to false, then the collection's default waitForSync behavior is applied. The waitForSync URL parameter cannot be used to disable synchronisation for collections that have a default waitForSync value of true.

The body of the response contains a JSON object with the information about the handle and the revision. The attribute _id contains the known document-handle of the updated document, the attribute @LIT{_rev} contains the new document revision.

If the document does not exist, then a HTTP 404 is returned and the body of the response contains an error document.

There are two ways for specifying the targeted document revision id for conditional replacements (i.e. replacements that will only be executed if the revision id found in the database matches the document revision id specified in the request): - specifying the target revision in the rev URL parameter
- specifying the target revision in the if-match HTTP header

Specifying a target revision is optional, however, if done, only one of the described mechanisms must be used (either the rev URL parameter or the if-match HTTP header). Regardless which mechanism is used, the parameter needs to contain the target document revision id as returned in the _rev attribute of a document or by an HTTP etag header.

For example, to conditionally replace a document based on a specific revision id, you the following request: @REST{PUT /_api/document/document-handle?rev=etag}

If a target revision id is provided in the request (e.g. via the etag value in the rev URL parameter above), ArangoDB will check that the revision id of the document found in the database is equal to the target revision id provided in the request. If there is a mismatch between the revision id, then by default a HTTP 412 conflict is returned and no replacement is performed.

The conditional update behavior can be overriden with the policy URL parameter:

@REST{PUT /_api/document/document-handle?policy=policy}

If policy is set to error, then the behavior is as before: replacements will fail if the revision id found in the database does not match the target revision id specified in the request.

If policy is set to last, then the replacement will succeed, even if the revision id found in the database does not match the target revision id specified in the request. You can use the last policy to force replacements.

", "summary": "replaces a document", "httpMethod": "PUT", - "examples": "Using document handle:

> curl --data @- -X PUT --dump - http://localhost:8529/_api/document/73482/29853486\n{ \"World\" : \"Hello\" }\n\nHTTP/1.1 200 OK\ncontent-type: application/json; charset=utf-8\n\n{\n  \"_rev\": \"29919022\",\n  \"_id\": \"73482/29853486\",\n  \"error\": false\n}\n

var cn = \"products4\"; db._drop(cn); db._create(cn); var collection = db._collection(cn); var document = db.products4.save({\"hallo\":\"world\"}); var url = \"/_api/document/\" + document._id; var response = logCurlRequest('PUT', url, \"{}\"); assert(response.code === 200); logJsonResponse(response); db._drop(cn); @END_EXAMPLE_ARANGOSH_RUN Unknown document handle:

unix> curl -X PUT --data @- --dump - http://localhost:8529/_api/document/products5/30618202\n{}\n\nHTTP/1.1 202 Accepted\ncontent-type: application/json; charset=utf-8\netag: \"31208026\"\nlocation: /_api/document/products5/30618202\n\n{ \n  \"error\" : false, \n  \"_id\" : \"products5/30618202\", \n  \"_rev\" : \"31208026\", \n  \"_key\" : \"30618202\" \n}\n\n

Produce a revision conflict:

unix> curl -X PUT --data @- --dump - http://localhost:8529/_api/document/products6/22360666\n{}\n\nHTTP/1.1 202 Accepted\ncontent-type: application/json; charset=utf-8\netag: \"22950490\"\nlocation: /_api/document/products6/22360666\n\n{ \n  \"error\" : false, \n  \"_id\" : \"products6/22360666\", \n  \"_rev\" : \"22950490\", \n  \"_key\" : \"22360666\" \n}\n\n

Last write wins:

unix> curl -X PUT --data @- --dump - http://localhost:8529/_api/document/products7/17642074\n{}\n\nHTTP/1.1 202 Accepted\ncontent-type: application/json; charset=utf-8\netag: \"18100826\"\nlocation: /_api/document/products7/17642074\n\n{ \n  \"error\" : false, \n  \"_id\" : \"products7/17642074\", \n  \"_rev\" : \"18100826\", \n  \"_key\" : \"17642074\" \n}\n\n

Alternative to header field:

unix> curl -X PUT --data @- --dump - http://localhost:8529/_api/document/products8/20722266\n{}\n\nHTTP/1.1 202 Accepted\ncontent-type: application/json; charset=utf-8\netag: \"21312090\"\nlocation: /_api/document/products8/20722266\n\n{ \n  \"error\" : false, \n  \"_id\" : \"products8/20722266\", \n  \"_rev\" : \"21312090\", \n  \"_key\" : \"20722266\" \n}\n\n

", + "examples": "Using document handle:

unix> curl -X PUT --data @- --dump - http://localhost:8529/_api/document/products/32653735\n{}\n\n

Unknown document handle:

unix> curl -X PUT --data @- --dump - http://localhost:8529/_api/document/products/35799463\n{}\n\n

Produce a revision conflict:

unix> curl -X PUT --data @- --dump - http://localhost:8529/_api/document/products/27410855\n{}\n\n

Last write wins:

unix> curl -X PUT --data @- --dump - http://localhost:8529/_api/document/products/22757799\n{}\n\n

Alternative to header field:

unix> curl -X PUT --data @- --dump - http://localhost:8529/_api/document/products/25903527\n{}\n\n

", "nickname": "replacesADocument" } ], diff --git a/html/admin/api-docs/system b/html/admin/api-docs/system index 2f3db76f8b..cf1d475ace 100644 --- a/html/admin/api-docs/system +++ b/html/admin/api-docs/system @@ -102,6 +102,28 @@ } ], "path": "/_admin/statistics-description" + }, + { + "operations": [ + { + "errorResponses": [], + "parameters": [ + { + "dataType": "String", + "paramType": "body", + "required": "false", + "name": "body", + "description": "A valid json document for your data, for instance {\"hello\": \"world\"}." + } + ], + "notes": "", + "summary": "executes a program", + "httpMethod": "POST", + "examples": "", + "nickname": "executesAProgram" + } + ], + "path": "/_admin/execute" } ] } diff --git a/lib/SimpleHttpClient/SimpleHttpClient.cpp b/lib/SimpleHttpClient/SimpleHttpClient.cpp index ecf603971f..5fa90fd927 100644 --- a/lib/SimpleHttpClient/SimpleHttpClient.cpp +++ b/lib/SimpleHttpClient/SimpleHttpClient.cpp @@ -227,9 +227,15 @@ namespace triagens { _writeBuffer.appendText(l); _writeBuffer.appendText(" HTTP/1.1\r\n"); + string hostname = _connection->getEndpoint()->getHostString(); + if (hostname.find(':') != string::npos) { + hostname = hostname.substr(0, hostname.find(':')); + } + _writeBuffer.appendText("Host: "); - _writeBuffer.appendText(_connection->getEndpoint()->getHostString()); + _writeBuffer.appendText(hostname); _writeBuffer.appendText("\r\n"); + _writeBuffer.appendText("Connection: Keep-Alive\r\n"); _writeBuffer.appendText("User-Agent: VOC-Client/1.0\r\n"); @@ -263,9 +269,14 @@ namespace triagens { _writeBuffer.appendText("\r\n"); } - _writeBuffer.appendText("Content-Length: "); - _writeBuffer.appendInteger(bodyLength); - _writeBuffer.appendText("\r\n\r\n"); + if (method != HttpRequest::HTTP_REQUEST_GET) { + _writeBuffer.appendText("Content-Length: "); + _writeBuffer.appendInteger(bodyLength); + _writeBuffer.appendText("\r\n\r\n"); + } + else { + _writeBuffer.appendText("\r\n"); + } _writeBuffer.appendText(body, bodyLength); LOGGER_TRACE("Request: " << _writeBuffer.c_str());