Created
December 6, 2014 04:29
-
-
Save lusis/6f0b7e925da747d8bd2c to your computer and use it in GitHub Desktop.
Parsing the Link HTTP header with lpeg
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local lpeg = require 'lpeg' | |
local P, C, R, S, Cs, Cc, Ct, Cf, Cg, V, Cmt = lpeg.P, lpeg.C, lpeg.R, lpeg.S, lpeg.Cs, lpeg.Cc, lpeg.Ct, lpeg.Cf, lpeg.Cg, lpeg.V, lpeg.Cmt | |
local lpegmatch, lpegpatterns, replacer = lpeg.match, lpeg.patterns, lpeg.replacer | |
local inspect = require 'inspect' | |
local link_header = '<https://api.github.com/organizations/XXXXXXX/members?per_page=10&page=2>; rel="next", <https://api.github.com/organizations/XXXXXX/members?per_page=10&page=6>; rel="last"' | |
-- This is our placeholder for matches | |
local links = links or {} | |
-- As we get a table match, we add a new entry to the links table in the format of: | |
-- { reltype = "target" } | |
local function build_pagination(t1) | |
links[t1.rel] = t1.url | |
return t1 | |
end | |
-- link headers look like so: | |
-- <someurl>; rel="sometype" | |
-- multiple links can be joined together with commas: | |
-- <someurl1>; rel="foo",<someurl2>; rel="bar" | |
-- | |
local openbracket = P("<") | |
local closebracket = P(">") | |
local semicolon = P(";") | |
local equal = P("=") | |
local comma = P(",") | |
local quote = P('"') | |
local endofstring = P(-1) | |
local nothing = Cc("") | |
local whitespace = P(" ")^1 | |
-- target is the url in in between <> | |
local target = Cg(((P(1) - closebracket)^-0), "url") | |
-- reltype is the value for rel | |
local reltype = Cg(((P(1) - quote)^-0), "rel") | |
-- Make a capture table of one match | |
-- { rel = "next", url = "https://....." } | |
local match_one = Ct((whitespace)^0 * openbracket * target * closebracket * semicolon * (whitespace)^0 * "rel=" * quote * reltype * quote * (whitespace)^0 * (comma)^0) | |
-- apply function to one match | |
local linkwfunc = (match_one / build_pagination) | |
-- make a capture table of one or more matches | |
local match_any = Ct((linkwfunc)^1) | |
-- do the match | |
match_links = lpegmatch(match_any, link_header) | |
print(inspect(links)) | |
-- returns | |
-- { | |
-- last = "https://api.github.com/organizations/XXXXXX/members?per_page=10&page=6", | |
-- next = "https://api.github.com/organizations/XXXXXXX/members?per_page=10&page=2" | |
-- } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment