Coder Social home page Coder Social logo

swisspost / gateleen Goto Github PK

View Code? Open in Web Editor NEW
76.0 76.0 38.0 5.02 MB

Gateleen is a RESTful middleware toolkit for building API gateways

License: Other

Java 90.22% HTML 1.00% CSS 0.43% JavaScript 6.73% Scala 0.92% Lua 0.28% Gherkin 0.11% Shell 0.02% Groovy 0.29%

gateleen's People

Contributors

bertranoel avatar dependabot[bot] avatar dominik-cnx avatar floriankammermann avatar gateleen avatar gcastaldi avatar geekrumper avatar hiddenalpha avatar kusig avatar lbovet avatar linovifian avatar ljucam avatar mcweba avatar nidi3 avatar oli-h avatar roggerj avatar swisspusher avatar taar1 avatar thwint avatar xssilva avatar zhengxincn avatar zorba71 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

gateleen's Issues

Connection: close should not be forwarded

Connection header (e.g Connection: close) set by proxy is forwarded to backends by gateleen.
This is a wrong behaviour according to https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html:

14.10 Connection
The Connection general-header field allows the sender to specify options that are desired for that particular connection and MUST NOT be communicated by proxies over further connections.

This has for effect to sporadically (but often) corrupt the connections between gateleen and backends. Logged error was "Connection was closed" and 503 error returned to client.

As workaround we can clear the header in routing rules with:

   "staticHeaders": {
      "connection": ""
    }

Remove RedisClient from MonitoringHandler

The MonitoringHandler class provides methods to access the queueing functionality. Queue functionality is provided by the Redisques module and can be accessed through the EventBus.

Address.redisquesAddress().

In MonitoringHandler, the queueing functionality is directly accessed via the RedisClient. See example below:

redisClient.llen(queueName, reply -> {
    if(reply.failed()){
        log.error("Error gathering queue size for queue '" + queue + "'");
    } else {
        final long count = reply.result();
        vertx.eventBus().publish(Address.monitoringAddress(), new JsonObject().put(METRIC_NAME, prefix + LAST_USED_QUEUE_SIZE_METRIC).put(METRIC_ACTION, "update").put("n", count));
    }
});

This direct database access through the RedisClient should be omitted, because the correct way would be to use the Redisques module.
Maybe the Redisques module has to be extended to provide the needed information.

Add support for deploying artifacts to given snapshot repository

In order to be able to deploy artifact not only to local repository, we have to add support for deploying artifact to a given repository.

Example:
Local Repository:
gradle clean install -Prepository=http://artifactory.pnet.ch/artifactory/swisspost

Snapshot Repository:
gradle uploadarchives -Prepository=http://artifactory.pnet.ch/artifactory/swisspost -PuploadRepository=http://artifactory.pnet.ch/artifactory/libs-release-local -PsnapshotRepository=http://artifactory.pnet.ch/artifactory/libs-snapshot-local

Improve DelegateName recognition pattern

The DelegateName recognition pattern has to be improved to allow the following calls:
 /gateleen/server/delegate/v1/delegates//definition
 /gateleen/server/delegate/v1/delegates//execution
 /gateleen/server/delegate/v1/delegates//execution/
 /gateleen/server/delegate/v1/delegates//execution/xxx
 /gateleen/server/delegate/v1/delegates//
 /gateleen/server/delegate/v1/delegates/

Queued Requests are not logged with the x-queue Header

The queued requests are not logged with the x-queue Header. This makes it impossible to identify them in the log files.
Find a way to log the request before it is queued and the x-queue header gets removed (QueuingHandler, line 57)

Solution

  1. In the QueuingHandler don't remove the x-queue header, but set an additional header eg. x-queue-inbound-processed="true"
  2. In the QueuingHandler the method isQueued will check additionally if the the x-queue-inbound-processed is not set

Adapt log levels

With INFO level, we should only see one log per request.

We currently have handlers logging too much:

2016-05-31 14:33:06,736 v000h8.pnet.ch_development test eagle WARN Forwarder - %cSaW Translated status 202 to 200
2016-05-31 14:33:06,736 v000h8.pnet.ch_development test eagle INFO LoggingHandler - %cSaW About to log to destination default
2016-05-31 14:33:06,739 v000h8.pnet.ch_development test eagle INFO RequestPropertyFilter - %cSaW Request to ...

Queue processor may use x-server-timestamp set by another gateleen instance

When a gateleen instance forwards to another one, the original x-server-timestamp header is used to calculate the expiration time in QueueProcessor. In case of delay or unsynchronized clocks, the expected TTL is not respected.

Proposal: add another header that would only be used internally by the queue handler. It will be set at enqueue time and removed when the request is played: x-queue-timestamp
This header would never be forwarded.
So we decouple the x-server-timestamp header and queue behaviour.

ERROR Attempted to append to closed appender

The request logging feature seems to have a bug when a special combination of filter values (url, method, destination) are configured in the logging resource.

The following configuration defines a filter for an url and the destination where to log the requests. This configuration works without any problems:

{
  "headers": [],
  "payload": {
    "destinations": [
      {
        "name": "requestLog",
        "type": "file",
        "file": "requestsTest.log"
      }
    ],
    "filters": [
      {
        "url": "/playground/server/tests/exp/.*",
        "destination": "requestLog"
      }
    ]
  }
}

The following configuration also works without problems. This configuration again defines an url and the method (PUT) to log. The destination is configured with the system property org.swisspush.logging.dir:

{
  "headers": [],
  "payload": {
    "destinations": [
      {
        "name": "requestLog",
        "type": "file",
        "file": "requestsTest.log"
      }
    ],
    "filters": [
      {
        "url": "/playground/server/tests/exp/.*",
        "method": "PUT"
      }
    ]
  }
}

Not working configuration

When using all three filter values (url, method and destination), the requests are not written to the logfile and the following error occurs:

log4j:ERROR Attempted to append to closed appender named [requestLog].

An example of such a logging resource would be:

{
  "headers": [],
  "payload": {
    "destinations": [
      {
        "name": "requestLog",
        "type": "file",
        "file": "requestsTest.log"
      }
    ],
    "filters": [
      {
        "url": "/playground/server/tests/exp/.*",
        "method": "PUT",
        "destination": "requestLog"
      }
    ]
  }
}

Encoding problem listing collections?

According to the spec (https://tools.ietf.org/html/rfc3986#page-13), those chars are allowed in url path sements:

pchar         = unreserved / pct-encoded / sub-delims / ":" / "@"
sub-delims  = "!" / "$" / "&" / "'" / "(" / ")"
                  / "*" / "+" / "," / ";" / "="
path-abempty  = *( "/" segment )
segment       = *pchar

Reproduction:
Open Postman and PUT those resources to the gateleen storage (body does not matter) - note: only the last segment of the URL does matter:

  • http://nemotest.pnet.ch:7012/nemo/server/tests/collection/1_hello-$&()*+,;=
  • http://nemotest.pnet.ch:7012/nemo/server/tests/collection/2_hello-$&()*+,;=
  • http://nemotest.pnet.ch:7012/nemo/server/tests/collection/3_hello-$&()*+,;=
  • http://nemotest.pnet.ch:7012/nemo/server/tests/collection/1_hello-:$&()*+,;=
  • http://nemotest.pnet.ch:7012/nemo/server/tests/collection/4_hello-:@$&()*+,;=

Those path segments do not contain characters that need to be percent encoded (according to the spec).

Now do a GET using postman:

http://nemotest.pnet.ch:7012/nemo/server/tests/collection/

Result

{
  "collection": [
    "1_hello-$&()*+,;=",
    "1_hello-§$&()*+,;=",
    "2_hello-$&()*+,;=",
    "3_hello-$&()*+,;=",
    "4_hello-§@$&()*+,;="
  ]
}

Note those two results - the character § - originally this was ::

  • 1_hello-§$&()*+,;=
  • 4_hello-§@$&()*+,;=

GETing the resources (GET works with the URL used in PUT but DOES NOT work using the URL returned by the collection listing):

  • 404: http://nemotest.pnet.ch:7012/nemo/server/tests/collection/4_hello-§@$&()*+,;=
  • 404: http://nemotest.pnet.ch:7012/nemo/server/tests/collection/1_hello-§$&()*+,;=
  • 200: http://nemotest.pnet.ch:7012/nemo/server/tests/collection/4_hello-:@$&()*+,;=
  • 200: http://nemotest.pnet.ch:7012/nemo/server/tests/collection/1_hello-:$&()*+,;=

The problem can also be reproduced using the GUI:

problem_grafisch

Implement a MergeHandler

We need a new Handler (MergeHandler) which allows us to perform a request over more than one route. To implement this, we first have to implement the issue #96.

The MergeHandler has to be addressed by a header: x-merge-collections
The value of the header is the base collection where the routes are created / hosted in.

"/gateleen/data/(.*)" : {
    "path": "data/$1",
    "staticHeaders": {
        "x-merge-collections": "/gateleen/masterdata/parent/"
    }
}

The simplest way is to read from all sources.
Example:

collection1: 123
collection2: 122

Execution:

// targeted request
GET /gateleen/data/collection/122
	MergeHandler
	GET /gateleen/masterdata/parent/collection1/data/collection/123 => 404
	GET /gateleen/masterdata/parent/collection2/data/collection/122 => 200

// request on a collection
GET /gateleen/data/collection
	MergeHandler
	GET /gateleen/masterdata/parent/collection1/data/collection => 200
	GET /gateleen/masterdata/parent/collection2/data/collection => 200
    =>
        { "collection": [ "122", "123" ] }

404 is only returned if nothing is found in any of the given routes / sources.

The implementation has to be performed in a new module ‘gateleen-merge’.

Introduce a circuit breaker

If backends are gone all of the requests (from the queues as well as synchronous ones from the clients) might hang and run into a timeout. This can use up sockets pretty fast.

By introducing some kind of circuit breaker, the opening of connections to backends which timeout too often could be stopped and immediately return an error to the client for some time. This could prevent instances from "going down" by using up all its available sockets.

Check https://github.com/Netflix/Hystrix/wiki/Dashboard (Hystrix: Circuit Breaker from Netflix)

Hook expiration time without timezone

It seems that the hook expiration time is wrongly set. I observed one hour shift, probably because of missing timezone information in the stored timestamp.

Add property to execute scheduler on startup

Currently the schedulers are not executed at startup. If a scheduler only runs after a long period and the system is restarted before this period is over it never gets executed.

To ensure that a job is running at least once it should be possible to create a scheduler which is executed at startup.

Therefore I propose to introduce a new property.

Proposal:
"executeOnStartup" : true

Please comment.

Add additional monitoring metrics

For documentation and monitoring purposes, it would be useful to be able to extract information about the requests and their matching routing rule.

The request could be identfied by a configurable (system property) request header name. To identify the rule, an additional (unique) property called name could be added to each routing rule entry.

Adapt Hook to be able to fire after/before original request

In order to be able to implement the delegate system, hooks must be able to fire after the original request is performed (default is before). We should add a new attribute to the hook:

"type": "after"

Possible values: "before", "after". Defaults to "before".

Drone.io build not working

Since the introduction of the gradle-release plugin, the build on drone.io does not work anymore. See this build for example.

The error is:

Could not find net.researchgate:gradle-release:2.4.0

The dependency is listed as classpath dependency, so Drone.io cannot find it.

Please fix

Introduce randomness in scheduler to avoid network load peaks

Schedulers user cron expressions and are thus aligned with the clock. That means that all Gateleen servers with the same configuration will performs scheduled requests at the same time.
For requests going to a central communication server, this will introduce unbearable network load peaks.
We should add a randomness configuration value. This defines the maximal offset in seconds.

For example:

    randomOffset: 300 

means that the actual time can be shifted up to 5 minutes after the planned time.

Summary:
• We add a new configuration property to define the maximal offset in seconds.
• During the load of the scheduler configuration we calculate an offset for each scheduler, which stays the same for the specific schedulers, till the next reload of the scheduler configuration. This way the interval between executions of the schedulers remain always the same.

Hanging requests on routing rule update

With the introduction of json schemas, the validation of the routing rules resource could be improved. However, not all restrictions are covered with the schema.

The following routing rule entry will result in a hanging request:

{
  "/playground/": {
    "description": "Home Page",
    "storage": "main"
  },
  "/(.*)": {
    "description": "Resource Storage",
    "path": "/$1",
    "storage": "main"
  }
}

The problem with the entry above is the missing path property in the first rule. When a storage property is defined, the path property must be defined as well.

This restriction is not covered by the schema and has to be made manually. Looking at the logfile, the error has been logged successfully but the request was not responded.

java.lang.IllegalArgumentException: For storage routing, 'path' must be specified.
at org.swisspush.gateleen.routing.RuleFactory.setStorage(RuleFactory.java:113)
at org.swisspush.gateleen.routing.RuleFactory.createRules(RuleFactory.java:100)
at org.swisspush.gateleen.routing.RuleFactory.parseRules(RuleFactory.java:41)
at org.swisspush.gateleen.routing.Router.lambda$route$18(Router.java:147)
at org.swisspush.gateleen.routing.Router$$Lambda$158/1153343910.handle(Unknown Source)

This request should have been responded with a http status code 400.

Adapt HookHandler to allow listing of routes

Currently it’s not possible to list routes in a collection.

PUT /collection/resource1
PUT /collection/resource2/_hook/route
GET /collection/resource2 => HookHandler -> Forwarder
GET /collection => Resource storage => { "collection": [ "resource1" ] }

In order to be able to list routes in a collection, we have to adapt the HookHandler. This way a request to a parent collection will check, if routes exist and if so, list them properly. Therefor the HookHandler takes control of creating the listing, if a route - handled by the HookHandler – is present (not the Router), otherwise the Router takes control.

PUT /collection/resource1
PUT /collection/resource2/_hook/route
GET /collection/resource2 => HookHandler -> Forwarder
GET /collection => HookHandler -> Resource Storage + Route hook list => { "collection": [ "resource1", "resource2" ] }

Extend the configuration of Hooks for Routes with two new attributes ‘listable’ and ‘collection’.
listable => if true routes will be shown, otherwise not (current behavior)
collection => because it’s not visible by an URL, if it points to a collection or a resource, we need to specify if the rout is a collection (default) or a resource. This is necessary if the listable feature is used with for example the expand feature.

{ "destination": ..,          // as usual 
  "listable": false,          // new, allows to override the default
  "collection": false }       // new, indicates if route points to collection or resource. 

We also need a new constructor, which allows to set the default for the listable feature:
new HookHandler(...., true) // enable / disable listable as default

Queue Circuit Breaker: periodic tasks executed by each instance

In the Queue Circuit Breaker we use periodic tasks (vertx.setPeriodic(...)) to execute tasks like unlocking sample queues and switching open circuits to state halfOpen.

These periodic tasks are schedulded by the configuration resource and then executed in every verticle instance.

This means unlocking a locked queue will result in multiple (corresponding the count of verticles) delete lock requests.

This behaviour should be changed, so every task execution is made by a single instance only. Use the SETNX command from redis to achieve this.

Another solution could be cluster wide locks. See http://vertx.io/docs/vertx-core/java/#_cluster_wide_locks

Extend staticHeaders functionality

With the current implemenation we can define static headers for routing rules like this:

{
    "/playground/tests/(.*)": {
        "path": "/playground/server/tests/$1",
        "storage": "main",
        "staticHeaders": {
            "X-Expire-After": "3600"
        }
    }
}

Defining a X-Expire-After static header like in the example above will add this header to the request. However, an already added X-Expire-After header will be replaced.

It would be useful to have a feature which allows to add a static headers only when they are not already present.

This could be accomplished by adding a forced flag. This flag would result in the following behaviour:

Force flag Behaviour
true Replaces (overrides) already defined header values with the staticHeader value
false Does nothing when header value already exists, adds defined header value otherwise
not set Replaces (overrides) already defined header values with the staticHeader value. This is used for backward compatibility, since headers are replaced in current implementation

A possible staticHeader configuration could look like this:

{
    "/playground/tests/(.*)": {
        "path": "/playground/server/tests/$1",
        "storage": "main",
        "staticHeaders": {
            "X-Expire-After": { "value": "3600", "force": true }
        }
    }
}

Extend ZipHandler to allow uncompressed zip file creation

Extend the ZipHandler of the ExpansionHandler to use a zip method without compression. This could be helpful, if there is a need to pack some zips together in one zip, to save PUT / GET requests.

Currently:
zip=true

New:
zip=ture (compressed)
zip=store (uncompressed)

Missing Request-Log entries

The LoggingHandler class can be used to log the payload of requests to a log file. We have found situations where requests which should be logged (according to the logging configuration) have not been found in the log file.

In this case, the configuration should be correct since other requests of the same pattern could be successfully logged.

I would suggest to investigate in the logging code and make the improvements/reviews listed below:

  • Add log statements (not in requests log) when a request matches a logging configuration entry
  • Check implementation for possible bugs like swallowed exceptions for example
  • Maybe try to ensure whether the log entry could be successfull written to the log file (log4j)

As additional information it would be helpful to add the timestamp to the requests log entries!

Make QueueClient injectable to allow custom queuing

In QueueHandler and HookHandler, the QueueClient is instanciated with new.
I propose to make it overridable in order to allow custom implementation.
For example, on single-instance gateleen servers where we don't need persistence we can enqueue in memory, without redisques.

Improve queue expiry management

In order to be able to optimize the transport from a source via hook to the target, we have to be able to define how long a request remains maximally in the queue. The TTL for the request in the queue shouldn’t be the TTL of the resource (that’s currently the default behavior).

To be able to separate the TTL of a resource and the TTL of a request in the queue, we need an additional header x-queue-expire-after, which enables us to override the default setting of the TTL in the queue.

If the x-queue-expire-after header is set, this header will be used instead of the header x-expire-after to determine if a request in the queue expires or not. If the header is not set, the current behavior will not change.

Scheduler doesn't set "X-Server-Timestamp" header

The Scheduler doesn’t currently set a ‘X-Server-Timestamp’ header when it enqueues a request.
Because of this the expiration of schedulers queues is broken.

Add the "X-Server-Timestamp" header to each request of a schedulers, when it is enqueued.

Implement a DelegateHandler as a new module

Implement the delegate feature. With this mechanism we are able to replace a request by another.
For example, we could make a GET that will be replaced by another one (or even a POST). This allows for creating cheap adapters.

Cookbook for the delegate:
Name a delegate:
/gateleen/server/delegate/v1/delegates/<delegate>/

Create a definition:
/gateleen/server/delegate/v1/delegates/<delegate>/definition

DelegateHandler automatically checks if the Pattern
/gateleen/server/delegate/v1/delegates/<delegate>/execution
is called.

Example:

 // create a delegate
PUT /gateleen/server/delegate/v1/delegates/user-zip-copy/definition
{
    "methods": [ "PUT", "DELETE" ],
    "pattern": ".*/([^/]+.*)",
    "requests": [
        {
            "method": "POST",
            "url": "/gateleen/server/v1/copy",
            "payload": {
                "source": "/gateleen/$1?expand=100&zip=true",
                "destination": "/gateleen/zips/users/$1.zip"
            }
        }
        ]
    }
}

// create a hook triggering the delegate
PUT /gateleen/users/_hooks/listeners/user-zip-copy
{
    "destination": "/gateleen/server/delegate/v1/delegates/user-zip-copy/execution"
}

Validation: Non-valid resources result in hanging requests

To reproduce follow these steps:

  • Make sure you have an API schema deployed for the resource to be validedated
  • Configure validation resource to validate the corresponding resource.
{
    "resources": [
        {
            "url": "/resources/resourceToBeValidated",
            "method": "PUT"
        }
    ]
}
  • PUT resourceToBeValidated with invalid content (according to the schema)

Result: The PUT request for the resourceToBeValidated resource is never responded!

Queue Circuit Breaker: Calculate minQueueSampleCount threshold based on entriesMaxAgeMS

The current implementation (circuitbreaker_update.lua) calculates the failRatio of an endpoint based on the amount of recorded statistic values (failed and succeeded requests) and the ratio between the count of those statistic values.

sampleCountThresholdReached
Whether or not the amount of recorded statistic values is reached, is decided by counting the entries in the success/fail sets using the redis command ZCARD. The ZCARD command does simply return the amount of entries in a sorted set not respecting the score.

calculateFailurePercentage
The failure percentage is also calculated based on the amount of entries in the success/fail sets. However, this time, the redis command ZCOUNT is used. The ZCOUNT command has to be executed with additional score parameters. In this case, the score parameter relates to the timestamp when the entry was added to the set. So also entries not older than Now - entriesMaxAgeMS are respected for the fail ratio calculation.

Problem
Since the sampleCountThresholdReached does not respect the age of the entries, all entries are counted. This leads to a sampleCountThresholdReached = TRUE once the minQueueSampleCount _ treshold has reached.
From now on, sampleCountThresholdReached
is always true (until the endpoint has opened and closed again resulting in a reset of the endpoint statistics and failRatio) and therefore only the calculateFailurePercentage value is respected.

The problem here is when in the configured entriesMaxAgeMS range a single failing request is made, the failRatio calucation will look like this:

Count successful: 0
Count failure: 1
failRatio: (1/1)*100 => 100%

The endpoint will be opened based on just one failing request.

Solution
Like the calculateFailurePercentage value, the sampleCountThresholdReached value has to be calculated using the redis command ZCOUNT which respects the age of the entries.
In the scenario mentioned above, this will lead to a sampleCountThresholdReached = FALSE, since only one entry is respected.

QueueBrowser: QueueItems with index higher than 99 cannot be loaded

In the QueueBrowser class is a mapping for GET requests to load a single QueueItem by index.

GET /playground/queues/my_queue/{index}

This mapping is implemented as follows:

// Get item
router.getWithRegex(prefix + "/queues/([^/]+)/[0-9]+").handler(ctx -> {
    final String queue = lastPart(ctx.request().path().substring(0, ctx.request().path().length() - 2), "/");
    final int index = Integer.parseInt(lastPart(ctx.request().path(), "/"));
    eb.send(redisquesAddress, buildGetQueueItemOperation(queue, index), new Handler<AsyncResult<Message<JsonObject>>>() {
        @Override
        public void handle(AsyncResult<Message<JsonObject>> reply) {
            JsonObject replyBody = reply.result().body();
            if (OK.equals(replyBody.getString(STATUS))) {
                ctx.response().putHeader(CONTENT_TYPE, APPLICATION_JSON);
                ctx.response().end(decode(reply.result().body().getString(VALUE)));
            } else {
                ctx.response().setStatusCode(StatusCode.NOT_FOUND.getStatusCode());
                ctx.response().setStatusMessage(StatusCode.NOT_FOUND.getStatusMessage());
                ctx.response().end("Not Found");
            }
        }
    });
});

The following line is wrong, since it only works for indices from 0 to 99

final String queue = lastPart(ctx.request().path().substring(0, ctx.request().path().length() - 2), "/");

Making a request like this

GET /playground/queues/my_queue/500

would result in a queuename with value 5 instead of my_queue.

doneHandlers in Router are called every time the routing rules change

Problem

In the Router class an ellipsis of doneHandlers can be passed.

Handler<Void>... doneHandlers

The purpose of these doneHandlers is to get notified when the router is completely initialized.
Every time the routing rules are changed, the method

void updateRouting(List<Rule> rules)

is called. This method includes the notification of the doneHandlers with the following loop

for (Handler<Void> doneHandler : doneHandlers) {
    doneHandler.handle(null);
}

This behaviour is currently used in the HookHandler class. There, with every notification of the doneHandler the init method is called

public void init() {
    registerListenerRegistrationHandler();
    registerRouteRegistrationHandler();

    loadStoredListeners();
    loadStoredRoutes();

    registerCleanupHandler();
}

leading to new consumers. The creation of new consumers in this case should be avoided.

Possible solution

To await the complete initialization of the Router class, a RouterFactory could be implemented which builds the Router and returns a Future holding the initialized Router. This could look something like this:

public class RouterProvider {

    public Future<Router> buildRouter(Object param1, Object param2, Object param3) {
        Future<Router> future = Future.future();
        // instantiate the router and call future.complete() when ready
        return future;
    }   
}

The doneHandlers ellipsis parameter could then be removed from the constructors.

Please comment.

Fix ignored ZipExtractTest

In the gateleen-test module the test testExtractZipContentFound from class ZipExtractTest does fail every time when executed on drone.io but succeeds locally.

The test always fails on the following assertion

// compare if the extracted file is identical to the original file
context.assertTrue(Files.equal(originalFile, responseFile));

Please fix this test

Adapt the HookHandler to use staticHeaders

We have to adapt the HookHandler to be able to define staticHeaders in a hook.
"hook": { "methods": [ "PUT" ], "destination": "/test", "expireAfter": 86400, "staticHeaders" : { "x-queue-expire-after" : 20 } }

Static headers overrides always currently set headers (as well as default headers).

Extend validation to validate multiple resources with the same schema

Current validation feature

Let's say you have the following structure of resources and want to validate the res_1, res_2 and res_3 resource.
image
To validate these resources, you would have to deploy 3 different schemas and configure them in the validation resource like this:

{
  "resources": [
    {
      "url": "/playground/server/tests/resources/res_1",
      "method": "PUT"
    },
    {
      "url": "/playground/server/tests/resources/res_2",
      "method": "PUT"
    },
    {
      "url": "/playground/server/tests/resources/res_3",
      "method": "PUT"
    }    
  ]
}

Required additional validation functionality

So when res_1, res_2 and res_3 are instances of the same resource and therefore can be validated by the same schema, it would be useful to define one schema only.

It would be useful when the configuration could look something like this:

{
  "resources": [
    {
      "url": "/playground/server/tests/resources/.*",
      "method": "PUT"
    }    
  ]
}

This would mean that all resources under /playground/server/tests/resources/ will be validated. It has to be defined how the corresponding schema for this resources can be selected (maybe by defining the name of the schema as additional property in the validation resource).

Queue Circuit Breaker: Enhance logging

The logging for the Queue Circuit Breaker should be enhanced. It has to be checked where the logging could be improved.

One place to enhance the logging is:

  • When a circuit is opened, a log entry should be written

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.