Skip to content

Commit

Permalink
fix(#36): make middleware layer thread-safe
Browse files Browse the repository at this point in the history
  • Loading branch information
h2non committed Sep 20, 2017
1 parent fd1c3d3 commit 06ee7f0
Show file tree
Hide file tree
Showing 8 changed files with 36 additions and 8 deletions.
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
The MIT License

Copyright (c) 2016 Tomas Aparicio
Copyright (c) 2016-2017 Tomas Aparicio

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
# gentleman [![Build Status](https://travis-ci.org/h2non/gentleman.png)](https://travis-ci.org/h2non/gentleman) [![GitHub release](https://img.shields.io/badge/version-2.0.1-orange.svg?style=flat)](https://github.com/h2non/gentleman/releases) [![GoDoc](https://godoc.org/gopkg.in/h2non/gentleman.v2?status.svg)](https://godoc.org/gopkg.in/h2non/gentleman.v2) [![Coverage Status](https://coveralls.io/repos/github/h2non/gentleman/badge.svg?branch=master)](https://coveralls.io/github/h2non/gentleman?branch=master) [![Go Report Card](https://goreportcard.com/badge/github.com/h2non/gentleman)](https://goreportcard.com/report/github.com/h2non/gentleman) [![Go Version](https://img.shields.io/badge/go-v2.0+-green.svg?style=flat)](https://github.com/h2non/gentleman)

<a target='_blank' rel='nofollow' href='https://app.codesponsor.io/link/1MpD3pzt63uUeG43NP4tDHPY/h2non/gentleman'> <img alt='Sponsor' width='888' height='68' src='https://app.codesponsor.io/embed/1MpD3pzt63uUeG43NP4tDHPY/h2non/gentleman.svg' /></a>

Full-featured, plugin-driven, middleware-oriented toolkit to easily create rich, versatile and composable HTTP clients in [Go](http://golang.org).

<img src="http://s10.postimg.org/5e31ox1ft/gentleman.png" align="right" height="260" />
Expand All @@ -14,6 +12,8 @@ Take a look to the [examples](#examples), list of [supported plugins](#plugins),

For testing purposes, see [baloo](https://github.com/h2non/baloo), an utility library for expressive end-to-end HTTP API testing, built on top of `gentleman` toolkit. For HTTP mocking, see [gentleman-mock](https://github.com/h2non/gentleman-mock), which uses [gock](https://github.com/h2non/gock) under the hood for easy and expressive HTTP client request mocking.

<a target='_blank' rel='nofollow' href='https://app.codesponsor.io/link/1MpD3pzt63uUeG43NP4tDHPY/h2non/gentleman'> <img alt='Sponsor' width='888' height='68' src='https://app.codesponsor.io/embed/1MpD3pzt63uUeG43NP4tDHPY/h2non/gentleman.svg' /></a>

## Versions

- [v2](https://github.com/h2non/gentleman/) - Latest version. Stable. Recommended.
Expand Down
2 changes: 1 addition & 1 deletion context/LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
The MIT License

Copyright (c) 2016 Tomas Aparicio
Copyright (c) 2016-2017 Tomas Aparicio

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
Expand Down
2 changes: 1 addition & 1 deletion middleware/LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
The MIT License

Copyright (c) 2016 Tomas Aparicio
Copyright (c) 2016-2017 Tomas Aparicio

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
Expand Down
28 changes: 28 additions & 0 deletions middleware/middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ type Middleware interface {
// Layer type represent an HTTP domain
// specific middleware layer with inheritance support.
type Layer struct {
// mtx protects data races for stack
mtx sync.RWMutex

// stack stores the plugins registered in the current middleware instance.
stack []plugin.Plugin

Expand All @@ -63,60 +66,80 @@ func New() *Layer {

// Use registers a new plugin to the middleware stack.
func (s *Layer) Use(plugin plugin.Plugin) Middleware {
s.mtx.Lock()
s.stack = append(s.stack, plugin)
s.mtx.Unlock()
return s
}

// UseHandler registers a phase specific plugin handler in the middleware stack.
func (s *Layer) UseHandler(phase string, fn c.HandlerFunc) Middleware {
s.mtx.Lock()
s.stack = append(s.stack, plugin.NewPhasePlugin(phase, fn))
s.mtx.Unlock()
return s
}

// UseResponse registers a new response phase middleware handler.
func (s *Layer) UseResponse(fn c.HandlerFunc) Middleware {
s.mtx.Lock()
s.stack = append(s.stack, plugin.NewResponsePlugin(fn))
s.mtx.Unlock()
return s
}

// UseRequest registers a new request phase middleware handler.
func (s *Layer) UseRequest(fn c.HandlerFunc) Middleware {
s.mtx.Lock()
s.stack = append(s.stack, plugin.NewRequestPlugin(fn))
s.mtx.Unlock()
return s
}

// UseError registers a new error phase middleware handler.
func (s *Layer) UseError(fn c.HandlerFunc) Middleware {
s.mtx.Lock()
s.stack = append(s.stack, plugin.NewErrorPlugin(fn))
s.mtx.Unlock()
return s
}

// UseParent attachs a parent middleware.
func (s *Layer) UseParent(parent Middleware) Middleware {
s.mtx.Lock()
s.parent = parent
s.mtx.Unlock()
return s
}

// Flush flushes the plugins stack.
func (s *Layer) Flush() {
s.mtx.Lock()
s.stack = s.stack[:0]
s.mtx.Unlock()
}

// SetStack sets the middleware plugin stack overriding the existent one.
func (s *Layer) SetStack(stack []plugin.Plugin) {
s.mtx.Lock()
s.stack = stack
s.mtx.Unlock()
}

// GetStack gets the current middleware plugins stack.
func (s *Layer) GetStack() []plugin.Plugin {
s.mtx.RLock()
defer s.mtx.RUnlock()
return s.stack
}

// Clone creates a new Middleware instance based on the current one.
func (s *Layer) Clone() Middleware {
mw := New()
mw.parent = s.parent
s.mtx.Lock()
mw.stack = append([]plugin.Plugin(nil), s.stack...)
s.mtx.Unlock()
return mw
}

Expand All @@ -129,7 +152,12 @@ func (s *Layer) Run(phase string, ctx *c.Context) *c.Context {
}
}

s.mtx.Lock()
s.stack = filter(s.stack)
s.mtx.Unlock()

s.mtx.RLock()
defer s.mtx.RUnlock()
return trigger(phase, s.stack, ctx)
}

Expand Down
2 changes: 1 addition & 1 deletion mux/LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
The MIT License

Copyright (c) 2016 Tomas Aparicio
Copyright (c) 2016-2017 Tomas Aparicio

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
Expand Down
2 changes: 1 addition & 1 deletion plugin/LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
The MIT License

Copyright (c) 2016 Tomas Aparicio
Copyright (c) 2016-2017 Tomas Aparicio

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
Expand Down
2 changes: 1 addition & 1 deletion utils/LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
The MIT License

Copyright (c) 2016 Tomas Aparicio
Copyright (c) 2016-2017 Tomas Aparicio

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
Expand Down

0 comments on commit 06ee7f0

Please sign in to comment.