PageRenderTime 50ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/share/www/script/test/rewrite.js

http://github.com/apache/couchdb
JavaScript | 477 lines | 406 code | 50 blank | 21 comment | 47 complexity | 90dc0971b383148fd736d1d892a75621 MD5 | raw file
Possible License(s): BSD-3-Clause, Apache-2.0
  1. // Licensed under the Apache License, Version 2.0 (the "License"); you may not
  2. // use this file except in compliance with the License. You may obtain a copy of
  3. // the License at
  4. //
  5. // http://www.apache.org/licenses/LICENSE-2.0
  6. //
  7. // Unless required by applicable law or agreed to in writing, software
  8. // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  9. // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  10. // License for the specific language governing permissions and limitations under
  11. // the License.
  12. couchTests.rewrite = function(debug) {
  13. if (debug) debugger;
  14. var dbNames = ["test_suite_db", "test_suite_db/with_slashes"];
  15. for (var i=0; i < dbNames.length; i++) {
  16. var db = new CouchDB(dbNames[i]);
  17. var dbName = encodeURIComponent(dbNames[i]);
  18. db.deleteDb();
  19. db.createDb();
  20. run_on_modified_server(
  21. [{section: "httpd",
  22. key: "authentication_handlers",
  23. value: "{couch_httpd_auth, special_test_authentication_handler}"},
  24. {section:"httpd",
  25. key: "WWW-Authenticate",
  26. value: "X-Couch-Test-Auth"}],
  27. function(){
  28. var designDoc = {
  29. _id:"_design/test",
  30. language: "javascript",
  31. _attachments:{
  32. "foo.txt": {
  33. content_type:"text/plain",
  34. data: "VGhpcyBpcyBhIGJhc2U2NCBlbmNvZGVkIHRleHQ="
  35. }
  36. },
  37. rewrites: [
  38. {
  39. "from": "foo",
  40. "to": "foo.txt"
  41. },
  42. {
  43. "from": "foo2",
  44. "to": "foo.txt",
  45. "method": "GET"
  46. },
  47. {
  48. "from": "hello/:id",
  49. "to": "_update/hello/:id",
  50. "method": "PUT"
  51. },
  52. {
  53. "from": "/welcome",
  54. "to": "_show/welcome"
  55. },
  56. {
  57. "from": "/welcome/:name",
  58. "to": "_show/welcome",
  59. "query": {
  60. "name": ":name"
  61. }
  62. },
  63. {
  64. "from": "/welcome2",
  65. "to": "_show/welcome",
  66. "query": {
  67. "name": "user"
  68. }
  69. },
  70. {
  71. "from": "/welcome3/:name",
  72. "to": "_update/welcome2/:name",
  73. "method": "PUT"
  74. },
  75. {
  76. "from": "/welcome3/:name",
  77. "to": "_show/welcome2/:name",
  78. "method": "GET"
  79. },
  80. {
  81. "from": "/welcome4/*",
  82. "to" : "_show/welcome3",
  83. "query": {
  84. "name": "*"
  85. }
  86. },
  87. {
  88. "from": "/welcome5/*",
  89. "to" : "_show/*",
  90. "query": {
  91. "name": "*"
  92. }
  93. },
  94. {
  95. "from": "basicView",
  96. "to": "_view/basicView",
  97. },
  98. {
  99. "from": "simpleForm/basicView",
  100. "to": "_list/simpleForm/basicView",
  101. },
  102. {
  103. "from": "simpleForm/basicViewFixed",
  104. "to": "_list/simpleForm/basicView",
  105. "query": {
  106. "startkey": 3,
  107. "endkey": 8
  108. }
  109. },
  110. {
  111. "from": "simpleForm/basicViewPath/:start/:end",
  112. "to": "_list/simpleForm/basicView",
  113. "query": {
  114. "startkey": ":start",
  115. "endkey": ":end"
  116. },
  117. "formats": {
  118. "start": "int",
  119. "end": "int"
  120. }
  121. },
  122. {
  123. "from": "simpleForm/complexView",
  124. "to": "_list/simpleForm/complexView",
  125. "query": {
  126. "key": [1, 2]
  127. }
  128. },
  129. {
  130. "from": "simpleForm/complexView2",
  131. "to": "_list/simpleForm/complexView",
  132. "query": {
  133. "key": ["test", {}]
  134. }
  135. },
  136. {
  137. "from": "simpleForm/complexView3",
  138. "to": "_list/simpleForm/complexView",
  139. "query": {
  140. "key": ["test", ["test", "essai"]]
  141. }
  142. },
  143. {
  144. "from": "simpleForm/complexView4",
  145. "to": "_list/simpleForm/complexView2",
  146. "query": {
  147. "key": {"c": 1}
  148. }
  149. },
  150. {
  151. "from": "simpleForm/complexView5/:a/:b",
  152. "to": "_list/simpleForm/complexView3",
  153. "query": {
  154. "key": [":a", ":b"]
  155. }
  156. },
  157. {
  158. "from": "simpleForm/complexView6",
  159. "to": "_list/simpleForm/complexView3",
  160. "query": {
  161. "key": [":a", ":b"]
  162. }
  163. },
  164. {
  165. "from": "simpleForm/complexView7/:a/:b",
  166. "to": "_view/complexView3",
  167. "query": {
  168. "key": [":a", ":b"],
  169. "include_docs": ":doc"
  170. },
  171. "format": {
  172. "doc": "bool"
  173. }
  174. },
  175. {
  176. "from": "/",
  177. "to": "_view/basicView",
  178. }
  179. ],
  180. lists: {
  181. simpleForm: stringFun(function(head, req) {
  182. log("simpleForm");
  183. send('<ul>');
  184. var row, row_number = 0, prevKey, firstKey = null;
  185. while (row = getRow()) {
  186. row_number += 1;
  187. if (!firstKey) firstKey = row.key;
  188. prevKey = row.key;
  189. send('\n<li>Key: '+row.key
  190. +' Value: '+row.value
  191. +' LineNo: '+row_number+'</li>');
  192. }
  193. return '</ul><p>FirstKey: '+ firstKey + ' LastKey: '+ prevKey+'</p>';
  194. }),
  195. },
  196. shows: {
  197. "welcome": stringFun(function(doc,req) {
  198. return "Welcome " + req.query["name"];
  199. }),
  200. "welcome2": stringFun(function(doc, req) {
  201. return "Welcome " + doc.name;
  202. }),
  203. "welcome3": stringFun(function(doc,req) {
  204. return "Welcome " + req.query["name"];
  205. })
  206. },
  207. updates: {
  208. "hello" : stringFun(function(doc, req) {
  209. if (!doc) {
  210. if (req.id) {
  211. return [{
  212. _id : req.id
  213. }, "New World"]
  214. }
  215. return [null, "Empty World"];
  216. }
  217. doc.world = "hello";
  218. doc.edited_by = req.userCtx;
  219. return [doc, "hello doc"];
  220. }),
  221. "welcome2": stringFun(function(doc, req) {
  222. if (!doc) {
  223. if (req.id) {
  224. return [{
  225. _id: req.id,
  226. name: req.id
  227. }, "New World"]
  228. }
  229. return [null, "Empty World"];
  230. }
  231. return [doc, "hello doc"];
  232. })
  233. },
  234. views : {
  235. basicView : {
  236. map : stringFun(function(doc) {
  237. if (doc.integer) {
  238. emit(doc.integer, doc.string);
  239. }
  240. })
  241. },
  242. complexView: {
  243. map: stringFun(function(doc) {
  244. if (doc.type == "complex") {
  245. emit([doc.a, doc.b], doc.string);
  246. }
  247. })
  248. },
  249. complexView2: {
  250. map: stringFun(function(doc) {
  251. if (doc.type == "complex") {
  252. emit(doc.a, doc.string);
  253. }
  254. })
  255. },
  256. complexView3: {
  257. map: stringFun(function(doc) {
  258. if (doc.type == "complex") {
  259. emit(doc.b, doc.string);
  260. }
  261. })
  262. }
  263. }
  264. }
  265. db.save(designDoc);
  266. var docs = makeDocs(0, 10);
  267. db.bulkSave(docs);
  268. var docs2 = [
  269. {"a": 1, "b": 1, "string": "doc 1", "type": "complex"},
  270. {"a": 1, "b": 2, "string": "doc 2", "type": "complex"},
  271. {"a": "test", "b": {}, "string": "doc 3", "type": "complex"},
  272. {"a": "test", "b": ["test", "essai"], "string": "doc 4", "type": "complex"},
  273. {"a": {"c": 1}, "b": "", "string": "doc 5", "type": "complex"}
  274. ];
  275. db.bulkSave(docs2);
  276. // test simple rewriting
  277. req = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/foo");
  278. T(req.responseText == "This is a base64 encoded text");
  279. T(req.getResponseHeader("Content-Type") == "text/plain");
  280. req = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/foo2");
  281. T(req.responseText == "This is a base64 encoded text");
  282. T(req.getResponseHeader("Content-Type") == "text/plain");
  283. // test POST
  284. // hello update world
  285. var doc = {"word":"plankton", "name":"Rusty"}
  286. var resp = db.save(doc);
  287. T(resp.ok);
  288. var docid = resp.id;
  289. xhr = CouchDB.request("PUT", "/"+dbName+"/_design/test/_rewrite/hello/"+docid);
  290. T(xhr.status == 201);
  291. T(xhr.responseText == "hello doc");
  292. T(/charset=utf-8/.test(xhr.getResponseHeader("Content-Type")))
  293. doc = db.open(docid);
  294. T(doc.world == "hello");
  295. req = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/welcome?name=user");
  296. T(req.responseText == "Welcome user");
  297. req = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/welcome/user");
  298. T(req.responseText == "Welcome user");
  299. req = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/welcome2");
  300. T(req.responseText == "Welcome user");
  301. xhr = CouchDB.request("PUT", "/"+dbName+"/_design/test/_rewrite/welcome3/test");
  302. T(xhr.status == 201);
  303. T(xhr.responseText == "New World");
  304. T(/charset=utf-8/.test(xhr.getResponseHeader("Content-Type")));
  305. xhr = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/welcome3/test");
  306. T(xhr.responseText == "Welcome test");
  307. req = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/welcome4/user");
  308. T(req.responseText == "Welcome user");
  309. req = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/welcome5/welcome3");
  310. T(req.responseText == "Welcome welcome3");
  311. xhr = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/basicView");
  312. T(xhr.status == 200, "view call");
  313. T(/{"total_rows":9/.test(xhr.responseText));
  314. xhr = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/");
  315. T(xhr.status == 200, "view call");
  316. T(/{"total_rows":9/.test(xhr.responseText));
  317. // get with query params
  318. xhr = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/simpleForm/basicView?startkey=3&endkey=8");
  319. T(xhr.status == 200, "with query params");
  320. T(!(/Key: 1/.test(xhr.responseText)));
  321. T(/FirstKey: 3/.test(xhr.responseText));
  322. T(/LastKey: 8/.test(xhr.responseText));
  323. xhr = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/simpleForm/basicViewFixed");
  324. T(xhr.status == 200, "with query params");
  325. T(!(/Key: 1/.test(xhr.responseText)));
  326. T(/FirstKey: 3/.test(xhr.responseText));
  327. T(/LastKey: 8/.test(xhr.responseText));
  328. // get with query params
  329. xhr = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/simpleForm/basicViewFixed?startkey=4");
  330. T(xhr.status == 200, "with query params");
  331. T(!(/Key: 1/.test(xhr.responseText)));
  332. T(/FirstKey: 3/.test(xhr.responseText));
  333. T(/LastKey: 8/.test(xhr.responseText));
  334. // get with query params
  335. xhr = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/simpleForm/basicViewPath/3/8");
  336. T(xhr.status == 200, "with query params");
  337. T(!(/Key: 1/.test(xhr.responseText)));
  338. T(/FirstKey: 3/.test(xhr.responseText));
  339. T(/LastKey: 8/.test(xhr.responseText));
  340. // get with query params
  341. xhr = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/simpleForm/complexView");
  342. T(xhr.status == 200, "with query params");
  343. T(/FirstKey: [1, 2]/.test(xhr.responseText));
  344. xhr = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/simpleForm/complexView2");
  345. T(xhr.status == 200, "with query params");
  346. T(/Value: doc 3/.test(xhr.responseText));
  347. xhr = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/simpleForm/complexView3");
  348. T(xhr.status == 200, "with query params");
  349. T(/Value: doc 4/.test(xhr.responseText));
  350. xhr = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/simpleForm/complexView4");
  351. T(xhr.status == 200, "with query params");
  352. T(/Value: doc 5/.test(xhr.responseText));
  353. xhr = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/simpleForm/complexView5/test/essai");
  354. T(xhr.status == 200, "with query params");
  355. T(/Value: doc 4/.test(xhr.responseText));
  356. xhr = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/simpleForm/complexView6?a=test&b=essai");
  357. T(xhr.status == 200, "with query params");
  358. T(/Value: doc 4/.test(xhr.responseText));
  359. xhr = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/simpleForm/complexView7/test/essai?doc=true");
  360. T(xhr.status == 200, "with query params");
  361. var result = JSON.parse(xhr.responseText);
  362. T(typeof(result.rows[0].doc) === "object");
  363. // test path relative to server
  364. designDoc.rewrites.push({
  365. "from": "uuids",
  366. "to": "../../../_uuids"
  367. });
  368. T(db.save(designDoc).ok);
  369. var xhr = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/uuids");
  370. T(xhr.status == 500);
  371. var result = JSON.parse(xhr.responseText);
  372. T(result.error == "insecure_rewrite_rule");
  373. run_on_modified_server(
  374. [{section: "httpd",
  375. key: "secure_rewrites",
  376. value: "false"}],
  377. function() {
  378. var xhr = CouchDB.request("GET", "/"+dbName+"/_design/test/_rewrite/uuids?cache=bust");
  379. T(xhr.status == 200);
  380. var result = JSON.parse(xhr.responseText);
  381. T(result.uuids.length == 1);
  382. var first = result.uuids[0];
  383. });
  384. });
  385. // test invalid rewrites
  386. // string
  387. var ddoc = {
  388. _id: "_design/invalid",
  389. rewrites: "[{\"from\":\"foo\",\"to\":\"bar\"}]"
  390. }
  391. db.save(ddoc);
  392. var res = CouchDB.request("GET", "/"+dbName+"/_design/invalid/_rewrite/foo");
  393. TEquals(400, res.status, "should return 400");
  394. var ddoc_requested_path = {
  395. _id: "_design/requested_path",
  396. rewrites:[
  397. {"from": "show", "to": "_show/origin/0"},
  398. {"from": "show_rewritten", "to": "_rewrite/show"}
  399. ],
  400. shows: {
  401. origin: stringFun(function(doc, req) {
  402. return req.headers["x-couchdb-requested-path"];
  403. })}
  404. };
  405. db.save(ddoc_requested_path);
  406. var url = "/"+dbName+"/_design/requested_path/_rewrite/show";
  407. var res = CouchDB.request("GET", url);
  408. TEquals(url, res.responseText, "should return the original url");
  409. var url = "/"+dbName+"/_design/requested_path/_rewrite/show_rewritten";
  410. var res = CouchDB.request("GET", url);
  411. TEquals(url, res.responseText, "returned the original url");
  412. var ddoc_loop = {
  413. _id: "_design/loop",
  414. rewrites: [{ "from": "loop", "to": "_rewrite/loop"}]
  415. };
  416. db.save(ddoc_loop);
  417. run_on_modified_server(
  418. [{section: "httpd",
  419. key: "rewrite_limit",
  420. value: "2"}],
  421. function(){
  422. var url = "/"+dbName+"/_design/loop/_rewrite/loop";
  423. var xhr = CouchDB.request("GET", url);
  424. T(xhr.status = 400);
  425. });
  426. }
  427. }