Skip to content

Commit

Permalink
Add a simple 'Context#GetReferrer', as requested by the People: adapt…
Browse files Browse the repository at this point in the history
… the goreferrer external package
  • Loading branch information
kataras committed Aug 4, 2018
1 parent 95822de commit f37e65e
Show file tree
Hide file tree
Showing 11 changed files with 4,667 additions and 3 deletions.
6 changes: 6 additions & 0 deletions Gopkg.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions Gopkg.toml
Expand Up @@ -77,3 +77,7 @@
[[constraint]]
branch = "v2"
name = "gopkg.in/yaml.v2"

[[constraint]]
branch = "master"
name = "github.com/Shopify/goreferrer"
39 changes: 39 additions & 0 deletions README.md
Expand Up @@ -209,6 +209,45 @@ func main() {
id: 1234; page: 1; name: manu; message: this_is_great
```

### Extract Referer

```go
package main

import (
"github.com/kataras/iris"
"github.com/kataras/iris/context"
)

func main() {
app := iris.New()

app.Get("/", func(ctx context.Context) /* or iris.Context, it's the same for Go 1.9+. */ {

// request header "referer" or url parameter "referer".
r := ctx.GetReferrer()
switch r.Type {
case context.ReferrerSearch:
ctx.Writef("Search %s: %s\n", r.Label, r.Query)
ctx.Writef("Google: %s\n", r.GoogleType)
case context.ReferrerSocial:
ctx.Writef("Social %s\n", r.Label)
case context.ReferrerIndirect:
ctx.Writef("Indirect: %s\n", r.URL)
}
})

app.Run(iris.Addr(":8080"))
}
```

How to `curl`:

```bash
curl http://localhost:8080?referer=https://twitter.com/Xinterio/status/1023566830974251008
curl http://localhost:8080?referer=https://www.google.com/search?q=Top+6+golang+web+frameworks&oq=Top+6+golang+web+frameworks
```

### Upload files

- [single file upload](_examples/http_request/upload-file/main.go)
Expand Down
1 change: 1 addition & 0 deletions _examples/README.md
Expand Up @@ -384,6 +384,7 @@ You can serve [quicktemplate](https://github.com/valyala/quicktemplate) and [her
- [Read Custom via Unmarshaler](http_request/read-custom-via-unmarshaler/main.go)
- [Upload/Read File](http_request/upload-file/main.go)
- [Upload multiple files with an easy way](http_request/upload-files/main.go)
- [Extract referrer from "referer" header or URL query parameter](http_request/extract-referer/main.go) **NEW**

> The `context.Request()` returns the same *http.Request you already know, these examples show some places where the Context uses this object. Besides that you can use it as you did before iris.

Expand Down
29 changes: 29 additions & 0 deletions _examples/http_request/extract-referer/main.go
@@ -0,0 +1,29 @@
package main

import (
"github.com/kataras/iris"
"github.com/kataras/iris/context"
)

func main() {
app := iris.New()

app.Get("/", func(ctx context.Context) /* or iris.Context, it's the same for Go 1.9+. */ {
// GetReferrer extracts and returns the information from the "Referer" header as specified
// in https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy or by the URL query parameter "referer".
r := ctx.GetReferrer()
switch r.Type {
case context.ReferrerSearch:
ctx.Writef("Search %s: %s\n", r.Label, r.Query)
ctx.Writef("Google: %s\n", r.GoogleType)
case context.ReferrerSocial:
ctx.Writef("Social %s\n", r.Label)
case context.ReferrerIndirect:
ctx.Writef("Indirect: %s\n", r.URL)
}
})

// http://localhost:8080?referer=https://twitter.com/Xinterio/status/1023566830974251008
// http://localhost:8080?referer=https://www.google.com/search?q=Top+6+golang+web+frameworks&oq=Top+6+golang+web+frameworks
app.Run(iris.Addr(":8080"), iris.WithoutServerError(iris.ErrServerClosed), iris.WithoutVersionChecker)
}
89 changes: 86 additions & 3 deletions context/context.go
Expand Up @@ -21,15 +21,16 @@ import (
"sync/atomic"
"time"

"github.com/kataras/iris/core/errors"
"github.com/kataras/iris/core/memstore"

"github.com/Shopify/goreferrer"
"github.com/fatih/structs"
formbinder "github.com/iris-contrib/formBinder"
"github.com/json-iterator/go"
"github.com/microcosm-cc/bluemonday"
"gopkg.in/russross/blackfriday.v2"
"gopkg.in/yaml.v2"

"github.com/kataras/iris/core/errors"
"github.com/kataras/iris/core/memstore"
)

type (
Expand Down Expand Up @@ -445,6 +446,10 @@ type Context interface {
//
// Keep note that this checks the "User-Agent" request header.
IsMobile() bool
// GetReferrer extracts and returns the information from the "Referer" header as specified
// in https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy
// or by the URL query parameter "referer".
GetReferrer() Referrer
// +------------------------------------------------------------+
// | Headers helpers |
// +------------------------------------------------------------+
Expand Down Expand Up @@ -1687,6 +1692,84 @@ func (ctx *context) IsMobile() bool {
return isMobileRegex.MatchString(s)
}

type (
// Referrer contains the extracted information from the `GetReferrer`
//
// The structure contains struct tags for JSON, form, XML, YAML and TOML.
// Look the `GetReferrer() Referrer` and `goreferrer` external package.
Referrer struct {
Type ReferrerType `json:"type" form:"referrer_type" xml:"Type" yaml:"Type" toml:"Type"`
Label string `json:"label" form:"referrer_form" xml:"Label" yaml:"Label" toml:"Label"`
URL string `json:"url" form:"referrer_url" xml:"URL" yaml:"URL" toml:"URL"`
Subdomain string `json:"subdomain" form:"referrer_subdomain" xml:"Subdomain" yaml:"Subdomain" toml:"Subdomain"`
Domain string `json:"domain" form:"referrer_domain" xml:"Domain" yaml:"Domain" toml:"Domain"`
Tld string `json:"tld" form:"referrer_tld" xml:"Tld" yaml:"Tld" toml:"Tld"`
Path string `jsonn:"path" form:"referrer_path" xml:"Path" yaml:"Path" toml:"Path"`
Query string `json:"query" form:"referrer_query" xml:"Query" yaml:"Query" toml:"GoogleType"`
GoogleType ReferrerGoogleSearchType `json:"googleType" form:"referrer_google_type" xml:"GoogleType" yaml:"GoogleType" toml:"GoogleType"`
}

// ReferrerType is the goreferrer enum for a referrer type (indirect, direct, email, search, social).
ReferrerType int

// ReferrerGoogleSearchType is the goreferrer enum for a google search type (organic, adwords).
ReferrerGoogleSearchType int
)

// Contains the available values of the goreferrer enums.
const (
ReferrerInvalid ReferrerType = iota
ReferrerIndirect
ReferrerDirect
ReferrerEmail
ReferrerSearch
ReferrerSocial

ReferrerNotGoogleSearch ReferrerGoogleSearchType = iota
ReferrerGoogleOrganicSearch
ReferrerGoogleAdwords
)

func (gs ReferrerGoogleSearchType) String() string {
return goreferrer.GoogleSearchType(gs).String()
}

func (r ReferrerType) String() string {
return goreferrer.ReferrerType(r).String()
}

// unnecessary but good to know the default values upfront.
var emptyReferrer = Referrer{Type: ReferrerInvalid, GoogleType: ReferrerNotGoogleSearch}

// GetReferrer extracts and returns the information from the "Referer" header as specified
// in https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy
// or by the URL query parameter "referer".
func (ctx *context) GetReferrer() Referrer {
// the underline net/http follows the https://tools.ietf.org/html/rfc7231#section-5.5.2,
// so there is nothing special left to do.
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy
refURL := ctx.GetHeader("Referer")
if refURL == "" {
refURL = ctx.URLParam("referer")
}

if ref := goreferrer.DefaultRules.Parse(refURL); ref.Type > goreferrer.Invalid {
return Referrer{
Type: ReferrerType(ref.Type),
Label: ref.Label,
URL: ref.URL,
Subdomain: ref.Subdomain,
Domain: ref.Domain,
Tld: ref.Tld,
Path: ref.Path,
Query: ref.Query,
GoogleType: ReferrerGoogleSearchType(ref.GoogleType),
}
}

return emptyReferrer
}

// +------------------------------------------------------------+
// | Response Headers helpers |
// +------------------------------------------------------------+
Expand Down
20 changes: 20 additions & 0 deletions vendor/github.com/Shopify/goreferrer/LICENSE

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit f37e65e

Please sign in to comment.