diff --git a/docs/api/context.md b/docs/api/context.md
index dbc5098..912afc8 100644
--- a/docs/api/context.md
+++ b/docs/api/context.md
@@ -190,6 +190,7 @@ koa uses [http-assert](https://github.com/jshttp/http-assert) for assertions.
- `ctx.redirect()`
- `ctx.attachment()`
- `ctx.set()`
+ - `ctx.append()`
- `ctx.remove()`
- `ctx.lastModified=`
- `ctx.etag=`
diff --git a/docs/api/response.md b/docs/api/response.md
index acd88ad..408e32d 100644
--- a/docs/api/response.md
+++ b/docs/api/response.md
@@ -151,6 +151,13 @@ var etag = this.get('ETag');
this.set('Cache-Control', 'no-cache');
```
+### response.append(field, value)
+ Append additional header `field` with value `val`.
+
+```js
+this.append('Link', '');
+```
+
### response.set(fields)
Set several response header `fields` with an object:
diff --git a/lib/context.js b/lib/context.js
index 7fa2eeb..e81077c 100644
--- a/lib/context.js
+++ b/lib/context.js
@@ -147,6 +147,7 @@ delegate(proto, 'response')
.method('remove')
.method('vary')
.method('set')
+ .method('append')
.access('status')
.access('message')
.access('body')
diff --git a/lib/response.js b/lib/response.js
index 26e979d..3ea3727 100644
--- a/lib/response.js
+++ b/lib/response.js
@@ -424,6 +424,33 @@ module.exports = {
}
},
+ /**
+ * Append additional header `field` with value `val`.
+ *
+ * Examples:
+ *
+ * this.append('Link', ['', '']);
+ * this.append('Set-Cookie', 'foo=bar; Path=/; HttpOnly');
+ * this.append('Warning', '199 Miscellaneous warning');
+ *
+ * @param {String} field
+ * @param {String|Array} val
+ * @api public
+ */
+
+ append: function(field, val){
+ var prev = this.get(field);
+ var value = val;
+ if (prev) {
+ // concat the new and prev vals
+ value = Array.isArray(prev) ? prev.concat(val)
+ : Array.isArray(val) ? [prev].concat(val)
+ : [prev, val];
+ }
+
+ return this.set(field, value);
+ },
+
/**
* Remove header `field`.
*
diff --git a/test/response/append.js b/test/response/append.js
new file mode 100644
index 0000000..4f3cd89
--- /dev/null
+++ b/test/response/append.js
@@ -0,0 +1,38 @@
+
+var context = require('../context');
+
+describe('ctx.append(name, val)', function(){
+ it('should append multiple headers', function(){
+ var ctx = context();
+ ctx.append('x-foo', 'bar1');
+ ctx.append('x-foo', 'bar2');
+ ctx.response.header['x-foo'].should.eql(['bar1', 'bar2']);
+ })
+
+ it('should accept array of values', function (){
+ var ctx = context();
+
+ ctx.append('Set-Cookie', ['foo=bar', 'fizz=buzz']);
+ ctx.response.header['set-cookie'].should.eql(['foo=bar', 'fizz=buzz']);
+ })
+
+ it('should get reset by res.set(field, val)', function (){
+ var ctx = context();
+
+ ctx.append('Link', '');
+ ctx.append('Link', '');
+
+ ctx.set('Link', '');
+
+ ctx.response.header.link.should.equal('');
+ })
+
+ it('should work with res.set(field, val) first', function (){
+ var ctx = context();
+
+ ctx.set('Link', '');
+ ctx.append('Link', '');
+
+ ctx.response.header.link.should.eql(['', '']);
+ })
+})