add better generate

Signed-off-by: Jess Frazelle <acidburn@microsoft.com>
This commit is contained in:
Jess Frazelle 2018-03-20 01:33:56 -04:00
parent 3fc6abf56b
commit cdd93563f5
5655 changed files with 1187011 additions and 392 deletions

7
vendor/github.com/peterhellberg/link/.travis.yml generated vendored Normal file
View file

@ -0,0 +1,7 @@
language: go
go:
- 1.6
- 1.5.3
sudo: false

81
vendor/github.com/peterhellberg/link/README.md generated vendored Normal file
View file

@ -0,0 +1,81 @@
# link
[![Build Status](https://travis-ci.org/peterhellberg/link.svg?branch=master)](https://travis-ci.org/peterhellberg/link)
[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg?style=flat)](https://godoc.org/github.com/peterhellberg/link)
[![License MIT](https://img.shields.io/badge/license-MIT-lightgrey.svg?style=flat)](https://github.com/peterhellberg/link#license-mit)
Parses **Link** headers used for pagination, as defined in [RFC 5988](https://tools.ietf.org/html/rfc5988).
This package was originally based on <https://github.com/swhite24/link>, but **Parse** takes a `string` instead of `*http.Request` in this version.
It also has the convenience functions **ParseHeader**, **ParseRequest** and **ParseResponse**.
## Installation
go get -u github.com/peterhellberg/link
## Exported functions
- [Parse(s string) Group](https://godoc.org/github.com/peterhellberg/link#Parse)
- [ParseHeader(h http.Header) Group](https://godoc.org/github.com/peterhellberg/link#ParseHeader)
- [ParseRequest(req \*http.Request) Group](https://godoc.org/github.com/peterhellberg/link#ParseRequest)
- [ParseResponse(resp \*http.Response) Group](https://godoc.org/github.com/peterhellberg/link#ParseResponse)
## Usage
```go
package main
import (
"fmt"
"net/http"
"github.com/peterhellberg/link"
)
func main() {
for _, l := range link.Parse(`<https://example.com/?page=2>; rel="next"; foo="bar"`) {
fmt.Printf("URI: %q, Rel: %q, Extra: %+v\n", l.URI, l.Rel, l.Extra)
// URI: "https://example.com/?page=2", Rel: "next", Extra: map[foo:bar]
}
if resp, err := http.Get("https://api.github.com/search/code?q=Println+user:golang"); err == nil {
for _, l := range link.ParseResponse(resp) {
fmt.Printf("URI: %q, Rel: %q, Extra: %+v\n", l.URI, l.Rel, l.Extra)
// URI: "https://api.github.com/search/code?q=Println+user%3Agolang&page=2", Rel: "next", Extra: map[]
// URI: "https://api.github.com/search/code?q=Println+user%3Agolang&page=34", Rel: "last", Extra: map[]
}
}
}
```
## Not supported
- Extended notation ([RFC 5987](https://tools.ietf.org/html/rfc5987))
## Alternatives to this package
- [github.com/tent/http-link-go](https://github.com/tent/http-link-go)
- [github.com/swhite24/link](https://github.com/swhite24/link)
## License (MIT)
Copyright (c) 2015-2016 [Peter Hellberg](http://c7.se/)
> Permission is hereby granted, free of charge, to any person obtaining
> a copy of this software and associated documentation files (the
> "Software"), to deal in the Software without restriction, including
> without limitation the rights to use, copy, modify, merge, publish,
> distribute, sublicense, and/or sell copies of the Software, and to
> permit persons to whom the Software is furnished to do so, subject to
> the following conditions:
> The above copyright notice and this permission notice shall be
> included in all copies or substantial portions of the Software.
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
> NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
> LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
> OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
> WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

40
vendor/github.com/peterhellberg/link/doc.go generated vendored Normal file
View file

@ -0,0 +1,40 @@
/*
Package link parses Link headers used for pagination, as defined in RFC 5988
Installation
Just go get the package:
go get -u github.com/peterhellberg/link
Usage
A small usage example
package main
import (
"fmt"
"net/http"
"github.com/peterhellberg/link"
)
func main() {
for _, l := range link.Parse(`<https://example.com/?page=2>; rel="next"; foo="bar"`) {
fmt.Printf("URI: %q, Rel: %q, Extra: %+v\n", l.URI, l.Rel, l.Extra)
// URI: "https://example.com/?page=2", Rel: "next", Extra: map[foo:bar]
}
if resp, err := http.Get("https://api.github.com/search/code?q=Println+user:golang"); err == nil {
for _, l := range link.ParseResponse(resp) {
fmt.Printf("URI: %q, Rel: %q, Extra: %+v\n", l.URI, l.Rel, l.Extra)
// URI: "https://api.github.com/search/code?q=Println+user%3Agolang&page=2", Rel: "next", Extra: map[]
// URI: "https://api.github.com/search/code?q=Println+user%3Agolang&page=34", Rel: "last", Extra: map[]
}
}
}
*/
package link

111
vendor/github.com/peterhellberg/link/link.go generated vendored Normal file
View file

@ -0,0 +1,111 @@
package link
import (
"net/http"
"regexp"
"strings"
)
var (
commaRegexp = regexp.MustCompile(`,\s{0,}`)
valueCommaRegexp = regexp.MustCompile(`([^"]),`)
equalRegexp = regexp.MustCompile(` *= *`)
keyRegexp = regexp.MustCompile(`[a-z*]+`)
linkRegexp = regexp.MustCompile(`\A<(.+)>;(.+)\z`)
semiRegexp = regexp.MustCompile(`; +`)
valRegexp = regexp.MustCompile(`"+([^"]+)"+`)
)
// Group returned by Parse, contains multiple links indexed by "rel"
type Group map[string]*Link
// Link contains a Link item with URI, Rel, and other non-URI components in Extra.
type Link struct {
URI string
Rel string
Extra map[string]string
}
// String returns the URI
func (l *Link) String() string {
return l.URI
}
// ParseRequest parses the provided *http.Request into a Group
func ParseRequest(req *http.Request) Group {
if req == nil {
return nil
}
return ParseHeader(req.Header)
}
// ParseResponse parses the provided *http.Response into a Group
func ParseResponse(resp *http.Response) Group {
if resp == nil {
return nil
}
return ParseHeader(resp.Header)
}
// ParseHeader retrieves the Link header from the provided http.Header and parses it into a Group
func ParseHeader(h http.Header) Group {
if headers, found := h["Link"]; found {
return Parse(strings.Join(headers, ", "))
}
return nil
}
// Parse parses the provided string into a Group
func Parse(s string) Group {
if s == "" {
return nil
}
s = valueCommaRegexp.ReplaceAllString(s, "$1")
group := Group{}
for _, l := range commaRegexp.Split(s, -1) {
linkMatches := linkRegexp.FindAllStringSubmatch(l, -1)
if len(linkMatches) == 0 {
return nil
}
pieces := linkMatches[0]
link := &Link{URI: pieces[1], Extra: map[string]string{}}
for _, extra := range semiRegexp.Split(pieces[2], -1) {
vals := equalRegexp.Split(extra, -1)
key := keyRegexp.FindString(vals[0])
val := valRegexp.FindStringSubmatch(vals[1])[1]
if key == "rel" {
vals := strings.Split(val, " ")
rels := []string{vals[0]}
if len(vals) > 1 {
for _, v := range vals[1:] {
if !strings.HasPrefix(v, "http") {
rels = append(rels, v)
}
}
}
rel := strings.Join(rels, " ")
link.Rel = rel
group[rel] = link
} else {
link.Extra[key] = val
}
}
}
return group
}

283
vendor/github.com/peterhellberg/link/link_test.go generated vendored Normal file
View file

@ -0,0 +1,283 @@
package link
import (
"fmt"
"net/http"
"testing"
)
func TestLinkString(t *testing.T) {
l := Parse(`<https://example.com/?page=2>; rel="next"; title="foo"`)["next"]
if got, want := l.String(), "https://example.com/?page=2"; got != want {
t.Fatalf(`l.String() = %q, want %q`, got, want)
}
}
func TestParseRequest(t *testing.T) {
req, _ := http.NewRequest("GET", "", nil)
req.Header.Set("Link", `<https://example.com/?page=2>; rel="next"`)
g := ParseRequest(req)
if got, want := len(g), 1; got != want {
t.Fatalf(`len(g) = %d, want %d`, got, want)
}
if g["next"] == nil {
t.Fatalf(`g["next"] == nil`)
}
if got, want := g["next"].URI, "https://example.com/?page=2"; got != want {
t.Fatalf(`g["next"].URI = %q, want %q`, got, want)
}
if got, want := g["next"].Rel, "next"; got != want {
t.Fatalf(`g["next"].Rel = %q, want %q`, got, want)
}
if got, want := len(ParseRequest(nil)), 0; got != want {
t.Fatalf(`len(ParseRequest(nil)) = %d, want %d`, got, want)
}
}
func TestParseResponse(t *testing.T) {
resp := &http.Response{Header: http.Header{}}
resp.Header.Set("Link", `<https://example.com/?page=2>; rel="next"`)
g := ParseResponse(resp)
if got, want := len(g), 1; got != want {
t.Fatalf(`len(g) = %d, want %d`, got, want)
}
if g["next"] == nil {
t.Fatalf(`g["next"] == nil`)
}
if got, want := g["next"].URI, "https://example.com/?page=2"; got != want {
t.Fatalf(`g["next"].URI = %q, want %q`, got, want)
}
if got, want := g["next"].Rel, "next"; got != want {
t.Fatalf(`g["next"].Rel = %q, want %q`, got, want)
}
if got, want := len(ParseResponse(nil)), 0; got != want {
t.Fatalf(`len(ParseResponse(nil)) = %d, want %d`, got, want)
}
}
func TestParseHeader_single(t *testing.T) {
h := http.Header{}
h.Set("Link", `<https://example.com/?page=2>; rel="next"`)
g := ParseHeader(h)
if got, want := len(g), 1; got != want {
t.Fatalf(`len(g) = %d, want %d`, got, want)
}
if g["next"] == nil {
t.Fatalf(`g["next"] == nil`)
}
if got, want := g["next"].URI, "https://example.com/?page=2"; got != want {
t.Fatalf(`g["next"].URI = %q, want %q`, got, want)
}
if got, want := g["next"].Rel, "next"; got != want {
t.Fatalf(`g["next"].Rel = %q, want %q`, got, want)
}
}
func TestParseHeader_multiple(t *testing.T) {
h := http.Header{}
h.Add("Link", `<https://example.com/?page=2>; rel="next",<https://example.com/?page=34>; rel="last"`)
g := ParseHeader(h)
if got, want := len(g), 2; got != want {
t.Fatalf(`len(g) = %d, want %d`, got, want)
}
if g["next"] == nil {
t.Fatalf(`g["next"] == nil`)
}
if got, want := g["next"].URI, "https://example.com/?page=2"; got != want {
t.Fatalf(`g["next"].URI = %q, want %q`, got, want)
}
if got, want := g["next"].Rel, "next"; got != want {
t.Fatalf(`g["next"].Rel = %q, want %q`, got, want)
}
if g["last"] == nil {
t.Fatalf(`g["last"] == nil`)
}
if got, want := g["last"].URI, "https://example.com/?page=34"; got != want {
t.Fatalf(`g["last"].URI = %q, want %q`, got, want)
}
if got, want := g["last"].Rel, "last"; got != want {
t.Fatalf(`g["last"].Rel = %q, want %q`, got, want)
}
}
func TestParseHeader_multiple_headers(t *testing.T) {
h := http.Header{}
h.Add("Link", `<https://example.com/?page=2>; rel="next",<https://example.com/?page=34>; rel="last"`)
h.Add("Link", `<https://example.com/?page=foo>; rel="foo",<https://example.com/?page=bar>; rel="bar"`)
g := ParseHeader(h)
if got, want := len(g), 4; got != want {
t.Fatalf(`len(g) = %d, want %d`, got, want)
}
if g["foo"] == nil {
t.Fatalf(`g["foo"] == nil`)
}
if got, want := g["bar"].URI, "https://example.com/?page=bar"; got != want {
t.Fatalf(`g["bar"].URI = %q, want %q`, got, want)
}
if got, want := g["next"].Rel, "next"; got != want {
t.Fatalf(`g["next"].Rel = %q, want %q`, got, want)
}
if g["last"] == nil {
t.Fatalf(`g["last"] == nil`)
}
if got, want := g["last"].URI, "https://example.com/?page=34"; got != want {
t.Fatalf(`g["last"].URI = %q, want %q`, got, want)
}
if got, want := g["last"].Rel, "last"; got != want {
t.Fatalf(`g["last"].Rel = %q, want %q`, got, want)
}
}
func TestParseHeader_extra(t *testing.T) {
h := http.Header{}
h.Add("Link", `<https://example.com/?page=2>; rel="next"; title="foo"`)
g := ParseHeader(h)
if got, want := len(g), 1; got != want {
t.Fatalf(`len(g) = %d, want %d`, got, want)
}
if g["next"] == nil {
t.Fatalf(`g["next"] == nil`)
}
if got, want := g["next"].Extra["title"], "foo"; got != want {
t.Fatalf(`g["next"].Extra["title"] = %q, want %q`, got, want)
}
}
func TestParseHeader_noLink(t *testing.T) {
if ParseHeader(http.Header{}) != nil {
t.Fatalf(`Parse(http.Header{}) != nil`)
}
}
func TestParseHeader_nilHeader(t *testing.T) {
if ParseHeader(nil) != nil {
t.Fatalf(`ParseHeader(nil) != nil`)
}
}
func TestParse_emptyString(t *testing.T) {
if Parse("") != nil {
t.Fatalf(`Parse("") != nil`)
}
}
func TestParse_valuesWithComma(t *testing.T) {
g := Parse(`<//www.w3.org/wiki/LinkHeader>; rel="original latest-version",<//www.w3.org/wiki/Special:TimeGate/LinkHeader>; rel="timegate",<//www.w3.org/wiki/Special:TimeMap/LinkHeader>; rel="timemap"; type="application/link-format"; from="Mon, 03 Sep 2007 14:52:48 GMT"; until="Tue, 16 Jun 2015 22:59:23 GMT",<//www.w3.org/wiki/index.php?title=LinkHeader&oldid=10152>; rel="first memento"; datetime="Mon, 03 Sep 2007 14:52:48 GMT",<//www.w3.org/wiki/index.php?title=LinkHeader&oldid=84697>; rel="last memento"; datetime="Tue, 16 Jun 2015 22:59:23 GMT"`)
if got, want := len(g), 5; got != want {
t.Fatalf(`len(g) = %d, want %d`, got, want)
}
if got, want := g["original latest-version"].URI, "//www.w3.org/wiki/LinkHeader"; got != want {
t.Fatalf(`g["original latest-version"].URI = %q, want %q`, got, want)
}
if got, want := g["last memento"].Extra["datetime"], "Tue 16 Jun 2015 22:59:23 GMT"; got != want {
t.Fatalf(`g["last memento"].Extra["datetime"] = %q, want %q`, got, want)
}
}
func TestParse_rfc5988Example1(t *testing.T) {
g := Parse(`<http://example.com/TheBook/chapter2>; rel="previous"; title="previous chapter"`)
if got, want := len(g), 1; got != want {
t.Fatalf(`len(g) = %d, want %d`, got, want)
}
if g["previous"] == nil {
t.Fatalf(`g["previous"] == nil`)
}
if got, want := g["previous"].Extra["title"], "previous chapter"; got != want {
t.Fatalf(`g["previous"].Extra["title"] = %q, want %q`, got, want)
}
}
func TestParse_rfc5988Example2(t *testing.T) {
g := Parse(`</>; rel="http://example.net/foo"`)
if got, want := len(g), 1; got != want {
t.Fatalf(`len(g) = %d, want %d`, got, want)
}
if g["http://example.net/foo"] == nil {
t.Fatalf(`g["http://example.net/foo"] == nil`)
}
l := g["http://example.net/foo"]
if got, want := l.URI, "/"; got != want {
t.Fatalf(`l.URI = %q, want %q`, got, want)
}
}
func TestParse_rfc5988Example3(t *testing.T) {
// Extended notation is not supported yet
// g := Parse(`</TheBook/chapter2>; rel="previous"; title*=UTF-8'de'letztes%20Kapitel, </TheBook/chapter4>; rel="next"; title*=UTF-8'de'n%c3%a4chstes%20Kapitel`)
}
func TestParse_rfc5988Example4(t *testing.T) {
// Extension relation types are ignored for now
g := Parse(`<http://example.org/>; rel="start http://example.net/relation/other"`)
if got, want := len(g), 1; got != want {
t.Fatalf(`len(g) = %d, want %d`, got, want)
}
if g["start"] == nil {
t.Fatalf(`g["start"] == nil`)
}
if got, want := g["start"].URI, "http://example.org/"; got != want {
t.Fatalf(`g["start"].URI = %q, want %q`, got, want)
}
}
func TestParse_fuzzCrashers(t *testing.T) {
Parse("0")
}
func ExampleParse() {
l := Parse(`<https://example.com/?page=2>; rel="next"; title="foo"`)["next"]
fmt.Printf("URI: %q, Rel: %q, Extra: %+v\n", l.URI, l.Rel, l.Extra)
// Output: URI: "https://example.com/?page=2", Rel: "next", Extra: map[title:foo]
}