vendor github.com/tent/http-link-go

This commit is contained in:
andrewsykim 2017-07-09 23:42:26 -04:00
parent e15bcba149
commit 36b51a851e
8 changed files with 302 additions and 0 deletions

3
.gitmodules vendored
View File

@ -319,3 +319,6 @@
[submodule "_vendor/github.com/google/go-querystring"]
path = _vendor/github.com/google/go-querystring
url = https://github.com/google/go-querystring.git
[submodule "_vendor/github.com/tent/http-link-go"]
path = _vendor/github.com/tent/http-link-go
url = https://github.com/tent/http-link-go.git

1
_vendor/github.com/tent/http-link-go generated Submodule

@ -0,0 +1 @@
Subproject commit ac974c61c2f990f4115b119354b5e0b47550e888

1
vendor/github.com/tent/http-link-go/.gitignore generated vendored Normal file
View File

@ -0,0 +1 @@
*.test

6
vendor/github.com/tent/http-link-go/.travis.yml generated vendored Normal file
View File

@ -0,0 +1,6 @@
language: go
go:
- 1.1
- tip
before_install:
- go get launchpad.net/gocheck

27
vendor/github.com/tent/http-link-go/LICENSE generated vendored Normal file
View File

@ -0,0 +1,27 @@
Copyright (c) 2013 Tent.is, LLC. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Tent.is, LLC nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

12
vendor/github.com/tent/http-link-go/README.md generated vendored Normal file
View File

@ -0,0 +1,12 @@
# http-link-go [![Build Status](https://travis-ci.org/tent/http-link-go.png?branch=master)](https://travis-ci.org/tent/http-link-go)
http-link-go implements parsing and serialization of Link header values as
defined in [RFC 5988](https://tools.ietf.org/html/rfc5988).
[**Documentation**](http://godoc.org/github.com/tent/http-link-go)
## Installation
```text
go get github.com/tent/http-link-go
```

185
vendor/github.com/tent/http-link-go/link.go generated vendored Normal file
View File

@ -0,0 +1,185 @@
// Package link implements parsing and serialization of Link header values as
// defined in RFC 5988.
package link
import (
"bytes"
"errors"
"sort"
"unicode"
)
type Link struct {
URI string
Rel string
Params map[string]string
}
// Format serializes a slice of Links into a header value. It does not currently
// implement RFC 2231 handling of non-ASCII character encoding and language
// information.
func Format(links []Link) string {
buf := &bytes.Buffer{}
for i, link := range links {
if i > 0 {
buf.Write([]byte(", "))
}
buf.WriteByte('<')
buf.WriteString(link.URI)
buf.WriteByte('>')
writeParam(buf, "rel", link.Rel)
keys := make([]string, 0, len(link.Params))
for k := range link.Params {
keys = append(keys, k)
}
sort.Strings(keys)
for _, k := range keys {
writeParam(buf, k, link.Params[k])
}
}
return buf.String()
}
func writeParam(buf *bytes.Buffer, key, value string) {
buf.Write([]byte("; "))
buf.WriteString(key)
buf.Write([]byte(`="`))
buf.WriteString(value)
buf.WriteByte('"')
}
// Parse parses a Link header value into a slice of Links. It does not currently
// implement RFC 2231 handling of non-ASCII character encoding and language
// information.
func Parse(l string) ([]Link, error) {
v := []byte(l)
v = bytes.TrimSpace(v)
if len(v) == 0 {
return nil, nil
}
links := make([]Link, 0, 1)
for len(v) > 0 {
if v[0] != '<' {
return nil, errors.New("link: does not start with <")
}
lend := bytes.IndexByte(v, '>')
if lend == -1 {
return nil, errors.New("link: does not contain ending >")
}
params := make(map[string]string)
link := Link{URI: string(v[1:lend]), Params: params}
links = append(links, link)
// trim off parsed url
v = v[lend+1:]
if len(v) == 0 {
break
}
v = bytes.TrimLeftFunc(v, unicode.IsSpace)
for len(v) > 0 {
if v[0] != ';' && v[0] != ',' {
return nil, errors.New(`link: expected ";" or "'", got "` + string(v[0:1]) + `"`)
}
var next bool
if v[0] == ',' {
next = true
}
v = bytes.TrimLeftFunc(v[1:], unicode.IsSpace)
if next || len(v) == 0 {
break
}
var key, value []byte
key, value, v = consumeParam(v)
if key == nil || value == nil {
return nil, errors.New("link: malformed param")
}
if k := string(key); k == "rel" {
if links[len(links)-1].Rel == "" {
links[len(links)-1].Rel = string(value)
}
} else {
params[k] = string(value)
}
v = bytes.TrimLeftFunc(v, unicode.IsSpace)
}
}
return links, nil
}
func isTokenChar(r rune) bool {
return r > 0x20 && r < 0x7f && r != '"' && r != ',' && r != '=' && r != ';'
}
func isNotTokenChar(r rune) bool { return !isTokenChar(r) }
func consumeToken(v []byte) (token, rest []byte) {
notPos := bytes.IndexFunc(v, isNotTokenChar)
if notPos == -1 {
return v, nil
}
if notPos == 0 {
return nil, v
}
return v[0:notPos], v[notPos:]
}
func consumeValue(v []byte) (value, rest []byte) {
if v[0] != '"' {
return nil, v
}
rest = v[1:]
buffer := &bytes.Buffer{}
var nextIsLiteral bool
for idx, r := range string(rest) {
switch {
case nextIsLiteral:
buffer.WriteRune(r)
nextIsLiteral = false
case r == '"':
return buffer.Bytes(), rest[idx+1:]
case r == '\\':
nextIsLiteral = true
case r != '\r' && r != '\n':
buffer.WriteRune(r)
default:
return nil, v
}
}
return nil, v
}
func consumeParam(v []byte) (param, value, rest []byte) {
param, rest = consumeToken(v)
param = bytes.ToLower(param)
if param == nil {
return nil, nil, v
}
rest = bytes.TrimLeftFunc(rest, unicode.IsSpace)
if len(rest) == 0 || rest[0] != '=' {
return nil, nil, v
}
rest = rest[1:] // consume equals sign
rest = bytes.TrimLeftFunc(rest, unicode.IsSpace)
if len(rest) == 0 {
return nil, nil, v
}
if rest[0] != '"' {
value, rest = consumeToken(rest)
} else {
value, rest = consumeValue(rest)
}
if value == nil {
return nil, nil, v
}
return param, value, rest
}

67
vendor/github.com/tent/http-link-go/link_test.go generated vendored Normal file
View File

@ -0,0 +1,67 @@
package link
import (
"testing"
. "launchpad.net/gocheck"
)
// Hook up gocheck into the "go test" runner.
func Test(t *testing.T) { TestingT(t) }
type LinkSuite struct{}
var _ = Suite(&LinkSuite{})
// TODO: add more tests
var linkParseTests = []struct {
in string
out []Link
}{
{
"<http://example.com/TheBook/chapter2>; rel=\"previous\";\n title=\"previous chapter\"",
[]Link{{URI: "http://example.com/TheBook/chapter2", Rel: "previous", Params: map[string]string{"title": "previous chapter"}}},
},
{
"</TheBook/chapter2>;\n rel=\"previous\"; title*=UTF-8'de'letztes%20Kapitel,\n </TheBook/chapter4>;\n rel=\"next\"; title*=UTF-8'de'n%c3%a4chstes%20Kapitel",
[]Link{
{URI: "/TheBook/chapter2", Rel: "previous", Params: map[string]string{"title*": "UTF-8'de'letztes%20Kapitel"}},
{URI: "/TheBook/chapter4", Rel: "next", Params: map[string]string{"title*": "UTF-8'de'n%c3%a4chstes%20Kapitel"}},
},
},
}
func (s *LinkSuite) TestLinkParsing(c *C) {
for i, t := range linkParseTests {
res, err := Parse(t.in)
c.Assert(err, IsNil, Commentf("test %d", i))
c.Assert(res, DeepEquals, t.out, Commentf("test %d", i))
}
}
var linkFormatTests = []struct {
in []Link
out string
}{
{
[]Link{{URI: "/a", Rel: "foo", Params: map[string]string{"a": "b", "c": "d"}}},
`</a>; rel="foo"; a="b"; c="d"`,
},
{
[]Link{
{URI: "/b", Rel: "foo", Params: map[string]string{"a": "b", "c": "d"}},
{URI: "/a", Rel: "foo", Params: map[string]string{"a": "b", "c": "d"}}},
`</b>; rel="foo"; a="b"; c="d", </a>; rel="foo"; a="b"; c="d"`,
},
}
func (s *LinkSuite) TestLinkGeneration(c *C) {
for i, t := range linkFormatTests {
res := Format(t.in)
cm := Commentf("test %d", i)
c.Assert(res, Equals, t.out, cm)
parsed, err := Parse(res)
c.Assert(err, IsNil, cm)
c.Assert(parsed, DeepEquals, t.in, cm)
}
}