Add a simple 'Context#GetReferrer', as requested by the People: adapt the goreferrer external package

Former-commit-id: 8f1dce93dd5a2449d806f0b28baf5a8c860193b5
This commit is contained in:
Gerasimos (Makis) Maropoulos 2018-08-04 15:19:17 +03:00
parent 1ec8452208
commit 2b2492abfa
6 changed files with 165 additions and 3 deletions

6
Gopkg.lock generated
View File

@ -271,6 +271,12 @@
packages = ["."]
revision = "eb3733d160e74a9c7e442f435eb3bea458e1d19f"
[[projects]]
branch = "master"
name = "github.com/Shopify/goreferrer"
packages = ["."]
revision = "aad8439df3bf67adb025382ee2e5f46a72fc9456"
[solve-meta]
analyzer-name = "dep"
analyzer-version = 1

View File

@ -77,3 +77,7 @@
[[constraint]]
branch = "v2"
name = "gopkg.in/yaml.v2"
[[constraint]]
branch = "master"
name = "github.com/Shopify/goreferrer"

View File

@ -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)

View File

@ -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.

View File

@ -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)
}

View File

@ -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 (
@ -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 |
// +------------------------------------------------------------+
@ -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 |
// +------------------------------------------------------------+