Skip to content

Commit

Permalink
add support for iris-specific form of generating connection IDs as re…
Browse files Browse the repository at this point in the history
…quested at: kataras/neffos#1 (comment)

Former-commit-id: 0994b63373ebe2b5383a28f042aa2133061cbd18
  • Loading branch information
kataras committed Jul 5, 2019
1 parent 9dbb300 commit 2576b3d
Show file tree
Hide file tree
Showing 9 changed files with 64 additions and 38 deletions.
13 changes: 6 additions & 7 deletions _examples/authentication/request/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import (
)

var (
// Change that to your owns, usally you have an ECDSA private key
// Change that to your own key.
// Usually you have an ECDSA private key
// per identify, let's say a user, stored in a database
// or somewhere else and you use its public key
// to sign a user's payload and when this client
Expand All @@ -17,11 +18,9 @@ var (
// with the user's public key.
//
// Use the crypto.MustGenerateKey to generate a random key
// or import
// the "github.com/kataras/iris/crypto/sign"
// and use its
// sign.ParsePrivateKey/ParsePublicKey(theKey []byte)
// to convert data or local file to an *ecdsa.PrivateKey.
// or
// crypto.ParsePrivateKey to convert data or local file to an *ecdsa.PrivateKey.
// and `crypto.ParsePublicKey` if you only have access to the public one.
testPrivateKey = crypto.MustGenerateKey()
testPublicKey = &testPrivateKey.PublicKey
)
Expand All @@ -34,7 +33,7 @@ type testPayloadStructure struct {
// The Iris crypto package offers
// authentication (with optional encryption in top of) and verification
// of raw []byte data with `crypto.Marshal/Unmarshal` functions
// and JSON payloads with `crypto.SignJSON/VerifyJSON functions.
// and JSON payloads with `crypto.SignJSON/VerifyJSON` functions.
//
// Let's use the `SignJSON` and `VerifyJSON` here as an example,
// as this is the most common scenario for a web application.
Expand Down
22 changes: 11 additions & 11 deletions context/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import (
"github.com/fatih/structs"
"github.com/iris-contrib/blackfriday"
formbinder "github.com/iris-contrib/formBinder"
"github.com/json-iterator/go"
jsoniter "github.com/json-iterator/go"
"github.com/microcosm-cc/bluemonday"
"gopkg.in/yaml.v2"
)
Expand Down Expand Up @@ -826,20 +826,20 @@ type Context interface {
//
// Example: https://github.com/kataras/iris/tree/master/_examples/cookies/basic
SetCookieKV(name, value string, options ...CookieOption)
// GetCookie returns cookie's value by it's name
// GetCookie returns cookie's value by its name
// returns empty string if nothing was found.
//
// If you want more than the value then:
// cookie, err := ctx.Request().Cookie("name")
//
// Example: https://github.com/kataras/iris/tree/master/_examples/cookies/basic
GetCookie(name string, options ...CookieOption) string
// RemoveCookie deletes a cookie by it's name and path = "/".
// RemoveCookie deletes a cookie by its name and path = "/".
// Tip: change the cookie's path to the current one by: RemoveCookie("name", iris.CookieCleanPath)
//
// Example: https://github.com/kataras/iris/tree/master/_examples/cookies/basic
RemoveCookie(name string, options ...CookieOption)
// VisitAllCookies takes a visitor which loops
// VisitAllCookies accepts a visitor function which is called
// on each (request's) cookies' name and value.
VisitAllCookies(visitor func(name string, value string))

Expand Down Expand Up @@ -3233,7 +3233,7 @@ func CookieHTTPOnly(httpOnly bool) CookieOption {

type (
// CookieEncoder should encode the cookie value.
// Should accept as first argument the cookie name
// Should accept the cookie's name as its first argument
// and as second argument the cookie value ptr.
// Should return an encoded value or an empty one if encode operation failed.
// Should return an error if encode operation failed.
Expand All @@ -3245,7 +3245,7 @@ type (
// See `CookieDecoder` too.
CookieEncoder func(cookieName string, value interface{}) (string, error)
// CookieDecoder should decode the cookie value.
// Should accept as first argument the cookie name,
// Should accept the cookie's name as its first argument,
// as second argument the encoded cookie value and as third argument the decoded value ptr.
// Should return a decoded value or an empty one if decode operation failed.
// Should return an error if decode operation failed.
Expand Down Expand Up @@ -3329,7 +3329,7 @@ func (ctx *context) SetCookieKV(name, value string, options ...CookieOption) {
ctx.SetCookie(c, options...)
}

// GetCookie returns cookie's value by it's name
// GetCookie returns cookie's value by its name
// returns empty string if nothing was found.
//
// If you want more than the value then:
Expand All @@ -3350,13 +3350,13 @@ func (ctx *context) GetCookie(name string, options ...CookieOption) string {
return value
}

// SetCookieKVExpiration is 2 hours by-default
// SetCookieKVExpiration is 365 days by-default
// you can change it or simple, use the SetCookie for more control.
//
// See `SetCookieKVExpiration` and `CookieExpires` for more.
var SetCookieKVExpiration = time.Duration(120) * time.Minute
var SetCookieKVExpiration = time.Duration(8760) * time.Hour

// RemoveCookie deletes a cookie by it's name and path = "/".
// RemoveCookie deletes a cookie by its name and path = "/".
// Tip: change the cookie's path to the current one by: RemoveCookie("name", iris.CookieCleanPath)
//
// Example: https://github.com/kataras/iris/tree/master/_examples/cookies/basic
Expand All @@ -3375,7 +3375,7 @@ func (ctx *context) RemoveCookie(name string, options ...CookieOption) {
ctx.request.Header.Set("Cookie", "")
}

// VisitAllCookies takes a visitor which loops
// VisitAllCookies takes a visitor function which is called
// on each (request's) cookies' name and value.
func (ctx *context) VisitAllCookies(visitor func(name string, value string)) {
for _, cookie := range ctx.request.Cookies() {
Expand Down
2 changes: 1 addition & 1 deletion core/router/api_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,7 @@ func (api *APIBuilder) HandleMany(methodOrMulti string, relativePathorMulti stri
// second parameter : the system or the embedded directory that needs to be served
// third parameter : not required, the directory options, set fields is optional.
//
// for more options look router.FileServer.
// Alternatively, to get just the handler for that look the FileServer function instead.
//
// api.HandleDir("/static", "./assets", DirOptions {ShowList: true, Gzip: true, IndexName: "index.html"})
//
Expand Down
10 changes: 7 additions & 3 deletions crypto/crypto.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,13 @@ import (
)

var (
// MustGenerateKey generates an ecdsa public and private key pair.
// MustGenerateKey generates an ecdsa private and public key pair.
// It panics if any error occurred.
MustGenerateKey = sign.MustGenerateKey
// ParsePrivateKey accepts a pem x509-encoded private key and decodes to *ecdsa.PrivateKey.
ParsePrivateKey = sign.ParsePrivateKey
// ParsePublicKey accepts a pem x509-encoded public key and decodes to *ecdsa.PrivateKey.
ParsePublicKey = sign.ParsePublicKey

// MustGenerateAESKey generates an aes key.
// It panics if any error occurred.
Expand Down Expand Up @@ -79,9 +83,9 @@ func Decrypt(aesKey, additionalData []byte) Decryption {
// Returns non-nil error if any error occurred.
//
// Usage:
// data, _ := ioutil.ReadAll(r.Body)
// data, _ := ioutil.ReadAll(ctx.Request().Body)
// signedData, err := crypto.Marshal(testPrivateKey, data, nil)
// w.Write(signedData)
// ctx.Write(signedData)
// Or if data should be encrypted:
// signedEncryptedData, err := crypto.Marshal(testPrivateKey, data, crypto.Encrypt(aesKey, nil))
func Marshal(privateKey *ecdsa.PrivateKey, data []byte, encrypt Encryption) ([]byte, error) {
Expand Down
6 changes: 3 additions & 3 deletions crypto/json.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,11 @@ func SignJSON(privateKey *ecdsa.PrivateKey, r io.Reader) (Ticket, error) {
// VerifyJSON verifies the incoming JSON request,
// by reading the "r" which should decodes to a `Ticket`.
// The `Ticket` is verified against the given "publicKey", the `Ticket#Signature` and
// `Ticket#Payload` data (original request's payload data which was signed by `SignPayload`).
// `Ticket#Payload` data (original request's payload data which was signed by `SignJSON`).
//
// Returns true wether the verification succeed or not.
// Returns true whether the verification succeed or not.
// The "toPayloadPtr" should be a pointer to a value of the same payload structure the client signed on.
// If and only if the verification succeed the payload value is filled from the `Ticket#Payload` raw data.
// If and only if the verification succeed the payload value is filled from the `Ticket.Payload` raw data.
//
// Check for both output arguments in order to:
// 1. verification (true/false and error) and
Expand Down
4 changes: 2 additions & 2 deletions crypto/sign/sign.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import (
"golang.org/x/crypto/sha3"
)

// MustGenerateKey generates a public and private key pair.
// MustGenerateKey generates a private and public key pair.
// It panics if any error occurred.
func MustGenerateKey() *ecdsa.PrivateKey {
privateKey, err := GenerateKey()
Expand All @@ -31,7 +31,7 @@ func MustGenerateKey() *ecdsa.PrivateKey {
return privateKey
}

// GenerateKey generates a public and private key pair.
// GenerateKey generates a private and public key pair.
func GenerateKey() (*ecdsa.PrivateKey, error) {
return ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
}
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ require (
github.com/iris-contrib/go.uuid v2.0.0+incompatible
github.com/json-iterator/go v1.1.6 // vendor removed.
github.com/kataras/golog v0.0.0-20180321173939-03be10146386
github.com/kataras/neffos v0.0.2
github.com/kataras/neffos v0.0.3
github.com/kataras/pio v0.0.0-20190103105442-ea782b38602d // indirect
github.com/microcosm-cc/bluemonday v1.0.2
github.com/ryanuber/columnize v2.1.0+incompatible
Expand Down
2 changes: 1 addition & 1 deletion view/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
Iris supports 6 template engines out-of-the-box, developers can still use any external golang template engine,
as `context/context#ResponseWriter()` is an `io.Writer`.

All of these five template engines have common features with common API,
All of these six template engines have common features with common API,
like Layout, Template Funcs, Party-specific layout, partial rendering and more.

- The standard html, its template parser is the [golang.org/pkg/html/template/](https://golang.org/pkg/html/template/)
Expand Down
41 changes: 32 additions & 9 deletions websocket/websocket.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,10 @@ var (
// See examples for more.
New = neffos.New
// DefaultIDGenerator returns a universal unique identifier for a new connection.
// It's the default `IDGenerator` for `Server`.
DefaultIDGenerator = neffos.DefaultIDGenerator
// It's the default `IDGenerator` if missing.
DefaultIDGenerator = func(ctx context.Context) string {
return neffos.DefaultIDGenerator(ctx.ResponseWriter(), ctx.Request())
}

// GorillaDialer is a `Dialer` type for the gorilla/websocket subprotocol implementation.
// Should be used on `Dial` to create a new client/client-side connection.
Expand Down Expand Up @@ -113,18 +115,39 @@ func SetDefaultUnmarshaler(fn func(data []byte, v interface{}) error) {
neffos.DefaultUnmarshaler = fn
}

// IDGenerator is an iris-specific IDGenerator for new connections.
type IDGenerator func(context.Context) string

// Handler returns an Iris handler to be served in a route of an Iris application.
func Handler(s *neffos.Server) context.Handler {
// Accepts the neffos websocket server as its first input argument
// and optionally an Iris-specific `IDGenerator` as its second one.
func Handler(s *neffos.Server, IDGenerator ...IDGenerator) context.Handler {
idGen := DefaultIDGenerator
if len(IDGenerator) > 0 {
idGen = IDGenerator[0]
}

return func(ctx context.Context) {
s.Upgrade(ctx.ResponseWriter(), ctx.Request(), func(socket neffos.Socket) neffos.Socket {
return &socketWrapper{
Socket: socket,
ctx: ctx,
}
})
if ctx.IsStopped() {
return
}
Upgrade(ctx, idGen(ctx), s)
}
}

// Upgrade upgrades the request and returns a new websocket Conn.
// Use `Handler` for higher-level implementation instead.
func Upgrade(ctx context.Context, customID string, s *neffos.Server) *neffos.Conn {
conn, _ := s.Upgrade(ctx.ResponseWriter(), ctx.Request(), func(socket neffos.Socket) neffos.Socket {
return &socketWrapper{
Socket: socket,
ctx: ctx,
}
}, customID)

return conn
}

type socketWrapper struct {
neffos.Socket
ctx context.Context
Expand Down

0 comments on commit 2576b3d

Please sign in to comment.