Skip to content

Commit

Permalink
Issue #370 - Parse Link header into object.
Browse files Browse the repository at this point in the history
  • Loading branch information
Mike Taylor committed Nov 12, 2014
1 parent 9cf31e5 commit 8ecbcd4
Showing 1 changed file with 50 additions and 12 deletions.
62 changes: 50 additions & 12 deletions webcompat/static/js/lib/models/issue.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Contains some code modified from https://github.com/jfromaniello/li
* which is released under the MIT license. */

var issues = issues || {};
var issueList = issueList || {};
Expand Down Expand Up @@ -119,22 +122,57 @@ issueList.IssueCollection = Backbone.Collection.extend({
model: issueList.Issue,
url: '/api/issues?page=1',
parse: function(response, jqXHR) {
this.linkHeader = jqXHR.xhr.getResponseHeader('Link');
if (jqXHR.xhr.getResponseHeader('Link') != null) {
//external code can access the parsed header via this.linkHeader
this.linkHeader = this.parseHeader(jqXHR.xhr.getResponseHeader('Link'));
} else {
this.linkHeader = null;
}
return response;

This comment has been minimized.

Copy link
@karlcow

karlcow Nov 13, 2014

Member

(If I understand)
Here the request is done by the JS client to webcompat.com. I'm asking because of later on.

},
getRelValue: function(header, relation) {
parseHeader: function(linkHeader) {
/* Returns an object like so:
{
next: "https://api.github.com/repositories/17839063/issues?page=3",
last: "https://api.github.com/repositories/17839063/issues?page=4",
first: "https://api.github.com/repositories/17839063/issues?page=1",
prev: "https://api.github.com/repositories/17839063/issues?page=1"
} */
var result = {};
var entries = linkHeader.split(',');
var relsRegExp = /\brel="?([^"]+)"?\s*;?/;
var keysRegExp = /(\b[0-9a-z\.-]+\b)/g;
var sourceRegExp = /^<(.*)>/;

for (var i = 0; i < entries.length; i++) {
var entry = entries[i].trim();
var rels = relsRegExp.exec(entry);
if (rels) {
var keys = rels[1].match(keysRegExp);
var source = sourceRegExp.exec(entry)[1];
var k, kLength = keys.length;
for (k = 0; k < kLength; k += 1) {
result[keys[k]] = source
}
}
}

return result;
},
getPageFromRel: function(relation) {
// GitHub will only send us a Link header if pagination is possible.
// if we return early with null, we'll know that next and prev pagination
// should be disabled.
if (header == null) {
if (this.linkHeader == null) {
return null;
}
// we only get the page number, rather than the link href, becuase we still
// need to proxy requests between our server and GitHub's.
var re = new RegExp('page=(\\d)>;\\s+rel=\\"' + relation + '\\"');
var rel;
if (rel = header.match(re)) {
return rel[1];
var page;
// we only return the page number
var re = new RegExp('page=(\\d)');

if (page = (this.linkHeader.hasOwnProperty(relation) &&
this.linkHeader[relation].match(re))) {
return page[1];
} else {
return null;
}
Expand All @@ -143,9 +181,9 @@ issueList.IssueCollection = Backbone.Collection.extend({
return this.getRelValue(this.linkHeader, 'last');
},
getNextPageNumber: function() {
return this.getRelValue(this.linkHeader, 'next');
return this.getPageFromRel('next');
},
getPreviousPageNumber: function() {
return this.getRelValue(this.linkHeader, 'prev');
return this.getPageFromRel('prev');
}
});

1 comment on commit 8ecbcd4

@karlcow
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the request goes through webcompat.com. Would not it be easier to send directly this information from Webcompat.com? Just asking.

Please sign in to comment.