Skip to content

Commit

Permalink
Merge pull request #631 from ayeshLK/master
Browse files Browse the repository at this point in the history
[Master] Add support to send custom parameters/headers in the subscription request
  • Loading branch information
ayeshLK committed Sep 14, 2023
2 parents 06f9822 + 2520004 commit 34f31b2
Show file tree
Hide file tree
Showing 7 changed files with 103 additions and 1 deletion.
4 changes: 4 additions & 0 deletions ballerina/annotation.bal
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
# + unsubscribeOnShutdown - This flag notifies whether or not to initiate unsubscription when the service is shutting down
# + httpConfig - The configuration for the subscriber client used to interact with the discovered/specified hub
# + discoveryConfig - HTTP client configurations for resource discovery
# + customParams - Additional parameters which need to be sent with the subscription request
# + customHeaders - Additional HTTP headers which need to be sent with the subscription request
# + servicePath - The generated service-path if the service-path is not provided. This is auto-generated at the compile-time.
public type SubscriberServiceConfiguration record {|
string|[string, string] target?;
Expand All @@ -39,6 +41,8 @@ public type SubscriberServiceConfiguration record {|
string|string[] acceptLanguage?;
ClientConfiguration httpConfig?;
|} discoveryConfig?;
map<string> customParams?;
map<string> customHeaders?;
readonly byte[] servicePath = [];
|};

Expand Down
4 changes: 4 additions & 0 deletions ballerina/commons.bal
Original file line number Diff line number Diff line change
Expand Up @@ -117,11 +117,15 @@ public type ListenerConfiguration record {|
# + callback - The callback which should be registered/unregistered for the subscription/unsubscription request sent
# + leaseSeconds - The lease period for which the subscription is expected to be active
# + secret - The secret to be used for authenticated content distribution with this subscription
# + customParams - Additional parameters which need to be sent with the subscription request
# + customHeaders - Additional HTTP headers which need to be sent with the subscription request
public type SubscriptionChangeRequest record {|
string topic = "";
string callback = "";
int leaseSeconds = 0;
string secret = "";
map<string> customParams?;
map<string> customHeaders?;
|};

# Record representing subscription/unsubscription details if a subscription/unsubscription request is successful.
Expand Down
9 changes: 8 additions & 1 deletion ballerina/subscriber_client.bal
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ public isolated client class SubscriptionClient {
returns SubscriptionChangeResponse|SubscriptionInitiationError {
http:Client httpClient = self.httpClient;
SubscriptionPayload payload = buildSubscriptionPayload(MODE_SUBSCRIBE, subscriptionRequest);
http:Response|error response = httpClient->post("", payload, mediaType = mime:APPLICATION_FORM_URLENCODED);
http:Response|error response = httpClient->post("", payload,
headers = subscriptionRequest.customHeaders, mediaType = mime:APPLICATION_FORM_URLENCODED);
return processHubResponse(self.url, MODE_SUBSCRIBE, subscriptionRequest.topic, response);
}

Expand Down Expand Up @@ -90,6 +91,12 @@ isolated function buildSubscriptionPayload(string mode, SubscriptionChangeReques
if subscriptionReq.leaseSeconds != 0 {
payload.hub\.lease_seconds = subscriptionReq.leaseSeconds.toString();
}
map<string>? customParams = subscriptionReq.customParams;
if customParams is map<string> {
foreach var ['key, value] in customParams.entries() {
payload['key] = value;
}
}
}
return payload;
}
Expand Down
68 changes: 68 additions & 0 deletions ballerina/tests/subscription_initiation_test.bal
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,13 @@ const string HUB_FAILURE_URL = "http://127.0.0.1:9192/common/failed";
const string COMMON_TOPIC = "https://sample.topic.com";

service /common on new http:Listener(9192) {
private final readonly & [string, string][] expectedAdditionalParams = [
["param1", "value1"], ["param2", "value2"]
];
private final readonly & [string, string][] expectedAdditionalHeaders = [
["head1", "headValue1"], ["head2", "headValue2"]
];

isolated resource function get discovery(http:Caller caller, http:Request request) returns error? {
http:Response response = new;
response.addHeader("Link", "<http://127.0.0.1:9192/common/hub>; rel=\"hub\"");
Expand All @@ -36,6 +43,30 @@ service /common on new http:Listener(9192) {
isolated resource function post hub(http:Caller caller, http:Request request) returns error? {
check caller->respond();
}

isolated resource function post hub/additional(http:Caller caller, http:Request request) returns error? {
map<string> params = check request.getFormParams();
foreach var ['key, value] in self.expectedAdditionalParams {
test:assertTrue(params.hasKey('key), "expected additional parameter not present");
test:assertEquals(params.get('key), value, "expected parameter value not present");
}
foreach var [header, headerValue] in self.expectedAdditionalHeaders {
test:assertTrue(request.hasHeader(header), "expected additional header not present");
test:assertEquals(check request.getHeader(header), headerValue, "expected header value not present");
}
check caller->respond();
}

isolated resource function post hub/additional/unsub(http:Caller caller, http:Request request) returns error? {
map<string> params = check request.getFormParams();
foreach var ['key, _] in self.expectedAdditionalParams {
test:assertTrue(!params.hasKey('key), "unexpected additional parameter present");
}
foreach var [header, _] in self.expectedAdditionalHeaders {
test:assertTrue(!request.hasHeader(header), "unexpected additional header present");
}
check caller->respond();
}
}

isolated function getServiceAnnotationConfig(string|[string, string] target) returns SubscriberServiceConfiguration {
Expand Down Expand Up @@ -115,6 +146,22 @@ isolated function testSubscriptionInitiationFailureWithHubAndTopic() returns err
}
}

@test:Config {
groups: ["subscriptionInitiation"]
}
isolated function testSubscriptionInitiationSuccessWithAdditionalParams() returns error? {
SubscriberServiceConfiguration config = getServiceAnnotationConfig([ "http://127.0.0.1:9192/common/hub/additional", COMMON_TOPIC ]);
config.customParams = {
"param1": "value1",
"param2": "value2"
};
config.customHeaders = {
"head1": "headValue1",
"head2": "headValue2"
};
check subscribe(config, "https://sample.com/sub1");
}

@test:Config {
groups: ["unSubscriptionInitiation"]
}
Expand Down Expand Up @@ -187,6 +234,27 @@ isolated function testUnSubscriptionInitiationDisable() returns error? {
check unsubscribe(config, "https://sample.com/sub1");
}

@test:Config {
groups: ["unSubscriptionInitiation"]
}
isolated function testUnSubscriptionInitiationSuccessWithAdditionalParams() returns error? {
SubscriberServiceConfiguration config = {
target: ["http://127.0.0.1:9192/common/hub/additional/unsub", COMMON_TOPIC],
leaseSeconds: 36000,
callback: CALLBACK,
unsubscribeOnShutdown: true
};
config.customParams = {
"param1": "value1",
"param2": "value2"
};
config.customHeaders = {
"head1": "headValue1",
"head2": "headValue2"
};
check unsubscribe(config, "https://sample.com/sub1");
}

listener Listener ls = new (9100);

@test:Config {
Expand Down
8 changes: 8 additions & 0 deletions ballerina/utils.bal
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,14 @@ isolated function retrieveSubscriptionRequest(string topicUrl, SubscriberService
request.secret = secret;
}

map<string>? customParams = config.customParams;
if customParams is map<string> {
request.customParams = customParams;
}
map<string>? customHeaders = config.customHeaders;
if customHeaders is map<string> {
request.customHeaders = customHeaders;
}
return request;
}

Expand Down
7 changes: 7 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,16 @@ This file contains all the notable changes done to the Ballerina WebSub package
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Added
- [Introduce new `ClientConfiguration` record to be used for `websub:SubscriptionClient` and `websub:DiscoveryService`](https://github.com/ballerina-platform/ballerina-standard-library/issues/4706)

## [2.9.1] - 2023-09-14

### Added
- [Add support to send custom parameters in the subscription request](https://github.com/ballerina-platform/ballerina-standard-library/issues/4795)

## [2.5.0] - 2022-11-30

### Fixed
Expand Down
4 changes: 4 additions & 0 deletions docs/spec/spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,8 @@ should be `websub:SubscriberServiceConfig` a service-level-annotation for `websu
# + unsubscribeOnShutdown - This flag notifies whether or not to initiate unsubscription when the service is shutting down
# + httpConfig - The configuration for the subscriber client used to interact with the discovered/specified hub
# + discoveryConfig - HTTP client configurations for resource discovery
# + customParams - Additional parameters which need to be sent with the subscription request
# + customHeaders - Additional HTTP headers which need to be sent with the subscription request
# + servicePath - The generated service-path if the service-path is not provided. This is auto-generated at the compile-time
public type SubscriberServiceConfiguration record {|
string|[string, string] target?;
Expand All @@ -294,6 +296,8 @@ public type SubscriberServiceConfiguration record {|
string|string[] acceptLanguage?;
ClientConfiguration httpConfig?;
|} discoveryConfig?;
map<string> customParams?;
map<string> customHeaders?;
readonly byte[] servicePath = [];
|};
```
Expand Down

0 comments on commit 34f31b2

Please sign in to comment.