Repository: expressjs/express (JavaScript)

Issue:
Extend res.links() to allow adding multiple links with the same rel
Currently, `res.links` allows to only add a single link per rel per call. One can add multiple link with the same rel through calling `res.links` multiple times. #2575 would also allow to add multiple links with the same call. Both of these methods are, however, quite cumbersome when one wants to simply add multiple links with the same rel and without optional parameters.

A possible alternative would be to allow the following:

``` js
res.links({
  self: '/a',
  item: ['/a/0', '/a/1']
})
```

Note that this would currently result in `Link: </a>; rel="self", </a/0,/a/1>; rel="item"`, which is incorrect - the path may contain commas, so /a/0,/a/1 is a single path. The expected result would be `Link: </a>; rel="self", </a/0>; rel="item", </a/1>; rel="item"`.



Discussion:

Patch:
diff --git a/History.md b/History.md
index 021315c5ab9..98cfb14c259 100644
--- a/History.md
+++ b/History.md
@@ -11,6 +11,7 @@ unreleased
 * Remove unused `depd` dependency
 * Add support for `Uint8Array` in `res.send`
 * Add support for ETag option in res.sendFile
+* Extend res.links() to allow adding multiple links with the same rel
 * deps: debug@^4.4.0
 * deps: body-parser@^2.1.0
 * deps: router@^2.1.0
diff --git a/lib/response.js b/lib/response.js
index b1dfcb23350..9362d0ed5dd 100644
--- a/lib/response.js
+++ b/lib/response.js
@@ -80,7 +80,11 @@ res.status = function status(code) {
  *
  *    res.links({
  *      next: 'http://api.example.com/users?page=2',
- *      last: 'http://api.example.com/users?page=5'
+ *      last: 'http://api.example.com/users?page=5',
+ *      pages: [
+ *        'http://api.example.com/users?page=1',
+ *        'http://api.example.com/users?page=2'
+ *      ]
  *    });
  *
  * @param {Object} links
@@ -88,11 +92,18 @@ res.status = function status(code) {
  * @public
  */
 
-res.links = function(links){
+res.links = function(links) {
   var link = this.get('Link') || '';
   if (link) link += ', ';
-  return this.set('Link', link + Object.keys(links).map(function(rel){
-    return '<' + links[rel] + '>; rel="' + rel + '"';
+  return this.set('Link', link + Object.keys(links).map(function(rel) {
+    // Allow multiple links if links[rel] is an array
+    if (Array.isArray(links[rel])) {
+      return links[rel].map(function (singleLink) {
+        return `<${singleLink}>; rel="${rel}"`;
+      }).join(', ');
+    } else {
+      return `<${links[rel]}>; rel="${rel}"`;
+    }
   }).join(', '));
 };
 


Test patch:
diff --git a/test/res.links.js b/test/res.links.js
index 240b7fcfda3..40665fd558a 100644
--- a/test/res.links.js
+++ b/test/res.links.js
@@ -43,5 +43,23 @@ describe('res', function(){
       .expect('Link', '<http://api.example.com/users?page=2>; rel="next", <http://api.example.com/users?page=5>; rel="last", <http://api.example.com/users?page=1>; rel="prev"')
       .expect(200, done);
     })
+
+    it('should set multiple links for single rel', function (done) {
+      var app = express();
+
+      app.use(function (req, res) {
+        res.links({
+          next: 'http://api.example.com/users?page=2',
+          last: ['http://api.example.com/users?page=5', 'http://api.example.com/users?page=1']
+        });
+
+        res.end();
+      });
+
+      request(app)
+      .get('/')
+      .expect('Link', '<http://api.example.com/users?page=2>; rel="next", <http://api.example.com/users?page=5>; rel="last", <http://api.example.com/users?page=1>; rel="last"')
+      .expect(200, done);
+    })
   })
 })