Skip to content

Commit

Permalink
Fix compression forwarding via proxy (#1920)
Browse files Browse the repository at this point in the history
* Add api-core inx to the public routes

* Add parameter to enable GZIP compression

* Fix compression forwarding via proxy

* Release v2.0.1
  • Loading branch information
muXxer authored Oct 5, 2023
1 parent 4e1eea0 commit cc3e851
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 15 deletions.
2 changes: 1 addition & 1 deletion components/app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ var (
Name = "HORNET"

// Version of the app.
Version = "2.0.0"
Version = "2.0.1"
)

func App() *app.App {
Expand Down
4 changes: 3 additions & 1 deletion components/restapi/component.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,9 @@ func provide(c *dig.Container) error {
ParamsRestAPI.DebugRequestLoggerEnabled,
)
e.Use(middleware.CORS())
e.Use(middleware.Gzip())
if ParamsRestAPI.UseGZIP {
e.Use(middleware.Gzip())
}
e.Use(middleware.BodyLimit(ParamsRestAPI.Limits.MaxBodyLength))

return e
Expand Down
4 changes: 4 additions & 0 deletions components/restapi/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ type ParametersRestAPI struct {
PublicRoutes []string `usage:"the HTTP REST routes which can be called without authorization. Wildcards using * are allowed"`
// the HTTP REST routes which need to be called with authorization. Wildcards using * are allowed
ProtectedRoutes []string `usage:"the HTTP REST routes which need to be called with authorization. Wildcards using * are allowed"`
// UseGZIP defines whether to use the gzip middleware to compress HTTP responses
UseGZIP bool `default:"true" usage:"use the gzip middleware to compress HTTP responses"`
// whether the debug logging for requests should be enabled
DebugRequestLoggerEnabled bool `default:"false" usage:"whether the debug logging for requests should be enabled"`

Expand Down Expand Up @@ -55,6 +57,8 @@ var ParamsRestAPI = &ParametersRestAPI{
"/api/participation/v1/events*",
"/api/participation/v1/outputs*",
"/api/participation/v1/addresses*",
"/api/core/v0/*",
"/api/core/v1/*",
},
ProtectedRoutes: []string{
"/api/*",
Expand Down
5 changes: 4 additions & 1 deletion config_defaults.json
Original file line number Diff line number Diff line change
Expand Up @@ -191,11 +191,14 @@
"/api/mqtt/v1",
"/api/participation/v1/events*",
"/api/participation/v1/outputs*",
"/api/participation/v1/addresses*"
"/api/participation/v1/addresses*",
"/api/core/v0/*",
"/api/core/v1/*"
],
"protectedRoutes": [
"/api/*"
],
"useGZIP": true,
"debugRequestLoggerEnabled": false,
"jwtAuth": {
"salt": "HORNET"
Expand Down
26 changes: 15 additions & 11 deletions configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -481,16 +481,17 @@ Example:

## <a id="restapi"></a> 13. RestAPI

| Name | Description | Type | Default value |
| --------------------------- | ---------------------------------------------------------------------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| enabled | Whether the REST API plugin is enabled | boolean | true |
| bindAddress | The bind address on which the REST API listens on | string | "0.0.0.0:14265" |
| publicRoutes | The HTTP REST routes which can be called without authorization. Wildcards using \* are allowed | array | /health<br/>/api/routes<br/>/api/core/v2/info<br/>/api/core/v2/tips<br/>/api/core/v2/blocks\*<br/>/api/core/v2/transactions\*<br/>/api/core/v2/milestones\*<br/>/api/core/v2/outputs\*<br/>/api/core/v2/treasury<br/>/api/core/v2/receipts\*<br/>/api/debug/v1/\*<br/>/api/indexer/v1/\*<br/>/api/mqtt/v1<br/>/api/participation/v1/events\*<br/>/api/participation/v1/outputs\*<br/>/api/participation/v1/addresses\* |
| protectedRoutes | The HTTP REST routes which need to be called with authorization. Wildcards using \* are allowed | array | /api/\* |
| debugRequestLoggerEnabled | Whether the debug logging for requests should be enabled | boolean | false |
| [jwtAuth](#restapi_jwtauth) | Configuration for JWT Auth | object | |
| [pow](#restapi_pow) | Configuration for Proof of Work | object | |
| [limits](#restapi_limits) | Configuration for limits | object | |
| Name | Description | Type | Default value |
| --------------------------- | ---------------------------------------------------------------------------------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| enabled | Whether the REST API plugin is enabled | boolean | true |
| bindAddress | The bind address on which the REST API listens on | string | "0.0.0.0:14265" |
| publicRoutes | The HTTP REST routes which can be called without authorization. Wildcards using \* are allowed | array | /health<br/>/api/routes<br/>/api/core/v2/info<br/>/api/core/v2/tips<br/>/api/core/v2/blocks\*<br/>/api/core/v2/transactions\*<br/>/api/core/v2/milestones\*<br/>/api/core/v2/outputs\*<br/>/api/core/v2/treasury<br/>/api/core/v2/receipts\*<br/>/api/debug/v1/\*<br/>/api/indexer/v1/\*<br/>/api/mqtt/v1<br/>/api/participation/v1/events\*<br/>/api/participation/v1/outputs\*<br/>/api/participation/v1/addresses\*<br/>/api/core/v0/\*<br/>/api/core/v1/\* |
| protectedRoutes | The HTTP REST routes which need to be called with authorization. Wildcards using \* are allowed | array | /api/\* |
| useGZIP | Use the gzip middleware to compress HTTP responses | boolean | true |
| debugRequestLoggerEnabled | Whether the debug logging for requests should be enabled | boolean | false |
| [jwtAuth](#restapi_jwtauth) | Configuration for JWT Auth | object | |
| [pow](#restapi_pow) | Configuration for Proof of Work | object | |
| [limits](#restapi_limits) | Configuration for limits | object | |

### <a id="restapi_jwtauth"></a> JWT Auth

Expand Down Expand Up @@ -535,11 +536,14 @@ Example:
"/api/mqtt/v1",
"/api/participation/v1/events*",
"/api/participation/v1/outputs*",
"/api/participation/v1/addresses*"
"/api/participation/v1/addresses*",
"/api/core/v0/*",
"/api/core/v1/*"
],
"protectedRoutes": [
"/api/*"
],
"useGZIP": true,
"debugRequestLoggerEnabled": false,
"jwtAuth": {
"salt": "HORNET"
Expand Down
33 changes: 32 additions & 1 deletion pkg/restapi/proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package restapi
import (
"errors"
"fmt"
"net/http"
"net/url"
"strings"
"sync"
Expand Down Expand Up @@ -110,14 +111,44 @@ func NewDynamicProxy(e *echo.Echo, prefix string) *DynamicProxy {
}

func (p *DynamicProxy) middleware(prefix string) echo.MiddlewareFunc {
hasAcceptEncodingGZIP := func(header http.Header) bool {
return strings.Contains(header.Get(echo.HeaderAcceptEncoding), "gzip")
}

config := middleware.DefaultProxyConfig
config.Skipper = p.balancer.skipper
config.Balancer = p.balancer
config.Rewrite = map[string]string{
fmt.Sprintf("^%s/%s/*", p.balancer.prefix, prefix): "/$1",
}

return middleware.ProxyWithConfig(config)
configUncompressed := middleware.DefaultProxyConfig
configUncompressed.Skipper = p.balancer.skipper
configUncompressed.Balancer = p.balancer
configUncompressed.Rewrite = map[string]string{
fmt.Sprintf("^%s/%s/*", p.balancer.prefix, prefix): "/$1",
}
//nolint:forcetypeassert // we can safely assume that the DefaultTransport is a http.Transport
transportUncompressed := http.DefaultTransport.(*http.Transport).Clone()
transportUncompressed.DisableCompression = true
configUncompressed.Transport = transportUncompressed

return func(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
// we forward compressed requests if the client also supports compressed responses
compressed := hasAcceptEncodingGZIP(c.Request().Header)

// we need to remove "Accept-Encoding" headers in the request,
// because the transport handles this automatically if not set
c.Request().Header.Del(echo.HeaderAcceptEncoding)

if !compressed {
return middleware.ProxyWithConfig(configUncompressed)(next)(c)
}

return middleware.ProxyWithConfig(config)(next)(c)
}
}
}

func (p *DynamicProxy) AddGroup(prefix string) *echo.Group {
Expand Down

0 comments on commit cc3e851

Please sign in to comment.